Skip to content

An exploration of chord generation based on Transformer.

Notifications You must be signed in to change notification settings

AMagicPear/Chord-GPT

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chord GPT: Transformer架构和弦生成可行性研究

本项目南京邮电大学大学生创新创业训练计划项目
测试使用Transformer架构生成音乐中的和弦进行的可行性的方案

目标

我们的目标是训练一个可以生成具有流畅自然的听感的和弦进行的模型。它可以直接生成和弦进行,也可以在用户写好旋律以后为他的旋律来生成对应的和弦进行。
这个模型可以被运用于给音乐制作人提供灵感,或者简化编曲的过程,也可以被用做给普通人提供一个把自己的歌曲变得更加精美的巧妙黑盒。
试想你可曾有过这样的经历——你某一天突发灵感创作出了一段旋律,可由于你没有学习过作曲,你只能单调地哼着这一段旋律,却没有办法把它写成完整的乐曲。今天,有了我们的模型,你就可以把你的灵感快速转变成一首有模有样的曲子。就算没有作曲知识,你也可以创作出属于你自己的曲子!

思路

Attention is All You Need

自从 Attention is All You Need (arXiv:1706.03762) 发布以来,它被运用于各行各业,其中颇为出圈的就是ChatGPT。似乎,这种注意力机制格外适合自然语言处理(NLP)任务。
我们生成和弦的思路其实和NLP任务是一脉相承的。为什么?语言是一个一个词讲出来的,讲完一句话,它就有一个完整的含义。注意力机制恰好能够阐明语言前后的关联。那音乐呢?我们常说音乐是一种世界性的语言,你可能会认为这是一种比喻或类比……但它真的仅仅是比喻吗?音乐难道不本来就是一种“语言”吗?
对于我们人类而言,平常的语言用来传达确切的信息,而音乐则更像是一种抽象的情绪表现,它们有着很大的差别,但是如果我们脱离开人的感官,假设我们就是一堆神经网络,仅仅从数据层面上看,音乐其实和语言没什么区别。甚至,音乐比像汉语、英语这样的语言来得更简单,也更自由。这也就意味着,只需要更少的训练就可以达到一个和语言模型同等组织力的音乐生成模型。

数据集

数据集选择

由于我们的目标是生成一个偏向流行歌曲的和弦进行,我们的数据集应当能够较好地反应歌曲的和弦进行。起初我试图使用业界流行的maestroadl-piano-midiBACH DOODLEMusicScore等数据集,然而,我发现这些数据集并不能完美地契合我们的需要。
事实上,最近Transformer也有被运用于音乐生成领域,例如MusicTransformer (arXiv:1809.04281) 项目,这是一个使用了maestro MIDI数据集训练而成的Transformer模型,生成的结果好像还像那么回事。只是MIDI看上去是一团乱麻。作为音乐制作人,我观察了他们所做的工作,发现他们使用的数据集内的很多歌曲的MIDI要不就是古典钢琴曲,那种旋律和和弦不是很明确区分的,本来作为人都不好寻找它的规律,又怎么去训练出一个辅助音乐人的AI呢?而另一个游戏音乐的MIDI集,其中又有很多写法奇奇怪怪的MIDI,这种技法用来流行音乐是不现实的,也是一种干扰性质的数据。
好在,在查找了各种音乐类的数据集之后,我们发现有一个宝藏网站HookTheory竟然收录了现成的两万多首流行歌曲的乐谱!不仅如此,它甚至还是每首歌严格分为旋律和和弦轨的。我勒个去,这不就是我想要的理想数据集吗?!于是,我们使用HookTheory数据集作为我们的训练用数据集,开始了我们的模型设计。

首调模式

