<jupyter_start><jupyter_text>MNIST classification example with TensorFlow  Install packages on Google  Cloud Datalab (locally use conda env) Select in the Python3 Kernel:In the menu bar the of 'Kernel', select   **python3** Install needed packagescopy the command below in a Google Cloud Datalab cell  **!pip install tensorflow==1.12** Restart the Kernel this is to take into account the new installed packages. Click in the menu bar on:  **Reset Session**  Needed librairies<jupyter_code>import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import time
import gzip
import sys
import _pickle as cPickle
tf.__version__
tf.logging.set_verbosity(tf.logging.INFO)<jupyter_output><empty_output><jupyter_text>Import the Data<jupyter_code># get mnist data, split between train and test sets
# on GCP
#(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# with AXA network
def load_data(path):
    f = gzip.open(path, 'rb')
    if sys.version_info < (3,):
        data = cPickle.load(f)
    else:
        data = cPickle.load(f, encoding='bytes')
    f.close()
    return data
(x_train, y_train), (x_test, y_test) = load_data(path='../data/mnist.pkl.gz')
# check data shape (training)
x_train.shape
# check data shape (train)
x_test.shape
x_train.dtype, x_test.dtype
np.max(x_train), np.min(x_train), np.max(x_test), np.min(x_test)  
x_test.nbytes/1024.0**2
x_train.nbytes/1024.0**2
y_test.nbytes/1024.0**2
y_train.nbytes/1024.0**2<jupyter_output><empty_output><jupyter_text>Normalize and reorganize the data<jupyter_code># cast uint8 -> float32
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
# renormalize the data 255 grey variation
x_train /= 255
x_test /= 255
# reshape the data 28 x 28 -> 784
x_train = x_train.reshape(len(x_train), x_train.shape[1]*x_train.shape[2])
x_test = x_test.reshape(len(x_test), x_test.shape[1]*x_test.shape[2])
x_train.shape
x_test.shape<jupyter_output><empty_output><jupyter_text>Reshape the labels<jupyter_code>y_train.shape
y_test.shape
np.unique(y_train), np.unique(y_test)
num_classes = len(np.unique(y_train))
num_classes
# convert class vectors to binary class matrices
y_train = tf.keras.utils.to_categorical(y_train, num_classes)
y_test = tf.keras.utils.to_categorical(y_test, num_classes)
y_train.shape
y_test.shape
dim_input=x_train.shape[1]
dim_input<jupyter_output><empty_output><jupyter_text>Visualize the data<jupyter_code>plt.figure(figsize=(20,4))
for index, (image, label) in enumerate(zip(x_train[0:5], y_train[0:5])):
    plt.subplot(1, 5, index + 1)
    plt.imshow(np.reshape(image, (28,28)), cmap=plt.cm.gray)
    plt.title('Training: %i\n' % np.argmax(label), fontsize = 20)<jupyter_output><empty_output><jupyter_text>Defined some hyperparameters<jupyter_code># learning rate
learning_rate = 0.5

# number of epoch to train our model
EPOCHS = 5

# size of our mini batch
#BATCH_SIZE = len(x_train)
BATCH_SIZE = 128

# shuffle buffer size
SHUFFLE_BUFFER_SIZE = 10 * BATCH_SIZE

# prefetch buffer size
PREFETCH_BUFFER_SIZE = 1 #tf.contrib.data.AUTOTUNE

# number of paralell calls
NUM_PARALELL_CALL = 4

# hidden layer 1
n1=300
BATCH_SIZE, EPOCHS<jupyter_output><empty_output><jupyter_text>Defined flags<jupyter_code>def del_all_flags(FLAGS):
    flags_dict = FLAGS._flags()    
    keys_list = [keys for keys in flags_dict]    
    for keys in keys_list:
        FLAGS.__delattr__(keys)
    
