---
# System prepended metadata

title: Untitled

---

## look at line 124:
estimator.export_saved_model(output_dir +'/saved_model', serving_input_receiver_fn)

## tensorflow tutorial:
https://www.tensorflow.org/guide/saved_model#models

```python3=
import click
from sklearn.model_selection import train_test_split
import pandas as pd
import tensorflow as tf
import tensorflow_hub as hub
from datetime import datetime
import bert
from bert import run_classifier
from bert import optimization
from bert import tokenization
import simple_data_feeder as data_feeder
import simple_model_evaluator as evaluator
from tensorflow import keras
import os
import re
import json
import mlflow
import sys
import csv

os.environ["TFHUB_CACHE_DIR"] = '/tmp/tfhub'


def run(dataset, output_dir, do_delete, max_seq_length, batch_size, learning_rate, num_train_epochs,warmup_proportion,save_checkpoints_steps,save_summary_steps, bert_model_hub, train_test_split, pre_split):
    if pre_split:
       train, test, tag_map = data_feeder.getDataSplitted(dataset+'/train.csv', dataset+'/train_label.csv', dataset+'/test.csv', dataset+'/test_label.csv' )
    else:
       train, test, tag_map= data_feeder.getData(dataset, train_test_split)
    if do_delete:
      try:
        tf.gfile.DeleteRecursively(output_dir)
      except:
        # Doesn't matter if the directory didn't exist
        pass
    if len(train) > 10000:
      train = train.sample(10000)

    tf.gfile.MakeDirs(output_dir)
    print('***** Model output directory: {} *****'.format(output_dir),  file=sys.stderr)

    tag_reverse_map = {}
    for k,v in tag_map.items():
        tag_reverse_map[v] = k

    w = csv.writer(open(output_dir+"/labels.csv", "w"))
    for key, val in tag_reverse_map.items():
        w.writerow([key, val])

    train['tag'] = train['label'].apply(lambda x : tag_map[x])
    test['tag'] = test['label'].apply(lambda x : tag_map[x])

    label_list = test['tag'].unique()

    train_intent_count = getLabelCount(train)
    test_intent_count = getLabelCount(test)

    print('***** Training Data Set: {} *****'.format(json.dumps(train_intent_count)), file=sys.stderr)
    print('***** Testing Data Set: {} *****'.format(json.dumps(test_intent_count)), file=sys.stderr)
    print('***** Labels: {} *****'.format(json.dumps(tag_map)), file=sys.stderr)

    tokenizer = bert.tokenization.FullTokenizer(
      vocab_file='data/vocab.txt', do_lower_case=True)


    print('***** preparing features *****', file=sys.stderr)

    train_features = toFeature(train, label_list, max_seq_length, tokenizer)
    test_features = toFeature(test, label_list, max_seq_length, tokenizer)

    # Compute # train and warmup steps from batch size
    num_train_steps = int(len(train_features) / batch_size * num_train_epochs)
    num_warmup_steps = int(num_train_steps * warmup_proportion)

    run_config = tf.estimator.RunConfig(
        model_dir=output_dir,
        save_summary_steps=save_summary_steps,
        save_checkpoints_steps=save_checkpoints_steps)

    model_fn = model_fn_builder(
      bert_model_hub = bert_model_hub,
      num_labels=len(label_list),
      learning_rate=learning_rate,
      num_train_steps=num_train_steps,
      num_warmup_steps=num_warmup_steps)

    estimator = tf.estimator.Estimator(
      model_fn=model_fn,
      config=run_config,
      params={"batch_size": batch_size})

    # Create an input function for training. drop_remainder = True for using TPUs.
    train_input_fn = bert.run_classifier.input_fn_builder(
        features=train_features,
        seq_length=max_seq_length,
        is_training=True,
        drop_remainder=False)

    print('***** start training *****', file=sys.stderr)

    current_time = datetime.now()
   # estimator.train(input_fn=train_input_fn, max_steps=num_train_steps)


    test_input_fn = run_classifier.input_fn_builder(
        features=test_features,
        seq_length=max_seq_length,
        is_training=False,
        drop_remainder=False)

    print('***** start evaluating *****', file=sys.stderr)

    estimator.evaluate(input_fn=test_input_fn, steps=None)

    #pred_sentences = test['text']
    #predictions = getPrediction(pred_sentences, label_list, max_seq_length, tokenizer, estimator)
    #accuracy, tp, fp, fn, precision, recall = evaluator.eval(test['tag'] , column(predictions, 2), label_list)

    #result = parseResult(tp,fp,fn,precision, recall, tag_reverse_map)

    #print(result, file=sys.stderr)
    
    print('***** saving model *****', file=sys.stderr)

    estimator.export_saved_model(output_dir +'/saved_model', serving_input_receiver_fn)

    print('***** publishing result *****', file=sys.stderr)

    return json.dumps({"accuracy": accuracy, "details": result})
    

class PredResult:
  def __init__(self, tp, fp, fn, precision, recall, f1):
    self.tp = tp
    self.fp = fp
    self.fn = fn
    self.precision = precision
    self.recall = recall
    self.f1 = f1

def parseResult(tp, fp, fn, precision, recall, map):
    result = {}
    for k,v in map.items():
        f1=0
        if precision[k] + recall[k] != 0:
            f1 = 2* precision[k] * recall[k] / (precision[k] + recall[k])
        result[v] = PredResult(tp[k], fp[k], fn[k], precision[k], recall[k], f1).__dict__
    return result


def column(matrix, i):
    return [row[i] for row in matrix]

def analyzePredictions(predictions, class2id, id2class ):
    print(predictions)

def toFeature(dataset, label_list, max_seq_length, tokenizer):
    # Use the InputExample class from BERT's run_classifier code to create examples from the data
    train_InputExamples = dataset.apply(lambda x: bert.run_classifier.InputExample(guid=None, # Globally unique ID for bookkeeping, unused in this example
                                                                       text_a = x['text'],
                                                                       text_b = None,
                                                                       label = x['tag']), axis = 1)

    train_features = bert.run_classifier.convert_examples_to_features(train_InputExamples, label_list, max_seq_length, tokenizer)
    return train_features

def create_tokenizer_from_hub_module(bert_model_hub = "https://tfhub.dev/google/bert_uncased_L-12_H-768_A-12/1"):
    print(bert_model_hub)
    """Get the vocab file and casing info from the Hub module."""
    with tf.Graph().as_default():
        bert_module = hub.Module(bert_model_hub)
        tokenization_info = bert_module(signature="tokenization_info", as_dict=True)
    with tf.Session() as sess:
        vocab_file, do_lower_case = sess.run([tokenization_info["vocab_file"],
                                            tokenization_info["do_lower_case"]])

    return bert.tokenization.FullTokenizer(
      vocab_file=vocab_file, do_lower_case=do_lower_case)


def getTagMap(test):
    tag_set = set()
    for row in test['label'] :
        tag_set.add(row)
    tag_map = dict()
    i=0
    for tag in tag_set :
        tag_map[tag] = i
        i=i+1
    return tag_map

def getLabelCount(dataset):
    tag_map = getTagMap(dataset)
    intent_count = {}

    for key in tag_map:
        intent_count[key] =0

    for intent in dataset['label'] :
        intent_count[intent]+=1

    return intent_count


def create_model(bert_model_hub, is_predicting, input_ids, input_mask, segment_ids, labels,
                 num_labels):
  """Creates a classification model."""

  bert_module = hub.Module(
      bert_model_hub,
      trainable=True)
  bert_inputs = dict(
      input_ids=input_ids,
      input_mask=input_mask,
      segment_ids=segment_ids)
  bert_outputs = bert_module(
      inputs=bert_inputs,
      signature="tokens",
      as_dict=True)

  # Use "pooled_output" for classification tasks on an entire sentence.
  # Use "sequence_outputs" for token-level output.
  output_layer = bert_outputs["pooled_output"]

  hidden_size = output_layer.shape[-1].value

  # Create our own layer to tune for politeness data.
  output_weights = tf.get_variable(
      "output_weights", [num_labels, hidden_size],
      initializer=tf.truncated_normal_initializer(stddev=0.02))

  output_bias = tf.get_variable(
      "output_bias", [num_labels], initializer=tf.zeros_initializer())

  with tf.variable_scope("loss"):

    # Dropout helps prevent overfitting
    output_layer = tf.nn.dropout(output_layer, keep_prob=0.9)

    logits = tf.matmul(output_layer, output_weights, transpose_b=True)
    logits = tf.nn.bias_add(logits, output_bias)
    log_probs = tf.nn.log_softmax(logits, axis=-1)

    # Convert labels into one-hot encoding
    one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32)

    predicted_labels = tf.squeeze(tf.argmax(log_probs, axis=-1, output_type=tf.int32))
    # If we're predicting, we want predicted labels and the probabiltiies.
    if is_predicting:
      return (predicted_labels, log_probs)

    # If we're train/eval, compute loss between predicted and actual label
    per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1)
    loss = tf.reduce_mean(per_example_loss)
    return (loss, predicted_labels, log_probs)

# model_fn_builder actually creates our model function
# using the passed parameters for num_labels, learning_rate, etc.
def model_fn_builder(bert_model_hub, num_labels, learning_rate, num_train_steps,
                     num_warmup_steps):
  """Returns `model_fn` closure for TPUEstimator."""
  def model_fn(features, labels, mode, params):  # pylint: disable=unused-argument
    """The `model_fn` for TPUEstimator."""

    input_ids = features["input_ids"]
    input_mask = features["input_mask"]
    segment_ids = features["segment_ids"]
    label_ids = features["label_ids"]

    is_predicting = (mode == tf.estimator.ModeKeys.PREDICT)

    # TRAIN and EVAL
    if not is_predicting:

      (loss, predicted_labels, log_probs) = create_model(bert_model_hub,
        is_predicting, input_ids, input_mask, segment_ids, label_ids, num_labels)

      train_op = bert.optimization.create_optimizer(
          loss, learning_rate, num_train_steps, num_warmup_steps, use_tpu=False)

      # Calculate evaluation metrics.
      def metric_fn(label_ids, predicted_labels):
        accuracy = tf.metrics.accuracy(label_ids, predicted_labels)
        return {
            "eval_accuracy": accuracy,
        }

      eval_metrics = metric_fn(label_ids, predicted_labels)

      if mode == tf.estimator.ModeKeys.TRAIN:
        return tf.estimator.EstimatorSpec(mode=mode,
          loss=loss,
          train_op=train_op)
      else:
          return tf.estimator.EstimatorSpec(mode=mode,
            loss=loss,
            eval_metric_ops=eval_metrics)
    else:
      (predicted_labels, log_probs) = create_model(bert_model_hub,
        is_predicting, input_ids, input_mask, segment_ids, label_ids, num_labels)

      predictions = {
          'probabilities': log_probs,
          'labels': predicted_labels
      }
      return tf.estimator.EstimatorSpec(mode, predictions=predictions)

  # Return the actual model function in the closure
  return model_fn



def serving_input_receiver_fn():
    """Serving input_fn that builds features from placeholders

    Returns
    -------
    tf.estimator.export.ServingInputReceiver
    """
    input_ids = tf.placeholder(dtype=tf.int32, shape=[None, 128], name='input_ids')
    input_mask = tf.placeholder(dtype=tf.int32, shape=[None, 128], name='input_mask')
    segment_ids = tf.placeholder(dtype=tf.int32, shape=[None, 128], name='segment_ids')
    label_ids = tf.placeholder(dtype=tf.int32, shape=[None], name='label_ids')

    receiver_tensors = {'input_ids': input_ids, 'input_mask': input_mask,'segment_ids': segment_ids, 'label_ids': label_ids}
    return tf.estimator.export.ServingInputReceiver(receiver_tensors, receiver_tensors)



def getPrediction(in_sentences, labels, max_seq_length, tokenizer, estimator):
  input_examples = [run_classifier.InputExample(guid="", text_a = x, text_b = None, label = 0) for x in in_sentences] # here, "" is just a dummy label
  input_features = run_classifier.convert_examples_to_features(input_examples, labels, max_seq_length, tokenizer)

  predict_input_fn = run_classifier.input_fn_builder(features=input_features, seq_length=max_seq_length, is_training=False, drop_remainder=False)
  predictions = estimator.predict(predict_input_fn)
  return [(sentence, prediction['probabilities'], labels[prediction['labels']]) for sentence, prediction in zip(in_sentences, predictions)]

if __name__ == '__main__':
    run()

```