基于深度学习生成音乐

   以前在看Andrew Ng 的deep learning 视频教程,在RNN 这一节的课后做业里,实现了一个基于deepjazz的music generator,实验以后发现产生的结果还有模有样的,这激发了个人兴趣,因而我就查阅了一些资料,看看音乐的自动生成方面最近有哪些进展,特别是深度学习在这一块的应用.在这里稍微总结一下,而且写一写一些有趣的应用.

---------------------------------------------------- Part I : deep jazz 的简单介绍-------------------------------------------------------------

1.What is deepjazz?

   如下内容搬运自deepjazz的官网:

deepjazz 是一个使用theano 和keras的基于深度学习的jazz music 生成器.我在编程马拉松(hackathon)使用36个小时建立了deepjazz.它使用了theano和keras这两个库来生成jazz music.具体地说,它构建了两层的LSTM,从midi files 中学习.它使用了深度学习技术,以及AI技术,这个技术创造了著名的google AlphaGo和IBM的Watson,来产生音乐.而音乐被认为是很是human的.html

2.怎样使用deepjazz?

2.1 训练模型并产生midi文件

   咱们首先去deepjazz的github首页看一下.github上面说的比较简单,咱们首先git clone https://github.com/jisungk/deepjazz,而后 cd deepjazz,再运行python generator.py 应该就能够产生 学习出来的.mid 文件了.可是在测试的过程里,首先会报错(python3):''' from itertools import groupby, izip_longest ImportError: cannot import name 'izip_longest' '''.这是因为原来的脚本是用python2写的,咱们须要将原来全部的"from itertools import izip_longest" 替换为"from itertools import zip_longest".

   继续运行,仍是因为兼容性的问题,仍然会报错:

"melody_voice.insert(0, key.KeySignature(sharps=1,mode='major'))TypeError: init() got an unexpected keyword argument 'mode'
这里咱们只须要将mode = 'major'移除就能够了,后面还须要将generator.py中的 _sample 函数修改成:python

def __sample(a, temperature=1.0):
    a = np.log(a) / temperature
    # a = np.exp(a) / np.sum(np.exp(a))
    # return np.argmax(np.random.multinomial(1, a, 1))
    dist = np.exp(a)/np.sum(np.exp(a))
    choices = range(len(a)) 
    return np.random.choice(choices, p=dist)

作了如上的修改以后,再运行python generator.py 应该就能够正常run起来了,运行结束以后,在midi 文件夹下,会多出一个deepjazz_on_metheny...128_epochs.midi 文件,这个就是咱们经过 original_metheny.mid 训练学习获得的生成文件了.须要注意的是,不管咱们训练仍是生成的都不是常见的.mp3,.wav格式的音频文件,而是.mid(或者.midi)格式的文件.那么这二者有什么区别呢?这里引用百度百科的定义简单说明一下:git

与波形文件不一样,MIDI文件不对音乐进行抽样,而是对音乐的每一个音符记录为一个数字,因此与波形文件相比文件要小得多,能够知足长时间音乐的须要。MIDI标准规定了各类音调的混合及发音,经过输出装置能够将这些数字从新合成为音乐。
MIDI音乐的主要限制是它缺少重现真实天然声音的能力,所以不能用在须要语音的场合。此外,MIDI只能记录标准所规定的有限种乐器的组合,并且回放质量受到声音卡的合成芯片的限制。近年来,国外流行的声音卡广泛采用波表法进行音乐合成,使MIDI的音乐质量大大提升。
MIDI文件有几个变通格式,如RMI和CIF等。其中CMF文件(creative music format)是随声霸卡一块儿使用的音乐文件。RMI文件是Windows使用的RIFF(resource interchange file format)文件的一种子格式,称为RMID,即包含MIDI文件的格式。
   简单来讲就是:常见的.mp3,.wav格式的文件记录的都是真实的音频内容,所以通常体积会比较大(几兆到几十兆不等),而midi格式的文件没有记录真实的音频信息,它只是记录了一种表明格式的数字,计算机能够按照必定的标准识别出这种数字,而后把它转化为对应的音频播放出来.所以通常.midi格式的文件体积很是小,这是它的一个很大的优势,其缺点就是对于真实的声音还原较差(由于它只能经过有限种指定的乐器来模拟声音).github

