如何用 TensorFlow 教机器人作曲?秘诀原来是这样

作者: 杨熹 2017-05-09 15:39:33

今天想来看看 AI 是怎样作曲的。

本文会用 TensorFlow 来写一个音乐生成器。

当你对一个机器人说: 我想要一种能够表达出希望和奇迹的歌曲时,发生了什么呢?

计算机会首先把你的语音转化成文字,并且提取出关键字,转化成词向量。然后会用一些打过标签的音乐的数据,这些标签就是人类的各种情感。接着通过在这些数据上面训练一个模型,模型训练好后就可以生成符合要求关键词的音乐。程序最终的输出结果就是一些和弦,他会选择最贴近主人所要求的情感关键词的一些和弦来输出。当然你不只是可以听,也可以作为创作的参考,这样就可以很容易地创作音乐,即使你还没有做到刻意练习1万小时。

机器学习其实是为了扩展我们的大脑,扩展我们的能力。

DeepMind 发表了一篇论文,叫做WaveNet, 这篇论文介绍了音乐生成和文字转语音的艺术。

通常来讲,语音生成模型是串联。这意味着如果我们想从一些文字的样本中来生成语音的话,是需要非常大量的语音片段的数据库,通过截取它们的一部分,并且再重新组装到一起,来组成一个完整的句子。

生成音乐也是同样的道理,但是它有一个很大的难点:就是当你把一些静止的组件组合到一起的时候,生成声音需要很自然,并且还要有情感,这一点是非常难的。

一种理想的方式是,我们可以把所有生成音乐所需要的信息存到模型的参数里面。也就是那篇论文里讲的事情。

我们并不需要把输出结果传给信号处理算法来得到语音信号,而是直接处理语音信号的波。

他们用的模型是 CNN。这个模型的每一个隐藏层中,每个扩张因子,可以互联,并呈指数型的增长。每一步生成的样本,都会被重新投入网络中,并且用于产生下一步。

我们可以来看一下这个模型的图。输入的数据,是一个单独的节点,它作为粗糙的音波,首先需要进行一下预处理,以便于进行下面的操作。

接着我们对它进行编码,来产生一个 Tensor,这个 Tensor 有一些 sample 和 channel。然后把它投入到 CNN 网络的***层中。这一层会产生 channel 的数量,为了进行更简单地处理。然后把所有输出的结果组合在一起,并且增加它的维度。再把维度增加到原来的 channel 的数量。把这个结果投入到损失函数中,来衡量我们的模型训练的如何。***,这个结果会被再次投入到网络中,来生成下一个时间点所需要的音波数据。重复这个过程就可以生成更多的语音。这个网络很大,在他们的 GPU 集群上需要花费九十分钟,并且仅仅只能生成一秒的音频。

接下来我们会用一个更简单的模型在 TensorFlow 上来实现一个音频生成器。

1.引入packaGEs:

数据科学包 Numpy ,数据分析包 Pandas,tqdm 可以生成一个进度条,显示训练时的进度。

  1. import numpy as np 
  2.  
  3. import pandas as pd 
  4.  
  5. import msgpack 
  6.  
  7. import glob 
  8.  
  9. import tensorflow as tf 
  10.  
  11. from tensorflow.python.ops import control_flow_ops 
  12.  
  13. from tqdm import tqdm 
  14.  
  15. import midi_manipulation 

我们会用到一种神经网络的模型 RBM-Restricted Boltzmann Machine 作为生成模型。

它是一个两层网络:***层是可见的,第二层是隐藏层。同一层的节点之间没有联系,不同层之间的节点相互连接。每一个节点都要决定它是否需要将已经接收到的数据发送到下一层,而这个决定是随机的。

2.定义超参数:

先定义需要模型生成的 note 的 range

  1. lowest_note = midi_manipulation.lowerBound #the index of the lowest note on the piano roll 
  2.  
  3. highest_note = midi_manipulation.uPPerBound #the index of the highest note on the piano roll 
  4.  
  5. note_range = highest_note-lowest_note #the note range 

