y_train, y_validation = y_shuffled[:validation_index], y_shuffled[
    validation_index:]
print("Vocabulary: {:d}".format(len(vocabulary_processor.vocabulary_)))
print("Train validation ratio: {:d}/{:d}".format(len(y_train),
                                                 len(y_validation)))

# Training============================================================
with tf.Graph().as_default():
    configuration = tf.ConfigProto(
        log_device_placement=FLAGS.log_device_placement)
    sess = tf.Session(config=configuration)
    with sess.as_default():
        text_CNN = TextCNN(
            sequence_length=x_train.shape[1],
            num_classes=y_train.shape[1],
            vocabulary_size=len(vocabulary_processor.vocabulary_),
            embedding_size=FLAGS.embedding_dim,
            filter_sizes=list(map(int, FLAGS.filter_sizes.split(","))),
            num_filters=FLAGS.num_filters,
            l2_reg_lambda=FLAGS.l2_reg_lambda)

        # Define Training procedure
        global_step = tf.Variable(0, name="global_step", trainable=False)
        optimizer = tf.train.AdamOptimizer(1e-3)
        grads_and_vars = optimizer.compute_gradients(text_CNN.loss)
        train_op = optimizer.apply_gradients(grads_and_vars,
                                             global_step=global_step)

        # Model directory
        timestamp = time.strftime('%Y-%m-%d_%H-%M-%S',
                                  time.localtime(time.time()))
        model_dir = os.path.abspath(
Example #2
0
def train():
    config = Config.Config()
    print("device = ", config.device)
    torch.set_default_tensor_type(torch.DoubleTensor)

    word_dict = json.load(open(config.vocab_dict_file, 'r', encoding='utf-8'))
    word2vec_embed = np.load(config.embedding_file)

    model_name = input('choose CNN/RNN\n')
    x_right, y_right = process.get_tensor(config.train_file, config, word_dict,
                                          word2vec_embed, model_name, 'train')
    # x_right为 [all_sentence_num, max_sentence_len] 的二维array,要继续经过Word2vec的embedding映射才能得到词向量
    # y_right为 [all_sentence_num, label_size] 的情感标签array

    # TextCNN   ->   train
    if model_name == 'CNN':
        model = TextCNN(config, word2vec_embed).to(config.device)
    elif model_name == 'RNN':
        model = TextRNN(config, word2vec_embed).to(config.device)
    model.train()
    optimizer = torch.optim.Adam(model.parameters(), lr=config.learning_rate)

    batch_sum = len(x_right) // config.batch_size
    if len(x_right) % config.batch_size != 0:
        batch_sum += 1

    batch_num = 0
    for k in range(config.epochs):
        for i in range(batch_sum):
            x = torch.LongTensor(x_right[i * config.batch_size:(i + 1) *
                                         config.batch_size]).to(config.device)
            if model_name == 'CNN':
                y = torch.tensor(y_right[i * config.batch_size:(i + 1) *
                                         config.batch_size]).to(config.device)
            elif model_name == 'RNN':
                y = torch.LongTensor(y_right[i * config.batch_size:(i + 1) *
                                             config.batch_size]).to(
                                                 config.device)

            y_pred = model.forward(x)
            loss = model.loss_fn(y_pred, y)

            batch_num += 1
            if batch_num % config.print_epochs_num == 0 or batch_num == batch_sum * config.epochs:
                print('Batch [{}/{}]\tLoss = {}'.format(
                    batch_num, batch_sum * config.epochs, loss.item()))

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

        # save after each epoch
        if model_name == 'CNN':
            torch.save(model, config.CNN_model_file)
        elif model_name == 'RNN':
            torch.save(model, config.RNN_model_file)

    if model_name == 'CNN':
        torch.save(model, config.CNN_model_file)
    elif model_name == 'RNN':
        torch.save(model, config.RNN_model_file)
Example #3
0
def train():
    print('start training...')
    train_X, train_Y, dev_X, dev_Y = data_preprocess()

    with tf.Graph().as_default():
        session_conf = tf.ConfigProto(
            allow_soft_placement=FLAGS.allow_soft_placement,
            log_device_placement=FLAGS.log_device_placement)
        sess = tf.Session(config=session_conf)
        with sess.as_default():
            cnn = TextCNN(
                sequence_length=train_X.shape[1],
                num_classes=train_Y.shape[1],
                embedding_size=FLAGS.embedding_dim,
                filter_sizes=list(map(int, FLAGS.filter_sizes.split(','))),
                num_filters=FLAGS.num_filters,
                l2_reg_lambda=FLAGS.l2_reg_lambda)

            # define Training procedure
            global_step = tf.Variable(0, name='global_step', trainable=False)
            optimizer = tf.train.AdamOptimizer(1e-3)    # Adam optimization algorithm
            grads_and_vars = optimizer.compute_gradients(cnn.loss)
            train_op = optimizer.apply_gradients(grads_and_vars, global_step=global_step)

            # keep track of gradient values and sparsity (optional)
            grad_summaries = []
            for g, v in grads_and_vars:
                if g is not None:
                    grad_hist_summary = tf.summary.histogram('{}/grad/hist'.format(v.name), g)
                    sparsity_summary = tf.summary.scalar('{}/grad/spasity'.format(v.name), tf.nn.zero_fraction(g))
                    grad_summaries.append(grad_hist_summary)
                    grad_summaries.append(sparsity_summary)
            grad_summaries_merged = tf.summary.merge(grad_summaries)

            # Output directory for models and summaries
            timestamp = str(int(time.time()))
            out_dir = os.path.abspath(os.path.join(os.path.curdir, 'logs', timestamp))
            print('Writting to {}\n'.format(out_dir))

            # Summaries for loss and accuracy
            loss_summary = tf.summary.scalar('loss', cnn.loss)
            acc_summary = tf.summary.scalar('accuracy', cnn.accuracy)

            # train summaries
            train_summary_op = tf.summary.merge([loss_summary, acc_summary, grad_summaries_merged])
            train_summary_dir = os.path.join(out_dir, 'summaries', 'train')
            train_summary_writer = tf.summary.FileWriter(train_summary_dir, sess.graph)

            # dev summaries
            dev_summary_op = tf.summary.merge([loss_summary, acc_summary])
            dev_summary_dir = os.path.join(out_dir, 'summaries', 'dev')
            dev_summary_writer = tf.summary.FileWriter(dev_summary_dir, sess.graph)

            # checkpoint directory. tensorflow assumes this directory already exists so we need to create it
            checkpoint_dir = os.path.abspath(os.path.join(out_dir, 'checkpoint'))
            checkpoint_prefix = os.path.join(checkpoint_dir, 'model')
            if not os.path.exists(checkpoint_dir):
                os.makedirs(checkpoint_dir)
            saver = tf.train.Saver(tf.global_variables(), max_to_keep=FLAGS.num_checkpoints)

            # initialize all variables
            sess.run(tf.global_variables_initializer())


            def train_step(x_batch, y_batch):
                # a single training step
                feed_dict = {
                    cnn.input_x: x_batch,
                    cnn.input_y: y_batch,
                    cnn.dropout_keep_prob: FLAGS.dropout_keep_prob
                }

                _, step, summaries, loss, accuracy, result = sess.run(
                    [train_op, global_step, train_summary_op, cnn.loss, cnn.accuracy, cnn.result],
                    feed_dict)

                # print result
                time_str = datetime.datetime.now().isoformat()
                print('{}: 训练集 第{}次, loss:{:g}, accuracy:{:g}'.format(time_str, step, loss, accuracy))
                train_summary_writer.add_summary(summaries, step)

            def dev_step(x_batch, y_batch, writer=None):
                # evaluates model on a dev set
                feed_dict = {
                    cnn.input_x: x_batch,
                    cnn.input_y: y_batch,
                    cnn.dropout_keep_prob: 1.0
                }
                step, summaries, loss, accuracy = sess.run(
                    [global_step, dev_summary_op, cnn.loss, cnn.accuracy],
                    feed_dict)
                time_str = datetime.datetime.now().isoformat()
                print('{}: 验证集 第{}次, loss: {:g}, accuracy: {:g}'.format(time_str, step, loss, accuracy))
                if writer:
                    writer.add_summary(summaries, step)
            # generate batches
            batches = PreProcess().batch_iter(
                list(zip(train_X, train_Y)), FLAGS.batch_size, FLAGS.num_epochs)

            # training loop. For each batch
            for batch in batches:
                x_batch, y_batch = zip(*batch)
                train_step(x_batch, y_batch)
                current_step = tf.train.global_step(sess, global_step)
                if current_step % FLAGS.evaluate_every == 0:
                    print('\nEvaluation:')
                    dev_step(dev_X, dev_Y, writer=dev_summary_writer)
                    print('')
                if current_step % FLAGS.checkpoint_every == 0:
                    path = saver.save(sess, checkpoint_prefix, global_step=current_step)
                    print('Saved model checkpoint to {}\n'.format(path))
Example #4
0
def train_cnn():
	"""Step 0: load sentences, labels, and training parameters"""
	#train_file = sys.argv[1]
	input_file = 'C:/Users/bvkka/Desktop/New folder/consumer_complaints.csv.zip'
	x_raw, y_raw, df, labels = dataHelpers.load_data_and_labels(input_file)

	#parameter_file = sys.argv[0]
	#paramater_file='C:/Users/bvkka/Desktop/New folder/parameters.json'
	# Model Hyper parameters
	tf.flags.DEFINE_integer("embedding_dim", 40, "Dimensionality of character embedding (default: 128)")
	tf.flags.DEFINE_string("filter_sizes", "3,4,5", "Comma-separated filter sizes (default: '3,4,5')")
	tf.flags.DEFINE_integer("num_filters", 32, "Number of filters per filter size (default: 128)")
	tf.flags.DEFINE_float("dropout_keep_prob", 0.5, "Dropout keep probability (default: 0.5)")
	tf.flags.DEFINE_float("l2_reg_lambda", 0.0, "L2 regularization lambda (default: 0.0)")

	# Training parameters
	tf.flags.DEFINE_integer("batch_size", 64, "Batch Size (default: 64)")
	tf.flags.DEFINE_integer("num_epochs", 1, "Number of training epochs (default: 200)")
	tf.flags.DEFINE_integer("evaluate_every", 100, "Evaluate model on dev set after this many steps (default: 100)")
	tf.flags.DEFINE_integer("checkpoint_every", 100, "Save model after this many steps (default: 100)")
	tf.flags.DEFINE_integer("num_checkpoints", 5, "Number of checkpoints to store (default: 5)")
	# Misc Parameters
	tf.flags.DEFINE_boolean("allow_soft_placement", True, "Allow device soft device placement")
	tf.flags.DEFINE_boolean("log_device_placement", False, "Log placement of ops on devices")

	FLAGS = tf.flags.FLAGS
	FLAGS._parse_flags()
	print("\nParameters:")
	for attr, value in sorted(FLAGS.__flags.items()):
		print("{}={}".format(attr.upper(), value))
	print("")

	#params = json.loads(open(parameter_file).read())

	"""Step 1: pad each sentence to the same length and map each word to an id"""
	max_document_length = max([len(x.split(' ')) for x in x_raw])
	logging.info('The maximum length of all sentences: {}'.format(max_document_length))
	vocab_processor = learn.preprocessing.VocabularyProcessor(max_document_length)
	x = np.array(list(vocab_processor.fit_transform(x_raw)))
	y = np.array(y_raw)

	"""Step 2: split the original dataset into train and test sets"""
	x_, x_test, y_, y_test = train_test_split(x, y, test_size=0.1, random_state=42)

	"""Step 3: shuffle the train set and split the train set into train and dev sets"""
	shuffle_indices = np.random.permutation(np.arange(len(y_)))
	x_shuffled = x_[shuffle_indices]
	y_shuffled = y_[shuffle_indices]
	x_train, x_dev, y_train, y_dev = train_test_split(x_shuffled, y_shuffled, test_size=0.1)

	"""Step 4: save the labels into labels.json since predict.py needs it"""
	#with open('./labels.json', 'w') as outfile:
	#	json.dump(labels, outfile, indent=4)

	logging.info('x_train: {}, x_dev: {}, x_test: {}'.format(len(x_train), len(x_dev), len(x_test)))
	logging.info('y_train: {}, y_dev: {}, y_test: {}'.format(len(y_train), len(y_dev), len(y_test)))

	"""Step 5: build a graph and cnn object"""
	graph = tf.Graph()
	with graph.as_default():
		session_conf = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)
		sess = tf.Session(config=session_conf)
		with sess.as_default():
			cnn = TextCNN(
				sequence_length=x_train.shape[1],
				num_classes=y_train.shape[1],
				vocab_size=len(vocab_processor.vocabulary_),
				embedding_size=FLAGS.embedding_dim,
				filter_sizes=list(map(int, FLAGS.filter_sizes.split(","))),
				num_filters=FLAGS.num_filters,
				l2_reg_lambda=FLAGS.l2_reg_lambda)

			global_step = tf.Variable(0, name="global_step", trainable=False)
			optimizer = tf.train.AdamOptimizer(1e-3)
			grads_and_vars = optimizer.compute_gradients(cnn.loss)
			train_op = optimizer.apply_gradients(grads_and_vars, global_step=global_step)

			timestamp = str(int(time.time()))
			out_dir = os.path.abspath(os.path.join(os.path.curdir, "trained_model_" + timestamp))

			checkpoint_dir = os.path.abspath(os.path.join(out_dir, "checkpoints"))
			checkpoint_prefix = os.path.join(checkpoint_dir, "model")
			if not os.path.exists(checkpoint_dir):
				os.makedirs(checkpoint_dir)
			saver = tf.train.Saver(tf.global_variables())

			# One training step: train the model with one batch
			def train_step(x_batch, y_batch):
				feed_dict = {
					cnn.input_x: x_batch,
					cnn.input_y: y_batch,
					cnn.dropout_keep_prob: FLAGS.dropout_keep_prob}
				_, step, loss, acc = sess.run([train_op, global_step, cnn.loss, cnn.accuracy], feed_dict)

			# One evaluation step: evaluate the model with one batch
			def dev_step(x_batch, y_batch):
				feed_dict = {cnn.input_x: x_batch, cnn.input_y: y_batch, cnn.dropout_keep_prob: 1.0}
				step, loss, acc, num_correct = sess.run([global_step, cnn.loss, cnn.accuracy, cnn.num_correct], feed_dict)
				return num_correct

			# Save the word_to_id map since predict.py needs it
			vocab_processor.save(os.path.join(out_dir, "vocab.pickle"))
			#sess.run(tf.initialize_all_variables())
			sess.run(tf.global_variables_initializer())

			# Training starts here
			train_batches = dataHelpers.batch_iter(list(zip(x_train, y_train)),FLAGS.batch_size,FLAGS.num_epochs)
			best_accuracy, best_at_step = 0, 0

			"""Step 6: train the cnn model with x_train and y_train (batch by batch)"""
			for train_batch in train_batches:
				x_train_batch, y_train_batch = zip(*train_batch)
				train_step(x_train_batch, y_train_batch)
				current_step = tf.train.global_step(sess, global_step)

				"""Step 6.1: evaluate the model with x_dev and y_dev (batch by batch)"""
				if current_step % FLAGS.evaluate_every == 0:
					dev_batches = dataHelpers.batch_iter(list(zip(x_dev, y_dev)), FLAGS.batch_size, 1)
					total_dev_correct = 0
					for dev_batch in dev_batches:
						x_dev_batch, y_dev_batch = zip(*dev_batch)
						num_dev_correct = dev_step(x_dev_batch, y_dev_batch)
						total_dev_correct += num_dev_correct

					dev_accuracy = float(total_dev_correct) / len(y_dev)
					logging.critical('Accuracy on dev set: {}'.format(dev_accuracy))

					"""Step 6.2: save the model if it is the best based on accuracy on dev set"""
					if dev_accuracy >= best_accuracy:
						best_accuracy, best_at_step = dev_accuracy, current_step
						path = saver.save(sess, checkpoint_prefix, global_step=current_step)
						logging.critical('Saved model at {} at step {}'.format(path, best_at_step))
						logging.critical('Best accuracy is {} at step {}'.format(best_accuracy, best_at_step))

			"""Step 7: predict x_test (batch by batch)"""
			test_batches = dataHelpers.batch_iter(list(zip(x_test, y_test)),FLAGS.batch_size, 1)
			total_test_correct = 0
			for test_batch in test_batches:
				x_test_batch, y_test_batch = zip(*test_batch)
				num_test_correct = dev_step(x_test_batch, y_test_batch)
				total_test_correct += num_test_correct

			test_accuracy = float(total_test_correct) / len(y_test)
			logging.critical('Accuracy on test set is {} based on the best model {}'.format(test_accuracy, path))
			logging.critical('The training is complete')
