| 107 | |
| 108 | **Скрипта 2 – macedon_melody_predict.py** |
| 109 | |
| 110 | import pickle |
| 111 | import numpy |
| 112 | from music21 import instrument, note, stream, chord, meter |
| 113 | from keras.models import Sequential |
| 114 | from keras.layers import Dense |
| 115 | from keras.layers import Dropout |
| 116 | from keras.layers import CuDNNLSTM |
| 117 | from keras.layers import Activation |
| 118 | |
| 119 | def io_neural_sequences(macedonian_notes,mac_notes_vocabulary): # Функција за дефинирање на влезната и излезната секвенца на моделот на невронската мрежа. |
| 120 | input_sequence = None |
| 121 | output_sequence = None |
| 122 | n_i_neural_sequence = None |
| 123 | sequence_size = 150 |
| 124 | n_patterns = 0 |
| 125 | pitch_names = sorted(set(elem for elem in macedonian_notes)) |
| 126 | mac_notes_to_int = dict((note, number) for number, note in enumerate(pitch_names)) |
| 127 | i_neural_sequence = [] |
| 128 | o_neural_sequence = [] |
| 129 | for m in range(0, len(macedonian_notes)-sequence_size,1): |
| 130 | input_sequence = macedonian_notes[m:m + sequence_size] |
| 131 | output_sequence = macedonian_notes[m + sequence_size] |
| 132 | i_neural_sequence.append([mac_notes_to_int[char] for char in input_sequence]) |
| 133 | o_neural_sequence.append(mac_notes_to_int[output_sequence]) |
| 134 | n_patterns = len(i_neural_sequence) |
| 135 | n_i_neural_sequence = numpy.reshape(i_neural_sequence, (n_patterns,sequence_size,1)) |
| 136 | n_i_neural_sequence = n_i_neural_sequence / float(mac_notes_vocabulary) |
| 137 | return (i_neural_sequence, n_i_neural_sequence) |
| 138 | |
| 139 | def model_neural_netrowk(i_neural_sequence, mac_notes_vocabulary): # Функција за креирање на артитектура на секвенционен модел на невронска мрежа (го има истиот модел на невронска мрежа за тренирање, но на излез не враќа модел туку ги вчитуваме тежините од веќе тренираниот модел |
| 140 | model = Sequential() |
| 141 | model.add(CuDNNLSTM(256,input_shape=(i_neural_sequence.shape[1],neural_sequence.shape[2]), |
| 142 | return_sequences=True)) |
| 143 | model.add(Dropout(0.3)) |
| 144 | model.add(CuDNNLSTM(512, return_sequences=True)) |
| 145 | model.add(Dropout(0.3)) |
| 146 | model.add(CuDNNLSTM(256)) |
| 147 | model.add(Dropout(0.3)) |
| 148 | model.add(Dense(256)) |
| 149 | model.add(Dense(mac_notes_vocabulary)) |
| 150 | model.add(Activation('softmax')) |
| 151 | model.compile(loss='categorical_crossentropy', optimizer='rmsprop') |
| 152 | model.load_weights('weights.hdf5') |
| 153 | return model |
| 154 | def mac_notes_generation(model, i_neural_sequence, pitch_names,mac_notes_vocabulary): # Функција за декодирање на излезот од тренираниот модел на мрежа |
| 155 | start = numpy.random.randint(0, len(i_neural_sequence)-1) # Бираме случаен почеток за нота за |
| 156 | секвенцата на новата мелодија |
| 157 | int_to_mac_notes = dict((number, note) for number, note in enumerate(pitch_names)) # Мапирање на висината на нотите од цели броеви во речник од ноти |
| 158 | pattern = i_neural_sequence[start] |
| 159 | prediction_output = [] |
| 160 | for note_index in range(400): # Генерирање на ноти за музичко дело со должина од приближно минута и 30 секунди |
| 161 | prediction_input = numpy.reshape(pattern, (1, len(pattern), 1)) |
| 162 | n_prediction_input = prediction_input / float(mac_notes_vocabulary) |
| 163 | prediction = model.predict(n_prediction_input, verbose=0) |
| 164 | index = numpy.argmax(prediction) |
| 165 | result = int_to_mac_notes[index] |
| 166 | prediction_output.append(result) |
| 167 | pattern.append(index) |
| 168 | pattern = pattern[1:len(pattern)] |
| 169 | return prediction_output # На излез се добива низа со 400 генерирани ноти |
| 170 | |
| 171 | def generate_macedon_melody(prediction_output): # Функција за декодирање на предвидените ноти во објекти Note и Chord, претставени во music21 за да можеме после да ја запишеме мелодијата во формат кој може да се слушне |
| 172 | offset = 0 |
| 173 | mac_output_notes = [] |
| 174 | # |
| 175 | for pattern in prediction_output: |
| 176 | # Доколку запишаната вредност е акорд |
| 177 | if ('.' in pattern) or pattern.isdigit(): |
| 178 | notes_in_chord = pattern.split('.') |
| 179 | notes = [] |
| 180 | for current_note in notes_in_chord: |
| 181 | new_note = note.Note(int(current_note)) |
| 182 | new_note.storedInstrument = instrument.Piano() |
| 183 | notes.append(new_note) |
| 184 | new_chord = chord.Chord(notes) |
| 185 | new_chord.offset = offset |
| 186 | mac_output_notes.append(new_chord) |
| 187 | # Доколку запишаната вредност е нота |
| 188 | else: |
| 189 | new_note = note.Note(pattern) |
| 190 | new_note.offset = offset |
| 191 | new_note.storedInstrument = instrument.Piano() |
| 192 | mac_output_notes.append(new_note) |
| 193 | |
| 194 | # Растојание на нотите, за да не се случи нивно повторување (Вредноста е добиена со истражување на растојанието помеѓу нотите во песните за тренирање со помош на функцијата .show() на потокот на податоци). |
| 195 | offset += 0.5 |
| 196 | mac_midi_stream = stream.Stream(mac_output_notes) |
| 197 | mac_midi_stream.write('midi', fp='ai_mac_melody.mid') # Запишување на предвидената мелодија во .mid формат |
| 198 | if __name__ == '__main__': |
| 199 | #Вчитување на нотите врз кои беше трениран моделот |
| 200 | with (open('data/macedonian_notes', 'rb')) as filepath: |
| 201 | macedonian_notes = pickle.load(filepath) |
| 202 | # Вокабулар на висина на ноти |
| 203 | pitch_names = sorted(set(elem for elem in macedonian_notes)) |
| 204 | # Бројот на различни висини на ноти во песните за тренирање |
| 205 | mac_notes_vocabulary = len(set(macedonian_notes)) |
| 206 | i_neural_sequence, n_i_neural_sequence = io_neural_sequences(macedonian_notes, mac_notes_vocabulary) |
| 207 | model = model_neural_netrowk(n_i_neural_sequence, mac_notes_vocabulary) |
| 208 | prediction_output = mac_notes_generation(model, i_neural_sequence, pitch_names,mac_notes_vocabulary) |
| 209 | generate_macedon_melody(prediction_output) # Оваа функција генерира мак. народна мелодија и ја запишува во документ: ai_mac_melody.mid |