예제 #1
0
def pre_train():
    print('### Generator MLE Pre-Train Mode ###')

    #--construct data loader--#
    data_loader = Data_Loader(config)
    vocab_size = data_loader.get_vocab_size()

    #--construct generator model--#
    GEN = Generator(config, vocab_size, build_train_op=True)

    #--tensorflow session--#
    with tf.Session() as sess:

        #--initialize training--#
        sess.run(tf.global_variables_initializer())
        GEN = _check_restore_parameters(sess,
                                        model=GEN,
                                        specific_model=config.pre_train_model)
        history_loss = []
        best_loss = 777.777
        counter = 0

        #--training epochs--#
        for epoch in range(config.pre_train_epochs):

            #--initialize epoch--#
            epoch_loss = []
            data_loader.shuffle_data()

            #--run over all buckets--#
            bucket_ids = data_loader.shuffle_buckets()
            for bucket_n, bucket_id in enumerate(bucket_ids):

                #--run epoch on each bucket--#
                n_batch = 0
                while (n_batch * config.batch_size
                       ) < data_loader.get_bucket_len(bucket_id):

                    #--get batch--#
                    (batch_encoder_inputs, batch_decoder_inputs,
                     decoder_masks) = data_loader.generator_get_batch(
                         bucket_id=bucket_id,
                         batch_id=n_batch,
                         mode='pre_train')
                    n_batch += 1

                    #--update--#
                    step_loss = GEN.run_step(
                        sess,
                        batch_encoder_inputs,
                        batch_decoder_inputs,
                        decoder_masks,
                        bucket_id,
                        feed_previous=
                        False,  # >> in train mode, decoder_inputs are used as given, we dont feed the previous output, feed_previous=False
                        add_reward=False,
                        mc_search=False)
                    #--print info--#
                    epoch_loss.append(step_loss)
                    print(
                        'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, cur_Loss: %.5f'
                        % (epoch + 1, config.pre_train_epochs, bucket_n + 1,
                           data_loader.get_num_buckets(), n_batch - 1,
                           data_loader.get_bucket_len(bucket_id) /
                           config.batch_size, step_loss),
                        end='\r')

            #--epoch checkpoint--#
            history_loss.append(np.mean(epoch_loss))
            best_loss, to_save = _model_checkpoint_save_best(
                best_val=best_loss, cur_val=history_loss[-1], mode='min')
            counter, to_stop = _model_checkpoint_earlystopping(
                counter=counter, reset=to_save, patient=config.patient)

            #--save best and show training info--#
            if config.force_save: to_save = True
            print(
                'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, avg_Loss: %.5f, Saved: %s'
                % (epoch + 1, config.pre_train_epochs,
                   data_loader.get_num_buckets(),
                   data_loader.get_num_buckets(), n_batch - 1, n_batch - 1,
                   history_loss[-1], 'True' if to_save else 'False'))
            #--save model and training log--#
            if to_save == True:
                GEN.saver.save(sess,
                               os.path.join(config.model_dir, 'pre_train'),
                               global_step=(epoch + 1))
                pickle.dump(
                    history_loss,
                    open(os.path.join(config.model_dir, 'history_loss.pkl'),
                         'wb'), True)

            #--earlystopping--#
            if to_stop: break

        #--pre train end--#
        print('Pre-training process complete, model saved to: ',
              config.model_dir)