def getSentenceEmbedding(sentence: str,
                         embedding: dict,
                         maxSentenceLen: int,
                         method: int = SentenceEmbedding.NaiveAdding):
    """
    The sentence Embedding is formed by concatting the words
    in the sentence to the maximum length.
    And then use max-pooling like TextCNN to reduce to fixed dimension representation.
    """

    # search preserved sentence embedding
    if PRESERVE_ALL_SENTENCE_EMBEDDING:
        if sentence in all_sentence_embedding:
            return all_sentence_embedding[sentence]

    if EMBEDDING == EmbeddingMethod.FastText:
        if method != SentenceEmbedding.TextCNN:
            returnEmbedding = np.zeros((300, ))
        if method == SentenceEmbedding.NaiveAdding:
            for word in sentence.split():
                try:
                    returnEmbedding += embedding[word.strip(punctuation)]
                except KeyError:  # getting word which is not in embedding table
                    continue
        elif method == SentenceEmbedding.NaiveNormalized:
            sentenceLen = 0
            for word in sentence.split():
                try:
                    returnEmbedding += embedding[word.strip(punctuation)]
                    sentenceLen += 1
                except KeyError:  # getting word which is not in embedding table
                    continue
            returnEmbedding /= sentenceLen
        elif method == SentenceEmbedding.NaiveAvgPadding:
            sentenceLen = 0
            for word in sentence.split():
                try:
                    returnEmbedding += embedding[word.strip(punctuation)]
                except KeyError:  # getting word which is not in embedding table
                    returnEmbedding += embedding['AVG']
                sentenceLen += 1
            for _ in range(maxSentenceLen - sentenceLen):
                # padding the sentence to maxSentenceLen
                returnEmbedding += embedding['AVG']
            returnEmbedding /= maxSentenceLen

        elif method == SentenceEmbedding.TextCNN:
            textCNN_model = TextCNN(maxSentenceLen, 300, len(embedding))
            tempWordEmbedding = np.zeros((maxSentenceLen, 300))
            sentenceLen = 0
            for word in sentence.split():
                try:
                    tempWordEmbedding[sentenceLen, :] = embedding[word.strip(
                        punctuation)]
                except KeyError:  # getting word which is not in embedding table
                    tempWordEmbedding[sentenceLen, :] = embedding['AVG']
                sentenceLen += 1
            for i in range(sentenceLen, maxSentenceLen):
                # padding the sentence to maxSentenceLen
                tempWordEmbedding[i, :] = embedding['AVG']

            returnEmbedding = textCNN_model.getSentenceEmbedding(
                np.reshape(tempWordEmbedding, (1, maxSentenceLen, 300)))

    elif EMBEDDING == EmbeddingMethod.BERT:
        returnEmbedding = np.zeros((768, ))
        if method == SentenceEmbedding.NaiveAdding:
            # dimension should be (768,)
            embeddingList = bert_embedding(sentence.split())
            for _, arrayList in embeddingList:
                returnEmbedding += arrayList[0]

    elif EMBEDDING == EmbeddingMethod.BERT_TORCH:
        ids = torch.tensor(
            [tokenizer.convert_tokens_to_ids(tokenizer.tokenize(sentence))])
        returnEmbedding = bert(
            ids, output_all_encoded_layers=False)[-1][0].detach().numpy()

    # preserve sentence embedding
    if PRESERVE_ALL_SENTENCE_EMBEDDING:
        all_sentence_embedding[sentence] = returnEmbedding

    return returnEmbedding
