昨天我们介绍了马可夫模型的基础原理,那麽今天我们接着介绍要怎麽把音乐套用马可夫模型里面。
首先,马可夫模型需要先对他做训练(Training),训练的目的是让马可夫链了解机率要如何分布。拿昨天盐酥鸡的例子来说就是,一开始我也不知道我每次吃完盐酥鸡後,下一餐继续吃盐酥鸡或改吃鱿鱼/豆腐的机率是多少。但是没关系,我可以开始记录我每餐吃什麽,持续吃了三个月後,我就会有大约90磅的脂肪 90餐的资讯,而这些90餐的资讯就是用来训练马可夫链所用的资料。而马可夫链透过这些资讯的训练後,就会得到一个我吃盐酥鸡摊的模型。
那麽如果我们要套用到作曲上面,首先我们一样要选择资料来对马可夫模型做训练,而训练用的资料就会成为作出来的乐曲的主要依据。举个例子来说,如果我今天拿了一个全部都只有中音 Do的曲子来训练马可夫模型,那想当然尔,创作出来的音乐也会只有 Do而已,因为他所收到的资讯就是每次只要从 Do出发,下一个音一定是100%回到 Do。
我们拿生日快乐歌来当例子:
先不考虑节奏的话,旋律的进行为
Do->Do->Re->Do->Fa->Mi->
Do->Do->Re->Do->Sol->Fa->
Do->Do->Do(高音)->La->Fa->Mi->Re->
Si->Si->La->Fa->Sol->Fa
首先我们先从 中音Do (非高音Do以外的Do都是中音Do)开始,根据整首生日快乐歌,Do 总共出现了8次:
第一次由 Do 回到 Do;
第二次由 Do 来到 Re;
第三次由 Do 来到 Fa;
第四次由 Do 回到 Do;
第五次由 Do 来到 Re;
第六次由 Do 来到 Sol;
第七次由 Do 回到 Do;
第八次由 Do 来到 Do (高音);
我们接着对这些数据做个统计:
Do 回到 Do 的次数是3次,总次数为8次,因此机率是37.5%;
Do 来到 Re 的次数是2次,总次数为8次,因此机率是25%;
Do 来到 Fa 的次数是1次,总次数为8次,因此机率是12.5%;
Do 来到 Sol 的次数是1次,总次数为8次,因此机率是12.5%;
Do 来到 Do (高音) 的次数是1次,总次数为8次,因此机率是12.5%;
接着我们就可以根据以上的资料,推断出每次只要来到Do的时候,就会有
37.5% 的机率依然是 Do;
25% 的机率会移动到是 Re;
12.5% 的机率会移动到 Fa、 Sol 或是 Do (高音)。
接下来我们再针对每一个音去做一样的统计,最後所得到的就是透过整首生日快乐歌训练出来的旋律马可夫模型。
具体机率如下:
而训练好的马可夫模型就可以根据这些基础来开始创作音乐了,要做的事情就是给他开头的第一个音,接着他就会依据上述的机率开始产生下一个音、再下一个音、再下一个音、再下一个音.......,就像石柳煎鸠一样不断的重复重复直到音符的数量达到设定的目标为止,而这就是马可夫模型应用在作曲上的基础。
那麽马可夫模型用来作曲的优缺点在那呢?
首先,马可夫模型的训练非常简单又快速,只要给予资料後算出所有音符之间的转换机率,即可快速的作曲;而只要你喂给马可夫模型的资料够专一,就有很高的机率能够产生听起来感觉类似的曲子,例如你准备的资料全部都是同一个时期的古典乐而且风格都相近,则产生出来的旋律很高的概率能够产生类似的感觉。
然後以上这点是优点也是缺点,如果你没有办法准备足够多且专一的资料给马可夫模型,则训练出来的模型就会相对的比较发散,道理就像是射雕英雄传一开始时,郭靖跟江南七怪学了各种武功但是却打不过每天专心致志练全真武功的尹志平一样 (先不考虑资质还有师父们到底会不会教QQ);除此之外,虽然马可夫模型可以无止尽的一直产生音符下去,但由於没有记忆性 (我今天要吃鱿鱼还是盐酥鸡还是豆腐只跟我前一餐吃什麽有关系,再之前吃什麽都不管),因此创作出来的音乐相对来说没有结构性,听久了会觉得好像是有点乱数在跑得旋律 (虽然不难听,如果喂给它训练的资料够好的话)而前後没有任何因果关系。
除了用来训练主旋律之外,节拍也是可以独立出来当作马可夫模型训练的目标,有些研究就是用其他演算法来做主旋律的创作,并且搭配马可夫模型训练出来的节拍来产生新的乐曲。也可以把主旋律与节拍同时放在马可夫模型里面给它训练,但相对的训练的结果就会比较发散。
目前以各大主流的AI作曲来说,已经比较少看到完全使用马可夫模型来作曲,取而代之的是
一认真起来梗图就好难塞...
那麽明天我们再来继续讲讲其他AI演算法要如何应用在作曲上。
>>: Day 16 JavaScript boxing vs unboxing
Windows 安装IIS 控制台 > 程序和功能 > 开启或关闭Windows功能 &...
Q: 请问icon要怎麽出图好呢? A: 一定要用图片吗? 本篇要实作的是「加到最爱」的按钮,结合...
箭头函式 传统函式 const callName = function(someone){ retu...
多执行绪(multithreading) 所以我们的多执行绪在程序是怎麽运作呢? 一般情况: 假设 ...
一般的ViewPager在做滑动的过程中总是会觉得少了点流畅感,今天会使用PageTransform...