2.2 如何播放midi文件?

   言归正传,在获得生成的midi文件以后,咱们固然须要播放它好好欣赏一番啦.在windows下有很多软件能够播放midi格式的文件,可是我使用的系统是ubuntu16.04,默认的播放器不支持midi格式,在查阅了资料之后发现须要安装timidity,在ubuntu 下
直接sudo apt-get install timidity 便可.我找了一个python脚本play_midi.py(基于pygame),能够播放midi 文件,代码以下:编程

import pygame
import pygame as pg
def play_music(music_file):
    '''
    stream music with mixer.music module in blocking manner
    this will stream the sound from disk while playing
    '''
    clock = pg.time.Clock()
    try:
      pg.mixer.music.load(music_file)
      print("Music file {} loaded!".format(music_file))
    except pygame.error:
        print("File {} not found! {}".format(music_file, pg.get_error()))
        return
    pg.mixer.music.play()
    # check if playback has finished
    while pg.mixer.music.get_busy():
        clock.tick(30)
# pick a midi or MP3 music file you have in the working folder
# or give full pathname
music_file = input("Please input the midi file path:")
#music_file = "Drumtrack.mp3"
freq = 44100  # audio CD quality
bitsize = -16  # unsigned 16 bit
channels = 2  # 1 is mono, 2 is stereo
buffer = 2048  # number of samples (experiment to get right sound)
pg.mixer.init(freq, bitsize, channels, buffer)
# optional volume 0 to 1.0
pg.mixer.music.set_volume(0.8)
try:
    play_music(music_file)
except KeyboardInterrupt:
    # if user hits Ctrl/C then exit
    # (works only in console mode)
    pg.mixer.music.fadeout(1000)
    pg.mixer.music.stop()
    raise SystemExit

运行python play_midi.py ,而后输入midi文件的路径,就能够播放啦.试着播放咱们生成的midi文件,你会发现听起来是至关不错的!
固然其实安装了timidity以后,咱们就能够直接播放midi文件了,直接运行 timidity xxx.midi 就能够了.可是有可能会出问题,由于咱们还须要一些额外的配置文件,运行命令'sudo apt-get install fluid-soundfont-gm fluid-soundfont-gs' 安装好soundfont(声音字体,用于解析midi,而且播放),而后打开/etc/timidity/timidity.cfg 文件,将最后一行'source freepats.cfg' 注释掉,若是是ubuntu系统的话改成:
dir /usr/share/sounds/sf2/
soundfont FluidR3_GM.sf2
若是是centos系统的话改成:
dir /usr/share/soundfonts/
soundfont FluidR3_GM.sf2
而后重启timidity,执行命令:sudo /etc/init.d/timidity restart
这样咱们再执行timidity xxx.midi应该就能够正常播放啦!ubuntu

2.3 如何将midi文件转化为通常的音频文件(mp3,wav等格式)

   如今咱们能够正常播放midi文件了.可是还有一个问题,通常咱们使用的音频格式是wav,mp3这种格式的,由于它们更易于被通常的播放器识别而且播放.那么有没有上面办法能够将midi文件转化为这样的格式呢?固然是有办法的,最简单的办法就是使用timidity(以前咱们已经安装过啦),运行下面的命令:
