| | 1 | **5.4. Имплементација** |
| | 2 | |
| | 3 | Системот за автоматско генерериње на македонска народна мелодија наречен MacedonMelody се состои од две python скрипти. Првата скрипта се користи за креирање и тренирање на моделот врз базата на податоци, додека во втората се генерира македонска народна мелодија врз база на тренираниот модел. |
| | 4 | |
| | 5 | Скрипта 1 – macedon_melody_train.py |
| | 6 | |
| | 7 | import glob # За да можеме да пристапиме локално во системот |
| | 8 | import pickle # За да ги зачуваме нотите во документ |
| | 9 | import numpy # За менување на формата на влезот на невронската мрежа |
| | 10 | from keras.models import Sequential |
| | 11 | from keras.layers import CuDNNLSTM |
| | 12 | from keras.layers import Dropout |
| | 13 | from keras.layers import Dense |
| | 14 | from keras.layers import Activation |
| | 15 | from keras.utils import np_utils |
| | 16 | from keras.callbacks import ModelCheckpoint |
| | 17 | from music21 import converter, instrument, note, chord, stream |
| | 18 | |
| | 19 | def mac_notes(): # Функција за креирање вокабулар од ноти од сите муз. документи во базата на податоци за тренирање |
| | 20 | |
| | 21 | macedonian_notes = [] # Листа за зачувување на сите ноти од МИДИ документите |
| | 22 | for file in glob.glob("mac_midi/*.mid"): |
| | 23 | |
| | 24 | macedonian_midi = converter.parse(file) #Парсирање на нотен запис од фајл |
| | 25 | print("The song parsed is: %s " %file) |
| | 26 | # macedonian_midi.show('text') – За прикажување на содржините на миди документите |
| | 27 | |
| | 28 | |
| | 29 | mac_notes_to_be_parsed = None |
| | 30 | offsets = None |
| | 31 | try: |
| | 32 | mac_notes_to_be_parsed = macedonian_midi.flat.notes |
| | 33 | except: |
| | 34 | mac_instruments = instrument.partitionByInstrument(macedonian_midi) |
| | 35 | mac_notes_to_be_parsed = mac_instruments.parts[0].recurse() |
| | 36 | |
| | 37 | for element in mac_notes_to_be_parsed: |
| | 38 | if isinstance(element, note.Note): |
| | 39 | macedonian_notes.append(str(element.pitch)) |
| | 40 | elif isinstance(element, chord.Chord): |
| | 41 | macedonian_notes.append('.'.join(str(m) for m in element.normalOrder)) |
| | 42 | |
| | 43 | with open('data/macedonian_notes','wb') as filepath: |
| | 44 | pickle.dump(macedonian_notes, filepath) |
| | 45 | return macedonian_notes # На излез дава листа со ноти |
| | 46 | |
| | 47 | def io_neural_sequences(macedonian_notes,mac_notes_vocabulary): # Функција за дефинирање на влезната и излезната секвенца на моделот на невронската мрежа. |
| | 48 | |
| | 49 | input_sequence = None |
| | 50 | output_sequence = None |
| | 51 | sequence_size = 150 |
| | 52 | n_patterns = 0 |
| | 53 | pitch_names = sorted(set(elem for elem in macedonian_notes)) |
| | 54 | mac_notes_to_int = dict((note, number) for number, note in enumerate(pitch_names)) |
| | 55 | i_neural_sequence = [] |
| | 56 | o_neural_sequence = [] |
| | 57 | for m in range(0, len(macedonian_notes)-sequence_size,1): |
| | 58 | input_sequence = macedonian_notes[m:m + sequence_size] |
| | 59 | output_sequence = macedonian_notes[m + sequence_size] |
| | 60 | i_neural_sequence.append([mac_notes_to_int[char] for char in input_sequence]) |
| | 61 | o_neural_sequence.append(mac_notes_to_int[output_sequence]) |
| | 62 | n_patterns = len(i_neural_sequence) |
| | 63 | i_neural_sequence = numpy.reshape(i_neural_sequence, (n_patterns,sequence_size,1)) |
| | 64 | i_neural_sequence = i_neural_sequence / float(mac_notes_vocabulary) |
| | 65 | o_neural_sequence = np_utils.to_categorical(o_neural_sequence) |
| | 66 | |
| | 67 | return (i_neural_sequence, o_neural_sequence) # На излез ни ги дава дефинираните внезна и излезна секвенца за невронската мрежа |
| | 68 | |
| | 69 | def model_neural_netrowk(i_neural_sequence, mac_notes_vocabulary): # Функција за креирање на артитектура на секвенционен модел на невронска мрежа, кој се состои од 3 CuDNNLSTM слоја, 3 Dropout слоја, 2 Dense слоја и слој за активација. |
| | 70 | |
| | 71 | model = Sequential() |
| | 72 | model.add(CuDNNLSTM(256,input_shape=(i_neural_sequence.shape[1], i_neural_sequence.shape[2]),return_sequences=True)) |
| | 73 | model.add(Dropout(0.3)) |
| | 74 | model.add(CuDNNLSTM(512, return_sequences=True)) |
| | 75 | model.add(Dropout(0.3)) |
| | 76 | model.add(CuDNNLSTM(256)) |
| | 77 | model.add(Dropout(0.3)) |
| | 78 | model.add(Dense(256)) |
| | 79 | model.add(Dense(mac_notes_vocabulary)) |
| | 80 | model.add(Activation('softmax')) |
| | 81 | model.compile(loss='categorical_crossentropy', optimizer='rmsprop') |
| | 82 | return model # На излез дава моделиран модел на LSTM невронска мрежа |
| | 83 | |
| | 84 | def train_neural_network(model, i_neural_sequence, o_neural_sequence): # Функција за тренирање на невронската мрежа |
| | 85 | filepath = "weights-{epoch:02d}-{loss:.4f}-bigger.hdf5" |
| | 86 | checkpoint = ModelCheckpoint( |
| | 87 | filepath, |
| | 88 | monitor='loss', |
| | 89 | verbose=0, |
| | 90 | save_best_only=True, |
| | 91 | mode='min' |
| | 92 | ) |
| | 93 | |
| | 94 | callbacks_list = [checkpoint] |
| | 95 | |
| | 96 | model.fit(i_neural_sequence, o_neural_sequence, epochs=50, batch_size=10, callbacks=callbacks_list) |
| | 97 | |
| | 98 | |
| | 99 | if __name__ == '__main__': |
| | 100 | macedonian_notes = mac_notes() # Ја повикуваме функцијата за креирање вокабулар од мак. ноти |
| | 101 | mac_notes_vocabulary = len(set(macedonian_notes)) |
| | 102 | mac_notes_vocabulary2 = len(macedonian_notes) |
| | 103 | print("Num vocab is: %s " % mac_notes_vocabulary) |
| | 104 | print("Size is: %s " % mac_notes_vocabulary2) |
| | 105 | i_neural_sequence, o_neural_sequence = io_neural_sequences(macedonian_notes,mac_notes_vocabulary) # Ја повикуваме функцијата која ни ги дава влезната и излезната секвенца за н. мрежа |
| | 106 | model = model_neural_netrowk(i_neural_sequence, mac_notes_vocabulary) # Ja повикуваме функцијата за креирање на моделот |
| | 107 | train_neural_network(model, i_neural_sequence, o_neural_sequence) # Ја повикуваме функцијата за тренирање на модел на невронска мрежа |