예제 #2
0
def chat(speak_with_audio=False, model_name=None):
    print('### Model Chat and Test Mode ###')

    #--enable audio mode--#
    if speak_with_audio:
        mixer.init()
        print('### Daisy Speak with Audio Response Mode Enabled ###')

    #--modify batch size--#
    config.batch_size = 1

    #--construct data loader--#
    data_loader = Data_Loader(config, load_bucket=False)
    word2idx, idx2word = data_loader.get_mapping()
    vocab_size = data_loader.get_vocab_size()

    #--construct generator model--#
    GEN = Generator(config, vocab_size, build_train_op=False)

    #--tensorflow saver--#
    saver = tf.train.Saver()

    #--tensorflow session--#
    with tf.Session() as sess:

        #--initialize testing--#
        sess.run(tf.global_variables_initializer())
        GEN = _check_restore_parameters(sess,
                                        model=GEN,
                                        specific_model=model_name)

        #--output file--#
        with open(os.path.join(config.data_dir, 'chat_dialog.txt'), 'w') as f:

            #--greeting message--#
            max_length = BUCKETS[-1][0]
            print('\nHi, my name is Daisy! Nice to meet you, let\'s chat!')
            print('(Input max length: %i, enter empty line to exit. )' %
                  max_length)
            if speak_with_audio:
                _speak('Hi, my name is Daisy! Nice to meet you, let\'s chat!.')

            #--testing loop--#
            while True:

                #--decode from standard input--#
                line = _get_user_input()
                if len(line) > 0 and line[-1] == '\n':
                    line = line[:-1]
                if line == '':
                    print('Bye!')
                    if speak_with_audio: _speak('Bye!')
                    break

                #--record human input--#
                f.write('HUMAN +++++++ ' + line + '\n')

                #--get token-ids for the input sentence--#
                token_ids = _sentence2id(word2idx, line)
                if (len(token_ids) > max_length):
                    print(
                        'Max length I can handle is: %i, tell me something else.'
                        % max_length)
                    line = _get_user_input()
                    continue

                #--feed input line to the right bucket--#
                bucket_id = _find_right_bucket(len(token_ids))

                #--get a 1-element batch to feed the sentence to the model--#
                (
                    chat_encoder_inputs,
                    chat_decoder_inputs,
                    decoder_masks,
                ) = data_loader.generator_get_batch(bucket_id=bucket_id,
                                                    mode='chat',
                                                    chat_input=[
                                                        token_ids,
                                                    ])

                #--get output logits for the sentence--#
                _, _, output_logits = GEN.run_step(
                    sess,
                    chat_encoder_inputs,
                    chat_decoder_inputs,
                    decoder_masks,
                    bucket_id,
                    feed_previous=
                    True,  # >> in chat mode, we feed forward the previous outputs.
                    add_reward=False,
                    mc_search=False)
                #--construct response--#
                response = _construct_response(output_logits,
                                               dec_vocab=idx2word,
                                               eos_id=config.EOS_ID)
                print('DAISY +++++++ ', response)
                if speak_with_audio:
                    _speak(response)

                #--record machine response--#
                f.write('DAISY +++++++ ' + response + '\n')
            f.write('=============================================\n')
예제 #3
0
def gan_train():
    print(
        '### Generative Adversarial Training with Reinforcement Learning Mode ###'
    )

    #--construct data loader--#
    data_loader = Data_Loader(config)
    vocab_size = data_loader.get_vocab_size()

    #--construct generator and discriminator model--#
    GEN = Generator(config, vocab_size, build_train_op=True)
    DIS = Discriminator(config, vocab_size)

    #--tensorflow session--#
    with tf.Session() as sess:

        #--initialize training--#
        sess.run(tf.global_variables_initializer())
        GEN = _check_restore_parameters(sess,
                                        model=GEN,
                                        specific_model=config.gan_train_model)
        dis_history_loss = []
        gen_history_loss = []
        tf_history_loss = []
        r_history_loss = []
        best_loss = 777.777
        counter = 0

        #--training epochs--#
        for epoch in range(config.gan_train_epochs):

            #--initialize epoch--#
            dis_epoch_loss = []
            gen_epoch_loss = []
            tf_epoch_loss = []
            r_epoch_loss = []
            data_loader.shuffle_data()

            #--run over all buckets--#
            bucket_ids = data_loader.shuffle_buckets()
            for bucket_n, bucket_id in enumerate(bucket_ids):

                #--run epoch on each bucket--#
                n_batch = 0
                while (n_batch * config.batch_size
                       ) < data_loader.get_bucket_len(bucket_id):

                    #---Update Discriminator---#
                    for _ in range(config.update_d):

                        #--get batch--#
                        (
                            batch_encoder_inputs,
                            batch_decoder_inputs,
                            decoder_masks,
                            encoder_inputs,
                            decoder_inputs,
                        ) = data_loader.generator_get_batch(
                            bucket_id=bucket_id,
                            batch_id=n_batch,
                            mode='gan_train')
                        n_batch += 1

                        #--gather (X,Y) and sample (X, ^Y) through ^Y ~ G(*|X)--#
                        train_query, train_answer, train_labels = GEN.sample(
                            sess,
                            batch_encoder_inputs,
                            batch_decoder_inputs,
                            decoder_masks,
                            encoder_inputs,
                            decoder_inputs,
                            bucket_id,
                            mc_search=False)

                        #--update D using (X, Y) as positive examples and (X, ^Y) as negative examples--#
                        _, dis_step_loss = DIS.run_step(
                            sess,
                            train_query,
                            train_answer,
                            train_labels,
                            bucket_id,
                            train=True)  # >> This trains the discriminator

                        #--record--#
                        dis_epoch_loss.append(dis_step_loss)

                    #---Update Generator---#
                    for _ in range(config.update_g):

                        #--gather (X,Y) and sample (X, ^Y) through ^Y ~ G(*|X) with Monte Carlo search--#
                        train_query, train_answer, train_labels = GEN.sample(
                            sess,
                            batch_encoder_inputs,
                            batch_decoder_inputs,
                            decoder_masks,
                            encoder_inputs,
                            decoder_inputs,
                            bucket_id,
                            mc_search=True)

                        #--compute reward r for (X, ^Y ) using D based on monte carlo search--#
                        reward, _ = DIS.run_step(
                            sess,
                            train_query,
                            train_answer,
                            train_labels,
                            bucket_id,
                            train=False
                        )  # >> This does not train the discriminator

                        #--update G on (X, ^Y ) using reward r--#
                        gen_step_loss = GEN.run_step(
                            sess,
                            batch_encoder_inputs,
                            batch_decoder_inputs,
                            decoder_masks,
                            bucket_id,
                            reward=reward,
                            feed_previous=False,
                            add_reward=True,  # >> add reward
                            mc_search=False)

                        #--teacher forcing: update G on (X, Y)--#
                        tf_step_loss = GEN.run_step(sess,
                                                    batch_encoder_inputs,
                                                    batch_decoder_inputs,
                                                    decoder_masks,
                                                    bucket_id,
                                                    reward=None,
                                                    feed_previous=False,
                                                    add_reward=False,
                                                    mc_search=False)

                        #--record--#
                        gen_epoch_loss.append(gen_step_loss)
                        tf_epoch_loss.append(tf_step_loss)
                        r_epoch_loss.append(reward)

                    #--print info--#
                    print(
                        'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, Reward: %.5f, dis_Loss: %.5f, gen_Loss: %.5f, tf_Loss: %.5f'
                        % (epoch + 1, config.gan_train_epochs, bucket_n + 1,
                           data_loader.get_num_buckets(), n_batch - 1,
                           data_loader.get_bucket_len(bucket_id) /
                           config.batch_size, reward, dis_step_loss,
                           gen_step_loss, tf_step_loss),
                        end='\r')

            #--epoch checkpoint--#
            dis_history_loss.append(np.mean(dis_epoch_loss))
            gen_history_loss.append(np.mean(gen_epoch_loss))
            tf_history_loss.append(np.mean(tf_epoch_loss))
            r_history_loss.append(np.mean(r_epoch_loss))
            best_loss, to_save = _model_checkpoint_save_best(
                best_val=best_loss, cur_val=tf_history_loss[-1], mode='min')
            counter, to_stop = _model_checkpoint_earlystopping(
                counter=counter, reset=to_save, patient=config.patient)

            #--save best and show training info--#
            if config.force_save: to_save = True
            print(
                'Epoch: %i/%i, Bucket: %i/%i, Batch: %i/%i, Reward: %.5f, dis_Loss: %.5f, gen_Loss: %.5f, tf_Loss: %.5f, Saved: %s'
                %
                (epoch + 1, config.gan_train_epochs,
                 data_loader.get_num_buckets(), data_loader.get_num_buckets(),
                 n_batch - 1, n_batch - 1, r_history_loss[-1],
                 dis_history_loss[-1], gen_history_loss[-1],
                 tf_history_loss[-1], 'True' if to_save else 'False'))
            #--save model and training log--#
            if to_save == True:
                DIS.saver.save(sess,
                               os.path.join(config.model_dir, 'gan_dis_model'),
                               global_step=(epoch + 1))
                GEN.saver.save(sess,
                               os.path.join(config.model_dir, 'gan_gen_model'),
                               global_step=(epoch + 1))
                pickle.dump(
                    dis_history_loss,
                    open(
                        os.path.join(config.model_dir, 'dis_history_loss.pkl'),
                        'wb'), True)
                pickle.dump(
                    gen_history_loss,
                    open(
                        os.path.join(config.model_dir, 'gen_history_loss.pkl'),
                        'wb'), True)
                pickle.dump(
                    tf_history_loss,
                    open(os.path.join(config.model_dir, 'tf_history_loss.pkl'),
                         'wb'), True)
                pickle.dump(
                    r_history_loss,
                    open(os.path.join(config.model_dir, 'r_history_loss.pkl'),
                         'wb'), True)

            #--earlystopping--#
            # if to_stop: break
            if r_history_loss[-1] < 0.00000001 and r_history_loss[
                    -2] < 0.00000001:
                break

        #--pre train end--#
        print(
            'Generative Adversarial Training process complete, model saved to: ',
            config.model_dir)
