Skip to main content

Generating Piano Music with Music Transformer 用Music Transformer生成钢琴曲

了解谷歌Magenta的Music Transformer如何从头开始生成钢琴曲。
Created on January 27|Last edited on January 27
本报告是作者Hao Hao Tan所写的"Generating Piano Music with Music Transformer"的翻译

引言

在过去5年里,利用机器学习算法来学习生成音乐获得了极大关注。随着深度学习的出现,卷积神经网络(CNN)、长短期记忆网络(LSTM)、受限玻尔兹曼机(RBM)这些神经网络架构已经成为算法生成音乐任务的热门选择(详情请参见这篇调研报告)。

在本报告中,我们将探讨Music Transformer论文,该论文由谷歌Magenta团队的黄成之(Anna Huang)等人所著,提出了一个最先进的基于语言模型的音乐生成架构。Transformers在自然语言处理(NLP)领域获得了极大成功,而这篇论文是最先把Transformers引入符号化音乐生成领域的作品之一。

背景

一般情况下,在生成任务中主要有两种方式来表示音乐。第一种方式是把音乐表示为音频波形。利用该方式的常见音乐数据表示包括原始音频波形、声谱图、梅尔频谱图、恒Q变换(CQT)等等。第二种方式是把音乐表示为符号化的事件符号(symbolic event tokens)。其具体形式包括乐器数字接口(MIDI)事件(本论文采用)、钢琴卷帘、文本(如ABC记谱法)等等。之前有一篇W&B报告介绍了JukeBox,JukeBox是利用基于音频的方式来生成音乐。而在本报告中,我们将介绍的是Music Transformer,用的是基于符号化的方式。

把钢琴曲表示为事件符号(event token)

MIDI事件把弹奏钢琴时的每个细微动作映射为事件符号。在该过程中,将会模拟以下4种事件:

  1. NOTE_ON - 按下音符

  2. NOTE_OFF - 释放音符

  3. TIME_SHIFT - 进入下一个时间步

  4. SET_VELOCITY - 设置弹奏音符的速度

    在该过程中,将引入总计128个NOTE_ON和NOTE_OFF事件,对应着128个音高,以及100个TIME_SHIFT事件(从10ms至1s),还有128个SET_VELOCITY事件,对应着128种不同的音符速度。该论文一个示例如下。

通过使用该方式,我们可以看到它对应着自然语言处理中的分词(tokenization)

  • 一个音乐片段相当于一个句子或一个语段;
  • 每个音符事件相当于句子/语段中的一个词;
  • 全部可能的音符事件组成“词汇集”。

因此,我们的生成模型用Transformers作为架构就顺理成章,因为我们把音乐生成当做语言生成任务。

Music Transformer对比Vanilla Transformer

Vanilla Transformer在处理长序列方面臭名昭著,因为它需要二次方内存。这是个大问题,尤其是对于音乐生成而言,因为一分钟的作曲轻易就包含几千个乐器数字接口事件符号。另外,作者辩称,音乐应用中的相对位置信息非常重要,因为音乐常常由重复、音阶和琶音等结构化的乐句组成。因此,模型应该用更高效的方式捕捉相对位置信息。

考虑到以上原因,作者改进了Transformer模型,改动如下:

1 - 相对注意力(Relative attention)

两个Transformer的主要区别在于自注意力机制。Vanilla Transformer依靠点积注意力,可表示如下:

Attention(Q,K,V)=softmax(QKTdk)VAttention(Q, K, V) = softmax(\frac{Q K^T}{\sqrt{d_k}})V

其中QQ, KK, VV 分别表示查询、键和值的张量,每个都有张量形状(ll, dd),分别表示模型中的句子长度和维数。

Shaw等人提出的相对注意力,可以让模型通过序列中两个位置的距离来确定信息。为了表示这一信息,公式改为以下形式:

Attention(Q,K,V)=softmax(QKT+Sreldk)VAttention(Q, K, V) = softmax(\frac{Q K^T + S_{rel}}{\sqrt{d_k}})V

附加了一项 SrelS_{rel},​是一个形状张量(ll, ll),张量vi,jv_{i, j}的值与位置iijj之间的相对距离ll.有关。因为其本质是相对的,这就是说如果i1−j1=i2−j2i_1 - j_1 = i_2 - j_2,则vi1,j1=vi2,j2v_{i_1, j_1} = v_{i_2, j_2}

那么我们如何得到SrelS_{rel}?

  1. 首先,我们初始化一套固定的嵌入集ErE_r,每一个相对距离r=i−jr = i - j有一个唯一的嵌入ere_r
  2. 然后,我们建立形状(l,l,d)(l, l, d)的三维张量RR ,其中Ri,j=ei−jR_{i, j} = e_{i -j}​。
  3. 最后,我们把QQ变为张量(l,1,d)(l, 1 ,d)Srel=QRTS_{rel} = QR^{T}

2 - 高效运用内存

从以上图表可知,很明显中间张量RR 需要一个内存占用O(L2D)O(L^{2}D),这对于长序列是不可行的。因此,作者提出了“偏移”这个诀窍,“偏移”可以无需计算R即可得到Srel​,让内存占用保持在O(LD)O(LD)

步骤如下:

  1. QQ 乘以ErE_r​;
  2. 在最左边一列的前面填补一个虚拟向量;
  3. 改变矩阵并得到形状(l+1,l)(l + 1, l)
  4. 切分矩阵并得到最后ll 行,就相当于SrelS_{rel}​。

结果

正如那篇论文所述,提出的Music Transformer架构在生成钢琴曲方面比Vanilla Transformer和另一个基于长短期记忆网络的模型(称为PerformanceRNN)有明显优势:

  1. Transformer与长短期记忆网络比较,总体而言,基于Transformer的模型更善于保留、重用引导主题(primer motif)。得益于使用相对注意力,Music Transformer创作的乐句是重复的、变化的,而Vanilla Transformer以固定不变的风格使用主题(motif)。长短期记忆网络��型最开始使用主题(motif),但很快转变到其它东西上去了。

  2. Vanilla Transformer与Music Transformer比较,结果表明相对注意力能够泛化至比训练更长的长度。超过训练长度后,Vanilla Transformer看起来就恶化了,而Music Transformer仍然能够生成连贯的音乐结构。

生成

利用预训练的Music Transformer模型生成音乐有3种模式:(i)从头开始生成,(ii)根据引导旋律生成,(iii)为旋律生成伴奏。

我们首先用谷歌Magenta提供的Colab笔记本,因为它已经做过预训练模型加载、tensor2tensor框架初始化以及问题定义。用Weights and Biases的wandb库记录所生成的音频文件以及对应的钢琴卷帘,如下所示。

用这个Colab笔记本重现结果



从头开始生成




Run: stoic-bush-8
1


根据引导旋律生成




Run: stoic-bush-8
1


为给定旋律生成伴奏




Run: stoic-bush-8
1


总结

Music Transformer是一篇很不错的论文,把语言模型的能力带到了符号化音乐生成领域,它能够生成更长的钢琴曲,并且生成的钢琴曲具有连贯的音乐结构和风格。如今随着各种线性复杂度Transformer的出现,还可探究一下把Music Transformer换成其它架构,比如LinformerTransformers are RNNs,这也会非常有趣。

如果你有兴趣深入了解,请参见原论文以及Music Transformer的论坛帖子

给我们分享一些你生成的钢琴曲吧!推文发给我们 @weights_biases@gudgud96



Iterate on AI agents and models faster. Try Weights & Biases today.