选自OpenAI
作者:Christine Payne
机器之心编译
前不久,为纪念伟大作曲家巴赫,谷歌创建了 Coconet 多功能模型,该模型可以将任何人的作品以巴赫的风格的演奏。该 AI 模型虽然不错,但只限于巴赫风格的曲子。若我们想创作肖邦、莫扎特呢?OpenAI 新近创建的模型 MuseNet 可以解决这个问题啦~
MuseNet 是一个深度神经网络,它可以用 10 种不同的乐器生成 4 分钟的音乐作品,并且还可以结合各种风格的音乐,如乡村音乐、莫扎特、披头士乐队。
Musenet 没有根据我们对音乐的理解来显式编程,而是通过学习预测成千上万个 MIDI 文件中的下一个 token,来发现和弦、节奏和曲风的模式。Musenet 使用了与 GPT-2 相同的通用无监督技术。
MuseNet 了解很多不同的音乐风格,我们可以用新颖的方式融合生成作品。此处展示的样本里,给定肖邦夜曲的前 6 个音符,要求模型用钢琴、鼓、贝斯和吉他生成一段流行风格的作品。模型成功地将这两种风格融合在一起,整合的片段大概在 30 秒左右开始演奏。
由于 OpenAI 没有提供下载地址,本音频为录音文件
5月份开放尝鲜
MuseNet 支持的合作作曲家很多(下面会有展示),并将在 5 月 12 号发布(届时 OpenAI 将根据反馈制定下一步计划)。也就是说,5 月 12 号的时候,大家可以利用 MuseNet 尝试创作自己的音乐作品啦。虽然到时候只能使用 MuseNet 众多选项中的一个子集,但大家还是可以创作很多种不同的音乐。
在『简单模式』(默认显示)下,你会听到 OpenAI 预先生成的随机未切割样本。选择一个作曲家或一种风格,一首著名作品的可选开头,然后开始生成。你可以探索模型能够创建的各种音乐风格。在『高级模式』下,你可以直接和模型交互。这种情况下生成音乐作品耗时更长,但你创建的将会是全新的作品。
这个工具目前还是一个原型,所以耐心点哦!MuseNet 具有以下限制:
你选择的乐器不是一定会使用,而是很可能会使用。MuseNet 通过计算所有可能的音符和乐器的概率来生成每个音符。模型会尽量倾向你选择的乐器,但有可能会选择其它乐器。
MuseNet 在风格和乐器的奇特搭配方面(比如肖邦与贝斯和鼓)也有困难。如果你选择的乐器与该作曲家或乐队的风格接近,则生成的音乐也会更自然一些。
好多好多作曲家和乐器 token
OpenAI 创建了作曲家和乐器 token,以便更好地控制 MuseNet 生成的样本类型。在训练期间,这些作曲家和乐器 token 被预先添加到每个样本中,因此模型会学习利用这一信息进行音符预测。在生成音乐的时候,我们可以调整模型以选定的风格创建样本,比如以拉赫玛尼诺夫的钢琴曲开头作为前提,或者以旅程乐团、钢琴、贝斯、吉他、鼓作为前提。
我们可以可视化来自 MuseNet 的嵌入,以深入了解模型所学到的东西。下面 OpenAI 用 t-SNE 可视化了各个作曲家和风格嵌入的余弦相似性。
原图为交互图。将鼠标悬停在某个特定的作曲家或风格上可以查看其与其他作曲家或风格之间的关系。
利用 Sparse Transformer 记住长期结构
MuseNet 使用 Sparse Transformer 的重算和优化核来训练一个具有 24 个注意力头的 72 层网络—全部注意力放在拥有 4096 个 token 的语境中。这个长语境大概是 MuseNet 能够记住一个片段中长期结构的原因,就像以下示例中模仿肖邦一样:
MuseNet 还可以创建音乐旋律形态,就像该示例中模仿莫扎特一样:
音乐生成是测试 Sparse Transformer 的一个有用领域,因为音乐处于文本和图像的中间区域。音乐有文本流畅的 token 结构(在图形中,你可以查看 N 个 token,并找到上面行,而在音乐中,查看上一小节起点没有固定数)。但是,我们可以轻易地听到模型是否可以按照成百上千的 token 顺序来获取长期结构。一个音乐模型是否通过改变节奏而打乱自身结构会更显而易见,而文本模型是否出现了短暂偏离则没有那么明显。
它都用了哪些数据集?
OpenAI 从诸多不同的来源为 MuseNet 收集了训练数据。ClassicalArchives 和 BitMidi 为该项目贡献了大量的 MIDI 文件,同时他们还在网上找到了爵士乐、流行乐、非洲乐、印度乐和阿拉伯乐等几种不同风格的音乐合集。此外,他们使用了 MAESTRO 数据集。
Transformer 在时序数据上进行训练:OpenAI 根据给定的音符来预测即将出现的音符。他们尝试使用几种不同的方法将 MIDI 文件编码成适用于本次任务的 token。
首先,OpenAI 使用和弦方法,该方法将同一时间听到的每个音符组合作为一个独立的「和弦」,同时为每个和弦指定一个 token。其次,他们尝试通过仅关注音符的开头来压缩音乐模式,并且尝试使用字节对编码方案来进行进一步压缩。
OpenAI 还尝试使用两种不同的方法来标记时间推移:要么是根据音乐节奏进行缩放的 token(因此该类 token 表示一个音乐节拍或节拍的一部分),要么是以秒为单位标记绝对时间的 token。OpenAI 最终找到了一种结合了表现性和简洁性的编码:将音高、音量和乐器信息组合成一个单独的 token。
代码语言:javascript复制bach piano_strings start tempo90 piano:v72:G1 piano:v72:G2 piano:v72:B4 piano:v72:D4 violin:v80:G4 piano:v72:G4 piano:v72:B5 piano:v72:D5 wait:12 piano:v0:B5 wait:5 piano:v72:D5 wait:12 piano:v0:D5 wait:4 piano:v0:G1 piano:v0:G2 piano:v0:B4 piano:v0:D4 violin:v0:G4 piano:v0:G4 wait:1 piano:v72:G5 wait:12 piano:v0:G5 wait:5 piano:v72:D5 wait:12 piano:v0:D5 wait:5 piano:v72:B5 wait:12
样本编码
在训练中,OpenAI:
- 通过升调和降调来调换音符(之后,OpenAI 减少了变调数量,从而使生成的音符在单个乐器范围内)
- 提高音量,调高或调低不同样本的整体音量
- 延长计时(当使用以秒计量的绝对时间进行编码时),有效地稍微放慢或加快片段。
- 在 token 嵌入空间中使用 mixup
OpenAI 还创建了一个内部评测:在训练期间,要求模型预测给定的样本是出自数据集或是模型之前生成的样本。该评测分数被用来在生成作品时选择样本。
它添加了哪些嵌入?
OpenAI 添加了几种不同的嵌入,为模型提供更加结构化的语境。除了标准位置嵌入之外,他们还添加了一个学习到的嵌入,该嵌入可以在给定的样本中追踪时间推移。这样,所有同时发出声音的音符都有相同的时间嵌入。
接下来,OpenAI 为和弦中的每个音符添加了一个嵌入(这是在模仿相关注意力,因为这样可以让模型更容易学到:音符 4 需要回看音符 3,或者回顾前一个和弦的音符 4)。
最后,他们添加了两个结构化嵌入,该嵌入告诉模型指定的音乐样本在较大音乐片段中的位置。一个嵌入将较大的音乐片段分成 128 块,另一个嵌入编码是在模型接近(末尾)token 时从 127 倒数到 0。
原文链接:https://openai.com/blog/musenet/