del_all_flags(tf.flags.FLAGS)
tf.app.flags.DEFINE_string('f', '', 'kernel') # just for jupyter notebook and avoir : "UnrecognizedFlagError: Unknown command line flag 'f'"
tf.app.flags.DEFINE_string('model_dir', '../results/Models/Mnist/ckpt/', 'Dir to save a model and checkpoints')
tf.app.flags.DEFINE_string('saved_dir', '../results/Models/Mnist/pb/', 'Dir to save a model for TF serving')
tf.app.flags.DEFINE_integer('shuffle_buffer_size', SHUFFLE_BUFFER_SIZE , 'Shuffle buffer size')
tf.app.flags.DEFINE_integer('prefetch_buffer_size', PREFETCH_BUFFER_SIZE, 'Prefetch buffer size')
tf.app.flags.DEFINE_integer('batch_size', BATCH_SIZE, 'Batch size')
tf.app.flags.DEFINE_integer('epoch', EPOCHS, 'number of epoch')
tf.app.flags.DEFINE_integer('num_parallel_calls', NUM_PARALELL_CALL, 'Number of paralell calls')
FLAGS = tf.app.flags.FLAGS
print(FLAGS)<jupyter_output>/Users/tarrade/anaconda3/envs/env_gcp_dl_1_13/lib/python3.6/site-packages/ipykernel_launcher.py:
  --batch_size: Batch size
    (default: '128')
    (an integer)
  --epoch: number of epoch
    (default: '5')
    (an integer)
  --f: kernel
    (default: '')
  --model_dir: Dir to save a model and checkpoints
    (default: '../results/Models/Mnist/ckpt/')
  --num_parallel_calls: Number of paralell calls
    (default: '4')
    (an integer)
  --prefetch_buffer_size: Prefetch buffer size
    (default: '1')
    (an integer)
  --saved_dir: Dir to save a model for TF serving
    (default: '../results/Models/Mnist/pb/')
  --shuffle_buffer_size: Shuffle buffer size
    (default: '1280')
    (an integer)

absl.flags:
  --flagfile: Insert flag definitions from the given file into the command line.
    (default: '')
  --undefok: comma-separated list of flag names that it is okay to specify on
    the command line even if the program does not define a flag with that name.
    IMPORTANT: flags in thi[...]<jupyter_text>Using tf.data.Datasethttps://www.tensorflow.org/guide/performance/datasets  To summarize, one good order for the different transformations is:- create the dataset- shuffle (with a big enough buffer size https://stackoverflow.com/questions/46444018/meaning-of-buffer-size-in-dataset-map-dataset-prefetch-and-dataset-shuffle)- repeat- map with the actual work (preprocessing, augmentation…) using multiple parallel calls- batch- prefetchModeKeys:  https://www.tensorflow.org/api_docs/python/tf/estimator/ModeKeys  - EVAL- PREDICT- TRAIN<jupyter_code>tf.estimator.ModeKeys.EVAL, tf.estimator.ModeKeys.PREDICT, tf.estimator.ModeKeys.TRAIN
def input_dataset_fn(x_data, y_data, batch_size=128, mode=tf.estimator.ModeKeys.TRAIN):
    
    if mode == tf.estimator.ModeKeys.PREDICT:
        tf.logging.info("input_dataset_fn: PREDICT, {}".format(mode))
    elif mode == tf.estimator.ModeKeys.EVAL:
        tf.logging.info("input_dataset_fn: EVAL, {}".format(mode))
    elif mode == tf.estimator.ModeKeys.TRAIN:
        tf.logging.info("input_dataset_fn: TRAIN, {}".format(mode))
    
    # 1) convert the inputs to a Dataset.
    dataset = tf.data.Dataset.from_tensor_slices((x_data, y_data))
    
    # 2) shuffle (with a big enough buffer size)    :        
    if mode == tf.estimator.ModeKeys.TRAIN:
        #num_epochs = None # loop indefinitely
        num_epochs = FLAGS.epoch
        dataset = dataset.shuffle(buffer_size=FLAGS.shuffle_buffer_size, seed=2)# depends on sample size
    else:
        #num_epochs = 1 # end-of-input after this
        num_epochs = FLAGS.epoch # to use validation data with keras
        
    print('the number of epoch: num_epoch =', num_epochs)
        
    # caching data
    #dataset = dataset.cache()
    
    # 3) automatically refill the data queue when empty
    dataset = dataset.repeat(num_epochs)
    
    # 4) map
    #dataset = dataset.map(map_func=parse_fn, num_parallel_calls=FLAGS.num_parallel_calls)

    # 5) create batches of data
    dataset = dataset.batch(batch_size=batch_size, drop_remainder=True)
    
    # 6) prefetch data for faster consumption, based on your system and environment, allows the tf.data runtime to automatically tune the prefetch buffer sizes
    dataset = dataset.prefetch(FLAGS.prefetch_buffer_size)

    return dataset
training_dataset = input_dataset_fn(x_train, 
                                    y_train, 
                                    mode=tf.estimator.ModeKeys.TRAIN, 
                                    batch_size=FLAGS.batch_size)