接着需要定义 timestep ,可见层和隐藏层的大小。

  1. num_timesteps = 15 #This is the number of timesteps that we will create at a time 
  2.  
  3. n_visible = 2*note_range*num_timesteps #This is the size of the visible layer. 
  4.  
  5. n_hiDDen = 50 #This is the size of the hidden layer 

训练次数,批量处理的大小,还有学习率。

  1. num_epochs = 200 #The number of training epochs that we are going to run. For each epoch we go through the entire data set
  2.  
  3. BAtch_size = 100 #The number of training examples that we are going to send through the RBM at a time
  4.  
  5. lr = tf.constant(0.005, tf.float32) #The learning rate of our model 

3.定义变量:

x 是投入网络的数据

w 用来存储权重矩阵,或者叫做两层之间的关系

此外还需要两种 bias,一个是隐藏层的 bh,一个是可见层的 bv

  1. x = tf.placeholder(tf.float32, [None, n_visible], name="x") #The placeholder variable that holds our data 
  2.  
  3. W = tf.Variable(tf.random_normal([n_visible, n_hidden], 0.01), name="W") #The weightMATrix that stores the edge weights 
  4.  
  5. bh = tf.Variable(tf.zeros([1, n_hidden], tf.float32, name="bh")) #The bias vector for the hidden layer 
  6.  
  7. bv = tf.Variable(tf.zeros([1, n_visible], tf.float32, name="bv")) #The bias vector for the visible layer 

接着,用辅助方法 gibbs_sample 从输入数据 x 中建立样本,以及隐藏层的样本:

gibbs_sample 是一种可以从多重概率分布中提取样本的算法。

它可以生成一个统计模型,其中,每一个状态都依赖于前一个状态,并且随机地生成符合分布的样本。

  1. #The sample of x 
  2.  
  3. x_sample = gibbs_sample(1) 
  4.  
  5. #The sample of the hidden nodes, starting from the visible state of x 
  6.  
  7. h = sample(tf.sigmoid(tf.matMUl(x, W) + bh)) 
  8.  
  9. #The sample of the hidden nodes, starting from the visible state of x_sample 
  10.  
  11. h_sample = sample(tf.sigmoid(tf.matmul(x_sample, W) + bh)) 

4.更新变量:

  1. size_bt = tf. CA 
  2.  
  3. st(tf.shape(x)[0], tf.float32) 
  4.  
  5. W_adder = tf.mul(lr/size_bt, tf.sub(tf.matmul(tf.transpose(x), h), tf.matmul(tf.transpose(x_sample), h_sample))) 
  6.  
  7. bv_adder = tf.mul(lr/size_bt, tf.reduce_sum(tf.sub(x, x_sample), 0, True)) 
  8.  
  9. bh_adder = tf.mul(lr/size_bt, tf.reduce_sum(tf.sub(h, h_sample), 0, True)) 
  10.  
  11. #When we do sess.run(updt), TensorFlow will run all 3 update steps 
  12.  
  13. updt = [W.assign_add(W_adder), bv.assign_add(bv_adder), bh.assign_add(bh_adder)] 

5.运行 Graph 算法图:

1.先初始化变量

  1. with tf.Session() as sess: 
  2.  
  3. #First, we train the model 
  4.  
  5. #initialize the variables of the model 
  6.  
  7. init = tf.initialize_all_variables() 
  8.  
  9. sess.run(init) 

首先需要 reshape 每首歌,以便于相应的向量表示可以更好地被用于训练模型。

  1. for epoch in tqdm(range(num_epochs)): 
  2.  
  3. for song in sonGS: 
  4.  
  5. #The songs are stored in a time x notes format. The size of each song is timesteps_in_song x 2*note_range 
  6.  
  7. #Here we reshape the songs so that each training example is a vector with num_timesteps x 2*note_range elements 
  8.  
  9. song = np.array(song) 
  10.  
  11. song = song[:np.floor(song.shape[0]/num_timesteps)*num_timesteps] 
  12.  
  13. song = np.reshape(song, [song.shape[0]/num_timesteps, song.shape[1]*num_timesteps]) 

