美文网首页
基于keras的人工作曲代码积累

基于keras的人工作曲代码积累

作者: 瑶瑶_2930 | 来源:发表于2020-06-28 19:51 被阅读0次

utils.py

包含的函数有

  • def convert_midi_to_mp3():: 将神经网络生成的MIDI文件转换为MP3文件
  • def get_notes():: 从 music_midi 目录中的所有 MIDI 文件里提取 note(音符)和 chord(和弦) return notes
  • def create_music(prediction):: 用神经网络'预测'的音乐数据来生成 MIDI 文件,再转成 MP3 文件,最后一句调用了convert_midi_to_mp3()
  1. 使用方式: from utils import * ,然后直接调用函数即可,比如notes = get_notes()
    2.文件操作一般要引用import os, 文件操作建议写法,同时积累形式字符串的写法,如果用多个,写成format(xxx,xxx)
input_file = 'output.mid'
output_file = 'output.mp3'

if not os.path.exists(input_file):
        raise Exception("MIDI 文件 {} 不在此目录下,请确保此文件被正确生成".format(input_file))

print('将 {} 转换为 MP3'.format(input_file))
  1. 在代码中想执行命令行命令的写法,建议每一个比较大的操作都打一个log,需要引用import subprocess.发现如果使用的时候用的是import,那么在使用时需要写库名
command = 'timidity {} -Ow -o - | ffmpeg -i - -acodec libmp3lame -ab 64k {}'.format(input_file, output_file)
    return_code = subprocess.call(command, shell=True)

    if return_code != 0:
        print('转换时出错,请查看出错信息')
    else:
        print('转换完毕. 生成的文件是 {}'.format(output_file))
  1. glob.glob匹配所有符合条件的文件,并以 List 的形式返回,提前引用库import glob
    for midi_file in glob.glob("music_midi/*.mid"):
        stream = converter.parse(midi_file)
  1. music21的操作见原代码
  2. 判断类型,用isinstance( , )append()用于在list后面添加元素。string有 .join()。并且由于之前的note=[],所以相当于是把list的符号转成str输出,奇妙的转换 4.15.7
 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))
  1. 如果目录不存在,创建目录
if not os.path.exists("data"):
     os.mkdir("data")
  1. 写入文件,使用了 import pickle store the serialized object data into the file
with open('data/notes', 'wb') as filepath:
    pickle.dump(notes, filepath)

network.py

使用keras框架搭建网络
1.def network_model(inputs, num_pitch, weights_file=None): 输入,最后输出的个数,以及是否有权重文件。默认没有,如果有的话,就载入

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

2.步骤

  • 创建Sequential()类。model = tf.keras.models.Sequential()
  • 添加每一层网络,比如
LSTM层
model.add(tf.keras.layers.LSTM(
        512,  # LSTM 层神经元的数目是 512,也是 LSTM 层输出的维度
        input_shape=(inputs.shape[1], inputs.shape[2]),  # 输入的形状,对第一个 LSTM 层必须设置
        return_sequences=True  # 返回所有的输出序列(Sequences)
    ))
Dropout层

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

全连接层

model.add(tf.keras.layers.Dense(num_pitch))

  • softmax激活函数算概率
    model.add(tf.keras.layers.Activation('softmax'))
  • 交叉熵计算误差,使用对 循环神经网络来说比较优秀的 RMSProp 优化器 compile: configure the model for training
    model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

train.py

1.会from utils import *以及from network import *
2.步骤

  • 用utils.py中的函数得到数据及数据长度
  • 为神经网络准备好训练的序列prepare_sequence
    • 字符串与整数的映射
    • 序列长度,生成新的输入序列
    • 将输入的形状转为神经网络接受的
    • 归一化(注意不是除以输入的长度,而是输入的最大值)
    • 将期望输出转换成 {0, 1} 组成的布尔矩阵,为了配合 categorical_crossentropy 误差算法使用
      network_output = tf.keras.utils.to_categorical(network_output)
  • 生成checkpoint文件
  • 用fit方法生成模型

3.得到不重复的元素个数。set是不会有重复的数的
num_pitch = len(set(notes))

  1. notes中为字符串,要无重复并且按序
    pitch_names = sorted(set(item for item in notes))
  2. enumerate()同时得到索引和元素,创建字典用dict( , )。把set转换为dict,如下,建立字符串与整数的映射关系
    pitch_to_int = dict((pitch, num) for num, pitch in enumerate(pitch_names))
  3. range的用法
    range(start, stop, step) stop is not include
  4. 生成checkpoint文件
filepath = "weights-{epoch:02d}-{loss:.4f}.hdf5"

    # 用 Checkpoint(检查点)文件在每一个 Epoch 结束时保存模型的参数(Weights)
    # 不怕训练过程中丢失模型参数。可以在我们对 Loss(损失)满意了的时候随时停止训练
    checkpoint = tf.keras.callbacks.ModelCheckpoint(
        filepath,  # 保存的文件路径
        monitor='loss',  # 监控的对象是 损失(loss)
        verbose=0,
        save_best_only=True,  # 不替换最近的数值最佳的监控对象的文件
        mode='min'      # 取损失最小的
    )
    callbacks_list = [checkpoint] #后面的fit方法会调用
  1. 用 fit 方法来训练模型
    model.fit(network_input, network_output, epochs=100, batch_size=64, callbacks=callbacks_list)

generate.py

用训练好的神经网络模型参数来作曲

1.用pickle加载之前保存的文件

    with open('data/notes', 'rb') as filepath:
        notes = pickle.load(filepath)

2.载入之前训练时最好的参数文件,来生成曲子
model = network_model(normalized_input, num_pitch, "best-weights.hdf5")
其中network_model就是写的model,normalized_input是经过prepare_sequential的

相关文章

网友评论

      本文标题:基于keras的人工作曲代码积累

      本文链接:https://www.haomeiwen.com/subject/rifwfktx.html