教练我想写日式流行歌!

——黑科技magenta残差网络训练教程

Posted by Kriz on 2017-05-25

去年八月,统治宇宙的谷歌开源了自动作曲项目magenta。这个家伙的核心网络有28层,git上挂着的预训练模型*.mag由8000个midi输入调教而成,至于调教的效果,可以来油管膜拜一下我要退圈了:)

发现了这种有趣的东西,首先还是要亲手训♂练一下呀。(git地址戳这里

准备:配置环境

这里安装过程以macOS Sierra 10.12.4为例,开终端,敲入

1
2
curl https://raw.githubusercontent.com/tensorflow/magenta/master/magenta/tools/magenta-install.sh > /tmp/magenta-install.sh
bash /tmp/magenta-install.sh

依赖包很多,要耐心等待。顺便吐槽济事楼430的网速。安装完毕后关闭终端重新打开,激活magenta:

1
source activate magenta

如果不幸支持cuda,可以顺便配置GPU加速:

1
pip install tensorflow-gpu

热身:前期测试

毕竟是第一步,首先使用预训练模型来搞事吧。有三个模型可供选择:

我选用了第三个:【毕竟是油管上那个音频的亲生模型

1
2
3
4
5
6
7
melody_rnn_generate \
--config='attention_rnn' \
--bundle_file=/absolute/path/to/your/attention_rnn.mag \
--output_dir=/tmp/melody_rnn/generated \
--num_outputs=10 \
--num_steps=128 \
--primer_melody="[60]"

注意前两个参数要对应。num_steps参数规定每个音符的长度(疑似tempo),最后这个primer_melody参数似乎是提供初始几个音符的,readme里给了个范例:

1
--primer_melody="[60, -2, 60, -2, 67, -2, 67, -2]"

会创作出以小星星(歌名!歌名!歌名!)的前四个音符为引子的旋律(-2代表空事件;60代表C4,也就是中央do)。也可以更换成--primer_midi直接以某个midi文件指定引子的旋律。【我可以写一万首去月球同人

于是在运行之后(中间很多奇怪的bug就不讲了,大部分都是一轮pip uninstall接pip install就能解决的问题),我得到了10个分轨的midi文件。

因为找遍了官方文档都没有说明这十个文件的顺序和配器,所以我就随便选了几个试了一下。画风是这样的。

戳这里试听

……还谜之有股爵士味是怎么回事!

演练:训练模型

玩完了别人的模型,就来搞个自己的吧。一是出于学术严谨(推眼镜),二是因为我攒了几百个jpop的midi文件然而一直没(tai)时(la)间(ji)懒(xue)得(bu)动(hui),来来来我偏要看看一个方才28层的RNN能搞出什么名堂。

【虽然不知道几百个输入能调教出来什么但至少试一下

创建NoteSequences

首先,我们要将所有用到的midi文件转换成一个NoteSequences。这东西可以理解成一种数据交换的格式,速度快而高效。

这里我使用那一大堆jpop风格的midi文件构造数据集。如果手头没有什么midi的话,可以直接使用Lakh MIDI Dataset或在MidiWorld等网站下载或者放弃

构建数据集:

1
2
3
4
convert_dir_to_note_sequences \
--input_dir=/path/to/your/midi/folder/ \
--output_file=/tmp/notesequences.tfrecord \
--recursive

input_dir是可以有子目录的,但是最好不要放除了mid之外的多余文件。

来感受一下这个画风

pic

创建SequenceExamples

接下来要给网络喂SequenceExamples了,这个过程会贯穿training和validation(不知道为啥文档里写的是evaluation,应该没区别吧【心虚)。每一个SequenceExample会包括一组输入序列和一组标签序列,代表对应的旋律。

1
2
3
4
5
melody_rnn_create_dataset \
--config='attention_rnn' \
--input=/tmp/notesequences.tfrecord \
--output_dir=/tmp/melody_rnn/sequence_examples \
--eval_ratio=0.10

config仍然是三选一,这里也采用attention_rnn。eval_ratio参数用来确定训练集和验证集的占比。

训练和验证模型

1
2
3
4
5
6
melody_rnn_train \
--config=attention_rnn \
--run_dir=/tmp/melody_rnn/logdir/run1 \
--sequence_example_file=/tmp/melody_rnn/sequence_examples/training_melodies.tfrecord \
--hparams="{'batch_size':64,'rnn_layer_sizes':[64,64]}" \
--num_training_steps=20000

接下来就是按下电磁炉开关回车的时候了。不过第一次处理音频发现收敛还是很快的,内存占用也比较平稳。一边跑着网络居然还能一边撸PV整个人都陷入了巨大的满足之中

经过四十个小时的艰苦训练,模型已经初具雏形了。可以打开tensorboard进行信息的图表化阅览:

1
tensorboard --logdir=/tmp/melody_rnn/logdir

接下来打开http://0.0.0.0:6006即可进行观看。

这里贴出loss和accuracy的折线图,可以看出网络还是比较有效的。

pic-los

pic-acc

前途很光明,接下来使用我们的新模型写写歌吧:

1
2
3
4
5
6
7
8
melody_rnn_generate \
--config=attention_rnn \
--run_dir=/tmp/melody_rnn/logdir/run1 \
--output_dir=/tmp/melody_rnn/generated \
--num_outputs=10 \
--num_steps=128 \
--hparams="{'batch_size':64,'rnn_layer_sizes':[64,64]}" \
--primer_melody="[60]"

和刚才一样,模型会生成十个mid文件。仍然是随便拖几个把配器丢上去。可视化之后可以发现这个mid走向实在是很符合人类写loop的模式啊【跪

pic-tra

最上面的鼓是我自己加的不过并不影响什么

好的那么来听听看吧。屏息凝神。认真。

戳这里试听。

虽然并不是很日式(可能是配器的锅)可是真的好厉害啊。虽然怀疑有轻微的过拟合作祟【不你别想得这么糟糕

如果想用这个模型也可以戳这里下载

尾声:结构初探

最后一步打算了解一下网络的构成。因为一直没走TensorFlow线,看了看源码好像网也不是直接搭的,层级关系太复杂,gg。移步官网。

先刷了一遍说明,发现magenta使用了SketchRNN网络模型作为基础框架。之前听说过这个模型,似乎是用来进行草图描绘学习的,数据集是简笔画的一个网络。并不是很懂为什么能移植到音频处理……好玄学啊。

这个网络是一个多对多(官网的定义是Sequence-to-Sequence Variational Autoencoder)的RNN,也就是循环神经网络。RNN一般用在需要进行数据持久化的训练中,出现时间较晚,但目前已经有很不错的发展了。更多关于RNN及其应用的信息戳这里,看了这个才知道这东西居然应用这么广泛然而自己还没学,好像又被时代抛弃了(自抱自泣)

SketchRNN的网络结构示意图:

pic-rnn

之后有空的话还是专门写一篇学习笔记吧。