def pre_train(): print('### Generator MLE Pre-Train Mode ###') #--construct data loader--# data_loader = Data_Loader(config) vocab_size = data_loader.get_vocab_size() #--construct generator model--# GEN = Generator(config, vocab_size, build_train_op=True) #--tensorflow session--# with tf.Session() as sess: #--initialize training--# sess.run(tf.global_variables_initializer()) GEN = _check_restore_parameters(sess, model=GEN, specific_model=config.pre_train_model) history_loss = [] best_loss = 777.777 counter = 0 #--training epochs--# for epoch in range(config.pre_train_epochs): #--initialize epoch--# epoch_loss = [] data_loader.shuffle_data() #--run over all buckets--# bucket_ids = data_loader.shuffle_buckets() for bucket_n, bucket_id in enumerate(bucket_ids): #--run epoch on each bucket--# n_batch = 0 while (n_batch * config.batch_size ) < data_loader.get_bucket_len(bucket_id): #--get batch--# (batch_encoder_inputs, batch_decoder_inputs, decoder_masks) = data_loader.generator_get_batch( bucket_id=bucket_id, batch_id=n_batch, mode='pre_train') n_batch += 1 #--update--# step_loss = GEN.run_step( sess, batch_encoder_inputs, batch_decoder_inputs, decoder_masks, bucket_id, feed_previous= False, # >> in train mode, decoder_inputs are used as given, we dont feed the previous output, feed_previous=False add_reward=False, mc_search=False) #--print info--# epoch_loss.append(step_loss) print( 'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, cur_Loss: %.5f' % (epoch + 1, config.pre_train_epochs, bucket_n + 1, data_loader.get_num_buckets(), n_batch - 1, data_loader.get_bucket_len(bucket_id) / config.batch_size, step_loss), end='\r') #--epoch checkpoint--# history_loss.append(np.mean(epoch_loss)) best_loss, to_save = _model_checkpoint_save_best( best_val=best_loss, cur_val=history_loss[-1], mode='min') counter, to_stop = _model_checkpoint_earlystopping( counter=counter, reset=to_save, patient=config.patient) #--save best and show training info--# if config.force_save: to_save = True print( 'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, avg_Loss: %.5f, Saved: %s' % (epoch + 1, config.pre_train_epochs, data_loader.get_num_buckets(), data_loader.get_num_buckets(), n_batch - 1, n_batch - 1, history_loss[-1], 'True' if to_save else 'False')) #--save model and training log--# if to_save == True: GEN.saver.save(sess, os.path.join(config.model_dir, 'pre_train'), global_step=(epoch + 1)) pickle.dump( history_loss, open(os.path.join(config.model_dir, 'history_loss.pkl'), 'wb'), True) #--earlystopping--# if to_stop: break #--pre train end--# print('Pre-training process complete, model saved to: ', config.model_dir)
def chat(speak_with_audio=False, model_name=None): print('### Model Chat and Test Mode ###') #--enable audio mode--# if speak_with_audio: mixer.init() print('### Daisy Speak with Audio Response Mode Enabled ###') #--modify batch size--# config.batch_size = 1 #--construct data loader--# data_loader = Data_Loader(config, load_bucket=False) word2idx, idx2word = data_loader.get_mapping() vocab_size = data_loader.get_vocab_size() #--construct generator model--# GEN = Generator(config, vocab_size, build_train_op=False) #--tensorflow saver--# saver = tf.train.Saver() #--tensorflow session--# with tf.Session() as sess: #--initialize testing--# sess.run(tf.global_variables_initializer()) GEN = _check_restore_parameters(sess, model=GEN, specific_model=model_name) #--output file--# with open(os.path.join(config.data_dir, 'chat_dialog.txt'), 'w') as f: #--greeting message--# max_length = BUCKETS[-1][0] print('\nHi, my name is Daisy! Nice to meet you, let\'s chat!') print('(Input max length: %i, enter empty line to exit. )' % max_length) if speak_with_audio: _speak('Hi, my name is Daisy! Nice to meet you, let\'s chat!.') #--testing loop--# while True: #--decode from standard input--# line = _get_user_input() if len(line) > 0 and line[-1] == '\n': line = line[:-1] if line == '': print('Bye!') if speak_with_audio: _speak('Bye!') break #--record human input--# f.write('HUMAN +++++++ ' + line + '\n') #--get token-ids for the input sentence--# token_ids = _sentence2id(word2idx, line) if (len(token_ids) > max_length): print( 'Max length I can handle is: %i, tell me something else.' % max_length) line = _get_user_input() continue #--feed input line to the right bucket--# bucket_id = _find_right_bucket(len(token_ids)) #--get a 1-element batch to feed the sentence to the model--# ( chat_encoder_inputs, chat_decoder_inputs, decoder_masks, ) = data_loader.generator_get_batch(bucket_id=bucket_id, mode='chat', chat_input=[ token_ids, ]) #--get output logits for the sentence--# _, _, output_logits = GEN.run_step( sess, chat_encoder_inputs, chat_decoder_inputs, decoder_masks, bucket_id, feed_previous= True, # >> in chat mode, we feed forward the previous outputs. add_reward=False, mc_search=False) #--construct response--# response = _construct_response(output_logits, dec_vocab=idx2word, eos_id=config.EOS_ID) print('DAISY +++++++ ', response) if speak_with_audio: _speak(response) #--record machine response--# f.write('DAISY +++++++ ' + response + '\n') f.write('=============================================\n')
def gan_train(): print( '### Generative Adversarial Training with Reinforcement Learning Mode ###' ) #--construct data loader--# data_loader = Data_Loader(config) vocab_size = data_loader.get_vocab_size() #--construct generator and discriminator model--# GEN = Generator(config, vocab_size, build_train_op=True) DIS = Discriminator(config, vocab_size) #--tensorflow session--# with tf.Session() as sess: #--initialize training--# sess.run(tf.global_variables_initializer()) GEN = _check_restore_parameters(sess, model=GEN, specific_model=config.gan_train_model) dis_history_loss = [] gen_history_loss = [] tf_history_loss = [] r_history_loss = [] best_loss = 777.777 counter = 0 #--training epochs--# for epoch in range(config.gan_train_epochs): #--initialize epoch--# dis_epoch_loss = [] gen_epoch_loss = [] tf_epoch_loss = [] r_epoch_loss = [] data_loader.shuffle_data() #--run over all buckets--# bucket_ids = data_loader.shuffle_buckets() for bucket_n, bucket_id in enumerate(bucket_ids): #--run epoch on each bucket--# n_batch = 0 while (n_batch * config.batch_size ) < data_loader.get_bucket_len(bucket_id): #---Update Discriminator---# for _ in range(config.update_d): #--get batch--# ( batch_encoder_inputs, batch_decoder_inputs, decoder_masks, encoder_inputs, decoder_inputs, ) = data_loader.generator_get_batch( bucket_id=bucket_id, batch_id=n_batch, mode='gan_train') n_batch += 1 #--gather (X,Y) and sample (X, ^Y) through ^Y ~ G(*|X)--# train_query, train_answer, train_labels = GEN.sample( sess, batch_encoder_inputs, batch_decoder_inputs, decoder_masks, encoder_inputs, decoder_inputs, bucket_id, mc_search=False) #--update D using (X, Y) as positive examples and (X, ^Y) as negative examples--# _, dis_step_loss = DIS.run_step( sess, train_query, train_answer, train_labels, bucket_id, train=True) # >> This trains the discriminator #--record--# dis_epoch_loss.append(dis_step_loss) #---Update Generator---# for _ in range(config.update_g): #--gather (X,Y) and sample (X, ^Y) through ^Y ~ G(*|X) with Monte Carlo search--# train_query, train_answer, train_labels = GEN.sample( sess, batch_encoder_inputs, batch_decoder_inputs, decoder_masks, encoder_inputs, decoder_inputs, bucket_id, mc_search=True) #--compute reward r for (X, ^Y ) using D based on monte carlo search--# reward, _ = DIS.run_step( sess, train_query, train_answer, train_labels, bucket_id, train=False ) # >> This does not train the discriminator #--update G on (X, ^Y ) using reward r--# gen_step_loss = GEN.run_step( sess, batch_encoder_inputs, batch_decoder_inputs, decoder_masks, bucket_id, reward=reward, feed_previous=False, add_reward=True, # >> add reward mc_search=False) #--teacher forcing: update G on (X, Y)--# tf_step_loss = GEN.run_step(sess, batch_encoder_inputs, batch_decoder_inputs, decoder_masks, bucket_id, reward=None, feed_previous=False, add_reward=False, mc_search=False) #--record--# gen_epoch_loss.append(gen_step_loss) tf_epoch_loss.append(tf_step_loss) r_epoch_loss.append(reward) #--print info--# print( 'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, Reward: %.5f, dis_Loss: %.5f, gen_Loss: %.5f, tf_Loss: %.5f' % (epoch + 1, config.gan_train_epochs, bucket_n + 1, data_loader.get_num_buckets(), n_batch - 1, data_loader.get_bucket_len(bucket_id) / config.batch_size, reward, dis_step_loss, gen_step_loss, tf_step_loss), end='\r') #--epoch checkpoint--# dis_history_loss.append(np.mean(dis_epoch_loss)) gen_history_loss.append(np.mean(gen_epoch_loss)) tf_history_loss.append(np.mean(tf_epoch_loss)) r_history_loss.append(np.mean(r_epoch_loss)) best_loss, to_save = _model_checkpoint_save_best( best_val=best_loss, cur_val=tf_history_loss[-1], mode='min') counter, to_stop = _model_checkpoint_earlystopping( counter=counter, reset=to_save, patient=config.patient) #--save best and show training info--# if config.force_save: to_save = True print( 'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, Reward: %.5f, dis_Loss: %.5f, gen_Loss: %.5f, tf_Loss: %.5f, Saved: %s' % (epoch + 1, config.gan_train_epochs, data_loader.get_num_buckets(), data_loader.get_num_buckets(), n_batch - 1, n_batch - 1, r_history_loss[-1], dis_history_loss[-1], gen_history_loss[-1], tf_history_loss[-1], 'True' if to_save else 'False')) #--save model and training log--# if to_save == True: DIS.saver.save(sess, os.path.join(config.model_dir, 'gan_dis_model'), global_step=(epoch + 1)) GEN.saver.save(sess, os.path.join(config.model_dir, 'gan_gen_model'), global_step=(epoch + 1)) pickle.dump( dis_history_loss, open( os.path.join(config.model_dir, 'dis_history_loss.pkl'), 'wb'), True) pickle.dump( gen_history_loss, open( os.path.join(config.model_dir, 'gen_history_loss.pkl'), 'wb'), True) pickle.dump( tf_history_loss, open(os.path.join(config.model_dir, 'tf_history_loss.pkl'), 'wb'), True) pickle.dump( r_history_loss, open(os.path.join(config.model_dir, 'r_history_loss.pkl'), 'wb'), True) #--earlystopping--# # if to_stop: break if r_history_loss[-1] < 0.00000001 and r_history_loss[ -2] < 0.00000001: break #--pre train end--# print( 'Generative Adversarial Training process complete, model saved to: ', config.model_dir)
def evaluate(model_name): print('### Model Chat and Test Mode ###') #--construct data loader--# data_loader = Data_Loader(config, load_for_test=True) word2idx, idx2word = data_loader.get_mapping() vocab_size = data_loader.get_vocab_size() #--get testing data--# test_input, test_output = data_loader.get_test_data() #--truncate test data size--# n_batch_for_test = 100 if len(test_input) > config.batch_size * n_batch_for_test: test_input = test_input[:config.batch_size * n_batch_for_test] test_output = test_output[:config.batch_size * n_batch_for_test] #--construct generator model--# GEN = Generator(config, vocab_size, build_train_op=False) #--tensorflow saver--# saver = tf.train.Saver() #--tensorflow session--# with tf.Session() as sess: #--initialize testing--# eval_output = [] max_length = BUCKETS[0][ 0] - 2 # >> the first bucket but without <bos> and <eos> tokens, therefor - 2 sess.run(tf.global_variables_initializer()) GEN = _check_restore_parameters(sess, model=GEN, specific_model=model_name) #--run over all inputs--# n_batch = 0 while (n_batch * config.batch_size) < len(test_input): #--take 'batch_size' lines--# batch_inputs = [] batch_range = np.arange( (n_batch * config.batch_size), (n_batch * config.batch_size + config.batch_size)) for cnt, i in enumerate(batch_range): idx = i % len(test_input) # bound idx when i > data_length batch_inputs.append(_sentence2id(word2idx, test_input[idx])) n_batch += 1 #--get a 1-element batch to feed the sentence to the model--# ( chat_encoder_inputs, chat_decoder_inputs, decoder_masks, ) = data_loader.generator_get_batch(bucket_id=0, mode='chat', chat_input=batch_inputs) #--get output logits for the sentence--# _, _, output_logits = GEN.run_step( sess, chat_encoder_inputs, chat_decoder_inputs, decoder_masks, bucket_id=0, feed_previous= True, # >> in chat mode, we feed forward the previous outputs. add_reward=False, mc_search=False) output_logits = np.asarray(output_logits) #--construct response--# for i in range(config.batch_size): line = np.expand_dims(output_logits[:, i, :], axis=1) response = _construct_response(line, dec_vocab=idx2word, eos_id=config.EOS_ID) eval_output.append(response) print('Evaluation Batch: %i/%i' % (n_batch - 1, len(test_input) / config.batch_size), end='\r') print('Evaluation Batch: %i/%i' % (n_batch, len(test_input) / config.batch_size)) assert len(eval_output) == len(test_input) #--count BLEU score by average--# bleu = [] for i, eval_line in enumerate(eval_output): score_per_line = [] for test_line in test_output: score_per_line.append(_BLEU(eval_line, test_line)) bleu.append(np.mean(score_per_line)) print('BLEU evaluation: %i/%i' % (i, len(eval_output)), end='\r') print('BLEU evaluation: %i/%i' % (len(eval_output), len(eval_output))) average = np.mean(bleu) print("Originally, average bleu score is " + str(average)) """