timidity --output-24bit --output-mono -A120 source.mid -Ow -o source.wav
就能够把source.mid 转化为source.wav 了.其中 --output指定输出的格式,-A指定音量(volume),-Ow 表示转化为RIFF WAVE file输出格式,-o指定输出音频文件的名字,具体能够timidity --help 查看各个参数的含义.
若是没有问题的话,咱们就获得一个.wav文件啦,这样你使用任何一个音乐播放器均可以播放它啦!
顺便提一个小问题.wav文件通常体积比较大(质量较好),而在网络上更常见的是mp3文件,那么这二者该如何转化呢?这里我提供两种解决办法:
1.使用ffmpeg 这个音视频库来进行转化.运行命令
ffmpeg -i source.wav -acodec libmp3lame source.mp3
就能够将source.wav 转化为source.mp3了.这里 -i 表示输入音频,-acodec 表示设置 audio codec(音频编码)格式,是"-codec:a"的别名,更多的信息能够输入 ffmpeg --help 或者 man ffmpeg查看
2.也能够安装python的音频库pydub进行转化,这个我在以前的博客介绍几个python的音频处理库介绍过,有兴趣能够自行查看.windows

如何将wav,mp3文件转化为midi文件?

   这个问题我一开始觉得是挺容易实现的一个任务,哪知道查了资料之后才发现是一个很hard的问题,目前仍然有不少人研究music transcription(音乐转换)的问题.我没有找到一个很好地解决这个问题的api,具体能够参看stackoverflow的这个讨论,目前也有不少的plugin能够作这个事情,好比Sonic Annotator等,可是就涉及到很专业的知识了,我想了一个仍是放弃了...总之若是要作批量的从wav,mp3到midi的转化仍是很困难的,特别是要求比较高的质量的话,若是有兴趣,你们能够自行研究了.可是若是不要求大规模的自动转换,仍是有很多软件能够完成wav(mp3)到midi的转化的,好比这个网址能够在线将mp3转换为midi格式.centos

如何训练本身的midi文件?

   以前咱们是拿做者给的一个original_metheny.mid文件进行训练而后生成mid文件的.那么咱们能够拿本身的mid文件进行训练吗?这里有一个网址能够打包下载不少的midi文件,或者访问这个网址能够下载本身喜欢的流行音乐的midi格式.咱们发现咱们下载的midi文件的format,tracks,divisions都和deepjazz做者提供的original_metheny.mid格式不一样,因此若是只是把mid文件换成咱们本身的是没有办法顺利train的,老是会报错.我大概看了一下代码,主要是使用music21处理midi格式转换的代码部分有问题.我尝试了半天,由于本身对于music21以及midi格式不是很熟悉,因此这个问题暂时没有解决.若是我后面有时间了会好好再分析一下deepjazz的源码,解决这个问题.api

---------------------------------------------------------------------------Part II magenta ---------------------------------------------------------------浏览器

1.What is magenta?

   下面是magenta官方github的介绍.

magenta是一个旨在探索使用机器学习来创造艺术和音乐的研究项目.目前它主要使用新兴的深度学习技术以及强化学习技术来产生歌曲,绘画,图片等等.同时它也旨在探索构建智能化的工具和接口,这样艺术家可使用这些模型来扩展(而不是取代)他们的部分工做.
magenta最初是由Google Brain 的一些研究员发起的,可是其余的不少研究人员也为这个项目作出了巨大的贡献.咱们使用tensorflow在github上发布咱们的模型和代码.若是你想要了解更多关于magenta的事情,你能够查看咱们的博客,咱们在那里介绍了不少技术上的细节.你也能够加入讨论组.

2.How to install magenta and use it?

   安装magenta很是简单,能够直接使用pip install magenta 安装,可是要注意在此以前你须要安装好了tensorflow.
magenta支持gpu加速(你只须要安装gpu版本的tensorflow),使用pip install magenta-gpu 安装便可.magenta其实提供了很是多的models,包含了语音,图片等.这里咱们主要关注音乐生成方面的模型.

2.1 drums_rnn model

   这是一个训练获得drums 风格音乐的模型.这个模型使用了LSTM将语言模型应用在drum track 生成上.和melodies不同,drum tracks是多音的,多个drums可能会同时存在.尽管这样,咱们仍是经过如下手段将drum track 做为一个single sequence 来处理:
a)将全部不一样的midi drums 映射到一个更小的drum classes上去
b)将每个event表达为一个单一值,该值表明了该次struck(敲击)所属的drums classes 类别
这里model 提供了两个configurations:one drum 和drum kit.具体能够参考原网址的说明
   下面来讲明如何训练drums_rnn model.magenta其实已经提供了pre trained model,咱们能够首先快速来inference一下.首先下载drum_kit文件,而后将下载的drum_kit_rnn.mag文件放入某一个文件夹下(好比model/下).而后咱们写一个脚本generate_drums_rnn.sh:

#!/bin/bash
drums_rnn_generate \
        --config='drum_kit' \
        --bundle_file=../data/drum_kit_rnn.mag \
        --output_dir=../output \
        --num_outputs=5 \
        --num_steps=256 \
        --primer_drums="[(36,)]"

这里 --config 是配置 configuration,有'drum_kit'和'one_drum'两个选项
--bundle_file 指定咱们bundle file的地址(就是刚才下载的drum_kit_rnn.mag文件)
--output_dir 指定输出midi文件的地址
--num_outputs 指定输出midi文件的个数(默认是10个)
--num_steps 指定训练的epochs(训练轮数)
--primer_drums 指定开始的一些音节(必填)
上面的脚本会以一个bass drum hit(低音)开始,若是你愿意的话,你也可使用其余的字符串形式的python list,可是list中的元素必须是一个tuple,并且必需要是表明drum 的midi 音节的整数.好比说:--primer_drums="[(36, 42), (), (42,)]"表示的意思就是一个bass 和一个hit-hat,而后是一个silence,最后是一个hit-hat.若是你不使用--primer_drums参数,你也可使用--primer_midi参数,来使用一个drum midi 文件来做为primer(开头).
若是按照上面的方式来进行尝试的话,你会获得一些midi文件.而后播放它吧,有些仍是至关不错的!
   上面咱们使用了pre trained model,而后能够直接获得生成的midi文件,那么该如何来训练本身的model呢?训练本身的model有些复杂,咱们能够按照以下的steps 进行操做:

step1:build your dataset

   参考网址首先咱们须要准备本身的midi datasets,能够在这个网址打包下载,或者在这个midiworld本身手动下载,而后咱们须要将这些midi files 转化为NoteSequences.使用以下的脚本convert_midi.sh进行转换:

#!/bin/bash
convert_dir_to_note_sequences \
  --input_dir=$INPUT_DIRECTORY \
  --output_file=$SEQUENCES_TFRECORD \
  --recursive

上面的参数:
--input_dir表示输入midi files 的文件夹地址(能够包含子文件夹)
--output_file 表示输出.tfrecord文件的地址
--recursive 表示递归遍历midi files
注意若是你使用的是前一个midi datasets的话,因为这个数据集很是大(有1.6G左右),包含了很是多的midi文件,因此训练起来可能会很是耗时,我大概训练了两个小时还没训练完最后提早终止了,固然若是你的计算机性能很是好,你也能够尝试训练完.
训练完以后,咱们会获得一个lmd_matched_notesequences.tfrecord文件.接下来进入step2

step2:create sequenceExamples

   注意咱们输入模型进行训练和评估的是SequenceExamples.每个SequenceExample都会包含一个序列输入和一个序列标签,表明了一个drum track.能够运行下面的命令将以前获得的NoteSequences 转化为SequenceExamples.这样将会产生两个部分的SequenceExamples,一个用于training,一个用于evaluation.具体可使用--eval_ratio来指定二者的比例.好比指定eval_ratio = 0.1(或者10%),会将提取出的drums tracks 的10%用于evaluation,剩下的90%用于training.