예제 #4
0
def evaluate(model_name):
    print('### Model Chat and Test Mode ###')

    #--construct data loader--#
    data_loader = Data_Loader(config, load_for_test=True)
    word2idx, idx2word = data_loader.get_mapping()
    vocab_size = data_loader.get_vocab_size()

    #--get testing data--#
    test_input, test_output = data_loader.get_test_data()

    #--truncate test data size--#
    n_batch_for_test = 100
    if len(test_input) > config.batch_size * n_batch_for_test:
        test_input = test_input[:config.batch_size * n_batch_for_test]
        test_output = test_output[:config.batch_size * n_batch_for_test]

    #--construct generator model--#
    GEN = Generator(config, vocab_size, build_train_op=False)

    #--tensorflow saver--#
    saver = tf.train.Saver()

    #--tensorflow session--#
    with tf.Session() as sess:

        #--initialize testing--#
        eval_output = []
        max_length = BUCKETS[0][
            0] - 2  # >> the first bucket but without <bos> and <eos> tokens, therefor - 2
        sess.run(tf.global_variables_initializer())
        GEN = _check_restore_parameters(sess,
                                        model=GEN,
                                        specific_model=model_name)

        #--run over all inputs--#
        n_batch = 0
        while (n_batch * config.batch_size) < len(test_input):

            #--take 'batch_size' lines--#
            batch_inputs = []
            batch_range = np.arange(
                (n_batch * config.batch_size),
                (n_batch * config.batch_size + config.batch_size))
            for cnt, i in enumerate(batch_range):
                idx = i % len(test_input)  # bound idx when i > data_length
                batch_inputs.append(_sentence2id(word2idx, test_input[idx]))
            n_batch += 1

            #--get a 1-element batch to feed the sentence to the model--#
            (
                chat_encoder_inputs,
                chat_decoder_inputs,
                decoder_masks,
            ) = data_loader.generator_get_batch(bucket_id=0,
                                                mode='chat',
                                                chat_input=batch_inputs)

            #--get output logits for the sentence--#
            _, _, output_logits = GEN.run_step(
                sess,
                chat_encoder_inputs,
                chat_decoder_inputs,
                decoder_masks,
                bucket_id=0,
                feed_previous=
                True,  # >> in chat mode, we feed forward the previous outputs.
                add_reward=False,
                mc_search=False)
            output_logits = np.asarray(output_logits)

            #--construct response--#
            for i in range(config.batch_size):
                line = np.expand_dims(output_logits[:, i, :], axis=1)
                response = _construct_response(line,
                                               dec_vocab=idx2word,
                                               eos_id=config.EOS_ID)
                eval_output.append(response)

            print('Evaluation Batch: %i/%i' %
                  (n_batch - 1, len(test_input) / config.batch_size),
                  end='\r')
        print('Evaluation Batch: %i/%i' %
              (n_batch, len(test_input) / config.batch_size))
        assert len(eval_output) == len(test_input)

        #--count BLEU score by average--#
        bleu = []
        for i, eval_line in enumerate(eval_output):
            score_per_line = []
            for test_line in test_output:
                score_per_line.append(_BLEU(eval_line, test_line))
            bleu.append(np.mean(score_per_line))
            print('BLEU evaluation: %i/%i' % (i, len(eval_output)), end='\r')

        print('BLEU evaluation: %i/%i' % (len(eval_output), len(eval_output)))
        average = np.mean(bleu)
        print("Originally, average bleu score is " + str(average))
        """