大家好,在这篇文章中,我会分享给大家一些关于人工智能的实验,教大家如何利用深度学习天生音符,与我之前关于天生歌词的文章不同,这次我们将天生音乐条记并天生文件(MIDI格式)。

音乐的主角是钢琴。
本文将在自我把稳的帮助下,利用递归神经网络(RNN),门控递归单元(GRU)的变体天生钢琴音符。
本文不仅将先容如何天生条记,还将先容如何将其天生为精确的MIDI文件,可以在打算机中播放。

本文针对的是对AI感兴趣的人,尤其是那些想要练习深度学习的人。
我希望通过揭橥这篇文章来增加我的写作技巧,并也对你的文章内容产生帮助。

如果您想理解完全的源代码,那么本文末端有一个Github链接。
现在,我将在存储库中供应python条记本和Colaboratory链接。

深度进修演习经验分享若何生成钢琴音乐

这是开场音乐

声音1:打开钢琴

(该音乐是由我们将在本文中创建的模型天生的)

大纲

先容技能与数据管道预处理MIDI文件演习模型推理和天生MIDI文件结果结论后记

先容

人工智能当前的热门话题之一是如何仅利用数据(无监督)来天生某些东西。
在打算机视觉领域,有许多研究职员正在研究利用天生Advesarial网络(GAN)天生图像的一些前辈技能。
例如,NVIDIA利用GAN创建逼真的面部天生器。
还有一些关于利用GAN天生音乐的研究。

如果我们评论辩论音乐发生器的代价,它可以用来帮助音乐家创作他们的音乐。
它可以增强人们的创造力。
我想在未来,如果在这个领域有很多高度关注,大多数音乐家都会创作出由AI赞助的产生音乐。

本文将重点先容如何通过在音乐中天生连续的音符来天生音乐。
我们将知道如何预处理数据并将其转换为神经网络的输入以天生音乐。

该实验还将利用Tensorflow v2.0(仍处于alpha阶段)作为深度学习框架。
我想要展示的是通过遵照他们的一些最佳实践来测试和利用Tensorflow v2.0。
我在Tensorflow v2.0中喜好的一个功能是它通过利用AutoGraph来加速模型的演习。
它可以通过利用@tf.function定义我们的函数来利用。
而且,再也没有“tf.session”,也没有全局初始化。
这些特色是我从Tensorflow转移到PyTorch的缘故原由之一。
Tensorflow可用性可能对付我来说不太好。
只管如此,在我看来,Tensorflow v2.0改变了这统统并增加了它们的可用性,使得做一些实验变得舒适。

该实验还利用自我把稳层。
自我把稳层将见告我们,给定一个顺序实例(例如在音乐条记“C D E F G”中),每个标记将理解对该标记的其他标记的影响程度。
这是一些例子(对付NLP任务):

图1:把稳力的可视化

有关自我把稳的更多信息,特殊是有关transformer的信息,您可以阅读这篇很棒的文章。

没有任何进一步的问题,让我们连续天生音乐

技能与数据

这个实验将利用:

Tensorflow v2.0:深度学习框架、Tensorflow的新版本,仍处于alpha阶段的开拓阶段。
Python 3.7Colaboratory:免费的Jupyter条记本环境,无需设置即可完备在云中运行。
拥有GPU Tesla K80乃至TPU!
可悲的是,Tensorflow v2.0 alpha在撰写本文时仍旧不支持TPU。
Python库pretty_midi:一个用于操作和创建MIDI文件的库

对付数据,我们利用来自Magenta的MAESTRO(MIDI和音频编辑用于同步TRacks和组织)作为数据集。
此数据集仅包含钢琴乐器。
我们将从大约1000个音乐中随机抽取100个音乐,以加快我们的演习韶光。

管道

以下是关于我们的音乐天生器如何事情的管道:

图2:管道

我们将看到每个过程。
为简化起见,我们将每个流程划分如下:

预处理MIDI文件作为神经网络的输入演习过程天生MIDI文件

预处理MIDI文件

在谈论如何预处理midi文件之前,我们须要知道midi格式文件是什么。

从pcmag中,MIDI的定义为:

(乐器数字接口)乐器、合成器和打算机之间音乐信息交流的标准协议。
MIDI的开拓使一台合成器的键盘可以播放另一台合成器产生的音符。
它为音符以及按钮、拨盘和踏板的调度定义了代码,MIDI掌握可以编排一系列合成器,每个合成器都扮演乐谱的一部分。
MIDI 1.0版于1983年引入。

总之,MIDI文件包含了一系列包含注释的工具。
例如钢琴和吉他的组合,每种乐器常日有不同的音符。

对付预处理MIDI文件,有一些库可以在Python中利用。
个中一个是pretty_midi。
它可以操作MIDI文件,还可以创建一个新文件。
在本文中,我们将利用这个库。

pretty_midi文件格式如下:

图3:PrettyMidi格式

开始是第二个音符的开始。
结束是一秒钟内演奏的音符的结束。
一次可以有多个音符重叠。
音高是演奏音符的MIDI数字。
速率是发出音符的力。

MIDI数字与注名的关系参考如下图:

图4:Midi数字和注释名称

阅读Midi文件

我们将批量读取midi文件,这是我们利用pretty_midi读取它的办法:

midi_pretty_format = pretty_midi.PrettyMIDI (“song.mid”)

我们将得到PrettyMidi工具。

对钢琴卷轴阵列进行预处理

图5:从pretty tymidi到Piano Roll Array

在本文中,我们须要从乐器中提取所有的音符。
许多MIDI文件的音乐中有多种乐器。
在我们的数据集中,MIDI文件只包含一种乐器,那便是钢琴。
我们将从钢琴乐器中提取音符。
为了更大略,我们将提取所需帧每秒的音符。
pretty_midi有一个方便的函数get_piano_roll来获取二进制2D numpy中的音符。
数组在(注释、韶光)维度数组中,音符长度为128,韶光按照音乐的时长除以FPS。

我们怎么做的源代码:

预处理到字典的韶光和条记

图6:钢琴卷轴数组到字典

在得到钢琴卷轴的数组之后,我们将它们转换成字典。
字典将从音符播放的韶光开始。
例如,在上面的图中,我们从28开始(如果我们转换到秒,假设我们转换到piano_roll的速率是5 fps,音乐开始播放的速率是5.6 s,我们可以用28除以5)。

创建字典之后,我们将把字典的值转换为字符串。
例如:

array([49,68]) => '49,68'

要做到这一点,我们该当循环字典的所有键并改变它的值:

for key in dict_note: dict_note[key] = ','.join(dict_note[key])

预处理要输入的音符列表和神经网络的目标

图7:字典来列出序列

当我们得到字典后,将它转换成连续的条记,这些条记将被用来作为神经网络的输入。
然后我们得到下一个韶光步长作为神经网络输入的目标。

图8:滑动窗口

在本文中,序列列表的长度为50。
这意味着如果我们的fps是5,将得到一个包含10秒(50 / 5)游戏韶光的序列。

列表中的“e”表示在这段韶光内没有演奏音符。
由于有时候每个音符之间会有一个跳跃或者没有音符。
在图7中的示例中,我们可以看到从43跳到46。
如果我们转换这个序列,序列的列表将是:

[…'61,77', '61,77', 'e', 'e', '73',…]

我们怎么做呢?我们将用一批音乐来处理这个音符。

我们利用一个50长度的滑动窗口。
对付音乐中的第一个音符,我们将在列表中添加“e”49次。
然后将开始韶光设置为字典中的第一个timestep。
在图7中的例子中,它是28。
然后我们在音乐中添加第一个音符(在示例‘77’中)。

然后对付下一个实例,我们将窗口滑动1次,并向列表中添加48次“e”,并将timestep 28中播放的音符添加到列表中,将timestep 29中播放的音符添加到列表中,并重复操作,直到音乐结束。

不才一段音乐中,我们重复上面的过程。

这是源代码:

创建把稳分词器

在我们深入研究神经网络之前,我们必须创建标记器以将顺序音符变动为音符的顺序索引。
首先,我们该当将音符映射到表示音符id的索引。

例如:

