简单的LSTM生成钢琴纯音乐

每天逛一趟GitHub,向大神们学习。
1.拿出所有的音符

import glob
import pickle
from music21 import converter,instrument,note,chord,stream
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Dropout,LSTM,Activation,BatchNormalization
#from tensorflow.keras.utils import np_utils
from tensorflow.keras.callbacks import ModelCheckpoint


from keras.utils import np_utils

import numpy as np

#1.从midi文件中获取音符和和弦
def get_notes():
    notes=[]
    for file in glob.glob('./midi_songs/*.mid'):
        midi=converter.parse(file)
        print('Parsing %s'%file)
        notes_to_parse=None
        try: # file has instrument parts
            s2 = instrument.partitionByInstrument(midi)
            notes_to_parse = s2.parts[0].recurse() 
        except: # file has notes in a flat structure
            notes_to_parse = midi.flat.notes

        for element in notes_to_parse:
            if isinstance(element, note.Note):
                notes.append(str(element.pitch))
            elif isinstance(element, chord.Chord):
                notes.append('.'.join(str(n) for n in element.normalOrder))
    with open('data/notes','wb') as f:
        pickle.dump(notes,f)

    return notes

2.准备用于循环神经网络训练的数据,整合序列数据

def prepare_sequences(notes,n_vocab):#vocab#有多少种音符
    sequence_length=100#以100个notes为一个输入
    pitchnames=sorted(set(item for item in notes))#将所有note整合成集合并按出现次数排序
    note_to_int=dict((note,number) for number,note in enumerate(pitchnames))#将notes的内容和顺序排成字典,字符到数字的映射
    network_input=[]
    normalized_input=[]
    network_output=[]
    #制造序列输入和相应的输出
    for i in range(0,len(notes)-sequence_length,1):
        sequence_in=notes[i:i+sequence_length]
        sequence_out=notes[i+sequence_length]
        network_input.append([note_to_int[char] for char in sequence_in])
        network_output.append([note_to_int[sequence_out]])

    n_patterns=len(network_input)#一共有多少个以100个数字为输入的网络可以用的数据
    normalized_input=np.reshape(network_input,(n_patterns,sequence_length,1))#一所有数据作为一个batch,数据变成rnn的输入格式
    normalized_input=normalized_input/float(n_vocab)#输入数据标准化

    network_output=np_utils.to_categorical(network_output)#输出的一维数字转换成独热编码格式
    return (network_input,network_output,normalized_input,pitchnames)

3.创建循环训练网络

def creat_network(network_input,n_vocab):
    model=Sequential()
    model.add(LSTM(512,input_shape=(network_input.shape[1],network_input.shape[2]),recurrent_dropout=0.3,return_sequences=True))
    model.add(LSTM(512,recurrent_dropout=0.3,return_sequences=True))
    model.add(LSTM(512))
    model.add(BatchNormalization())
    model.add(Dropout(0.3))
    model.add(Dense(256))
    model.add(Activation('relu'))
    model.add(BatchNormalization())
    model.add(Dropout(0.3))
    model.add(Dense(n_vocab))
    model.add(Activation('softmax'))
    model.compile(loss='categorical_crossentropy',optimizer='rmsprop')
    return model
def train(model,network_input,network_output):
    filepath="weights-improvement-{epoch:02d}-{loss:.4f}-bigger.hdf5"
    checkpoint=ModelCheckpoint(filepath,monitor='loss',verbose=0,save_best_only=True,mode='min')
    callbacks_list=[checkpoint]
    model.fit(network_input, network_output, epochs=5, batch_size=128, callbacks=callbacks_list)

4.训练

def train_network():
    notes=get_notes()
    n_vocab=len(set(notes))
    network_input,network_output,normalized_input,pitchnames=prepare_sequences(notes, n_vocab)
    model=creat_network(normalized_input,n_vocab)
    train(model,normalized_input,network_output)
    return (notes,n_vocab,network_input,normalized_input,pitchnames)
if __name__=="__main__":
     notes,n_vocab,network_input,normalized_input,pitchnames=train_network()

5.实际生成音乐

def generate_notes(model,network_input,pitchnames,n_vocab):
    start=np.random.randint(0,len(network_input)-1)#随机生成一个序列的数字
    print(start)
    int_to_note={number:note for number,note in enumerate(pitchnames)}
    pattern=network_input[start]
    prediction_output=[]
    for note_index in range(20):#生成500个notes
        prediction_input=np.reshape(pattern, (1,len(pattern),1))
        prediction_input=prediction_input/float(n_vocab)#归一化
        prediction=model.predict(prediction_input,verbose=0)
        index=np.argmax(prediction)#预测出来概率最大的哪一项
        print(index)
        result=int_to_note[index]
        print(result)
        prediction_output.append(result)
        pattern.append(index)
        pattern=pattern[1:len(pattern)]
    return prediction_output
def create_midi(prediction_output):
    """ convert the output from the prediction to notes and create a midi file
        from the notes """
    offset = 0
    output_notes = []

    # create note and chord objects based on the values generated by the model
    for pattern in prediction_output:
        # pattern is a chord
        if ('.' in pattern) or pattern.isdigit():
            notes_in_chord = pattern.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)
        # pattern is a note
        else:
            new_note = note.Note(pattern)
            new_note.offset = offset
            new_note.storedInstrument = instrument.Piano()
            output_notes.append(new_note)

        # increase offset each iteration so that notes do not stack
        offset += 0.5

    midi_stream = stream.Stream(output_notes)

    midi_stream.write('midi', fp='test_output.mid')
#开始生成
from tensorflow.keras.models import load_model
def generate(notes,n_vocab,network_input,normalized_input,pitchnames):
    model=load_model('weights-improvement-05-4.4652-bigger.hdf5')
    prediction_output= generate_notes(model,network_input,pitchnames,n_vocab)
    create_midi(prediction_output)
generate(notes,n_vocab,network_input,normalized_input,pitchnames)

参考:https://github.com/Xunzhuo/LSTM-Music
资源:https://download.csdn.net/download/weixin_38226321/12619361

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是小z呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值