testing_dataset = input_dataset_fn(x_test, 
                                   y_test,
                                   mode=tf.estimator.ModeKeys.EVAL, 
                                   batch_size=len(x_test))<jupyter_output>INFO:tensorflow:input_dataset_fn: TRAIN, train
the number of epoch: num_epoch = 5
INFO:tensorflow:input_dataset_fn: EVAL, eval
the number of epoch: num_epoch = 5<jupyter_text>Exploration dataset API<jupyter_code>type(training_dataset)
training_dataset
#iterator = training_dataset.make_one_shot_iterator()
iterator = tf.compat.v1.data.make_one_shot_iterator(training_dataset)
# next_element
features, labels = iterator.get_next()
n=0
n_iter=10 #len(x_train)//BATCH_SIZE
with tf.Session() as sess:
    while True:
        try:
            start_time = time.clock()
            x,y = sess.run([features, labels])
            print('iteration n:', n, 'execution time:', time.clock() - start_time, 'seconds')
            print(x.shape)
            print(y.shape)
            print('first label of the batch',np.argmax(y[0]),'\n')
            n+=1
            if n>=n_iter:
                print('number of iteration reached')
                break
        except tf.errors.OutOfRangeError:
            print('tf.errors.OutOfRangeError')
            break
#iterator = testing_dataset.make_one_shot_iterator()
iterator = tf.compat.v1.data.make_one_shot_iterator(testing_dataset)
# next_element
features, labels = iterator.get_next()
with tf.Session() as sess:
    while True:
        try:
            start_time = time.clock()
            x,y = sess.run([features, labels])
            print(time.clock() - start_time, 'seconds')
            print(x.shape)
            print(y.shape)
            print('first label of the batch',np.argmax(y[0]),'\n')
        except tf.errors.OutOfRangeError:
            print('tf.errors.OutOfRangeError')
            break<jupyter_output>7.106386999999998 seconds
(10000, 784)
(10000, 10)
first label of the batch 7 

0.06016300000000285 seconds
(10000, 784)
(10000, 10)
first label of the batch 7 

0.056645000000003165 seconds
(10000, 784)
(10000, 10)
first label of the batch 7 

0.06703100000000006 seconds
(10000, 784)
(10000, 10)
first label of the batch 7 

0.049420000000004904 seconds
(10000, 784)
(10000, 10)
first label of the batch 7 

tf.errors.OutOfRangeError<jupyter_text>Our model Build the model<jupyter_code>def baseline_model():
    # create model
    model = tf.keras.Sequential()
 
    # hidden layer
    model.add(tf.keras.layers.Dense(dim_input, 
                    input_dim=dim_input, 
                    kernel_initializer=tf.keras.initializers.he_normal(),
                    bias_initializer=tf.keras.initializers.Zeros(),
                    activation='relu'))
    # last layer
    model.add(tf.keras.layers.Dense(num_classes, 
                    kernel_initializer=tf.keras.initializers.he_normal(),
                    bias_initializer=tf.keras.initializers.Zeros(),
                    activation='softmax'))
    
    # weight initialisation
    # He: keras.initializers.he_normal(seed=None)
    # Xavier: keras.initializers.glorot_uniform(seed=None)
    # Radom Normal: keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)
    # Truncated Normal: keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None)
    
    # optimiser (use tf.train and not tf.keras to use MirrorStrategy)
    # https://www.tensorflow.org/api_docs/python/tf/train/Optimizer
    #optimiser=tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.9)
    # GD/SGC:   tf.train.GradientDescentOptimizer(learning_rate, use_locking=False, name='GradientDescent') 
    # Adam:     tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-08, use_locking=False,name='Adam')
    # RMSProp:  tf.train.RMSPropOptimizer(learning_rate, decay=0.9, momentum=0.0, epsilon=1e-10, use_locking=False, centered=False, name='RMSProp')
    # Momentum: tf.train.MomentumOptimizer(learning_rate, momentum, use_locking=False, name='Momentum', use_nesterov=False)

   
    optimiser=tf.keras.optimizers.Adam(lr=0.01, beta_1=0.9)
    # GD/SGC:   keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
    # Adam:     keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
    # RMSProp:  keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=None, decay=0.0)
    # Momentum: keras.optimizers.SGD(lr=0.01, momentum=0.9, decay=0.0, nesterov=False)
    
    # Compile model
    model.compile(loss='categorical_crossentropy', 
                  optimizer=optimiser, 
                  metrics=['accuracy'])
    return model
