-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to Generate Music using a LSTM Neural Network in Keras #1
Comments
SummaryRepository
using music21 to deal with music data and from the standard of Piano ..
공식 문서를 참고하는 게 더 정확하겠다.
|
Preparing the Datafrom music21 import converter, instrument, note, chord
notes = []
for file in glob.glob("midi_songs/*.mid"): # glob()를 통해 * (wildcard)로 파일을 읽어들인다.
midi = converter.parse(file)
parts = instrument.partitionByInstrument(midi) # 1.
notes_to_parse = None
if parts: # file has instrument parts
notes_to_parse = parts.parts[0].recurse()
else: # 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))
|
Preprocessing the datasequence_length = 100
# get all pitch names
pitchnames = sorted(set(item for item in notes)) # 중복 제거 후, 정렬된 리스트로 변환 -> 0.
# create a dictionary to map pitches to integers -> 1.
note_to_int = dict((note, number) for number, note in enumerate(pitchnames))
# create input sequences and the corresponding outputs
network_input = []
network_output = []
for i in range(0, len(notes) - sequence_length, 1):
sequence_in = notes[i: i + sequence_length] # ex. 0~99까지 (100개) 음표를 저장
sequence_out = notes[i + sequence_length] # ex. 100의 음표를 저장
network_input.append([note_to_int[char] for char in sequence_in]) # 위에서 저장한 음표를 string -> int로 변환
network_output.append(note_to_int[sequence_out]) # 위와 동일
# reshape the input into a format compatible with LSTM layers -> 2.
n_patterns = len(network_input)
network_input = numpy.reshape(network_input, (n_patterns, sequence_length, 1))
# normalize input
n_vocab = len(note_to_int)
network_input = network_input / float(n_vocab)
network_output = np_utils.to_categorical(network_output) # 3.
enumerate()을 통해, 위에서 정렬한 순서(인덱스) 그대로 매핑하고 있음. 다시 말해 정말로 의미있는 데이터 값을 지니진 않는 것으로 보임.
>>> np_utils.to_categorical([0,1])
array([[1., 0.],
[0., 1.]], dtype=float32) 소결론이러한 형태로 전처리한 데이터를 One-Hot Encode Data라고 한다.
|
Building a modelmodel = Sequential()
# Input Layer
model.add(LSTM(
256,
input_shape=(network_input.shape[1], network_input.shape[2]), # 몇개의 행렬로 나누었는지 불러옴. (sequence_length, 1)
return_sequences=True
))
model.add(Dropout(0.3))
# Hidden Layers
model.add(LSTM(512, return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(256))
model.add(Dense(256))
model.add(Dropout(0.3))
# Output Layer
model.add(Dense(n_vocab))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop') |
Fitting the modelfilepath = "weights-improvement-{epoch:02d}-{loss:.4f}-bigger.hdf5"
# 1.
checkpoint = ModelCheckpoint(
filepath, monitor='loss',
verbose=0,
save_best_only=True,
mode='min'
)
callbacks_list = [checkpoint]
model.fit(network_input, network_output, epochs=200, batch_size=64, callbacks=callbacks_list)
|
Generating music with the model# make random seed
start = numpy.random.randint(0, len(network_input)-1)
pattern = network_input[start] # same as the variable sequence_length
int_to_note = dict((number, note) for number, note in enumerate(pitchnames))
# generate 500 notes
prediction_output = []
for note_index in range(500):
# 0.
prediction_input = numpy.reshape(pattern, (1, len(pattern), 1))
prediction_input = prediction_input / float(n_vocab)
prediction = model.predict(prediction_input, verbose=0)
# 1.
index = numpy.argmax(prediction)
result = int_to_note[index]
prediction_output.append(result)
# 2.
pattern.append(index)
pattern = pattern[1:len(pattern)]
|
Decode to musicoffset = 0
music = []
# create note and chord objects based on the values generated by the model
for pitches in prediction_output:
# pitches is a chord
if ('.' in pitches) or pitches.isdigit():
notes_in_chord = pitches.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
music.append(new_chord)
# pattern is a note
else:
new_note = note.Note(pitches)
new_note.offset = offset
new_note.storedInstrument = instrument.Piano()
music.append(new_note)
offset += 0.5 Convert to midi filemidi_stream = stream.Stream(music)
midi_stream.write('midi', fp='test_output.mid') |
Author Suggested
My thought
|
The generated midi file just plays the same chords continuously. |
|
did you ever fix the problem with prediction_output? I have not been able to solve this |
This article is introduced on the codecrafters-io/build-your-own-x
The text was updated successfully, but these errors were encountered: