Path: blob/master/site/zh-cn/tutorials/audio/music_generation.ipynb
25118 views
Copyright 2021 The TensorFlow Authors.
使用 RNN 生成音乐
本教程向您展示如何使用简单的循环神经网络 (RNN) 生成音符。您将使用来自 MAESTRO 数据集的钢琴 MIDI 文件集合来训练模型。给定一系列音符,您的模型将学习预测序列中的下一个音符。可以通过重复调用模型来生成更长的音符序列。
本教程包含解析和创建 MIDI 文件的完整代码。可以通过访问使用 RNN 的文本生成教程来详细了解 RNN 的运作方式。
安装
本教程使用 pretty_midi
库创建和解析 MIDI 文件,并使用 pyfluidsynth
在 Colab 中生成音频播放。
下载 Maestro 数据集
该数据集包含约 1,200 个 MIDI 文件。
处理 MIDI 文件
首先,使用 pretty_midi
解析单个 MIDI 文件并检查音符的格式。如果想下载下面的 MIDI 文件以在计算机上播放,则可以在 Colab 中通过编写 files.download(sample_file)
来实现。
为示例 MIDI 文件生成 PrettyMIDI
对象。
播放示例文件。播放微件可能需要几秒钟来加载。
对 MIDI 文件进行一些检查。使用什么样的工具?
提取音符
在训练模型时,将使用三个变量来表示音符:pitch
、step
和 duration
。pitch 是声音的感知质量,作为 MIDI 音符编号。step
是从前一个音符或曲目开始所经过的时间。duration
是音符将播放多长时间(以秒为单位),是音符结束时间和音符开始时间之间的差值。
从示例 MIDI 文件中提取音符。
解释音符名称可能比解释音高更容易,因此您可以使用下面的函数将数字音高值转换为音符名称。音符名称显示了音符类型、变音记号和八度数(例如 C#4)。
要呈现乐曲,请绘制音高、音轨(即钢琴卷帘)时长的开始点和结束点。从前 100 个音符开始
绘制整个音轨的音符。
检查每个音符变量的分布。
创建 MIDI 文件
可以使用以下函数从音符列表中生成自己的 MIDI 文件。
播放生成的 MIDI 文件,看看有什么区别。
和以前一样,可以编写 files.download(example_file)
来下载和播放此文件。
创建训练数据集
通过从 MIDI 文件中提取音符来创建训练数据集。可以先使用少量文件,然后再尝试更多文件。这可能需要几分钟。
接下来,从已解析的音符创建 tf.data.Dataset。
然后,针对成批的音符序列训练模型。每个样本将包含一系列音符作为输入特征,下一个音符作为标签。通过这种方式,模型将被训练来预测序列中的下一个音符。可以在使用 RNN 的文本分类中找到说明此过程的图表(以及更多详细信息)。
可以使用大小为 seq_length
的方便 window 函数来创建这种格式的特征和标签。
为每个样本设置序列长度。尝试不同的长度(例如 50、100、150),看看哪一个最适合数据,或者使用超参数调优。词汇表的大小 (vocab_size
) 设置为 128,表示 pretty_midi
支持的所有音高。
数据集的形状为 (100,1)
,表示模型将以 100 个音符作为输入,并学习预测以下音符作为输出。
对样本进行批处理,并配置数据集以提高性能。
创建并训练模型
该模型将具有三个输出,每个音符变量使用一个输出。对于 step
和 duration
,将使用基于均方误差的自定义损失函数,以鼓励模型输出非负值。
测试 model.evaluate
函数,可以看到 pitch
损失明显大于 step
和 duration
损失。请注意,loss
是通过对所有其他损失求和计算得出的总损失,目前主要由 pitch
损失决定。
平衡这种情况的一种方式是使用 loss_weights
参数进行编译:
然后,loss
成为各个损失的加权总和。
训练模型。
生成音符
要使用模型生成音符,首先需要提供音符的起始序列。下面的函数可以从一系列音符中生成一个音符。
对于音符音高,它会从模型产生的音符的 softmax 分布中抽取样本,而不是简单地选择概率最高的音符。始终选择概率最高的音符会导致生成重复的音符序列。
temperature
参数可用于控制所生成音符的随机性。可以在使用 RNN 的文本生成中详细了解温度。
现在,生成一些音符。可以在 next_notes
中调整温度和起始序列,看看会发生什么。
还可以通过添加以下两行来下载音频文件:
呈现生成的音符。
检查 pitch
、step
和 duration
的分布。
在上面的图中,您会注意到音符变量分布的变化。由于模型的输出和输入之间存在反馈回路,模型倾向于生成相似的输出序列以减少损失。这与使用 MSE 损失的 step
和 duration
特别相关。对于 pitch
,可以通过增大 predict_next_note
中的 temperature
来增加随机性。
后续步骤
本教程演示了使用 RNN 从 MIDI 文件数据集中生成音符序列的机制。要了解详情,您可以访问密切相关的使用 RNN 的文本生成教程,其中包含附加的图表和解释。
使用 RNN 生成音乐的一种替代方式是使用 GAN。基于 GAN 的方式并非生成音频,而是可以并行生成整个序列。Magenta 团队使用 GANSynth 在这种方式上完成了非凡的工作。此外,还可以在 Magenta 项目网站上找到许多精彩的音乐和艺术项目以及开源代码。