2.接下来就来训练 RBM 模型,一次训练一个样本

  1. for i in range(1, len(song), batch_size): 
  2.  
  3. tr_x = song[i:i+batch_size] 
  4.  
  5. sess.run(updt, feed_dict={x: tr_x}) 

模型完全训练好后,就可以用来生成 music 了。

3.需要训练 Gibbs chain

其中的 visible nodes 先初始化为0,来生成一些样本。

然后把向量 reshape 成更好的格式来 playback。

  1. sample = gibbs_sample(1).eval(session=sess, feed_dict={x: np.zeros((10, n_visible))}) 
  2.  
  3. for i in range(sample.shape[0]): 
  4.  
  5. if not any(sample[i,:]): 
  6.  
  7. continue 
  8.  
  9. #Here we reshape the vector to be time x notes, and then save the vector as a midi file 
  10.  
  11. S = np.reshape(sample[i,:], (num_timesteps, 2*note_range)) 

4.***,打印出生成的和弦

  1. midi_manipulation.noteStateMatrixToMidi(S, "generated_chord_{}".format(i))1212 

综上,就是用 CNN 来参数化地生成音波,

用 RBM 可以很容易地根据训练数据生成音频样本,

Gibbs 算法可以基于概率分布帮我们得到训练样本。

***送上Siraj 的原始视频和源代码链接。

ensorFlow 机器人 机器学习
上一篇:使用 Node.js 对文本内容分词和关键词抽取 下一篇:你可能正在制造一个人工智能,而你却不知道
评论
取消
暂无评论,快去成为第一个评论的人吧

更多资讯推荐

精心整理,机器学习的3大学习资源

机器学习有无尽可能性,该领域薪资高,工作者在工作上能享受到极大乐趣,这让他们大多数时候感觉不像工作。然而,零经验者如何在合理时间内掌握机器学习?本文会给出答案。

读芯术 ·  1天前
欺诈不可怕,机器学习算法分分钟拿下! 精选

根据一项调查,采用基于AI的解决方案的防欺诈专家中有80%认为AI对打击欺诈者有效。但是,仍然存在的问题是弄清楚哪种机器学习算法可以有效地检测未知的欺诈模式。监督学习和无监督学习算法哪一个更有效?

读芯术 ·  2天前
为什么用Go编写机器学习的基础架构,而不是Python?

虽然Python是使用广泛的语言,并用于每个主要的机器学习框架中。然而,你能想象?在Cortex(将机器学习模型部署为API的开放源代码平台之一)代码库中,87.5%的代码都是使用GO编写。

读芯术 ·  3天前
人工智能“捷径”将模拟速度提高数十亿倍

即使用最快的超级计算机模拟复杂的自然现象也要花上几个小时,如大气雾霾如何影响气候。

辛雨 ·  3天前
2020年了,深度学习接下来到底该怎么走?

机器学习资深从业者 Ajit Rajasekharan 在本文中汇集了深度学习领域各路大佬的想法,并分享了他本人的一些思考。

亚希伯恩•菲 ·  4天前
AI战「疫」:百度开源口罩人脸检测及分类模型

2 月 13 日,百度飞桨宣布开源业界首个口罩人脸检测及分类模型。基于此模型,可以在公共场景检测大量的人脸同时,把佩戴口罩和未佩戴口罩的人脸标注出来,快速识别各类场景中不重视、不注意防护病毒,甚至存在侥幸心理的人,减少公众场合下的安全隐患。

Synced ·  4天前
大规模存储基础设施对人工智能的要求

大规模的人工智能(AI)在容量和性能方面提高了存储基础设施的门槛。对于人工智能或机器学习(ML)环境,期望增长到数十个甚至数百TB的容量并不少见。

Harris ·  4天前
关于5G,你要知道的那些事,还不快来了解下

早在1g时代我们只能接打电话。2g时代可以打电话发短信,玩早期的qq,但网络十分不稳定。3g时代带给我们很大的改变就是宽带上网,视频通话,看视频,听歌玩游戏。那时的人们认为4g无用,认为不会有什么改变,但当4g出来时我们才发现这是一次质的飞跃。

林家科技铺 ·  4天前
Copyright©2005-2020 51CTO.COM 版权所有 未经许可 请勿转载