Example #6
0
def train():
    with tf.Graph().as_default():
        session_conf = tf.ConfigProto(
            allow_soft_placement=FLAGS.allow_soft_placement,
            log_device_placement=FLAGS.log_device_placement)
        session_conf.gpu_options.allow_growth = FLAGS.gpu_options_allow_growth
        sess = tf.Session(config=session_conf)
        with sess.as_default():
            print("init model .....")
            cnn = TextCNN(sequence_length=pad_seq_len,
                          num_classes=FLAGS.num_classes,
                          vocab_size=FLAGS.vocab_size,
                          fc_hidden_size=FLAGS.fc_hidden_size,
                          embedding_size=FLAGS.embedding_dim,
                          embedding_type=FLAGS.embedding_type,
                          filter_sizes=list(
                              map(int, FLAGS.filter_sizes.split(","))),
                          num_filters=FLAGS.num_filters,
                          l2_reg_lambda=FLAGS.l2_reg_lambda)

            # Define training procedure
            with tf.control_dependencies(
                    tf.get_collection(tf.GraphKeys.UPDATE_OPS)):
                learning_rate = tf.train.exponential_decay(
                    learning_rate=FLAGS.learning_rate,
                    global_step=cnn.global_step,
                    decay_steps=FLAGS.decay_steps,
                    decay_rate=FLAGS.decay_rate,
                    staircase=True)
                optimizer = tf.train.AdamOptimizer(learning_rate)
                grads, vars = zip(*optimizer.compute_gradients(cnn.loss))
                grads, _ = tf.clip_by_global_norm(grads,
                                                  clip_norm=FLAGS.norm_ratio)
                train_op = optimizer.apply_gradients(
                    zip(grads, vars),
                    global_step=cnn.global_step,
                    name="train_op")

            # Keep track of gradient values and sparsity (optional)
            grad_summaries = []
            for g, v in zip(grads, vars):
                if g is not None:
                    grad_hist_summary = tf.summary.histogram(
                        "{0}/grad/hist".format(v.name), g)
                    sparsity_summary = tf.summary.scalar(
                        "{0}/grad/sparsity".format(v.name),
                        tf.nn.zero_fraction(g))
                    grad_summaries.append(grad_hist_summary)
                    grad_summaries.append(sparsity_summary)
            grad_summaries_merged = tf.summary.merge(grad_summaries)

            # Output directory for models and summaries
            timestamp = str(int(time.time()))
            out_dir = os.path.abspath(os.path.join(os.path.curdir, "runs"))
            logger.info("✔︎ Writing to {0}\n".format(out_dir))

            # Summaries for loss and accuracy
            loss_summary = tf.summary.scalar("loss", cnn.loss)
            prec_summary = tf.summary.scalar("precision-micro", cnn.precision)
            rec_summary = tf.summary.scalar("recall-micro", cnn.recall)

            # Train summaries
            train_summary_op = tf.summary.merge([
                loss_summary, prec_summary, rec_summary, grad_summaries_merged
            ])
            train_summary_dir = os.path.join(out_dir, "summaries", "train")
            train_summary_writer = tf.summary.FileWriter(
                train_summary_dir, sess.graph)

            # Validation summaries
            validation_summary_op = tf.summary.merge(
                [loss_summary, prec_summary, rec_summary])
            validation_summary_dir = os.path.join(out_dir, "summaries",
                                                  "validation")
            validation_summary_writer = tf.summary.FileWriter(
                validation_summary_dir, sess.graph)

            saver = tf.train.Saver(tf.global_variables(),
                                   max_to_keep=FLAGS.num_checkpoints)

            checkpoint_dir = os.path.abspath(
                os.path.join(out_dir, "checkpoints"))
            if not os.path.exists(checkpoint_dir):
                os.makedirs(checkpoint_dir)
            sess.run(tf.global_variables_initializer())
            sess.run(tf.local_variables_initializer())

            current_step = sess.run(cnn.global_step)

            def train_step(x_batch, y_batch):
                """A single training step"""
                feed_dict = {
                    cnn.input_x: x_batch,
                    cnn.input_y: y_batch,
                    cnn.dropout_keep_prob: FLAGS.dropout_keep_prob
                }
                _, step, summaries, loss = sess.run(
                    [train_op, cnn.global_step, train_summary_op, cnn.loss],
                    feed_dict)

                logger.info("step {0}: loss {1:g}".format(step, loss))
                train_summary_writer.add_summary(summaries, step)

            def validation_step(x_validation, y_validation, writer=None):
                """Evaluates model on a validation set"""

                feed_dict = {
                    cnn.input_x: x_validation,
                    cnn.input_y: y_validation,
                    cnn.dropout_keep_prob: 1.0
                }
                step, summaries, scores, cur_loss = sess.run([
                    cnn.global_step, validation_summary_op, cnn.scores,
                    cnn.loss
                ], feed_dict)

                # Predict by threshold
                predicted_labels_threshold, predicted_values_threshold = \
                    DH.get_label_using_scores_by_threshold(scores=scores, threshold=FLAGS.threshold)

                cur_rec_ts, cur_acc_ts, cur_F_ts = 0.0, 0.0, 0.0

                for index, predicted_label_threshold in enumerate(
                        predicted_labels_threshold):
                    rec_inc_ts, acc_inc_ts, F_inc_ts = DH.cal_metric(
                        predicted_label_threshold, y_validation[index])

                    cur_rec_ts, cur_acc_ts, cur_F_ts = cur_rec_ts + rec_inc_ts, \
                                                       cur_acc_ts + acc_inc_ts, \
                                                       cur_F_ts + F_inc_ts

                cur_rec_ts = cur_rec_ts / len(y_validation)
                cur_acc_ts = cur_acc_ts / len(y_validation)
                cur_F_ts = cur_F_ts / len(y_validation)

                logger.info(
                    "︎☛ Predict by threshold: recall {0:g}, accuracy {1:g}, F {2:g}"
                    .format(cur_rec_ts, cur_acc_ts, cur_F_ts))

                # Predict by topK
                topK_predicted_labels = []
                for top_num in range(FLAGS.top_num):
                    predicted_labels_topk, predicted_values_topk = \
                        DH.get_label_using_scores_by_topk(scores=scores, top_num=top_num + 1)
                    topK_predicted_labels.append(predicted_labels_topk)

                cur_rec_tk = [0.0] * FLAGS.top_num
                cur_acc_tk = [0.0] * FLAGS.top_num
                cur_F_tk = [0.0] * FLAGS.top_num

                for top_num, predicted_labels_topK in enumerate(
                        topK_predicted_labels):
                    for index, predicted_label_topK in enumerate(
                            predicted_labels_topK):
                        rec_inc_tk, acc_inc_tk, F_inc_tk = DH.cal_metric(
                            predicted_label_topK, y_validation[index])
                        cur_rec_tk[top_num], cur_acc_tk[top_num], cur_F_tk[top_num] = \
                            cur_rec_tk[top_num] + rec_inc_tk, \
                            cur_acc_tk[top_num] + acc_inc_tk, \
                            cur_F_tk[top_num] + F_inc_tk

                    cur_rec_tk[top_num] = cur_rec_tk[top_num] / len(
                        y_validation)
                    cur_acc_tk[top_num] = cur_acc_tk[top_num] / len(
                        y_validation)
                    cur_F_tk[top_num] = cur_F_tk[top_num] / len(y_validation)

                logger.info("︎☛ Predict by topK: ")
                for top_num in range(FLAGS.top_num):
                    logger.info(
                        "Top{0}: recall {1:g}, accuracy {2:g}, F {3:g}".format(
                            top_num + 1, cur_rec_tk[top_num],
                            cur_acc_tk[top_num], cur_F_tk[top_num]))
                if writer:
                    writer.add_summary(summaries, step)

            # Generate batches
            batches_train = DH.batch_iter(list(zip(x_train, y_train)),
                                          FLAGS.batch_size, FLAGS.num_epochs)

            num_batches_per_epoch = int(
                (len(x_train) - 1) / FLAGS.batch_size) + 1

            # Training loop. For each batch...
            for batch_train in batches_train:
                x_batch_train, y_batch_train = zip(*batch_train)
                train_step(x_batch_train, y_batch_train)
                current_step = tf.train.global_step(sess, cnn.global_step)

                if current_step % FLAGS.evaluate_every == 0:
                    logger.info("\nEvaluation:")
                    validation_step(x_val,
                                    y_val,
                                    writer=validation_summary_writer)

                if current_step % FLAGS.checkpoint_every == 0:
                    checkpoint_prefix = os.path.join(checkpoint_dir, "model")
                    path = saver.save(sess,
                                      checkpoint_prefix,
                                      global_step=current_step)
                    logger.info(
                        "✔︎ Saved model checkpoint to {0}\n".format(path))

                if current_step % num_batches_per_epoch == 0:
                    current_epoch = current_step // num_batches_per_epoch
                    logger.info(
                        "✔︎ Epoch {0} has finished!".format(current_epoch))

        logger.info("✔︎ Done.")