def train(type_, epochs=epochs, checkpoint=False): tf.reset_default_graph() if type_ == "forward": path = "model/forward/seq2seq" dr = Data_Reader(reverse=False) else: dr = Data_Reader(reverse=True) path = "model/reverse/seq2seq" word_to_index, index_to_word, _ = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) word_vector = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) model = Chatbot(dim_wordvec, len(word_to_index), dim_hidden, batch_size, input_sequence_length, output_sequence_length, learning_rate) optimizer, place_holders, predictions, logits, losses = model.build_model() saver = tf.train.Saver() sess = tf.InteractiveSession() if checkpoint: saver.restore(sess, path) print("checkpoint restored at path: {}".format(path)) else: tf.global_variables_initializer().run() for epoch in range(epochs): n_batch = dr.get_batch_num(batch_size=batch_size) for batch in range(n_batch): batch_input, batch_target = dr.generate_training_batch(batch_size) inputs_ = h.make_batch_input(batch_input, input_sequence_length, dim_wordvec, word_vector) targets, masks = h.make_batch_target(batch_target, word_to_index, output_sequence_length) feed_dict = { place_holders['word_vectors']: inputs_, place_holders['caption']: targets, place_holders['caption_mask']: masks } _, loss_val, preds = sess.run( [optimizer, losses["entropy"], predictions], feed_dict=feed_dict) if batch % display_interval == 0: print(preds.shape) print("Epoch: {}, batch: {}, loss: {}".format( epoch, batch, loss_val)) print( "===========================================================" ) saver.save(sess, path) print("Model saved at {}".format(path)) print("Training done") sess.close()
def test(model_path=forward_model_path): testing_data = open(path_to_questions, 'r').read().split('\n') word_vector = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) _, index_to_word, _ = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) model = Chatbot(dim_wordvec, len(index_to_word), dim_hidden, batch_size, input_sequence_length, target_sequence_length, Training=False) place_holders, predictions, logits = model.build_model() sess = tf.InteractiveSession() saver = tf.train.Saver() saver.restore(sess, model_path) with open(responses_path, 'w') as out: for idx, question in enumerate(testing_data): print('question =>', question) question = [h.refine(w) for w in question.lower().split()] question = [ word_vector[w] if w in word_vector else np.zeros(dim_wordvec) for w in question ] question.insert(0, np.random.normal(size=( dim_wordvec, ))) # insert random normal at the first step if len(question) > input_sequence_length: question = question[:input_sequence_length] else: for _ in range(input_sequence_length - len(question)): question.append(np.zeros(dim_wordvec)) question = np.array([question]) feed_dict = { place_holders["word_vectors"]: np.concatenate([question] * 2, 0), } word_indices, prob_logit = sess.run([predictions, logits], feed_dict=feed_dict) # print(word_indices[0].shape) generated_sentence = h.index2sentence(word_indices[0], prob_logit[0], index_to_word) print('generated_sentence =>', generated_sentence) out.write(generated_sentence + '\n')
def test(model_path=default_model_path): testing_data = open(testing_data_path, 'r').read().split('\n') word_vector = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) _, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) model = PolicyGradient_chatbot(dim_wordvec=dim_wordvec, n_words=len(ixtoword), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector) word_vectors, caption_tf, feats = model.build_generator() sess = tf.InteractiveSession() saver = tf.train.Saver() try: print('\n=== Use model', model_path, '===\n') saver.restore(sess, model_path) except: print('\nUse default model\n') saver.restore(sess, default_model_path) with open(output_path, 'w') as out: generated_sentences = [] bleu_score_avg = [0., 0.] for idx, question in enumerate(testing_data): print('question =>', question) question = [refine(w) for w in question.lower().split()] question = [ word_vector[w] if w in word_vector else np.zeros(dim_wordvec) for w in question ] question.insert(0, np.random.normal(size=( dim_wordvec, ))) # insert random normal at the first step if len(question) > n_encode_lstm_step: question = question[:n_encode_lstm_step] else: for _ in range(len(question), n_encode_lstm_step): question.append(np.zeros(dim_wordvec)) question = np.array([question]) # 1x22x300 generated_word_index, prob_logit = sess.run( [caption_tf, feats['probs']], feed_dict={word_vectors: question}) generated_word_index = np.array(generated_word_index).reshape( batch_size, n_decode_lstm_step)[0] prob_logit = np.array(prob_logit).reshape(batch_size, n_decode_lstm_step, -1)[0] # print('generated_word_index.shape', generated_word_index.shape) # print('prob_logit.shape', prob_logit.shape) # remove <unk> to second high prob. word # print('generated_word_index', generated_word_index) for i in range(len(generated_word_index)): if generated_word_index[i] == 3: sort_prob_logit = sorted(prob_logit[i]) # print('max val', sort_prob_logit[-1]) # print('second max val', sort_prob_logit[-2]) maxindex = np.where( prob_logit[i] == sort_prob_logit[-1])[0][0] secmaxindex = np.where( prob_logit[i] == sort_prob_logit[-2])[0][0] # print('max ind', maxindex, ixtoword[maxindex]) # print('second max ind', secmaxindex, ixtoword[secmaxindex]) generated_word_index[i] = secmaxindex # print('generated_word_index', generated_word_index) generated_words = [] for ind in generated_word_index: generated_words.append(ixtoword[ind]) # generate sentence punctuation = np.argmax(np.array(generated_words) == '<eos>') + 1 generated_words = generated_words[:punctuation] generated_sentence = ' '.join(generated_words) # modify the output sentence generated_sentence = generated_sentence.replace('<bos> ', '') generated_sentence = generated_sentence.replace(' <eos>', '') generated_sentence = generated_sentence.replace('--', '') generated_sentence = generated_sentence.split(' ') for i in range(len(generated_sentence)): generated_sentence[i] = generated_sentence[i].strip() if len(generated_sentence[i]) > 1: generated_sentence[i] = generated_sentence[i][0].upper( ) + generated_sentence[i][1:] + '.' else: generated_sentence[i] = generated_sentence[i].upper() generated_sentence = ' '.join(generated_sentence) generated_sentence = generated_sentence.replace(' i ', ' I ') generated_sentence = generated_sentence.replace("i'm", "I'm") generated_sentence = generated_sentence.replace("i'd", "I'd") generated_sentence = generated_sentence.replace("i'll", "I'll") generated_sentence = generated_sentence.replace("i'v", "I'v") generated_sentence = generated_sentence.replace(" - ", "") print('generated_sentence =>', generated_sentence) out.write(generated_sentence + '\n')
def pg_train(epochs=epochs, checkpoint=False): tf.reset_default_graph() path = "model/reinforcement/seq2seq" word_to_indedx, index_to_word, _ = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) word_vectors = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) generic_caption, generic_mask = h.generic_batch(generic_responses, batch_size, word_to_indedx, output_sequence_length) # dr = Data_Reader() forward_graph = tf.Graph() reverse_graph = tf.Graph() default_graph = tf.get_default_graph() with forward_graph.as_default(): pg_model = Chatbot(dim_word_vec, len(word_to_indedx), dim_hidden, batch_size, input_sequence_length, output_sequence_length, learning_rate, policy_gradients=True) optimizer, place_holders, predictions, logits, losses = pg_model.build_model( ) sess = tf.InteractiveSession() saver = tf.train.Saver() if checkpoint: saver.restore(sess, path) print("checkpoint restored at path: {}".format(path)) else: tf.global_variables_initializer().run() saver.restore(sess, 'model/forward/seq2seq') with reverse_graph.as_default(): model = Chatbot(dim_word_vec, len(word_to_indedx), dim_hidden, batch_size, input_sequence_length, output_sequence_length, learning_rate) _, rev_place_holders, _, _, reverse_loss = model.build_model() sess2 = tf.InteractiveSession() saver2 = tf.train.Saver() saver2.restore(sess2, "model/reverse/seq2seq") print("reverse model restored") dr = Data_Reader(load_list=True) for epoch in range(epochs): n_batch = dr.get_batch_num(batch_size=batch_size) for batch in range(n_batch): # kv note batch_input, batch_caption, prev_utterance = dr.generate_training_batch_with_former( batch_size) if batch == 1: print('batch_input: {}'.format(batch_input[0])) print('batch_target: {}'.format(batch_caption[0])) targets, masks = h.make_batch_target(batch_caption, word_to_indedx, output_sequence_length) inputs_ = h.make_batch_input(batch_input, input_sequence_length, dim_word_vec, word_vectors) word_indices, probabilities = sess.run( [predictions, logits], feed_dict={ place_holders['word_vectors']: inputs_, place_holders['caption']: targets }) sentence = [ h.index2sentence(generated_word, probability, index_to_word) for generated_word, probability in zip(word_indices, probabilities) ] word_list = [word.split() for word in sentence] generic_test_input = h.make_batch_input(word_list, input_sequence_length, dim_word_vec, word_vectors) forward_coherence_target, forward_coherence_masks = h.make_batch_target( sentence, word_to_indedx, output_sequence_length) generic_loss = 0.0 for response in generic_test_input: sentence_input = np.array([response] * batch_size) feed_dict = { place_holders['word_vectors']: sentence_input, place_holders['caption']: generic_caption, place_holders['caption_mask']: generic_mask } generic_loss_i = sess.run(losses['entropy'], feed_dict=feed_dict) generic_loss -= generic_loss_i / batch_size # print ("generic loss work: {}". format (generic_loss) ) feed_dict = { place_holders['word_vectors']: inputs_, place_holders['caption']: forward_coherence_target, place_holders['caption_mask']: forward_coherence_masks } forward_entropy = sess.run(losses["entropy"], feed_dict=feed_dict) previous_utterance, previous_mask = h.make_batch_target( prev_utterance, word_to_indedx, output_sequence_length) feed_dict = { rev_place_holders['word_vectors']: generic_test_input, rev_place_holders['caption']: previous_utterance, rev_place_holders['caption_mask']: previous_mask, } reverse_entropy = sess2.run(reverse_loss["entropy"], feed_dict=feed_dict) rewards = 1 / ( 1 + np.exp(-reverse_entropy - forward_entropy - generic_loss)) feed_dict = { place_holders['word_vectors']: inputs_, place_holders['caption']: targets, place_holders['caption_mask']: masks, place_holders['rewards']: rewards } _, loss_pg, loss_ent = sess.run( [optimizer, losses["pg"], losses["entropy"]], feed_dict=feed_dict) if batch % display_interval == 0: print( "Epoch: {}, batch: {}, Entropy loss: {}, Policy gradient loss: {}" .format(epoch, batch, loss_ent, loss_pg)) print("rewards: {}".format(rewards)) saver.save(sess, path) print("Model saved add {}".format(path)) print("Training done")
def train(): global dull_set wordtoix, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) word_vector = KeyedVectors.load_word2vec_format('./model/word_vector.bin', binary=True) if len(dull_set) > batch_size: dull_set = dull_set[:batch_size] else: for _ in range(len(dull_set), batch_size): dull_set.append('') dull_matrix, dull_mask = make_batch_Y( batch_Y=dull_set, wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) ones_reward = np.ones([batch_size, n_decode_lstm_step]) g1 = tf.Graph() g2 = tf.Graph() default_graph = tf.get_default_graph() with g1.as_default(): model = PolicyGradient_chatbot(dim_wordvec=dim_wordvec, n_words=len(wordtoix), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector, lr=learning_rate) train_op, loss, input_tensors, inter_value = model.build_model() tf_states, tf_actions, tf_feats = model.build_generator() sess = tf.InteractiveSession() saver = tf.train.Saver(max_to_keep=100) if checkpoint: print("Use Model {}.".format(model_name)) saver.restore(sess, os.path.join(model_path, model_name)) print("Model {} restored.".format(model_name)) else: print("Restart training...") tf.global_variables_initializer().run() r_wordtoix, r_ixtoword, r_bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=r_word_count_threshold) with g2.as_default(): reversed_model = Seq2Seq_chatbot( dim_wordvec=dim_wordvec, n_words=len(r_wordtoix), dim_hidden=dim_hidden, batch_size=reversed_batch_size, n_encode_lstm_step=r_n_encode_lstm_step, n_decode_lstm_step=r_n_decode_lstm_step, bias_init_vector=r_bias_init_vector, lr=learning_rate) _, _, word_vectors, caption, caption_mask, reverse_inter = reversed_model.build_model( ) sess2 = tf.InteractiveSession() saver2 = tf.train.Saver() saver2.restore(sess2, os.path.join(reversed_model_path, reversed_model_name)) print("Reversed model {} restored.".format(reversed_model_name)) # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.5) # sess = tf.InteractiveSession() dr = Data_Reader(cur_train_index=config.cur_train_index, load_list=config.load_list) for epoch in range(start_epoch, epochs): n_batch = dr.get_batch_num(batch_size) sb = start_batch if epoch == start_epoch else 0 for batch in range(sb, n_batch): start_time = time.time() batch_X, batch_Y, former = dr.generate_training_batch_with_former( batch_size) current_feats = make_batch_X(batch_X=copy.deepcopy(batch_X), n_encode_lstm_step=n_encode_lstm_step, dim_wordvec=dim_wordvec, word_vector=word_vector) current_caption_matrix, current_caption_masks = make_batch_Y( batch_Y=copy.deepcopy(batch_Y), wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) if training_type == 'pg': # action: generate batch_size sents action_word_indexs, inference_feats = sess.run( [tf_actions, tf_feats], feed_dict={tf_states: current_feats}) action_word_indexs = np.array(action_word_indexs).reshape( batch_size, n_decode_lstm_step) action_probs = np.array(inference_feats['probs']).reshape( batch_size, n_decode_lstm_step, -1) actions = [] actions_list = [] for i in range(len(action_word_indexs)): action = index2sentence( generated_word_index=action_word_indexs[i], prob_logit=action_probs[i], ixtoword=ixtoword) actions.append(action) actions_list.append(action.split()) action_feats = make_batch_X( batch_X=copy.deepcopy(actions_list), n_encode_lstm_step=n_encode_lstm_step, dim_wordvec=dim_wordvec, word_vector=word_vector) action_caption_matrix, action_caption_masks = make_batch_Y( batch_Y=copy.deepcopy(actions), wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) # ease of answering dull_loss = [] for vector in action_feats: action_batch_X = np.array( [vector for _ in range(batch_size)]) d_loss = sess.run(loss, feed_dict={ input_tensors['word_vectors']: action_batch_X, input_tensors['caption']: dull_matrix, input_tensors['caption_mask']: dull_mask, input_tensors['reward']: ones_reward }) d_loss = d_loss * -1. / len(dull_set) dull_loss.append(d_loss) # Information Flow pass # semantic coherence forward_inter = sess.run(inter_value, feed_dict={ input_tensors['word_vectors']: current_feats, input_tensors['caption']: action_caption_matrix, input_tensors['caption_mask']: action_caption_masks, input_tensors['reward']: ones_reward }) forward_entropies = forward_inter['entropies'] former_caption_matrix, former_caption_masks = make_batch_Y( batch_Y=copy.deepcopy(former), wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) action_feats = make_batch_X( batch_X=copy.deepcopy(actions_list), n_encode_lstm_step=r_n_encode_lstm_step, dim_wordvec=dim_wordvec, word_vector=word_vector) backward_inter = sess2.run(reverse_inter, feed_dict={ word_vectors: action_feats, caption: former_caption_matrix, caption_mask: former_caption_masks }) backward_entropies = backward_inter['entropies'] # reward: count goodness of actions rewards = count_rewards(dull_loss, forward_entropies, backward_entropies, actions, former, reward_type='pg') # policy gradient: train batch with rewards if batch % 10 == 0: _, loss_val = sess.run( [train_op, loss], feed_dict={ input_tensors['word_vectors']: current_feats, input_tensors['caption']: current_caption_matrix, input_tensors['caption_mask']: current_caption_masks, input_tensors['reward']: rewards }) print("Epoch: {}, batch: {}, loss: {}, Elapsed time: {}". format(epoch, batch, loss_val, time.time() - start_time)) else: _ = sess.run(train_op, feed_dict={ input_tensors['word_vectors']: current_feats, input_tensors['caption']: current_caption_matrix, input_tensors['caption_mask']: current_caption_masks, input_tensors['reward']: rewards }) if batch % 1000 == 0 and batch != 0: print("Epoch {} batch {} is done. Saving the model ...". format(epoch, batch)) saver.save( sess, os.path.join(model_path, 'model-{}-{}'.format(epoch, batch))) if training_type == 'normal': if batch % 10 == 0: _, loss_val = sess.run( [train_op, loss], feed_dict={ input_tensors['word_vectors']: current_feats, input_tensors['caption']: current_caption_matrix, input_tensors['caption_mask']: current_caption_masks, input_tensors['reward']: ones_reward }) print("Epoch: {}, batch: {}, loss: {}, Elapsed time: {}". format(epoch, batch, loss_val, time.time() - start_time)) else: _ = sess.run(train_op, feed_dict={ input_tensors['word_vectors']: current_feats, input_tensors['caption']: current_caption_matrix, input_tensors['caption_mask']: current_caption_masks, input_tensors['reward']: ones_reward }) print("Epoch ", epoch, " is done. Saving the model ...") saver.save(sess, os.path.join(model_path, 'model'), global_step=epoch)
def test(model_path=default_model_path): testing_data = open(testing_data_path, 'r').read().strip().split('\n') logger.info('number of input sentences: %d' % len(testing_data)) word_vector = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) _, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) model = Seq2Seq_chatbot(dim_wordvec=dim_wordvec, n_words=len(ixtoword), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector) word_vectors, caption_tf, probs, _ = model.build_generator() sess = tf.InteractiveSession() saver = tf.train.Saver() try: logger.info('\n=== Use model: %s ====' % model_path) saver.restore(sess, model_path) except: logger.info('\nUse default model\n') saver.restore(sess, default_model_path) with open(output_path, 'w') as out: generated_sentences = [] count = 0 for idx, question in enumerate(testing_data): if len(question) == 0: continue logger.info('question => %s' % question) question = [refine(w) for w in question.lower().split()] question = [ word_vector[w] if w in word_vector else np.zeros(dim_wordvec) for w in question ] question.insert(0, np.random.normal(size=( dim_wordvec, ))) # insert random normal at the first step if len(question) > n_encode_lstm_step: question = question[:n_encode_lstm_step] else: for _ in range(len(question), n_encode_lstm_step): question.append(np.zeros(dim_wordvec)) question = np.array([question]) # 1x22x300 generated_word_index, prob_logit = sess.run( [caption_tf, probs], feed_dict={word_vectors: question}) # remove <unk> to second high prob. word for i in range(len(generated_word_index)): if generated_word_index[i] == 3: sort_prob_logit = sorted(prob_logit[i][0]) maxindex = np.where( prob_logit[i][0] == sort_prob_logit[-1])[0][0] secmaxindex = np.where( prob_logit[i][0] == sort_prob_logit[-2])[0][0] generated_word_index[i] = secmaxindex generated_words = [] for ind in generated_word_index: generated_words.append(ixtoword[ind]) # generate sentence punctuation = np.argmax(np.array(generated_words) == '<eos>') + 1 generated_words = generated_words[:punctuation] generated_sentence = ' '.join(generated_words) # modify the output sentence generated_sentence = generated_sentence.replace('<bos> ', '') generated_sentence = generated_sentence.replace(' <eos>', '') generated_sentence = generated_sentence.replace('--', '') generated_sentence = generated_sentence.split(' ') for i in range(len(generated_sentence)): generated_sentence[i] = generated_sentence[i].strip() if len(generated_sentence[i]) > 1: generated_sentence[i] = generated_sentence[i][0].upper( ) + generated_sentence[i][1:] + '.' else: generated_sentence[i] = generated_sentence[i].upper() generated_sentence = ' '.join(generated_sentence) generated_sentence = generated_sentence.replace(' i ', ' I ') generated_sentence = generated_sentence.replace("i'm", "I'm") generated_sentence = generated_sentence.replace("i'd", "I'd") generated_sentence = generated_sentence.replace("i'll", "I'll") generated_sentence = generated_sentence.replace("i'v", "I'v") generated_sentence = generated_sentence.replace(" - ", "") logger.info('generated_sentence => %s' % generated_sentence) logger.info('\n') out.write(generated_sentence + '\n') count += 1 logger.info('number of answered quesitons: %d' % d) logger.info('Done! also check: %s' % output_path)
def simulate(model_path=default_model_path, simulate_type=default_simulate_type): ''' args: model_path: <type 'str'> the pre-trained model using for inference simulate_type: <type 'int'> how many former sents should use as state ''' testing_data = open(testing_data_path, 'r').read().split('\n') word_vector = KeyedVectors.load_word2vec_format('./model/word_vector.bin', binary=True) _, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) model = Seq2Seq_chatbot(dim_wordvec=dim_wordvec, n_words=len(ixtoword), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector) word_vectors, caption_tf, probs, _ = model.build_generator() sess = tf.InteractiveSession() saver = tf.train.Saver() try: print('\n=== Use model {} ===\n'.format(model_path)) saver.restore(sess, model_path) except: print('\nUse default model\n') saver.restore(sess, default_model_path) with open(output_path, 'w') as out: for idx, start_sentence in enumerate(testing_data): print('dialog {}'.format(idx)) print('A => {}'.format(start_sentence)) out.write('dialog {}\nA: {}\n'.format(idx, start_sentence)) dialog_history = init_history(simulate_type, start_sentence) for turn in range(max_turns): question = generate_question_vector( state=get_cur_state(simulate_type, dialog_history), word_vector=word_vector, dim_wordvec=dim_wordvec, n_encode_lstm_step=n_encode_lstm_step) generated_word_index, prob_logit = sess.run( [caption_tf, probs], feed_dict={word_vectors: question}) generated_sentence = generate_answer_sentence( generated_word_index=generated_word_index, prob_logit=prob_logit, ixtoword=ixtoword) dialog_history.append(generated_sentence) print('B => {}'.format(generated_sentence)) question_2 = generate_question_vector( state=get_cur_state(simulate_type, dialog_history), word_vector=word_vector, dim_wordvec=dim_wordvec, n_encode_lstm_step=n_encode_lstm_step) generated_word_index, prob_logit = sess.run( [caption_tf, probs], feed_dict={word_vectors: question_2}) generated_sentence_2 = generate_answer_sentence( generated_word_index=generated_word_index, prob_logit=prob_logit, ixtoword=ixtoword) dialog_history.append(generated_sentence_2) print('A => {}'.format(generated_sentence_2)) out.write('B: {}\nA: {}\n'.format(generated_sentence, generated_sentence_2))
def test(): """ Test procedure :return: no return """ ''' load dictionary ''' word_vector = KeyedVectors.load_word2vec_format(pre_train_emb, binary=True) w2i, i2w, bias_init_vector = data_parser.preProBuildWordVocab(word_count_threshold=word_count_threshold) ''' build tf model, saver ''' if TYPE_OF_OUR_MODEL in model_type: chat_model = model_proto( dim_wordvec=dim_wordvec, n_words=len(i2w), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector, ex_batch=1) else: chat_model = model_proto( dim_wordvec=dim_wordvec, n_words=len(i2w), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector) chat_model.build_generator() # build saver and restore checkpoint saver = tf.train.Saver() model_position = os.path.join(model_path, 'model-{}'.format(checkpoint)) print('\n=== Use model', model_position, '===\n') saver.restore(SESS, model_position) ''' open read and write path ''' dr = Data_Reader(test_data_path) n_batch = dr.get_batch_num(batch_size) query_out = open(test_out_path + '.query', 'w') reference_out = open(test_out_path + '.reference', 'w') generate_out = open(test_out_path + '.generate', 'w') ''' running batches ''' start_time = time.time() print('total batch:', n_batch) for batch in range(n_batch): ''' build data ''' batch_x, batch_y, _, kw = dr.generate_training_batch_with_former(batch_size) if model_type == 'rev': tmp = batch_x batch_x = batch_y batch_y = tmp ''' generation procedure for this batch ''' feats = make_batch_X(batch_x, n_encode_lstm_step, dim_wordvec, word_vector) generated_words_index, _ = chat_model.test(SESS, (feats, kw), word_vector) # 提取信息,以供输出 for idx, (x, y, gw) in enumerate(zip(batch_x, batch_y, generated_words_index)): words = [] for index in gw: if index == 2: break words.append(i2w[index].decode("utf-8")) sent = ' '.join(words) assert type(sent) == unicode query_out.write(x) query_out.write('\n') reference_out.write(y) reference_out.write('\n') generate_out.write(sent.encode('utf-8')) generate_out.write('\n') # 输出计数,让运行程序的人把握时间 if batch % print_every == 0: print(batch) query_out.close() reference_out.close() generate_out.close() print('cost time: {}'.format(time.time() - start_time))
def train(checkpoint = False): global dull_set wordtoix, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab(word_count_threshold=word_count_threshold) word_vector = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) #ixtoword is a dictionary that returns a word in the vocabulary for every index #bias_init_vector returns a bias vector for every word to based on relative frequencies if len(dull_set) > batch_size: dull_set = dull_set[:batch_size] else: for _ in range(len(dull_set), batch_size): dull_set.append('') #Truncate the dull set to the batch size else fill with null strings dull_matrix, dull_mask = make_batch_Y( batch_Y=dull_set, wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) #Returns the caption matrix and mask for the dull set ones_reward = np.ones([batch_size, n_decode_lstm_step]) g = tf.Graph() #Policy gradient model graph g2 = tf.Graph() #seq2seq reverse model graph default_graph = tf.get_default_graph() with g.as_default(): model = PolicyGradientDialogue( dim_wordvec,dim_hidden, len(wordtoix),batch_size, n_encode_lstm_step, n_decode_lstm_step, bias_init_vector, learning_rate) saver = tf.train.Saver(max_to_keep=100) sess = tf.InteractiveSession() train_op, loss, input_tensors, inter_value = model.build_model() tf_states, tf_actions, tf_feats = model.build_generator() tf.global_variables_initializer().run() if checkpoint: #Use checkpoint to resume from a pretrained state or restart training print("Use Model {}.".format(model_name)) saver.restore(sess, os.path.join(model_path, model_name)) print("Model {} restored.".format(model_name)) else: print("Restart training...") tf.global_variables_initializer().run() r_wordtoix, r_ixtoword, r_bias_init_vector = data_parser.preProBuildWordVocab(word_count_threshold=r_word_count_threshold) """ This module uses the the trained sequence to sequence model to reverse ...A seperate graph and a separate session """ with g2.as_default(): reversed_model = Seq2Seq_chatbot( dim_wordvec=dim_wordvec, n_words=len(r_wordtoix), dim_hidden=dim_hidden, batch_size=reversed_batch_size, n_encode_lstm_step=r_n_encode_lstm_step, n_decode_lstm_step=r_n_decode_lstm_step, bias_init_vector=r_bias_init_vector, lr=learning_rate) _, _, word_vectors, caption, caption_mask, reverse_inter = reversed_model.build_model() sess2 = tf.InteractiveSession() saver2 = tf.train.Saver() if Path(os.path.join(reversed_model_path, reversed_model_name)).exists(): saver2.restore(sess2, os.path.join(reversed_model_path, reversed_model_name)) print("Reversed model {} restored.".format(reversed_model_name)) else: tf.global_variables_initializer().run() dr = Data_Reader(cur_train_index=cur_train_index, load_list=False) for epoch in range(start_epoch, epochs): n_batch = dr.get_batch_num(batch_size) #Number of batches sb = start_batch if epoch == start_epoch else 0 for batch in range(sb, n_batch): start_time = time.time() batch_X, batch_Y, former = dr.generate_training_batch_with_former(batch_size) #generates a batch of the given size from the training data set current_feats = make_batch_X( batch_X=copy.deepcopy(batch_X), n_steps_encode=n_encode_lstm_step, dim_wordvec=dim_wordvec, word_vector=word_vector) current_caption_matrix, current_caption_masks = make_batch_Y( batch_Y=copy.deepcopy(batch_Y), wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) """Generate actions(responses) for the state of the dialogue""" action_word_indexs, inference_feats = sess.run([tf_actions, tf_feats], feed_dict={ tf_states: current_feats }) action_word_indexs = np.array(action_word_indexs).reshape(batch_size, n_decode_lstm_step) #Predicted words at each time step action_probs = np.array(inference_feats['probs']).reshape(batch_size, n_decode_lstm_step, -1) #The logits representing the relative probabilities for each word in the vocabulary actions = [] actions_list = [] for i in range(len(action_word_indexs)): action = index2sentence( generated_word_index=action_word_indexs[i], prob_logit=action_probs[i], ixtoword=ixtoword) actions.append(action) #Generates a coherent sentence from the predicted words and stacks them for each state in the batch actions_list.append(action.split()) action_feats = make_batch_X( batch_X=copy.deepcopy(actions_list), n_steps_encode=n_encode_lstm_step, dim_wordvec=dim_wordvec, word_vector=word_vector) #Returns a an input batch from the previous output action_caption_matrix, action_caption_masks = make_batch_Y( batch_Y=copy.deepcopy(actions), wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) #Returns a target(caption_matrix and mask ) from the previous output """ The ease of answering loss partains to the probilility of the response generating any of the responses fromt the dull set. This helps to prevent one of the primary problems in the original seq2seq model where the dialogue dulls out to generic responses. The actions generated are fed as input and the negative of the cross entropy loss with the dull set is take. hence a greater loss is incurred when the response is likely to yield such dull responses. This makes it possible for the agent to genertate lenghtier dialogues """ dull_loss = [] for vector in action_feats: action_batch_X = np.array([vector for _ in range(batch_size)]) d_loss = sess.run(loss, feed_dict={ input_tensors['word_vectors']: action_batch_X, input_tensors['caption']: dull_matrix, input_tensors['caption_mask']: dull_mask, input_tensors['reward']: ones_reward }) d_loss *= -1. / len(dull_set) dull_loss.append(d_loss) # semantic coherence """measures the adequacy of responses to avoid situations in which the generated replies are highly rewarded but are ungrammatical or not coherent. We therefore consider the mutual information between the action a and previous turns in the history to ensure the generated responses are coherent and appropriate...This combines the forward entropy and the backward entropy""" #Forward entropy between the dialogue input and the response forward_inter = sess.run(inter_value,feed_dict={input_tensors['word_vectors']: current_feats, input_tensors['caption']: action_caption_matrix,input_tensors['caption_mask']: action_caption_masks,input_tensors['reward']: ones_reward }) forward_entropies = forward_inter['entropies'] former_caption_matrix, former_caption_masks = make_batch_Y( batch_Y=copy.deepcopy(former), wordtoix=wordtoix, n_decode_lstm_step=n_decode_lstm_step) action_feats = make_batch_X( batch_X=copy.deepcopy(actions_list), n_steps_encode=r_n_encode_lstm_step, dim_wordvec=dim_wordvec, word_vector=word_vector) #Backward entropy loss measures the cross between the action and it's input when fed in a reverse seq2seq model backward_inter = sess2.run(reverse_inter, feed_dict={ word_vectors: action_feats, caption: former_caption_matrix, caption_mask: former_caption_masks }) backward_entropies = backward_inter['entropies'] # reward: count goodness of actions rewards = count_rewards(dull_loss, forward_entropies, backward_entropies, actions, former) # policy gradient: train batch with rewards if batch % 10 == 0: _, loss_val = sess.run( [train_op, loss], feed_dict={ input_tensors['word_vectors']: current_feats, input_tensors['caption']: current_caption_matrix, input_tensors['caption_mask']: current_caption_masks, input_tensors['reward']: rewards }) print("Epoch: {}, batch: {}, loss: {}, Elapsed time: {}".format(epoch, batch, loss_val, time.time() - start_time)) else: _ = sess.run(train_op, feed_dict={ input_tensors['word_vectors']: current_feats, input_tensors['caption']: current_caption_matrix, input_tensors['caption_mask']: current_caption_masks, input_tensors['reward']: rewards }) if batch % 1000 == 0 and batch != 0: print("Epoch {} batch {} is done. Saving the model ...".format(epoch, batch)) saver.save(sess, os.path.join(model_path, 'model-{}-{}'.format(epoch, batch))) print("Epoch ", epoch, " is done. Saving the model ...") saver.save(sess, os.path.join(model_path, 'model'), global_step=epoch)
def test(model_path=default_model_path): if model_path == default_model_path: model_path = convert_checkpoint(model_path) tf.reset_default_graph() sess = tf.InteractiveSession() testing_data = open(testing_data_path, 'r').read().split( '\n') #Contains preset questions to generate responses to word_vector = KeyedVectors.load_word2vec_format( 'model/word_vector.bin', binary=True ) #Load word_vector which returns a unique vector of dim_wordvec for every word in the corpus _, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) #ixtoword is a dictionary that returns a word in the vocabulary for every index #bias_init_vector returns a bias vector for every word to based on relative frequencies model = PolicyGradientDialogue(embed_dim=dim_wordvec, vocab_size=len(ixtoword), hidden_size=dim_hidden, batch_size=batch_size, n_steps_encode=n_encode_lstm_step, n_steps_decode=n_decode_lstm_step, bias_init=bias_init_vector) word_vectors, caption_tf, feats = model.build_generator() saver = tf.train.Saver() print('\n=== Use model', model_path, '===\n') saver.restore(sess, model_path) print("Model restored") with open(output_path, 'w') as out: generated_sentences = [] for idx, question in enumerate(testing_data): print('question =>', question) question = [ data_parser.refine(w) for w in question.lower().split() ] #Converts to lower case and extracts the only the vocabulary parts question = [ word_vector[w] if w in word_vector else np.zeros(dim_wordvec) for w in question ] #Return the word vector representation for each word in the sentence question.insert(0, np.random.normal( size=(dim_wordvec, ))) # insert random normal word vector at the first step if len(question) > n_encode_lstm_step: question = question[: n_encode_lstm_step] #If quesstion is longer than the encoder, truncate to encoder size else: for _ in range(len(question), n_encode_lstm_step): #If less, pad with zeros question.append(np.zeros(dim_wordvec)) question = np.array([question]) generated_word_index, prob_logit = sess.run( [caption_tf, feats['probs']], feed_dict={word_vectors: question}) #Runs the tensorflow session #generated_word_index returns the index of the most probable word #prob_logit returns the logits for every word at each timestep generated_word_index = np.array(generated_word_index).reshape( batch_size, n_decode_lstm_step)[0] prob_logit = np.array(prob_logit).reshape(batch_size, n_decode_lstm_step, -1)[0] for i in range(n_decode_lstm_step): if generated_word_index[i] == 3: #word is <unk> sort_prob_logit = sorted(prob_logit[i]) maxindex = np.where( prob_logit[i] == sort_prob_logit[-1])[0][0] secmaxindex = np.where( prob_logit[i] == sort_prob_logit[-2])[0][0] generated_word_index[ i] = secmaxindex #Returns the second most probable index if the most probable is 3 which corresponds to unknown '<unk>' generated_words = [] for ind in generated_word_index: generated_words.append( ixtoword[ind]) #Returns the word for each index # generate sentence punctuation = np.argmax(np.array(generated_words) == '<eos>') + 1 generated_words = generated_words[: punctuation] #Truncates all words following the '<eos>'---End of sentence marker generated_sentence = ' '.join(generated_words) # modify the output sentence generated_sentence = generated_sentence.replace('<bos> ', '') generated_sentence = generated_sentence.replace(' <eos>', '') generated_sentence = generated_sentence.replace( '--', '') #Exclude <bos>, <eos> and '--' generated_sentence = generated_sentence.split( ' ') # Split double spaces into seperate sentences for i in range(len(generated_sentence)): generated_sentence[i] = generated_sentence[i].strip() if len(generated_sentence[i]) > 1: generated_sentence[i] = generated_sentence[i][0].upper( ) + generated_sentence[i][1:] + '.' else: generated_sentence[i] = generated_sentence[i].upper( ) #starts a sentence with uppercase and ends with a fullstop generated_sentence = ' '.join(generated_sentence) generated_sentence = generated_sentence.replace(' i ', ' I ') generated_sentence = generated_sentence.replace("i'm", "I'm") generated_sentence = generated_sentence.replace("i'd", "I'd") generated_sentence = generated_sentence.replace("i'll", "I'll") generated_sentence = generated_sentence.replace("i'v", "I'v") generated_sentence = generated_sentence.replace(" - ", "") print('generated_sentence =>', generated_sentence ) #Carry out the above replacements and print out.write(generated_sentence + '\n')
def train(): wordtoix, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) word_vector = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) model = Seq2Seq_chatbot(dim_wordvec=dim_wordvec, n_words=len(wordtoix), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector, lr=learning_rate) train_op, tf_loss, word_vectors, tf_caption, tf_caption_mask, inter_value = model.build_model( ) saver = tf.train.Saver(max_to_keep=100) # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333) sess = tf.InteractiveSession() if checkpoint: print("Use Model {}.".format(model_name)) saver.restore(sess, os.path.join(model_path, model_name)) print("Model {} restored.".format(model_name)) else: print("Restart training...") tf.global_variables_initializer().run() dr = Data_Reader() for epoch in range(start_epoch, epochs): n_batch = dr.get_batch_num(batch_size) for batch in range(n_batch): start_time = time.time() batch_X, batch_Y = dr.generate_training_batch(batch_size) for i in range(len(batch_X)): batch_X[i] = [ word_vector[w] if w in word_vector else np.zeros(dim_wordvec) for w in batch_X[i] ] # batch_X[i].insert(0, np.random.normal(size=(dim_wordvec,))) # insert random normal at the first step if len(batch_X[i]) > n_encode_lstm_step: batch_X[i] = batch_X[i][:n_encode_lstm_step] else: for _ in range(len(batch_X[i]), n_encode_lstm_step): batch_X[i].append(np.zeros(dim_wordvec)) current_feats = np.array(batch_X) # print('current_feats.shape', current_feats.shape) current_captions = batch_Y current_captions = map(lambda x: '<bos> ' + x, current_captions) current_captions = map(lambda x: x.replace('.', ''), current_captions) current_captions = map(lambda x: x.replace(',', ''), current_captions) current_captions = map(lambda x: x.replace('"', ''), current_captions) current_captions = map(lambda x: x.replace('\n', ''), current_captions) current_captions = map(lambda x: x.replace('?', ''), current_captions) current_captions = map(lambda x: x.replace('!', ''), current_captions) current_captions = map(lambda x: x.replace('\\', ''), current_captions) current_captions = map(lambda x: x.replace('/', ''), current_captions) for idx, each_cap in enumerate(current_captions): word = each_cap.lower().split(' ') if len(word) < n_decode_lstm_step: current_captions[idx] = current_captions[idx] + ' <eos>' else: new_word = '' for i in range(n_decode_lstm_step - 1): new_word = new_word + word[i] + ' ' current_captions[idx] = new_word + '<eos>' current_caption_ind = [] for cap in current_captions: current_word_ind = [] for word in cap.lower().split(' '): if word in wordtoix: current_word_ind.append(wordtoix[word]) else: current_word_ind.append(wordtoix['<unk>']) current_caption_ind.append(current_word_ind) current_caption_matrix = pad_sequences(current_caption_ind, padding='post', maxlen=n_decode_lstm_step) current_caption_matrix = np.hstack([ current_caption_matrix, np.zeros([len(current_caption_matrix), 1]) ]).astype(int) current_caption_masks = np.zeros((current_caption_matrix.shape[0], current_caption_matrix.shape[1])) nonzeros = np.array( map(lambda x: (x != 0).sum() + 1, current_caption_matrix)) for ind, row in enumerate(current_caption_masks): row[:nonzeros[ind]] = 1 if batch % 100 == 0: _, loss_val = sess.run( [train_op, tf_loss], feed_dict={ word_vectors: current_feats, tf_caption: current_caption_matrix, tf_caption_mask: current_caption_masks }) print( "Epoch: {}, batch: {}, loss: {}, Elapsed time: {}".format( epoch, batch, loss_val, time.time() - start_time)) else: _ = sess.run(train_op, feed_dict={ word_vectors: current_feats, tf_caption: current_caption_matrix, tf_caption_mask: current_caption_masks }) print("Epoch ", epoch, " is done. Saving the model ...") saver.save(sess, os.path.join(model_path, 'model'), global_step=epoch)
def simulate(): """ Simulation procedure """ ''' load dictionary ''' word_vector = KeyedVectors.load_word2vec_format(pre_train_emb, binary=True) w2i, i2w, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) ''' build tf model, saver ''' if TYPE_OF_OUR_MODEL in model_type: chat_model = model_proto( dim_wordvec=dim_wordvec, n_words=len(i2w), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector, ex_batch=1 # 不进行多个采样以供训练时获取收益偏移,仅仅是普通的生成 ) else: chat_model = model_proto(dim_wordvec=dim_wordvec, n_words=len(i2w), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector) chat_model.build_generator() # print trainable variables print('\n------- VARS -------') variables = [v for v in tf.trainable_variables()] [print(v) for v in variables] # create saver saver = tf.train.Saver() model_position = os.path.join(model_path, 'model-{}'.format(checkpoint)) print('\n=== Use model', model_position, '===\n') saver.restore(SESS, model_position) ''' open read and write path ''' dr = Data_Reader(single_test_data_path) fout = open(simulate_out_path + '.sim', 'w') ''' running batches ''' origin_time = start_time = time.time() n_batch = dr.get_batch_num(batch_size) print('total batch:', n_batch) sum_len = 0. sum_div1 = 0. sum_div2 = 0. sum_div3 = 0. total_dis_lens1 = 0. total_dis_lens2 = 0. total_dis_lens3 = 0. total_lens1 = 0. total_lens2 = 0. total_lens3 = 0. total_case = 0 cnt = {1: Counter(), 2: Counter(), 3: Counter()} for batch in range(n_batch): ''' build data ''' batch_x, batch_y, _, kw = dr.generate_training_batch_with_former( batch_size) if model_type != 'rev': batch_x = batch_y assert type(batch_x[0]) == str assert type(batch_y[0]) == str assert type(kw[0]) == str ''' generation procedure for this batch ''' batch_reserve = copy.deepcopy(batch_x) records = [[x] for x in batch_x] batch_kws = [[] for _ in range(batch_size)] for i in range(simulate_length): ''' generation step i ''' feats = make_batch_X(batch_x, n_encode_lstm_step, dim_wordvec, word_vector) generated_words_index, kws = chat_model.test( SESS, (feats, kw), word_vector) # 提取信息,以供输出和下一轮输入 batch_generation = [] kw = [] for idx, gw in enumerate(generated_words_index): words = [] for index in gw: if index == 2: break words.append(i2w[index]) if len(words) > 0: assert type(words[0]) == str sent = ' '.join(words) assert type(sent) == str batch_generation.append(sent) batch_x[idx] = batch_reserve[idx] + ' ' + sent if rec_kw(): assert type(kws[idx]) == str kw.append(kws[idx]) batch_kws[idx].append(kws[idx]) records[idx].append(sent) batch_reserve = copy.deepcopy(batch_generation) # record kw down to simulation output file if rec_kw(): for i in range(batch_size): records[i].append('=======') records[i].extend(batch_kws[i]) ''' output this batch ''' for r in records: # r is list of string # we cannot bully chatbot with dull init input sentence if is_dull_responses(r[0]): continue total_case += 1 # write generation result fout.write('\n'.join(r)) # calculate dialog session length length = calc_length(r) sum_len += length fout.write('\nlength: {}\n'.format(length)) # calculate dialog session diversity diversity1, distinct_len1, total_len1 = get_stcs_diversity( r, 1, length, cnt) sum_div1 += diversity1 total_dis_lens1 += distinct_len1 total_lens1 += total_len1 diversity2, distinct_len2, total_len2 = get_stcs_diversity( r, 2, length, cnt) sum_div2 += diversity2 total_dis_lens2 += distinct_len2 total_lens2 += total_len2 diversity3, distinct_len3, total_len3 = get_stcs_diversity( r, 3, length, cnt) sum_div3 += diversity3 total_dis_lens3 += distinct_len3 total_lens3 += total_len3 fout.write( 'diversity 1: {}/{}={} 2: {}/{}={} 3: {}/{}={}\n'.format( distinct_len1, total_len1.__int__(), diversity1, distinct_len2, total_len2.__int__(), diversity2, distinct_len3, total_len3.__int__(), diversity3)) # print to shell in case programmers wait for too long and feel anxious print('{:3d}th batch cost {:3f}s'.format(batch, time.time() - start_time)) start_time = time.time() n_sessions = n_batch * batch_size ''' print outline ''' print_message = 'session number: {} cost time: {} total case: {}' \ .format(n_sessions, time.time() - origin_time, total_case) print(print_message) fout.write(print_message + '\n') # print average session length & diversity print_message = 'AVG Turns: {} AVG stc len: {}\nSession AVG div1: {} div2: {} div3: {}'. \ format(sum_len / n_sessions, total_lens1 / sum_len, sum_div1 / n_sessions, sum_div2 / n_sessions, sum_div3 / n_sessions) print(print_message) fout.write(print_message + '\n') # print total diversity print_message = 'TOTAL div1: {}->{} div2: {} div3: {}'. \ format(cnt[1].keys().__len__(), cnt[1].keys().__len__() / total_lens1, cnt[2].keys().__len__() / total_lens2, cnt[3].keys().__len__() / total_lens3) print(print_message) fout.write(print_message + '\n') # print average session distinct n-gram number print_message = 'Session avg distinct unigram: {} bigram: {} trigram: {}'. \ format(total_dis_lens1 / n_sessions, total_dis_lens2 / n_sessions, total_dis_lens3 / n_sessions) print(print_message) fout.write(print_message + '\n') fout.close()
import tensorflow as tf import numpy as np #===================================================== # Global Parameters #===================================================== default_model_path = './model/RL/model-56-3000' default_simulate_type = 1 # type 1 use one former sent, type 2 use two former sents testing_data_path = 'sample_input.txt' if len(sys.argv) <= 3 else sys.argv[3] output_path = 'sample_dialog_output.txt' if len(sys.argv) <= 4 else sys.argv[4] word_count_threshold = config.WC_threshold word_vector = KeyedVectors.load_word2vec_format('model/word_vector.bin', binary=True) _, ixtoword, bias_init_vector = data_parser.preProBuildWordVocab(word_count_threshold=word_count_threshold) #===================================================== # Inference Parameters #===================================================== dim_wordvec = 300 dim_hidden = 1000 n_encode_lstm_step = 22 * 2 + 1 # one random normal as the first timestep n_decode_lstm_step = 22 batch_size = 1 model = PolicyGradient_chatbot( dim_wordvec=dim_wordvec, n_words=len(ixtoword),
def train(): """ Training procedure """ if count_kw(): kw_index_counter = Counter() else: kw_index_counter = None ''' build dictionary ''' w2i, i2w, bias_init_vector = data_parser.preProBuildWordVocab( word_count_threshold=word_count_threshold) word_vector = KeyedVectors.load_word2vec_format(pre_train_emb, binary=True) ''' build model, summary and saver ''' # build model chat_model = model_proto(dim_wordvec=dim_wordvec, n_words=len(w2i), dim_hidden=dim_hidden, batch_size=batch_size, n_encode_lstm_step=n_encode_lstm_step, n_decode_lstm_step=n_decode_lstm_step, bias_init_vector=bias_init_vector, lr=learning_rate) if count_kw(): chat_model.build_generator(b_simulate=False) chat_model.kw_stc_sim() loss, true_loss = chat_model.build_model() train_entropy_summary = tf.summary.scalar('train_entropy', true_loss) valid_entropy_summary = tf.summary.scalar('valid_entropy', true_loss) train_loss_summary = tf.summary.scalar('train_loss', loss) valid_loss_summary = tf.summary.scalar('valid_loss', loss) train_summary = tf.summary.merge( [train_loss_summary, train_entropy_summary]) valid_summary = tf.summary.merge( [valid_loss_summary, valid_entropy_summary]) elif model_type == 'kw_sample': entropy, kw_entropy, loss = chat_model.build_model() train_loss_summary = tf.summary.scalar('train_loss', loss) valid_loss_summary = tf.summary.scalar('valid_loss', loss) train_entropy_summary = tf.summary.scalar('train_entropy', entropy) valid_entropy_summary = tf.summary.scalar('valid_entropy', entropy) train_kw_entropy_summary = tf.summary.scalar('train_kw_entropy', kw_entropy) valid_kw_entropy_summary = tf.summary.scalar('valid_kw_entropy', kw_entropy) train_summary = tf.summary.merge([ train_loss_summary, train_entropy_summary, train_kw_entropy_summary ]) valid_summary = tf.summary.merge([ valid_loss_summary, valid_entropy_summary, valid_kw_entropy_summary ]) else: loss = chat_model.build_model() train_summary = tf.summary.scalar('train_loss', loss) valid_summary = tf.summary.scalar('valid_loss', loss) # build summary writer = tf.summary.FileWriter(summary_dir, SESS.graph) # build saver saver = tf.train.Saver(max_to_keep=100) # check trainable print variables print('\n------- VARS -------') variables = [v for v in tf.trainable_variables()] [print(v) for v in variables] ''' reload chat_model or restart training ''' print('\n------- Reloading / Initialization -------') if checkpoint >= 0: # reload saver.restore(SESS, os.path.join(model_path, 'model-{}'.format(checkpoint))) print( "previous chat_model {} in {} restored, continue training".format( checkpoint, model_path)) else: # init tf.global_variables_initializer().run() if count_kw(): restorer = tf.train.Saver() restorer.restore(SESS, previous_model) print('pretrained chat_model {} restored'.format(previous_model)) elif 'kw_sample' in model_type: SESS.run(chat_model.op_kw_emb_init) print('kw embeddings inited') restorer = tf.train.Saver(variables[:5] + variables[8:12]) restorer.restore(SESS, previous_model) print('pretrained chat_model {} restored'.format(previous_model)) print("Start brand new training...") ''' load data ''' dr = Data_Reader(training_data_path) valid_dr = Data_Reader(valid_data_path) ''' running epochs ''' n_batch = dr.get_batch_num(batch_size) v_n_batch = valid_dr.get_batch_num(batch_size) print( 'data prepared.\ntraining batch number is {}\nvalid batch number is {}' .format(n_batch, v_n_batch)) for epoch in range(checkpoint + 1, max_epochs + 1): ''' validation. begin at epoch -1 ''' print('\n------- validation epoch: {} -------\n'.format(epoch - 1)) total_valid_loss = 0 start_time = time.time() for batch in range(v_n_batch): start_time2 = time.time() loss_result, v_summary = run_model(valid_dr, chat_model.valid, valid_summary, word_vector, w2i, i2w, kw_index_counter, output=batch % print_every == 0) writer.add_summary(v_summary, v_n_batch * epoch + batch) total_valid_loss += loss_result if batch % print_every == 0: print( "Valid Epoch: {}, batch: {}, total_loss: {}, Elapsed time: {}" .format(epoch - 1, batch, loss_result, time.time() - start_time2)) print( "valid epoch: {} average total_loss: {}, Elapsed time: {}".format( epoch - 1, total_valid_loss / v_n_batch, time.time() - start_time)) if count_kw(): # output keyword selection situation print('*****************') for ix in kw_index_counter.most_common(20): print('kw: {} cnt: {} prob: {}'.format( ix[0], ix[1], float(ix[1]) / ((n_step + 1) * v_n_batch * batch_size))) print('*****************') kw_index_counter = Counter( ) # reset keyword counter for next operation # valid comes first, and valid-times = train-times + 1 if epoch >= max_epochs: break ''' training. begin at epoch 0 ''' print('\n-------\ntraining epoch: {}\n-------\n'.format(epoch)) for batch in range(n_batch): start_time = time.time() loss_result, t_summary = run_model(dr, chat_model.run, train_summary, word_vector, w2i, i2w, kw_index_counter, output=batch % print_every == 0) writer.add_summary(t_summary, n_batch * epoch + batch) if batch % print_every == 0: print( "Train Epoch: {}, batch: {}, total_loss: {}, Elapsed time: {}" .format(epoch, batch, loss_result, time.time() - start_time)) print("Epoch {} is done. Saving the chat_model ...".format(epoch)) saver.save(SESS, os.path.join(model_path, 'model'), global_step=epoch) if count_kw(): # output keyword selection situation print('*****************') for ix in kw_index_counter.most_common(33): print('kw: {} cnt: {} prob: {}'.format( ix[0], ix[1], float(ix[1]) / ((n_step + 1) * n_batch * batch_size))) print('*****************') kw_index_counter = Counter()