{'61,77' : 1, # 61,77 will be identified as 1'e' : 2,'73' : 3,..}

如果我们之前的输入如下:

[...,'61,77','61,77','e','e','73',......]

我们将其转换为:

[... 1,1,2,2,3 ......]

这是我们的做法。

总结我们的预处理功能,以下是我们将利用的功能:

演习模型

在我们理解如何利用Tensorflow v2.0的新功能进行演习之前,我们将看到如下架构:

神经网络架构

图9:我们的神经网络架构

因此,深度学习架构将利用3层门控循环单元(GRU,一种回归神经网络的变体)和一些自把稳层。
利用丢失使得神经网络不会过快地过度拟合。

对付Self Attention Layers,我们将利用此存储库并对其进行一些编辑,以便我们可以在Tensorflow v2.0上利用它。

因此,深度学习架构将利用3层门控递归单元(GRU,递归神经网络的一种变体)和一些自我把稳层。
该方法采取了跳脱法,使神经网络不会快速过拟合。

对付Self - Attention层,我们将利用这个存储库并轻微编辑一下,以便在Tensorflow v2.0上利用它。

代码:

演习

我们将通过迭代数据集中的多个音乐来更新模型的权重,并如上所述预处理数据。
然后,以一批待输入的实例和神经网络的目标为例。

我们将利用GradientTape来更新神经网络的权重。
首先,我们利用apply_gradients打算丢失并运用反向传播。
如果您熟习利用PyTorch,这便是Pytorch在演习其神经网络模型方面的事情办法。

务必在函数上利用@ tf.function。
这会将功能转换为署名并使我们的演习更快。
tf.function的一个缺陷是不能利用不同大小的批量作为神经网络的输入。
例如,我们的批量大小为64。
如果数据集的大小为70,则末了一批将包含6个实例。
这将使程序抛出非常,由于图形将具有与初始图形不同大小的输入。
大概它的事情事理是通过在利用函数时查看第一个输入来创建占位符。

在本文中,我们将利用16 BATCH_SONG和96 BATCH_NNET_SIZE。
这意味着我们将从所有音乐列表中获取16个音乐,然后提取其序列。
然后,对付神经网络中的每一步,我们从提取的序列实例中获取96个序列作为神经网络的输入和目标。

代码如下:

推理和天生MIDI文件

图10:推理和天生MIDI文件

利用我们演习的神经网络模型天生MIDI文件有两种方法:

我们须要在开始时选择:

我们天生随机50个音符作为音乐的开头。
我们利用49个空音符('e'),然后是我们选择的开始音符(例如'72',确保音符在NoteTokenizer中)。

图11:关于天生器如何事情的可视化

在我们选择音乐天生器的种子之后,利用我们演习的模型基于50个随机音符预测下一个音符。
我们利用预测值作为如何随机选择音符的概率分布,这样做直到我们想要的指定的最大序列长度。
然后我们放下前50个音符。

在我们天生音符列表序列之后,将其再次转换为钢琴卷轴阵列。
然后将其转换为PrettyMidi工具。

之后,我们调度音乐的速率和节奏,末了我们天生MIDI文件。

代码 :

这是如何从天生的注释中编写midi文件:

结果

当我这样做时,演习耗时1小时,持续1个 epoch。
当我这样做时,我决定进行4个 epoch(4个小时)的演习。

已经演习了4个 epoch的模型,结果如下:

由于头条号限定,只能发送一条音频,故详细资料请私信

(请把稳,这些是从MIDI文件转换而来的mp3文件。
我利用在线转换器来实行此操作,这些注释彷佛有点遗漏。
如果您想听到,我会将原始MIDI上传到存储库中。

这些天生的条记之间存在明显差异。
如果我们用一个音符天生它,它将在播放音符时节奏缓慢。
它与我们从50个随机音符天生它时不同。
它没有缓慢的开始。

这是在选择以随机50个音符开始的音乐的末了序列上的自我把稳块的可视化:

首先把稳

图12:第一次自我把稳

第二个把稳

图13:第二次自我把稳

正如您所看到的,第一个自我把稳块会学习在序列实例中为每个音符聚焦的音符。
然而,在第二个关注区块中没有关注什么结果。
我们还可以判断,如果其他音符的位置离当前音符很远,则它不会聚焦于它(图像12和图像13中的玄色)。

结论

我们利用包含钢琴音乐的MAESTRO数据集构建了一个天生音乐的工具。
我们预处理它,演习我们的神经网络模型,然后用它天生音乐。
音乐是MIDI格式。
我们利用Tensorflow v2.0来完成它。
我认为Tensorflow v2.0用户体验(UX)比以前的版本更好。

我们的模型产生的音乐也很连贯,很好听。
它可以调度播放音符的办法。
例如:当发生器从音符(意味着它是音乐的开头)时,它以慢节奏开始。

我们可以考试测验一些音乐天生器。
在本文中,我们已经考试测验天生单个仪器。
如果音乐有多种乐器怎么办?须要有一个更好的架构来做到这一点。
我们可以考试测验多种方法来试验音乐数据。

后记

这便是关于天生钢琴音乐条记的文章。
实际上,通过查看我的第一篇关于深度学习的文章,我得到了启示,这便是天生音乐的抒怀效果。
“如何天生音符?”我做了一个试验它很有效。

对我来说,试验这个有一些困难。
首先,我须要搜索易于预处理和输着迷经网络的文件格式。
我创造MIDI很大略,文件很小。
然后,我须要知道是否有任何库可以在Python中预处理文件。
我找到了两个,有music21和pretty_midi,他们的存储库没有过期,我选择pretty_midi。
末了,我须要考虑如何预处理条记。
值得光彩的是,pretty_midi有一个方便的函数get_piano_roll来使它更随意马虎。

我还没有读过很多关于音乐的研究论文。
大概有一些研究论文可以在Colaboratory中复制和显示。

自我把稳层缺少可视化效果。

存储库:https://github.com/haryoa/note_music_generator