Merge branch 'seq2seq_model' of s444337/praca-magisterska into master

This commit is contained in:
Cezary Pukownik 2020-03-28 14:52:29 +00:00 committed by Gogs
commit 9fc30b6e17
5 changed files with 37 additions and 21 deletions

View File

@ -54,7 +54,7 @@ def extract_from_folder(model_workflow):
instrument=instrument, instrument=instrument,
bar_in_seq=BARS_IN_SEQ) bar_in_seq=BARS_IN_SEQ)
pickle.dump((x_train, y_train, program), open(save_path,'wb')) pickle.dump((x_train, y_train, program, BARS_IN_SEQ), open(save_path,'wb'))
if __name__ == '__main__': if __name__ == '__main__':
args = parse_argv() args = parse_argv()

View File

@ -9,21 +9,21 @@ parser = argparse.ArgumentParser()
parser.add_argument('n', help='name for experiment', type=str) parser.add_argument('n', help='name for experiment', type=str)
parser.add_argument('s', help='session name', type=str) parser.add_argument('s', help='session name', type=str)
parser.add_argument('--i', help='number of midis to generate', type=int) parser.add_argument('--i', help='number of midis to generate', type=int)
parser.add_argument('--l', help='latent_dim_of_model', type=int) # parser.add_argument('--l', help='latent_dim_of_model', type=int)
parser.add_argument('--m', help="mode {'from_seq', 'from_state}'", type=str) parser.add_argument('--m', help="mode {'from_seq', 'from_state}'", type=str)
args = parser.parse_args() args = parser.parse_args()
EXPERIMENT_NAME = args.n EXPERIMENT_NAME = args.n
SESSION_NAME = args.s SESSION_NAME = args.s
GENERETIONS_COUNT = args.i GENERETIONS_COUNT = args.i
LATENT_DIM = args.l # LATENT_DIM = args.l
MODE = args.m MODE = args.m
if not GENERETIONS_COUNT: if not GENERETIONS_COUNT:
GENERETIONS_COUNT = 1 GENERETIONS_COUNT = 1
if not LATENT_DIM: # if not LATENT_DIM:
LATENT_DIM = 256 # LATENT_DIM = 256
if not MODE: if not MODE:
MODE = 'from_seq' MODE = 'from_seq'
@ -42,17 +42,19 @@ for key, value in model_workflow.items():
band[instrument] = [None, None, generator] band[instrument] = [None, None, generator]
'''LOAD MODELS''' '''LOAD MODELS'''
print('Loading models...')
for instrument in tqdm(band): for instrument in tqdm(band):
data_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument.lower() + '_data.pkl') data_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument.lower() + '_data.pkl')
model_path = os.path.join('models', EXPERIMENT_NAME, instrument.lower() + '_model.h5') model_path = os.path.join('models', EXPERIMENT_NAME, instrument.lower() + '_model.h5')
x_train, y_train, program = pickle.load(open(data_path,'rb')) x_train, y_train, program, bars_in_seq = pickle.load(open(data_path,'rb'))
model = Seq2SeqModel(LATENT_DIM, x_train, y_train) model = Seq2SeqModel(x_train, y_train, bars_in_seq=bars_in_seq)
model.load(model_path) model.load(model_path)
band[instrument][0] = model band[instrument][0] = model
band[instrument][1] = program band[instrument][1] = program
print('Generating music...')
for midi_counter in tqdm(range(GENERETIONS_COUNT)): for midi_counter in tqdm(range(GENERETIONS_COUNT)):
''' MAKE MULTIINSTRUMENTAL MUSIC !!!''' ''' MAKE MULTIINSTRUMENTAL MUSIC !!!'''
notes = dict() notes = dict()
@ -89,6 +91,6 @@ for midi_counter in tqdm(range(GENERETIONS_COUNT)):
except: except:
pass pass
save_path = os.path.join('generated_music', EXPERIMENT_NAME, SESSION_NAME, f'{EXPERIMENT_NAME}_{midi_counter}_{MODE}_{LATENT_DIM}.mid') save_path = os.path.join('generated_music', EXPERIMENT_NAME, SESSION_NAME, f'{EXPERIMENT_NAME}_{midi_counter}_{MODE}.mid')
generated_midi.save(save_path) generated_midi.save(save_path)
# print(f'Generated succefuly to {save_path}') # print(f'Generated succefuly to {save_path}')

View File