# reset the model
tf.keras.backend.clear_session()
# build the model
model = baseline_model()<jupyter_output>WARNING:tensorflow:From /Users/tarrade/anaconda3/envs/env_gcp_dl_1_13/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:435: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.<jupyter_text>Check the nuber of parameters<jupyter_code>model.summary()<jupyter_output>_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 784)               615440    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                7850      
=================================================================
Total params: 623,290
Trainable params: 623,290
Non-trainable params: 0
_________________________________________________________________<jupyter_text>Check input and output layer names<jupyter_code>model.input_names # Use this name as the dictionary key in the TF input function
model.output_names<jupyter_output><empty_output><jupyter_text>Keras Call back  Print info during iterations<jupyter_code>class UDFPrint(tf.keras.callbacks.Callback):
    def __init__(self, test_data):
        self.test_data = test_data
        
    def on_train_begin(self, logs={}):
        return

    def on_train_end(self, logs={}):
        return

    def on_epoch_begin(self, epoch, logs={}):
        _, __, x_train, y_train = self.test_data
        loss_train, acc_train = self.model.evaluate(x_train, y_train, verbose=0)
        print('Reached epoch {0:3d} cost J = {1:.5f}'.format(epoch, loss_train))
        return

    def on_epoch_end(self, epoch, logs={}):
        x_test, y_test, x_train, y_train = self.test_data
        loss_train, acc_train = self.model.evaluate(x_train, y_train, verbose=0)
        loss_test, acc_test = self.model.evaluate(x_test, y_test, verbose=0)
        print(' accurary on the training set {0:.4f}'.format(acc_train))
        print(' accurary on the testing set {0:.4f}'.format(acc_test))

    def on_batch_begin(self, batch, logs={}):
        #print('  ---> starting minibatch', batch)
        return

    def on_batch_end(self, batch, logs={}):
        #print('  ---> ending minibatch', batch)
        return
return<jupyter_output><empty_output><jupyter_text>TensorBoard<jupyter_code>#keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, batch_size=32, write_graph=True, write_grads=False, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None, embeddings_data=None, update_freq='epoch')
tbCallBack=tf.keras.callbacks.TensorBoard(log_dir='../results/TensorBoard/Mnist/logs/', 
                                          histogram_freq=1, 
                                          write_graph=True)<jupyter_output><empty_output><jupyter_text>Store the original weights<jupyter_code>initial_weights = model.get_weights()<jupyter_output><empty_output><jupyter_text>Fit the model using Keras and numpy array  - batch_size   determines the number of samples in each mini batch. Its maximum is the number of all samples, which makes gradient descent accurate, the loss will decrease towards the minimum if the learning rate is small enough, but iterations are slower. Its minimum is 1, resulting in stochastic gradient descent: Fast but the direction of the gradient step is based only on one example, the loss may jump around. batch_size allows to adjust between the two extremes: accurate gradient direction and fast iteration. Also, the maximum value for batch_size may be limited if your model + data set does not fit into the available (GPU) memory.- steps_per_epoch   the number of batch iterations before a training epoch is considered finished. If you have a training set of fixed size you can ignore it but it may be useful if you have a huge data set or if you are generating random data augmentations on the fly, i.e. if your training set has a (generated) infinite size. If you have the time to go through your whole training data set I recommend to skip this parameter.- validation_steps   similar to steps_per_epoch but on the validation data set instead on the training data. If you have the time to go through your whole validation data set I recommend to skip this parameter.<jupyter_code># Set to the original weights for testing other pipelines
model.set_weights(initial_weights)

# Fit the model
hist=model.fit(x_train, 
               y_train, 
               validation_data=(x_test, y_test),
               callbacks=[UDFPrint((x_test, y_test, x_train, y_train)), tbCallBack],
               epochs=EPOCHS, 
               batch_size=BATCH_SIZE,
               verbose=2)
