3月21日,为了纪念著名作曲家及管风琴、小提琴、大键琴演奏家约翰•塞巴斯蒂安•巴赫的生日,谷歌推出了纪念版谷歌涂鸦。这不是一个简单的动画或者互动游戏,而是谷歌历史上第一个用到了AI的涂鸦作品。利用机器学习,只要你在乐谱上随意点击添加上几个音符,AI就可以自动为你生成一段“巴赫风”的和弦。除了线上欣赏之外,你还可以把这一小段音乐的MIDI文件下载下来。
巴赫 AI 涂鸦是谷歌内部的 Doodle、Magenta 和 PAIR团队合作的成果。Magenta 团队的使命是帮助人们使用机器学习创作音乐和艺术,PAIR 负责提供工具和经验,让每个人都能享受机器学习带来的好处。
创建 AI 涂鸦的第一步是构建一个机器学习模型。机器学习是通过展示大量示例来教会计算机自行找到答案的过程,而不是给它一堆要遵循的规则(传统计算机编程是这样做的)。Magenta 的 AI 研究员 Anna Huang 开发了 Coconet,这是一种可以用于各种音乐任务的机器学习模型,如调整旋律,在断开的音乐片段之间创建平滑过渡,以及从零开始编曲。
接下来,我们将模型个性化以匹配巴赫的音乐风格。为此,我们用巴赫的 306 首协奏曲训练 Coconet。他的协奏曲总是有四种声音:每种声音都有自己的旋律线,在一起演奏时会产生丰富的和声。这种简洁的结构使旋律线成为机器学习模型的良好训练数据。因此,当你在 Doodle 中模型上创作自己的作品时,它会匹配成巴赫风格的旋律。
Doodle 中除了艺术和机器学习元素之外,我们还需要大量服务器以确保世界各地的人们都可以使用 Doodle。从历史上看,机器学习向来在服务器上运行,这意味着信息需要从一个人的计算机发送到数据中心,然后再将结果发送回计算机。如果巴赫 Doodle 使用相同的方法,会产生大量 traffic。
为了实现这一目标,我们使用了 PAIR 的 TensorFlow.js,它让机器学习可以完全在互联网浏览器中进行。但是,可能有的人的计算机或设备使用 TensorFlow.js 运行 Doodle 会不够快,所以机器学习模型在谷歌的新 TPU 上运行,这是一种快速处理数据中心机器学习任务的方法。Doodle 首次以这种方式使用 TPU。
机器学习模型 Coconet
Magenta 的博客文章中介绍了 Coconet 的详细信息:
3 年前,当 Magenta 成立时,我们就开始研究这个模型。当时我们用机器学习(ML)只能生成旋律。为了让旋律更好听,我们用 Bach 的 306 首协奏曲数据集来训练机器学习模型,生成巴赫风格的音乐。
Coconet 受过训练后可以从片段中复原巴赫的音乐:我们把巴赫音乐的一小段取出来,随机删除一些音符,然后让模型根据上下文猜出丢失的音符。结果,我们得到一个多功能的对位模型,把任意不完整的乐谱作为输入,并得出完整的乐谱。这个设置涵盖了广泛的音乐任务,例如协奏曲旋律、创建平滑过渡、重写和改编,以及从零创作。
传统模型从始至终都是按时间顺序生成音符,但 Coconet 可以从任何地方开始,并以任何顺序创建音符。这种灵活性使其成为理想的支持组合过程的工具。音乐家将其用于工作的一种方法是让 Coconet 反复填写乐谱,取其精华,去其糟粕,最终得到一首好听的曲子。实际上,这就是 Coconet 的内部工作机制:循环生成音符,反复重写并删除自己的工作。从粗略的想法开始,它会反复计算细节,并将音符调整为一个连贯的整体。
下面的动画展示了重写的过程:
我们展示了两个 Coconet 创作的来自巴赫协奏的旋律,这些旋律未包含在训练集中。
我们还构建了一个名为Coucou的扩展接口,可以与 Coconet 进行更一般的交互。它支持一种新的 AI 协作生成,你可以通过擦除不满意的部分并要求模型再次填充来迭代地改进音乐作品。你可以反复单击填充得到不同的音符。试试下面的例子或在页面上随机抽取音符开始,自己动手尝试一下。你还可以使用Magenta.js中现有的 JavaScript 自行创建接口。
它是如何工作的?
Coconet 获得不完整的乐谱并填写缺失的部分。为了训练,我们以第四对位的巴赫协奏曲数据集作为例子,随机擦除一些音符,并要求模型重建被擦除的音符。巴赫的创作与 Coconet 的生成方法之间的区别为我们提供了学习信号,我们用它训练模型。
通过随机擦除笔记,我们希望获得一个可以处理任意不完整输入的模型。
就我们的目的而言,“乐谱”是个三维物体。巴赫的协奏曲为四种声音而写:女高音(S)、中音(A)、男高音(T)和低音(B)。每种声音的音符都用钢琴卷帘表示:二维阵列中时间为横轴,音调为纵轴。假设每个声音在任何给定时间都只唱一个音高。因此,通常对于每个声音,在每个时间点,我们会得到一个独热音调矢量,除了指示音高的单个音符,其他元素全部为零。在存在不确定性的情况下(例如,在模型输出中),该音调向量将包含音高的分类概率分布。
我们将这堆钢琴卷帘视为卷积特征图,时间和间距形成二维卷积空间,每个声音提供一个通道。由于模型训练所用的乐谱不完整,我们为每个语音提供一个额外的通道,带有一个掩码:二进制值,标记每个时间点是否已知该语音的音高。因此,模型中使用的是一个八通道功能图。
该模型是一个相当简单的卷积神经网络,具有批归一化和残余连接。对于使用 Tensorflow.js 实现在浏览器中运行模型的 Doodle,我们能够通过切换到深度可分离的卷积来加速计算。这与常规卷积的不同之处在于,它们将空间轴上的卷积和通道轴的混合分开。它们需要的参数更少,更适合在浏览器中加速。由于卷积扩张,我们得以在减少模型中的层数实现进一步加速的同时,保证性能无损。
模型又生成一堆钢琴卷帘,每种声音有一个钢琴卷帘,但这次包含了在删除音符的音高上的概率分布。该模型使用给出的音符来找出被删除的音符,从而得出在每个时间点由每个音调演唱的音高上的分类分布。
我们训练模型让真正的音高概率分布更大,让模型理解不完整乐谱的音乐含义,如这是什么音调,在某一时间是哪个和弦等。
经过训练后,我们有几种方法从模型产生的概率分布中提取音乐。我们可以根据其分布同时对每个音高进行采样。但是,这并不能解释被采样的音高之间的相互作用。通常,确定其中一个音高会改变其他音高的分布。
考虑到这些相互作用的一种方法是对其中一个音高进行采样,将其添加到不完整的乐谱,并把结果再次“喂”给模型,重新计算剩余音高的分布。重复此过程,直到确定所有音高,在考虑所有交互的情况下完成乐谱。这样的顺序采样让模型能够逐一准确地确定未知的音高。当模型被自己的创作搞晕时,这种“坚定”的假设常常导致过程出错。
因此,我们用另一种方法取而代之:将模型的输出视为草稿,通过重复重写逐步完善。具体来说就是,我们同时对所有音高进行采样,获得完整(但通常是无意义的)乐谱,然后将部分音符擦除后再次输入到模型中,之后重复这一过程。随着时间的推移,我们擦除并重写的音符越来越少,最终得到较为一致的结果。
致谢
本篇博文基于由 Cheng-Zhi Anna Huang、Tim Cooijmans、Adam Roberts,Aaron Courville 和 Douglas Eck 撰写的论文。研究论文中的Tensorflow代码可在Magenta GitHub中获得。
参考链接:
https://magenta.tensorflow.org/coconet
https://www.blog.google/technology/ai/honoring-js-bach-our-first-ai-powered-doodle/
评论