seq2seq model to master #2

Merged
s444337 merged 1 commits from seq2seq_model into master 2019-10-28 10:47:52 +01:00
5 changed files with 141 additions and 103 deletions

View File

@ -5,54 +5,70 @@ import pickle
from midi_processing import extract_data, analyze_data from midi_processing import extract_data, analyze_data
parser = argparse.ArgumentParser() def make_folder_if_not_exist(path):
parser.add_argument('midi_pack', help='folder name for midi pack in midi_packs folder', type=str) try:
parser.add_argument('name', help='name for experiment', type=str) os.mkdir(path)
parser.add_argument('--b', help='lengh of sequence in bars', type=int) except:
parser.add_argument('-a', help='analize data', action='store_true') pass
args = parser.parse_args()
'''SETTINGS''' def parse_argv():
MIDI_PACK_NAME = args.midi_pack parser = argparse.ArgumentParser()
EXPERIMENT_NAME = args.name parser.add_argument('midi_pack', help='folder name for midi pack in midi_packs folder', type=str)
BARS_IN_SEQ = args.b parser.add_argument('--n', help='name for experiment', type=str)
parser.add_argument('--b', help='lengh of sequence in bars', type=int)
parser.add_argument('-a', help='analize data', action='store_true')
args = parser.parse_args()
return args
midi_folder_path = os.path.join('midi_packs', MIDI_PACK_NAME) def ask_for_workflow():
'''MODEL WORKFLOW DIALOG'''
number_of_instruments = int(input('Please specify number of instruments\n'))
model_workflow = dict()
for i in range(number_of_instruments):
input_string = input('Please specify a workflow step <Instrument> [<Second Instrument>] <mode> {m : melody, a : arrangment}\n')
tokens = input_string.split()
if tokens[-1] == 'm':
model_workflow[i] = (tokens[0], 'melody')
elif tokens[-1] == 'a':
model_workflow[i] = ((tokens[1], tokens[0]), 'arrangment')
else:
raise ValueError("The step definitiom must end with {'m', 'a'}");
make_folder_if_not_exist(os.path.join('training_sets', EXPERIMENT_NAME))
pickle.dump(model_workflow, open(os.path.join('training_sets', EXPERIMENT_NAME, 'workflow.pkl'),'wb'))
return model_workflow
# analyze data set for intresting intruments def extract_from_folder(model_workflow):
if args.a: for key, (instrument, how) in model_workflow.items():
analyze_data(midi_folder_path) if how == 'melody':
sys.exit() instrument_name = instrument
else:
instrument_name = instrument[1]
make_folder_if_not_exist(os.path.join('training_sets', EXPERIMENT_NAME))
save_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument_name.lower() + '_data.pkl')
x_train, y_train, program = extract_data(midi_folder_path=os.path.join('midi_packs', MIDI_PACK_NAME),
how=how,
instrument=instrument,
bar_in_seq=BARS_IN_SEQ)
pickle.dump((x_train, y_train, program), open(save_path,'wb'))
if __name__ == '__main__':
args = parse_argv()
'''MODEL WORKFLOW DIALOG''' MIDI_PACK_NAME = args.midi_pack
number_of_instruments = int(input('Please specify number of instruments\n')) EXPERIMENT_NAME = args.n
model_workflow = dict() BARS_IN_SEQ = args.b
input_list = [] if not EXPERIMENT_NAME:
for i in range(number_of_instruments): EXPERIMENT_NAME = MIDI_PACK_NAME
input_string = input('Please specify a workflow step\n') if not BARS_IN_SEQ:
tokens = input_string.split() BARS_IN_SEQ = 4
if tokens[-1] == 'melody': ANALIZE = args.a
model_workflow[i] = (tokens[0], tokens[1])
if ANALIZE:
analyze_data(os.path.join('midi_packs', MIDI_PACK_NAME))
else: else:
model_workflow[i] = ((tokens[1], tokens[0]), tokens[2]) extract_from_folder(ask_for_workflow())
# make folder for new experiment if no exist
try:
os.mkdir(os.path.join('training_sets', EXPERIMENT_NAME))
except:
pass
# extract process
for key, (instrument, how) in model_workflow.items():
if how == 'melody':
instrument_name = instrument
else:
instrument_name = instrument[1]
save_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument_name.lower() + '_data.pkl')
x_train, y_train, program = extract_data(midi_folder_path=midi_folder_path, how=how,
instrument=instrument, bar_in_seq=BARS_IN_SEQ)
pickle.dump((x_train, y_train, program), open(save_path,'wb'))
pickle.dump(model_workflow, open(os.path.join('training_sets', EXPERIMENT_NAME, 'workflow.pkl'),'wb'))

