Example #1
0
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()
Example #2
0
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')
Example #3
0
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')
Example #4
0
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")
Example #5
0
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)
Example #6
0
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)
Example #7
0
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))
Example #8
0
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)
Example #10
0
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')
Example #11
0
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)
Example #12
0
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()
Example #13
0
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),
Example #14
0
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()