print(hist.history)
score = model.evaluate(x_test, 
                       y_test, 
                       verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
score = model.evaluate(x_train, 
                       y_train, 
                       verbose=0)
print('Train loss:', score[0])
print('Train accuracy:', score[1])
# with keras optimiser we save save the model+weight
model.save('../results/Models/Mnist/keras_model.h5')
!ls ../results/Models/Mnist/<jupyter_output>[34mckpt[m[m           keras_model.h5 [34mpb[m[m<jupyter_text>start in a separte shell with the env activated:tensorboard --logdir your_path/proj_DL_models_and_pipelines_with_GCP/results/TensorBoard/Mnist/logs<jupyter_code>## Fit the model using Keras annd tf.data.dataset<jupyter_output><empty_output><jupyter_text>Set to the original weights for testing other pipelinesmodel.set_weights(initial_weights) Fit the model (using data.Dataset)hist=model.fit(input_dataset_fn(x_train, y_train, mode=tf.estimator.ModeKeys.TRAIN, batch_size=FLAGS.batch_size),  use batch_size               steps_per_epoch=len(x_train) // BATCH_SIZE,               validation_data=input_dataset_fn(x_test, y_test, mode=tf.estimator.ModeKeys.EVAL, batch_size=len(x_test)),  use full validation dataset               validation_steps=1,               callbacks=[UDFPrint((x_test, y_test, x_train, y_train)), tbCallBack],               epochs=EPOCHS,               verbose = 2) print(hist.history) score = model.evaluate(x_test,                        y_test,                        verbose=0)print('Test loss:', score[0])print('Test accuracy:', score[1]) score = model.evaluate(x_train,                        y_train,                        verbose=0)print('Train loss:', score[0])print('Train accuracy:', score[1])<jupyter_code>start in a separte shell with the env activated:
tensorboard --logdir your_path/proj_DL_models_and_pipelines_with_GCP/results/TensorBoard/Mnist/logs<jupyter_output><empty_output><jupyter_text>Fit the model using tf.estimator and tf.data.dataset Create some helper function<jupyter_code>class TimeHistory(tf.train.SessionRunHook):
    def begin(self):
        self.times = []

    def before_run(self, run_context):
        self.iter_time_start = time.time()

    def after_run(self, run_context, run_values):
        self.times.append(time.time() - self.iter_time_start)
time_hist = TimeHistory()<jupyter_output><empty_output><jupyter_text>Use tf.distribute.startegy work across multiple devices/machines<jupyter_code># the tf.distribute.Strategy API is an easy way to distribute your training across multiple devices/machines

strategy=None
## doesn't work with Keras ?!?
#strategy = tf.distribute.Strategy('device:CPU:0')
#strategy = tf.distribute.Strategy('device:GPU:0')
#NUM_GPUS = 2
#strategy = tf.contrib.distribute.MirroredStrategy(num_gpus=NUM_GPUS)
#strategy = tf.contrib.distribute.MirroredStrategy()



# config tf.estimator to use a give strategy
training_config = tf.estimator.RunConfig(train_distribute=strategy,
                                         model_dir=FLAGS.model_dir,
                                         save_summary_steps=20,
                                         save_checkpoints_steps=20)<jupyter_output><empty_output><jupyter_text>transfor keras model to estimator modeldelete fist the folder for a clean start<jupyter_code>! rm -r ../results/Models/Mnist/ckpt
# Set to the original weights for testing other pipelines
model.set_weights(initial_weights)

# transfor keras model to estimator model
estimator_train_model = tf.keras.estimator.model_to_estimator(keras_model=model,
                                                              config=training_config)
#estimator_train_model = tf.keras.estimator.model_to_estimator(keras_model=model)
!ls ../results/Models/Mnist/ckpt<jupyter_output>[34mkeras[m[m<jupyter_text>Training our model<jupyter_code>train(
    input_fn,
    hooks=None,
    steps=None,
    max_steps=None,
    saving_listeners=None
)<jupyter_output><empty_output><jupyter_text>def get_train_input_fn():    return input_dataset_fn(x_train,                            y_train,                             mode=tf.estimator.ModeKeys.TRAIN,                             batch_size=FLAGS.batch_size)  Fit the model (using estimator.train and data.Dataset)estimator_train_model.train(input_fn=lambda: input_dataset_fn(x_train, y_train, mode=tf.estimator.ModeKeys.TRAIN, batch_size=FLAGS.batch_size),                            hooks=[time_hist],                            steps=10)estimator_train_model.train(input_fn=get_train_input_fn,                            steps=10),                            hooks=[time_hist]) total_time = sum(time_hist.times)print(f"total time with the current strategy: {total_time} seconds") avg_time_per_batch = np.mean(time_hist.times)print(f"{BATCH_SIZE/avg_time_per_batch} images/second")<jupyter_code>start in a separte shell with the env activated:
tensorboard --logdir your_path/proj_DL_models_and_pipelines_with_GCP/results/Models/Mnist/ckpt<jupyter_output><empty_output><jupyter_text>Evaluating the accuracy of our model<jupyter_code>evaluate(
    input_fn,
    steps=None,
    hooks=None,
    checkpoint_path=None,
    name=None
)<jupyter_output><empty_output><jupyter_text>score=estimator_train_model.evaluate(input_fn=lambda:input_dataset_fn(x_train,y_train, mode=tf.estimator.ModeKeys.TRAIN, batch_size=len(y_train)),                                    steps=1) score print('Train loss:', score['loss'])print('Train accuracy:', score['categorical_accuracy'])print('Train global steps:', score['global_step']) score=estimator_train_model.evaluate(input_fn=lambda:input_dataset_fn(x_test, y_test,mode=tf.estimator.ModeKeys.EVAL, batch_size=len(x_test))) score print('Test loss:', score['loss'])print('Test accuracy:', score['categorical_accuracy'])print('Test global steps:', score['global_step'])<jupyter_code>### Generating predictions on our trained model<jupyter_output><empty_output><jupyter_text>predict(    input_fn,    predict_keys=None,    hooks=None,    checkpoint_path=None,    yield_single_examples=True)<jupyter_code>predictions=list(estimator_train_model.predict(input_fn=lambda:input_dataset_fn(x_test, y_test,mode=tf.estimator.ModeKeys.EVAL, batch_size=len(x_test))))
len(predictions)
predictions[0].keys()
model.input_names
model.output_names
estimator_train_model.get_variable_names()
len(predictions)
for i in range(10):
    prediction_array = predictions[i]['dense_1']
    predicted_label = np.argmax(prediction_array)
    print('Actual label:', np.argmax(y_test[i]))
    print("Predicted label: ", predicted_label)<jupyter_output>Actual label: 7
Predicted label:  7
Actual label: 2
Predicted label:  2
Actual label: 1
Predicted label:  1
Actual label: 0
Predicted label:  0
Actual label: 4
Predicted label:  4
Actual label: 1
Predicted label:  1
Actual label: 4
Predicted label:  4
Actual label: 9
Predicted label:  9
Actual label: 5
Predicted label:  4
Actual label: 9
Predicted label:  7<jupyter_text>Model serving<jupyter_code>estimator_train_model.params
estimator_train_model.get_variable_names()
def serving_input_receiver_fn():
    """Serving input_fn that builds features from placeholders#

    Returns
    -------
    tf.estimator.export.ServingInputReceiver
    """
    input_images = tf.placeholder(tf.float32, [None, 784])
    features = {'dense_input' : input_images} # this is the dict that is then passed as "features" parameter to your model_fn
    receiver_tensors = {'dense_input': input_images} # As far as I understand this is needed to map the input to a name you can retrieve later
   
    return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)
estimator_train_model.export_saved_model(FLAGS.saved_dir, 
                                         serving_input_receiver_fn=serving_input_receiver_fn)
! saved_model_cli show --dir ../results/Models/Mnist/pb/1548880864/ --tag serve --signature_def serving
!python -c "import tensorflow as tf; print(tf.GIT_VERSION, tf.VERSION)"
!conda list<jupyter_output># packages in environment at /Users/tarrade/anaconda3/envs/env_gcp_dl_1_13:
#
# Name                    Version                   Build  Channel
absl-py                   0.7.0                     <pip>
appnope                   0.1.0            py36hf537a9a_0  
asn1crypto                0.24.0                   py36_0  
astor                     0.7.1                     <pip>
astroid                   2.1.0                    py36_0  
atomicwrites              1.2.1                    py36_0  
attrs                     18.2.0           py36h28b3542_0  
autopep8                  1.4.3                    py36_0  
backcall                  0.1.0                    py36_0  
blas                      1.0                         mkl  
bleach                    3.1.0                    py36_0  
ca-certificates           2018.12.5                     0  
certifi                   2018.11.29               py36_0  
cffi                      1.11.5           py36h6174b99_1  
ch[...]
{'fraction_non_alphanumeric': 0.10638297872340426, 'fraction_numerical': 0.02338916553493285, 'mean_word_length': 3.450805910006716, 'pattern_counts': {'":': 0, '<': 103, '<?xml version=': 0, '>': 107, 'https://': 4, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 5, 'word_list_counts': {'cursed_substrings.json': 23, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '27', 'dir': 'jupyter-structured-clean-dedup', 'id': '254269', 'license': 'Apache-2.0', 'n_tokens_mistral': 8992, 'n_tokens_neox': 8447, 'n_words': 1894, 'path': 'notebook/TF_2.0/08_Example_mnist_keras_estimator_tf_1_13.ipynb', 'repo_name': 'tarrade/proj_DL_models_and_pipelines_with_GCP', 'size': '26508'}