-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathgenerate_multiclass.py
150 lines (116 loc) · 4.79 KB
/
generate_multiclass.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import pickle
import numpy
from music21 import instrument, note, stream, chord
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import LSTM
from keras.layers import Activation
def generate():
# load the notes used to train the model
print("Loading the notes used to train the model")
with open('data/multi_notes', 'rb') as filepath:
notes = pickle.load(filepath)
# Get all pitch names
pitchnames = sorted(set(item for item in notes))
# Get all pitch names
n_vocab = len(set(notes))
print("Getting network input")
network_input, normalized_input = prepare_sequences(notes, pitchnames, n_vocab)
print("Creating model")
model = create_network(normalized_input, n_vocab)
print("Generating notes")
prediction_output = generate_notes(model, network_input, pitchnames, n_vocab)
print("Creating midi file")
create_midi(prediction_output)
def prepare_sequences(notes, pitchnames, n_vocab):
# map between notes and integers and back
note_to_int = dict((note, number) for number, note in enumerate(pitchnames))
sequence_length = 100
network_input = []
# 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])
# output.append(note_to_int[sequence_out])
n_patterns = len(network_input)
# reshape the input into a format compatible with LSTM layers
normalized_input = numpy.reshape(network_input, (n_patterns, sequence_length, 1))
# normalize input
normalized_input = normalized_input / float(n_vocab)
return (network_input, normalized_input)
def create_network(network_input, n_vocab):
model = Sequential()
model.add(LSTM(
512,
input_shape=(network_input.shape[1], network_input.shape[2]),
return_sequences=True
))
model.add(Dropout(0.3))
model.add(LSTM(512, return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(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='rmsprop')
# Load the weights to each node
model.load_weights('weights_multi.hdf5')
return model
def generate_notes(model, network_input, pitchnames, n_vocab):
# pick a random sequence from the input as a starting point for the prediction
start = numpy.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 = numpy.reshape(pattern, (1, len(pattern), 1))
prediction_input = prediction_input / float(n_vocab)
prediction = model.predict(prediction_input, verbose=0)
print(prediction)
index = numpy.argmax(prediction)
print(index)
result = int_to_note[index]
prediction_output.append(result)
pattern.append(index)
pattern = pattern[1:len(pattern)]
return prediction_output
def create_midi(prediction_output):
offset = 0
output_notes = []
print(prediction_output)
# create note and chord objects based on the values generated by the model
for element in prediction_output:
notes_at_offset = element.split('_')
for current_elem in notes_at_offset:
# if chord
if ('.' in current_elem) or current_elem.isdigit() and current_elem != "":
notes_in_chord = current_elem.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)
# if rest
elif current_elem == 'rest' and current_elem != "":
new_note = note.Rest()
new_note.offset = offset
new_note.storedInstrument = instrument.Piano()
output_notes.append(new_note)
# if note
elif current_elem != "":
new_note = note.Note(current_elem)
new_note.offset = offset
new_note.storedInstrument = instrument.Piano()
output_notes.append(new_note)
offset += 0.25
midi_stream = stream.Stream(output_notes)
midi_stream.write('midi', fp='test_output_multi.mid')
if __name__ == '__main__':
generate()