drums_rnn_create_dataset \
--config=<one of 'one_drum' or 'drum_kit'> \
--input=/tmp/notesequences.tfrecord \
--output_dir=/tmp/drums_rnn/sequence_examples \
--eval_ratio=0.10

上面的参数中:
--config 只能取值为'one_drum'或者'drum_kit'
--input 为step1获得的tfrecord文件地址
--output_dir 为输出SequenceExamples的文件夹地址
--eval_ratio 指定evaluation 和training的比例

step3:train and evaluate the model

   运行下面的代码(train.sh)就能够进行train了.

#!/bin/bash
drums_rnn_train \
--config=drum_kit \
--run_dir=/tmp/drums_rnn/logdir/run1 \
--sequence_example_file=/tmp/drums_rnn/sequence_examples/training_drum_tracks.tfrecord \
--hparams="batch_size=64,rnn_layer_sizes=[64,64]}" \
--num_training_steps=20000

各个参数的含义以下:
--config:'one_drum' or 'drum_kit'
--run_dir 是运行tensorflow训练模型checkpoints存放的文件夹地址
--sequence_example_file是用于训练模型的SequenceExamples tfrecord文件地址
--num_training_steps 指定训练的steps(轮数),若是不指定的话,会一直运行直到手动终止(CTRL-C或者CTRL-Z)
--hparams 用于指定其余的超参数,好比这里咱们指定了batch_size = 64,而不是默认的128.使用更小的batch size 有助于下降OOM(内存溢出)的风险,固然,若是你的内存够大,也能够设置较大的batch_size.这里还设定使用2 layers的RNN,每个layer 的hidden units都是64,而不是默认的3 layers,每一个layer有256个hidden units.这样能够加速训练(固然损失了必定的精度),若是你的计算机性能很高,你能够尝试更大的hidden units以得到更好的结果.咱们还能够设定--attn_length 参数来指定多少个steps进行一次attention machanism.这里咱们使用的是默认值32.
   运行下面的代码(eval.sh)就能够进行evaluation.

!/bin/bash
drums_rnn_train \
--config=drum_kit \
--run_dir=/tmp/drums_rnn/logdir/run1 \
--sequence_example_file=/tmp/drums_rnn/sequence_examples/eval_drum_tracks.tfrecord \
--hparams="batch_size=64,rnn_layer_sizes=[64,64]" \
--num_training_steps=20000 \
--eval

和train.sh差很少,惟一区别是--sequence_example_file须要指定eval的tfrecord file 了,还有就是多了一个--eval 用于指定这是一个eval过程,而不是train.注意eval过程不会改变任何一个参数,它只是用于评估模型的性能.
固然咱们也能够运行:tensorboard --logdir=/tmp/drums_rnn/logdir 来使用tensorboard来查看train 和eavl的结果,只要在浏览器打开:
http://localhost:6006 就能够了.

step4:generate drum tracks

   完成了step1~step3以后咱们就能够来产生本身的midi 文件了.运行的脚本为:

#!/bin/bash
drums_rnn_generate \
--config=drum_kit \
--run_dir=/tmp/drums_rnn/logdir/run1 \
--hparams="batch_size=64,rnn_layer_sizes=[64,64]" \
--output_dir=/tmp/drums_rnn/generated \
--num_outputs=10 \
--num_steps=128 \
--primer_drums="[(36,)]"

大部分参数上面都已经解释了,这里再也不赘述.

2.2 melody_rnn model

   melody_rnn model 和上面的 drums_rnn 很是相似,只不过这里产生的是melody,而上面产生的是drums.这里再也不赘述,具体能够参见melody_rnn

2.3 其余的模型

   除了上面说的drums_rnn 和melody_rnn以外,magenta还有不少其余有趣的模型,好比neural style transfer(神经风格迁移,能够产生指定风格的图片)等,有兴趣的能够去magenta详细了解.

------------------------本文完,感谢阅读!-----------------------------------------------------------------------

相关文章
相关标签/搜索