神刀安全网

TensorFlow应用实战-7-工具类与网络模型

编写转换midi到mp3的方法

# -*- coding: UTF-8 -*-  import os import subprocess  def convertMidi2Mp3():     """     将神经网络生成的 MIDI 文件转成 MP3 文件     """     input_file = 'output.mid'     output_file = 'output.mp3'      # 验证一下是否存在     assert os.path.exists(input_file)      print('Converting %s to MP3' % input_file)      # 用 timidity 生成 mp3 文件(写一个命令行的命令)     command = 'timidity {} -Ow -o - | ffmpeg -i - -acodec libmp3lame -ab 64k {}'.format(input_file, output_file)     # 运行这个命令     subprocess.call(command, shell=True)      print('Converted. Generated file is %s' % output_file) 
if __name__ == '__main__':     convertMidi2Mp3() 

Music21的使用和测试

主要的两个Music21的类

TensorFlow应用实战-7-工具类与网络模型

mark

音符。

什么是Chord和弦

TensorFlow应用实战-7-工具类与网络模型

mark

TensorFlow应用实战-7-工具类与网络模型

mark

http://web.mit.edu/music21/doc/moduleReference/moduleNote.html

pitch name 就是我们看过的C4 d#等

http://web.mit.edu/music21/doc/usersGuide/usersGuide_07_chords.html

体验一个midi文件的构成。

新建一个test21.py

# -*- coding: UTF-* -*-  from music21 import converter, instrument  def print_notes():     # 读取 MIDI 文件, 输出 Stream 流类型     stream = converter.parse("1.mid")      # 获得所有乐器部分     parts = instrument.partitionByInstrument(stream)      if parts: # 如果有乐器部分,取第一个乐器部分         notes = parts.parts[0].recurse()     else:         notes = midi.flat.notes      # 打印出每一个元素     for element in notes:         print(str(element))  if __name__ == "__main__":     print_notes() 
TensorFlow应用实战-7-工具类与网络模型

mark

node类和Chord类

TensorFlow应用实战-7-工具类与网络模型

mark

钢琴类 rest休息符

编写整个神经网络模型

# -*- coding: UTF-8 -*-  """ RNN-LSTM 循环神经网络 """  import tensorflow as tf import keras  # 神经网络的模型 def network_model(inputs, num_pitch, weights_file=None):     model = keras.models.Sequential()     model.add(keras.layers.LSTM(         512, # 输出的维度         input_shape=(inputs.shape[1], inputs.shape[2]), # 输入的形状         return_sequences=True # 返回 Sequences(序列)     ))     model.add(keras.layers.Dropout(0.3)) # 丢弃 30%     model.add(keras.layers.LSTM(512, return_sequences=True))     model.add(keras.layers.Dropout(0.3))     model.add(keras.layers.LSTM(512))     model.add(keras.layers.Dense(256)) # 256 个神经元的全连接层     model.add(keras.layers.Dropout(0.3))     model.add(keras.layers.Dense(num_pitch)) # 所有不重复的音调的数目     model.add(keras.layers.Activation('softmax')) # Softmax 激活函数算概率     # 交叉熵计算误差,使用 RMSProp 优化器     model.compile(loss='categorical_crossentropy', optimizer='rmsprop')      if weights_file is not None: # 如果是 生成 音乐时         # 从 HDF5 文件中加载所有神经网络层的参数(Weights)         model.load_weights(weights_file)      return model 

https://keras.io/models/sequential/

The Sequential model is a linear stack of layers.

线性堆叠的层级模型。官方样例代码:

# Optionally, the first layer can receive an `input_shape` argument: model = Sequential() model.add(Dense(32, input_shape=(500,))) # Afterwards, we do automatic shape inference: model.add(Dense(32)) 

使用add方法添加神经网络不同的层。样例中添加一个dense全连接层。

https://www.tensorflow.org/versions/master/api_docs/python/tf/keras/layers/Dense

我们可以添加的层在tf.keras.layer中。

1.4版本中在tf.keras.models.Squential中。之后的版本移动到了tf.keras.Squential

模型输入,音符的数量,weights_file是我们的模型,参数文件。生成音乐的时候要指定文件.

# 神经网络的模型 def network_model(inputs, num_pitch, weights_file=None):     model = keras.models.Sequential() 

创建了一个做汉堡的模子。在里面去填充它的各个层。

TensorFlow应用实战-7-工具类与网络模型

mark

汉堡没制作出来之前你的脑海已经有这个形状了。一层一层添加面包什么的。

第一层的输出会变成第二层的输入,第二层的输出变成第三层的输入。以此类推。

添加第一层

构建的神经网络模型

TensorFlow应用实战-7-工具类与网络模型

mark

  • lstm 神经元512
  • Dropout 丢弃一部分神经元 防止过拟合
  • 第二个lstm 神经元512
  • 第二个dropout依然丢弃30%
  • 第三个lstm给全连接层(dense),256个神经元。
  • 丢弃30%之后,这个全连接层神经元个数等于我们的不同音调的个数。(num_pitch)
  • softmax激活层 算概率(最大概率)

决定生成音符的判别依据: 百分比概率

TensorFlow应用实战-7-工具类与网络模型

mark

C是概率最高的音符,挑选C最为最终的输出。

TensorFlow应用实战-7-工具类与网络模型

mark

  • 神经网络生成新 音符/和弦原理

我们给神经网络输入一个序列音符,经过神经网络模型。

TensorFlow应用实战-7-工具类与网络模型

mark

将其中的A丢弃掉,然后产生新的预测。

