1 Star 1 Fork 2

Dr-Zhuang/midi-lstm-gan

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
lstm.py 6.00 KB
一键复制 编辑 原始数据 按行查看 历史
Cory Nguyen 提交于 2018-12-14 11:45 . Updated code
% pylab inline
import glob
import numpy as np
import pandas as pd
from music21 import converter, instrument, note, chord, stream
from keras.models import Sequential
from keras.models import load_model
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import CuDNNLSTM, LSTM, Bidirectional
from keras.layers import Activation
from keras.utils import np_utils
from keras.callbacks import ModelCheckpoint, History
def train_network():
""" Train a Neural Network to generate music """
# Get notes from midi files
notes = get_notes()
# Get the number of pitch names
n_vocab = len(set(notes))
# Convert notes into numerical input
network_input, network_output = prepare_sequences(notes, n_vocab)
# Set up the model
model = create_network(network_input, n_vocab)
history = History()
# Fit the model
n_epochs = 2
model.summary()
model.fit(network_input, network_output, callbacks=[history], epochs=n_epochs, batch_size=64)
model.save('LSTMmodel.h5')
# Use the model to generate a midi
prediction_output = generate_notes(model, notes, network_input, len(set(notes)))
create_midi(prediction_output, 'pokemon_midi')
# Plot the model losses
pd.DataFrame(history.history).plot()
plt.savefig('LSTM_Loss_per_Epoch.png', transparent=True)
plt.close()
def get_notes():
""" Get all the notes and chords from the midi files """
notes = []
for file in glob.glob("Pokemon MIDIs/*.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))
return notes
def prepare_sequences(notes, n_vocab):
""" Prepare the sequences used by the Neural Network """
sequence_length = 100
# get all pitch names
pitchnames = sorted(set(item for item in notes))
# create a dictionary to map pitches to integers
note_to_int = dict((note, number) for number, note in enumerate(pitchnames))
network_input = []
network_output = []
# create input sequences and the corresponding outputs
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])
# reshape the input into a format compatible with LSTM layers
n_patterns = len(network_input)
network_input = np.reshape(network_input, (n_patterns, sequence_length, 1))
# normalize input between 0 and 1
network_input = network_input / float(n_vocab)
network_output = np_utils.to_categorical(network_output)
return (network_input, network_output)
def create_network(network_input, n_vocab):
""" create the structure of the neural network """
model = Sequential()
model.add(CuDNNLSTM(512,input_shape=(network_input.shape[1], network_input.shape[2]),return_sequences=True))
model.add(Dropout(0.3))
model.add(Bidirectional(CuDNNLSTM(512, return_sequences=True)))
model.add(Dropout(0.3))
model.add(Bidirectional(CuDNNLSTM(512)))
model.add(Dense(256))
model.add(Dropout(0.3))
model.add(Dense(n_vocab))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
return model
def generate_notes(model, notes, network_input, n_vocab):
""" Generate notes from the neural network based on a sequence of notes """
# pick a random sequence from the input as a starting point for the prediction
pitchnames = sorted(set(item for item in notes))
start = np.random.randint(0, len(network_input)-1)
int_to_note = dict((number, note) for number, note in enumerate(pitchnames))
pattern = network_input[start]
prediction_output = []
# generate 500 notes
for note_index in range(500):
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)
result = int_to_note[index]
prediction_output.append(result)
pattern = np.append(pattern,index)
pattern = pattern[1:len(pattern)]
return prediction_output
def create_midi(prediction_output, filename):
""" 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='{}.mid'.format(filename))
if __name__ == '__main__':
train_network()
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhuang_shuo/midi-lstm-gan.git
git@gitee.com:zhuang_shuo/midi-lstm-gan.git
zhuang_shuo
midi-lstm-gan
midi-lstm-gan
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385