为了便于模型提取特征,减少干扰和参数量,我们决定所有和弦使用调式内的级数表示法,而非绝对表示。 例如,在G自然大调中出现的 G Major 和弦(组成音为G、B、D),我们只表示为Ⅰ级和弦,而其中出现的 B minor 和弦(组成音为B、D、F#),我们只表示为Ⅲ级和弦,而不会表示出它的具体组成音。
这种表示方式看似很美好,如果它直接成立,那么我们的Token总数将只有7种!试想,一个纯英文语境的语言模型就算只是单纯地将出现的字符集作为Token,都会有几十种。
然而,事实并非如此——作曲家们可不会都乖乖地固定着调式内的七个最基本的自然音三和弦来写所有的歌。在一首乐曲中,出现七和弦、九和弦、增减、挂留和弦那是家常便饭,尤其是在一些日式ACG音乐中(爵士和古典暂不考虑),还经常借用其他调式内的和弦。
因此,我们需要将和弦合理地量化,以能够很好地将其编码为张量。恰好HookTheory的数据集内的歌曲数据本就是首调表示法的。于是,我们打算借其原本的表示法,做一个转换以变成模型输入的张量。

token划分

在自然语言处理中,为了让我们的模型“认识”我们的文字,我们通常使用Tokenizer来处理文字。例如,OpenAI使用的是tiktoken。同样地,为了让模型“认识”乐谱,我们也需要通过某种方式把乐谱转化为一个个的Token。
我们使用了Chris Donahue、John Thickstun、Percy Liang团队处理后的HookTheory数据(arXiv:2212.01884)。在这份数据集中,每一个和弦采用例如如下数据结构表示:

{
    "onset": 0,
    "offset": 2,
    "root_pitch_class": 7,
    "root_position_intervals": [
        4,
        3
    ],
    "inversion": 0
},

这些内容分别代表:和弦开始小节数、结束小节数、和弦根音与调式根音间半音数、上方各音间相对音程的半音数、转位(0表示不转位,三和弦有第一转位和第二转位,七和弦有第一、第二、第三转位)。 我们要考虑的是这样的数据结构该如何转化为嵌入向量,这是这个工程的一大难点。和弦的色彩的决定因素就是root_position_intervals,这个字段在我们数据的表示中必须具有相当高的对和弦的代表性。然而,它是一个长度未知的数组,我尝试遍历了数据集,发现其中大部分乐曲所用的和弦的root_position_intervals都是[4,3][3,4],这分别对应了大三和弦和小三和弦。然而,存在少数歌曲中这个数组的长度为0或1,又有长度为5的。因此,单纯地将和弦划分为简单的几类,无法表示出所有的和弦类型。
好在,在musicpy的支持下,我们得以通过上面的这样一组音程关系来判断和弦的模式。因此,我们会先从数据集中读取原始数据,然后对其中的音程关系加由musicpy的检测,并对每种和弦类型的可能赋予一个唯一的编号。经过调试发现:在单一的和弦根音下,算上单音本身、双音和弦、普通的和弦以及一些较为特殊的复合和弦,仅仅依靠上方音程改变而组成的和弦种类就有95种之多。而如果要再算上root_pitch_class,对十二平均律中每一个和弦取唯一编码,则和弦的总种类将达到95*12=1,140种。
我们尝试了用这种编号方式,直接使用karpathy/minGPT的模型来训练,结果发现:模型大概率会被囚禁于局限的几种和弦的不断重复,而且这样求得的损失较高,最终稳定在2以上。因此,显然这不是一种合理的数据建模方式。
我现在正在考虑将和弦根音和和弦色彩分为两个不同维度输入和弦,通过一个嵌入层,再让它们在高维相加,不知道能否改善模型效果。

解码器自注意力机制

编码器使用和语言模型类似的Transformer Decoder架构。
首先,和弦序列将被划分为多个块,每个块内包含连续的block_size个和弦组成的进行。嵌入矩阵会将每个和弦转化为一个embedding_dim维度的向量。

编码器交叉注意力机制

为了使生成的和弦更加准确,我们希望引入更详细的、具有歌曲特色的外界信息,例如:

  • 根据已有的旋律来生成和弦。由于我们的模型是使用首调模式来生成和弦的,因此用户需要在写下旋律的同时再指定所处的调式。(后续可能我们会再做识别调式调号来自动对齐首调的模块,但那不是我们现阶段的主要目标)
  • 歌曲的曲速和曲风也会在一定程度上影响和弦的选择。
  • 允许用户指定特定位置的和弦。

对于已有旋律的编码比和弦要复杂。

TODO:

乐理上的理论支撑 - 色彩和声

在大模型的嵌入向量计算和注意力模式的探索中,我们发现了奇妙的一点,它竟然在机理上与华萃康老师的色彩和声理论的运作方式不谋而合!
下面,我将借由色彩和声-小田田发表的图文:自动化和声编写程序(构想)中的表述方式来阐述注意力机制和色彩和声的相通之处。

TODO: 待完善

参考&引用

TODO: 待完善

About

An exploration of chord generation based on Transformer.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published