TensorFlow应用实战-7-工具类与网络模型

mark

将其中的B丢弃掉,再去产生新的预测音符。

model.add(keras.layers.LSTM(         512, # Lstm层神经元的数目是512,也是它输出的维度         input_shape=(inputs.shape[1], inputs.shape[2]), # 输入的形状         return_sequences=True # 返回 Sequences(序列)     )) 

添加一个Lstm层。 第一个参数表示神经元的数目(也表示经过这一层之后输出的维度)。
第一层需要指定输入的形状。后面的lstm层就不需要指定了。

return_sequences 设置为true。默认是返回输出序列的最后一个输出。

指定为true会输出所有的输出序列。前两层要指定为true,将完整的序列输出给到下一层。第三层就不用了。

TensorFlow应用实战-7-工具类与网络模型

mark

在堆叠LSTM层时必须设置,最后一层 LSTM 不用设置

有两个维度,音符和音符对应的整型值。

添加第二层

    model.add(keras.layers.Dropout(0.3)) # 丢弃 30%神经元,防止过拟合  

第二个lstm层

    model.add(keras.layers.LSTM(512, return_sequences=True)) 

第二个Dropout层

    model.add(keras.layers.Dropout(0.3)) # 丢弃 30% 

第三层让它只输出默认的false下的输出序列的最后一个

    model.add(keras.layers.LSTM(512)) 

全连接层,神经元数目256个

    model.add(keras.layers.Dense(256)) # 256 个神经元的全连接层 

dropout层略

model.add(keras.layers.Dense(num_pitch)) # 输出的数目等于所有不重复的音调的数目 

类似于onehot编码。得到所有音符对应的预测概率,然后取最大的一个

TensorFlow应用实战-7-工具类与网络模型

mark

激活层使用softmax函数

    model.add(keras.layers.Activation('softmax')) # Softmax 激活函数算概率 

最后对于sequential做一些配置,指定一些参数

    # 交叉熵计算误差,使用 RMSProp 优化器     model.compile(loss='categorical_crossentropy', optimizer='rmsprop') 

损失函数使用categorical_crossentropy (交叉熵计算误差。) 优化器(rmsprop优化器)

循环神经网络来说比较优秀的Rmsprop优化器。

神经网络的结构已经写好了。

TensorFlow应用实战-7-工具类与网络模型

mark

    if weights_file is not None: # 如果是 生成 音乐时         # 从 HDF5 文件中加载所有神经网络层的参数(Weights)         model.load_weights(weights_file)      return model 

训练网络时不指定weights_file。训练和生成时都会用到这个model。

从训练文件中获取音符的方法

from music21 import converter, instrument, note, chord,stream # converter用于转换的,instrument处理乐器部分。 # 音符与和弦的类   def get_notes():     """     从 music_midi 目录中的所有 MIDI 文件里提取 note(音符)和 chord(和弦)     Note 样例: A, B, A#, B#, G#, E, ...     Chord 样例: [B4 E5 G#5], [C5 E5], ...     因为 Chord 就是几个 Note 的集合,所以我们把它们简单地统称为“Note”     """     notes = []      # glob : 匹配所有符合条件的文件,并以 List 的形式返回     for file in glob.glob("music_midi/*.mid"):         # 生成流数据         stream = converter.parse(file)          # 获取所有乐器部分         parts = instrument.partitionByInstrument(stream)          if parts: # 如果有乐器部分, 取第一个乐器部分             notes_to_parse = parts.parts[0].recurse()         else:             notes_to_parse = stream.flat.notes          for element in notes_to_parse:             # 如果是Note类型,那么取它的音调             if isinstance(element, note.Note):                 # 格式例如: E6                 notes.append(str(element.pitch))             # 如果是Chord类型,那么取它各个音调的序号             elif isinstance(element, chord.Chord):                 # 转换后格式例如: 4.15.7                 notes.append('.'.join(str(n) for n in element.normalOrder))      # 将数据写入 data/notes 文件     with open('data/notes', 'wb') as filepath:         pickle.dump(notes, filepath)      return notes  
TensorFlow应用实战-7-工具类与网络模型

mark

对于每个音调有一个固定的数字与之对应

从预测得到音乐

def create_music(prediction):     """     用神经网络'预测'的音乐数据来生成 MIDI 文件,再转成 MP3 文件     """     offset = 0   # 偏移 有音符和弦和空白,偏移空白值     output_notes = []      # 生成 Note(音符)或 Chord(和弦)对象     for data in prediction:         # 是 Chord。格式例如: 4.15.7 有可能只有一个整数         if ('.' in data) or data.isdigit():             notes_in_chord = data.split('.')             notes = []             for current_note in notes_in_chord:                 new_note = note.Note(int(current_note))                 new_note.storedInstrument = instrument.Piano() # 乐器用钢琴                 notes.append(new_note)             new_chord = chord.Chord(notes)             new_chord.offset = offset             output_notes.append(new_chord)         # 是 Note         else:             new_note = note.Note(data)             new_note.offset = offset             new_note.storedInstrument = instrument.Piano()             output_notes.append(new_note)          # 每次迭代都将偏移增加,这样才不会交叠覆盖         offset += 0.5      # 创建音乐流(Stram)     midi_stream = stream.Stream(output_notes)      # 写入 MIDI 文件     midi_stream.write('midi', fp='output.mid')      # 将生成的 MIDI 文件转换成 MP3     convertMidi2Mp3() 

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » TensorFlow应用实战-7-工具类与网络模型

分享到:更多 ()