text: from time import time
  
  from models.Gan import Gan
  from models.mle.MleDataLoader import DataLoader
  from models.mle.MleGenerator import Generator
  from utils.metrics.Bleu import Bleu
  from utils.metrics.EmbSim import EmbSim
  from utils.metrics.Nll import Nll
  from utils.oracle.OracleLstm import OracleLstm
  from utils.utils import *
  
  
  class Mle(Gan):
      def __init__(self, oracle=None):
          super().__init__()
          # you can change parameters, generator here
          self.vocab_size = 5000  # 20
          self.emb_dim = 32
          self.hidden_dim = 32
          self.sequence_length = 20
          self.filter_size = [2, 3]
          self.num_filters = [100, 200]
          self.l2_reg_lambda = 0.2
          self.dropout_keep_prob = 0.75
          self.batch_size = 64
          self.generate_num = 10000  # 128
          self.start_token = 0
  
          self.oracle_file = 'save/oracle.txt'
          self.generator_file = 'save/generator.txt'
          self.test_file = 'save/test_file.txt'
          self.test_log_path = 'save/output/'
  
      def init_oracle_trainng(self, oracle=None):
          if oracle is None:
              oracle = OracleLstm(num_vocabulary=self.vocab_size, batch_size=self.batch_size, emb_dim=self.emb_dim,
                                  hidden_dim=self.hidden_dim, sequence_length=self.sequence_length,
                                  start_token=self.start_token)
          self.set_oracle(oracle)
  
          generator = Generator(num_vocabulary=self.vocab_size, batch_size=self.batch_size, emb_dim=self.emb_dim,
                                hidden_dim=self.hidden_dim, sequence_length=self.sequence_length,
                                start_token=self.start_token)
          self.set_generator(generator)
  
          gen_dataloader = DataLoader(batch_size=self.batch_size, seq_length=self.sequence_length)
          oracle_dataloader = DataLoader(batch_size=self.batch_size, seq_length=self.sequence_length)
          dis_dataloader = None
  
          self.set_data_loader(gen_loader=gen_dataloader, dis_loader=dis_dataloader, oracle_loader=oracle_dataloader)
  
      def init_metric(self):
          nll = Nll(data_loader=self.oracle_data_loader, rnn=self.oracle, sess=self.sess)
          self.add_metric(nll)
  
          inll = Nll(data_loader=self.gen_data_loader, rnn=self.generator, sess=self.sess)
          inll.set_name('nll-test')
          self.add_metric(inll)
  
          from utils.metrics.DocEmbSim import DocEmbSim
          docsim = DocEmbSim(oracle_file=self.oracle_file, generator_file=self.generator_file, num_vocabulary=self.vocab_size)
          self.add_metric(docsim)
  
      def init_real_metric(self, test_real_file='data/testdata/test_coco.txt'):
          from utils.metrics.DocEmbSim import DocEmbSim
          docsim = DocEmbSim(oracle_file=self.oracle_file, generator_file=self.generator_file,
                             num_vocabulary=self.vocab_size)
          self.add_metric(docsim)
  
          inll = Nll(data_loader=self.gen_data_loader, rnn=self.generator, sess=self.sess)
          inll.set_name('nll-test')
          self.add_metric(inll)
  
          bleu_2 = Bleu(test_text=self.test_file, real_text=test_real_file, gram=2)
          bleu_2.set_name('Bleu-2')
          self.add_metric(bleu_2)
  
          bleu_3 = Bleu(test_text=self.test_file, real_text=test_real_file, gram=3)
          bleu_3.set_name('Bleu-3')
          self.add_metric(bleu_3)
  
          bleu_4 = Bleu(test_text=self.test_file, real_text=test_real_file, gram=4)
          bleu_4.set_name('Bleu-4')
          self.add_metric(bleu_4)
  
          bleu_5 = Bleu(test_text=self.test_file, real_text=test_real_file, gram=5)
          bleu_5.set_name('Bleu-5')
          self.add_metric(bleu_5)
  
      def train_discriminator(self):
          generate_samples(self.sess, self.generator, self.batch_size, self.generate_num, self.generator_file)
          self.dis_data_loader.load_train_data(self.oracle_file, self.generator_file)
          for _ in range(3):
              self.dis_data_loader.next_batch()
              x_batch, y_batch = self.dis_data_loader.next_batch()
              feed = {
                  self.discriminator.input_x: x_batch,
                  self.discriminator.input_y: y_batch,
              }
              _ = self.sess.run(self.discriminator.train_op, feed)
  
      def evaluate(self):
          generate_samples(self.sess, self.generator, self.batch_size, self.generate_num, self.generator_file)
          if self.oracle_data_loader is not None:
              self.oracle_data_loader.create_batches(self.generator_file)
          if self.log is not None:
              if self.epoch == 0 or self.epoch == 1:
                  for metric in self.metrics:
                      self.log.write(metric.get_name() + ',')
                  self.log.write('\n')
              scores = super().evaluate()
              for score in scores:
                  self.log.write(str(score)+',')
              self.log.write('\n')
              return scores
          return super().evaluate()
  
      def train_oracle(self):
          self.init_oracle_trainng()
          self.sess.run(tf.global_variables_initializer())
  
          self.pre_epoch_num = 80
          self.log = open('experiment-log-mle.csv', 'w')
          generate_samples(self.sess, self.oracle, self.batch_size, self.generate_num, self.oracle_file)
          generate_samples(self.sess, self.generator, self.batch_size, self.generate_num, self.generator_file)
          self.gen_data_loader.create_batches(self.oracle_file)
          self.oracle_data_loader.create_batches(self.generator_file)
          self.init_metric()
  
          print('start pre-train generator:')
          for epoch in range(self.pre_epoch_num):
              start = time()
              loss = pre_train_epoch(self.sess, self.generator, self.gen_data_loader)
              end = time()
              print('epoch:' + str(self.epoch) + '\t time:' + str(end - start))
              self.add_epoch()
              if epoch % 5 == 0:
                  self.evaluate()
          generate_samples(self.sess, self.generator, self.batch_size, self.generate_num, self.generator_file)
          return
  
  
      def init_real_trainng(self, data_loc=None):
          from utils.text_process import text_precess, text_to_code
          from utils.text_process import get_tokenlized, get_word_list, get_dict
          if data_loc is None:
              data_loc = 'data/image_coco.txt'
          self.sequence_length, self.vocab_size = text_precess(data_loc)
          generator = Generator(num_vocabulary=self.vocab_size, batch_size=self.batch_size, emb_dim=self.emb_dim,
                                hidden_dim=self.hidden_dim, sequence_length=self.sequence_length,
                                start_token=self.start_token)
          self.set_generator(generator)
  
          gen_dataloader = DataLoader(batch_size=self.batch_size, seq_length=self.sequence_length)
          oracle_dataloader = None
          dis_dataloader = None
  
          self.set_data_loader(gen_loader=gen_dataloader, dis_loader=dis_dataloader, oracle_loader=oracle_dataloader)
          tokens = get_tokenlized(data_loc)
          word_set = get_word_list(tokens)
          [word_index_dict, index_word_dict] = get_dict(word_set)
          with open(self.oracle_file, 'w') as outfile:
              outfile.write(text_to_code(tokens, word_index_dict, self.sequence_length))
          return word_index_dict, index_word_dict
  
      def train_real(self, data_loc=None):
          from utils.text_process import code_to_text
          from utils.text_process import get_tokenlized
          wi_dict, iw_dict = self.init_real_trainng(data_loc)
  
          test_data_loc = 'data/testdata/test_coco.txt'
          if data_loc == 'data/emnlp_news.txt':
              test_data_loc = 'data/testdata/test_emnlp.txt'
  
          self.init_real_metric(test_data_loc)
  
          def get_real_test_file(dict=iw_dict):
              with open(self.generator_file, 'r') as file:
                  codes = get_tokenlized(self.generator_file)
              with open(self.test_file, 'w', encoding='utf-8') as outfile:
                  outfile.write(code_to_text(codes=codes, dictionary=dict))
  
              # STORE THE REAL OUTPUT
              if test_data_loc == 'data/testdata/test_coco.txt':
                  test_log_file = self.test_log_path + 'mle_imagecoco.txt'
                  with open(test_log_file, 'w', encoding='utf-8') as outfile:
                      outfile.write(code_to_text(codes=codes, dictionary=dict))
              elif test_data_loc == 'data/testdata/test_emnlp.txt':
                  test_log_file = self.test_log_path + 'mle_emnlp.txt'
                  with open(test_log_file, 'w', encoding='utf-8') as outfile:
                      outfile.write(code_to_text(codes=codes, dictionary=dict))
  
          self.sess.run(tf.global_variables_initializer())
  
          self.pre_epoch_num = 80
          self.adversarial_epoch_num = 100
          self.log = open('experiment-log-mle-real.csv', 'w')
          generate_samples(self.sess, self.generator, self.batch_size, self.generate_num, self.generator_file)
          self.gen_data_loader.create_batches(self.oracle_file)
  
          print('start pre-train generator:')
          for epoch in range(self.pre_epoch_num):
              start = time()
              loss = pre_train_epoch(self.sess, self.generator, self.gen_data_loader)
              end = time()
              print('epoch:' + str(self.epoch) + '\t time:' + str(end - start))
              self.add_epoch()
              if epoch % 20 == 0:  # change from 5 to 10
                  generate_samples(self.sess, self.generator, self.batch_size, self.generate_num, self.generator_file)
                  get_real_test_file()
                  self.evaluate()
          generate_samples(self.sess, self.generator, self.batch_size, self.generate_num, self.generator_file)
          get_real_test_file()
          self.evaluate()
  
  
  
  