View File

@ -7,19 +7,27 @@ import pickle
parser = argparse.ArgumentParser() 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('--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
GENERETIONS_COUNT = args.i GENERETIONS_COUNT = args.i
LATENT_DIM = args.l LATENT_DIM = args.l
MODE = args.m MODE = args.m
if GENERETIONS_COUNT == None: if not GENERETIONS_COUNT:
GENERETIONS_COUNT = 1 GENERETIONS_COUNT = 1
if not LATENT_DIM:
LATENT_DIM = 256
if not MODE:
MODE = 'from_seq'
model_workflow = pickle.load(open(os.path.join('training_sets', EXPERIMENT_NAME, 'workflow.pkl'),'rb')) model_workflow = pickle.load(open(os.path.join('training_sets', EXPERIMENT_NAME, 'workflow.pkl'),'rb'))
band = dict() band = dict()
@ -45,7 +53,7 @@ for instrument in tqdm(band):
band[instrument][0] = model band[instrument][0] = model
band[instrument][1] = program band[instrument][1] = program
for midi_counter in range(GENERETIONS_COUNT): for midi_counter in tqdm(range(GENERETIONS_COUNT)):
''' MAKE MULTIINSTRUMENTAL MUSIC !!!''' ''' MAKE MULTIINSTRUMENTAL MUSIC !!!'''
notes = dict() notes = dict()
@ -76,7 +84,11 @@ for midi_counter in range(GENERETIONS_COUNT):
os.mkdir(os.path.join('generated_music', EXPERIMENT_NAME)) os.mkdir(os.path.join('generated_music', EXPERIMENT_NAME))
except: except:
pass pass
try:
os.mkdir(os.path.join('generated_music', EXPERIMENT_NAME, SESSION_NAME))
except:
pass
save_path = os.path.join('generated_music', EXPERIMENT_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}_{LATENT_DIM}.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

@ -10,8 +10,6 @@ from random import randint
import pretty_midi as pm import pretty_midi as pm
from tqdm import tqdm from tqdm import tqdm
# TODO: Stream class is no logner needed <- remore from code and make just SingleTrack.notes instead on SingleTrack.stream.notes # TODO: Stream class is no logner needed <- remore from code and make just SingleTrack.notes instead on SingleTrack.stream.notes
class Stream(): class Stream():
@ -486,7 +484,7 @@ def round_to_sixteenth_note(x, base=0.25):
''' '''
return base * round(x/base) return base * round(x/base)
def parse_pretty_midi_instrument(instrument, resolution, time_to_tick, key_offset): def parse_pretty_midi_instrument(instrument, resolution, time_to_tick, key_offset):
''' arguments: a prettyMidi instrument object ''' arguments: a prettyMidi instrument object
return: a custom SingleTrack object return: a custom SingleTrack object

View File

@ -52,7 +52,6 @@ class Seq2SeqTransformer():
self.x_vocab_size = len(self.x_vocab) self.x_vocab_size = len(self.x_vocab)
self.y_vocab_size = len(self.y_vocab) self.y_vocab_size = len(self.y_vocab)
self.x_transform_dict = dict( self.x_transform_dict = dict(
[(char, i) for i, char in enumerate(self.x_vocab)]) [(char, i) for i, char in enumerate(self.x_vocab)])
self.y_transform_dict = dict( self.y_transform_dict = dict(

View File

@ -3,64 +3,77 @@ import sys
import pickle import pickle
import keras import keras
import argparse import argparse
import warnings
from model import Seq2SeqModel from model import Seq2SeqModel
from extract import make_folder_if_not_exist
parser = argparse.ArgumentParser() # TODO:
parser.add_argument('n', help='name for experiment', type=str) # FIXME:
parser.add_argument('--b', help='batch_size', type=int)
parser.add_argument('--l', help='latent_dim', type=int)
parser.add_argument('--e', help='epochs', type=int)
parser.add_argument('--r', help='reset, use when you want to reset waights and train from scratch', action='store_true')
parser.add_argument('--i', help='refrance to instrument to train, if you want to train only one instument')
args = parser.parse_args()
def parse_argv():
parser = argparse.ArgumentParser()
parser.add_argument('n', help='name for experiment', type=str)
parser.add_argument('--b', help='batch_size', type=int)
parser.add_argument('--l', help='latent_dim', type=int)
parser.add_argument('--e', help='epochs', type=int)
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')
args = parser.parse_args()
return args
'''HYPER PARAMETERS''' def load_workflow():
EXPERIMENT_NAME = args.n workflow_path = os.path.join('training_sets', EXPERIMENT_NAME, 'workflow.pkl')
BATCH_SIZE = args.b if os.path.isfile(workflow_path):
LATENT_DIM = args.l model_workflow = pickle.load(open(workflow_path,'rb'))
EPOCHS = args.e else:
RESET = args.r raise FileNotFoundError(f'There is no workflow.pkl file in trainig_sets/{EXPERIMENT_NAME}/ folder')
INSTRUMENT = args.i return model_workflow
if BATCH_SIZE == None: def train_models(model_workflow):
BATCH_SIZE = 32
if LATENT_DIM == None: instruments = [instrument if how == 'melody' else instrument[1] for key, (instrument, how) in model_workflow.items()]
LATENT_DIM = 256 # make_folder_if_not_exist(os.mkdir(os.path.join('models',EXPERIMENT_NAME)))
if EPOCHS == None:
EPOCHS = 1 found = False
if RESET == None: for instrument in instruments:
RESET = False
## TODO: raise error if file not found if INSTRUMENT == None or INSTRUMENT == instrument:
model_workflow = pickle.load(open(os.path.join('training_sets', EXPERIMENT_NAME, 'workflow.pkl'),'rb')) data_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument.lower() + '_data.pkl')
tbCallBack = keras.callbacks.TensorBoard(log_dir='./Graph', histogram_freq=0, write_graph=True, write_images=True) model_path = os.path.join('models', EXPERIMENT_NAME, f'{instrument.lower()}_model.h5')
instruments = [instrument if how == 'melody' else instrument[1] for key, (instrument, how) in model_workflow.items()] x_train, y_train, _ = pickle.load(open(data_path,'rb'))
model = Seq2SeqModel(LATENT_DIM, x_train, y_train)
if os.path.isfile(model_path) and not RESET:
model.load(model_path)
# make folder for new experiment print(f'Training: {instrument}')
try: model.fit(BATCH_SIZE, EPOCHS, callbacks=[])
os.mkdir(os.path.join('models',EXPERIMENT_NAME)) model.save(model_path)
except: found = True
pass
# init models if not found:
found = False raise ValueError(f'Instrument not found. Use one of the {instruments}')
for instrument in instruments:
if __name__ == '__main__':
if INSTRUMENT == None or INSTRUMENT == instrument: warnings.filterwarnings("ignore")
data_path = os.path.join('training_sets', EXPERIMENT_NAME, instrument.lower() + '_data.pkl') args = parse_argv()
model_path = os.path.join('models', EXPERIMENT_NAME, f'{instrument.lower()}_model.h5')
EXPERIMENT_NAME = args.n
BATCH_SIZE = args.b
LATENT_DIM = args.l
EPOCHS = args.e
RESET = args.r
INSTRUMENT = args.i
x_train, y_train, _ = pickle.load(open(data_path,'rb')) # default settings if not args passed
model = Seq2SeqModel(LATENT_DIM, x_train, y_train) if not BATCH_SIZE:
if os.path.isfile(model_path) and not RESET: BATCH_SIZE = 32
model.load(model_path) if not LATENT_DIM:
LATENT_DIM = 256
print(f'Training: {instrument}') if not EPOCHS:
train_history = model.fit(BATCH_SIZE, EPOCHS, callbacks=[tbCallBack]) EPOCHS = 1
model.save(model_path) if not RESET:
found = True RESET = False
if not found: train_models(load_workflow())
raise ValueError(f'Instrument not found. Use one of the {instruments}')