@ -519,7 +519,7 @@ def parse_pretty_midi_instrument(instrument, resolution, time_to_tick, key_offse
if instrument.is_drum: if instrument.is_drum:
notes[tick][0].add(note.pitch) notes[tick][0].add(note.pitch)
else: else:
notes[tick][0].add(note.pitch+key_offset) notes[tick][0].add(note.pitch + key_offset)
notes[tick][1].add(note_lenth) notes[tick][1].add(note_lenth)

View File

@ -87,16 +87,19 @@ class Seq2SeqTransformer():
return encoder_input_data, decoder_input_data, decoder_target_data return encoder_input_data, decoder_input_data, decoder_target_data
class Seq2SeqModel(): class Seq2SeqModel():
'''NeuralNerwork Seq2Seq model. '''NeuralNerwork Seq2Seq model.
The network is created based on training data The network is created based on training data
''' '''
def __init__(self, latent_dim, x_train, y_train): def __init__(self, x_train, y_train, latent_dim=256, enc_dropout=0, dec_dropout=0, bars_in_seq=4):
self.has_predict_model = False self.has_predict_model = False
self.has_train_model = False self.has_train_model = False
self.x_train = x_train self.x_train = x_train
self.y_train = y_train self.y_train = y_train
self.bars_in_seq = bars_in_seq
self.latent_dim = latent_dim self.latent_dim = latent_dim
self.transformer = Seq2SeqTransformer() self.transformer = Seq2SeqTransformer()
self.encoder_input_data, self.decoder_input_data, self.decoder_target_data = self.transformer.transform(self.x_train, self.y_train) self.encoder_input_data, self.decoder_input_data, self.decoder_target_data = self.transformer.transform(self.x_train, self.y_train)
@ -115,7 +118,7 @@ class Seq2SeqModel():
self.encoder_inputs = Input(shape=(None, self.transformer.x_vocab_size )) self.encoder_inputs = Input(shape=(None, self.transformer.x_vocab_size ))
# 2 layer - LSTM_1, LSTM # 2 layer - LSTM_1, LSTM
self.encoder = LSTM(latent_dim, return_state=True) self.encoder = LSTM(latent_dim, return_state=True, dropout=enc_dropout)
#self.encoder = LSTM(latent_dim, return_state=True) #self.encoder = LSTM(latent_dim, return_state=True)
# 2 layer - LSTM_1 : outputs # 2 layer - LSTM_1 : outputs
@ -130,7 +133,7 @@ class Seq2SeqModel():
self.decoder_inputs = Input(shape=(None, self.transformer.y_vocab_size)) self.decoder_inputs = Input(shape=(None, self.transformer.y_vocab_size))
# 2 layer - LSTM_1, LSTM # 2 layer - LSTM_1, LSTM
self.decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True) self.decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True, dropout=dec_dropout)
#self.decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True) #self.decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True)
# 2 layer - LSTM_2 : outputs, full sequance as lstm layer # 2 layer - LSTM_2 : outputs, full sequance as lstm layer
@ -221,7 +224,6 @@ class Seq2SeqModel():
# 3 layer: Dense output: one-hot-encoded representation of element of sequance # 3 layer: Dense output: one-hot-encoded representation of element of sequance
self.decoder_outputs = self.decoder_dense(self.decoder_outputs) self.decoder_outputs = self.decoder_dense(self.decoder_outputs)
self.decoder_model = Model( self.decoder_model = Model(
[self.decoder_inputs] + self.decoder_states_inputs, [self.decoder_inputs] + self.decoder_states_inputs,
[self.decoder_outputs] + self.decoder_states) [self.decoder_outputs] + self.decoder_states)
@ -286,7 +288,8 @@ class Seq2SeqModel():
def develop(self, mode='from_seq'): def develop(self, mode='from_seq'):
# music generation for seq2seq for melody # music generation for seq2seq for melody
input_seq_start = random_seed_generator(16, # TODO: Hardcoded 16 ??
input_seq_start = random_seed_generator(self.bars_in_seq * 4,
self.transformer.x_max_seq_length, self.transformer.x_max_seq_length,
self.transformer.x_vocab_size, self.transformer.x_vocab_size,
self.transformer.x_transform_dict, self.transformer.x_transform_dict,
@ -300,7 +303,7 @@ class Seq2SeqModel():
# generate sequnce iterativly for melody # generate sequnce iterativly for melody
input_seq = input_seq_start.copy() input_seq = input_seq_start.copy()
melody = [] melody = []
for i in range(4): for i in range(self.bars_in_seq):
if mode == 'from_seq': if mode == 'from_seq':
decoded_sentence = self.predict(input_data)[:-1] decoded_sentence = self.predict(input_data)[:-1]
elif mode == 'from_state': elif mode == 'from_state':
@ -309,8 +312,8 @@ class Seq2SeqModel():
raise ValueError('mode must be in {from_seq, from_state}') raise ValueError('mode must be in {from_seq, from_state}')
melody.append(decoded_sentence) melody.append(decoded_sentence)
input_seq.extend(decoded_sentence) input_seq.extend(decoded_sentence)
input_bars = stream_to_bars(input_seq, 4) input_bars = stream_to_bars(input_seq, self.bars_in_seq)
input_bars = input_bars[1:5] input_bars = input_bars[1:self.bars_in_seq+1]
input_seq = [note for bar in input_bars for note in bar] input_seq = [note for bar in input_bars for note in bar]
input_data = seq_to_numpy(input_seq, input_data = seq_to_numpy(input_seq,
self.transformer.x_max_seq_length, self.transformer.x_max_seq_length,
@ -349,7 +352,6 @@ def random_seed_generator(time_of_seq, max_encoder_seq_length, num_encoder_token
items = 0 items = 0
stop_sign = False stop_sign = False
return random_seq return random_seq
# seq to numpy array: # seq to numpy array:

View File

@ -16,6 +16,8 @@ def parse_argv():
parser.add_argument('--b', help='batch_size', type=int) parser.add_argument('--b', help='batch_size', type=int)
parser.add_argument('--l', help='latent_dim', type=int) parser.add_argument('--l', help='latent_dim', type=int)
parser.add_argument('--e', help='epochs', type=int) parser.add_argument('--e', help='epochs', type=int)
parser.add_argument('--ed', help='encoder dropout', type=float)
parser.add_argument('--dd', help='decoder dropout', type=float)
parser.add_argument('--i', help='refrance to instrument to train, if you want to train only one instument') parser.add_argument('--i', help='refrance to instrument to train, if you want to train only one instument')
parser.add_argument('-r', help='reset, use when you want to reset waights and train from scratch', action='store_true') parser.add_argument('-r', help='reset, use when you want to reset waights and train from scratch', action='store_true')
args = parser.parse_args() args = parser.parse_args()
@ -37,17 +39,21 @@ def train_models(model_workflow):
found = False found = False
for instrument in instruments: for instrument in instruments:
if INSTRUMENT == None or INSTRUMENT == instrument: if not INSTRUMENT or INSTRUMENT == instrument:
data_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument.lower() + '_data.pkl') data_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument.lower() + '_data.pkl')
model_path = os.path.join('models', EXPERIMENT_NAME, f'{instrument.lower()}_model.h5') model_path = os.path.join('models', EXPERIMENT_NAME, f'{instrument.lower()}_model.h5')
x_train, y_train, _ = pickle.load(open(data_path,'rb')) x_train, y_train, _, bars_in_seq = pickle.load(open(data_path,'rb'))
model = Seq2SeqModel(LATENT_DIM, x_train, y_train)
if os.path.isfile(model_path) and not RESET: if os.path.isfile(model_path) and not RESET:
model = Seq2SeqModel(x_train, y_train)
model.load(model_path) model.load(model_path)
else:
model = Seq2SeqModel(x_train, y_train, LATENT_DIM, ENCODER_DROPOUT, DECODER_DROPOUT, bars_in_seq)
print(f'Training: {instrument}') print(f'Training: {instrument}')
model.fit(BATCH_SIZE, EPOCHS, callbacks=[]) model.fit(BATCH_SIZE, EPOCHS, callbacks=[])
make_folder_if_not_exist(os.path.join('models', EXPERIMENT_NAME))
model.save(model_path) model.save(model_path)
found = True found = True
@ -65,6 +71,8 @@ if __name__ == '__main__':
EPOCHS = args.e EPOCHS = args.e
RESET = args.r RESET = args.r
INSTRUMENT = args.i INSTRUMENT = args.i
ENCODER_DROPOUT = args.ed
DECODER_DROPOUT = args.dd
# default settings if not args passed # default settings if not args passed
if not BATCH_SIZE: if not BATCH_SIZE:
@ -75,5 +83,9 @@ if __name__ == '__main__':
EPOCHS = 1 EPOCHS = 1
if not RESET: if not RESET:
RESET = False RESET = False
if not ENCODER_DROPOUT:
ENCODER_DROPOUT = 0.0
if not DECODER_DROPOUT:
DECODER_DROPOUT = 0.0
train_models(load_workflow()) train_models(load_workflow())