Merge branch 'seq2seq_model' of s444337/praca-magisterska into master
This commit is contained in:
commit
9fc30b6e17
@ -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()
|
||||||
|
@ -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}')
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -85,6 +85,8 @@ class Seq2SeqTransformer():
|
|||||||
decoder_target_data[i, t - 1, self.y_transform_dict[char]] = 1.
|
decoder_target_data[i, t - 1, self.y_transform_dict[char]] = 1.
|
||||||
|
|
||||||
return encoder_input_data, decoder_input_data, decoder_target_data
|
return encoder_input_data, decoder_input_data, decoder_target_data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Seq2SeqModel():
|
class Seq2SeqModel():
|
||||||
@ -92,11 +94,12 @@ class Seq2SeqModel():
|
|||||||
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,
|
||||||
@ -348,7 +351,6 @@ def random_seed_generator(time_of_seq, max_encoder_seq_length, num_encoder_token
|
|||||||
random_seq = []
|
random_seq = []
|
||||||
items = 0
|
items = 0
|
||||||
stop_sign = False
|
stop_sign = False
|
||||||
|
|
||||||
|
|
||||||
return random_seq
|
return random_seq
|
||||||
|
|
||||||
|
@ -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())
|
Loading…
Reference in New Issue
Block a user