import os
PROJECT = 'my-project-id' # REPLACE WITH YOUR PROJECT ID
BUCKET = 'my-bucket-name' # REPLACE WITH YOUR BUCKET NAME
REGION = 'us-central1' # REPLACE WITH YOUR BUCKET REGION e.g. us-central1
MODEL_TYPE='dnn'       # deep neural network

# do not change these
os.environ['PROJECT'] = PROJECT
os.environ['BUCKET'] = BUCKET
os.environ['REGION'] = REGION
os.environ['MODEL_TYPE'] = MODEL_TYPE
os.environ['TFVERSION'] = '1.8'  # Tensorflow version

%bash
gcloud config set project $PROJECT
gcloud config set compute/region $REGION
gsutil -m rm -rf gs://${BUCKET}/fashion/trained_${MODEL_TYPE}

"""
Explanation: Fashion-MNIST Image Classification with TensorFlow
This notebook demonstrates how to implement a deep neural network image classification model on Fashion-MNIST using TensorFlow Estimator API.
End of explanation
"""


import numpy as np
import shutil
import os
import tensorflow as tf
print(tf.__version__)

"""
Explanation: The messages above in pink look like errors, but they are just warnings. Don't worry about the exception mentioning a file that could not be removed. The command that caused it simply tried to delete any previous models in case you are re-running this notebook.
End of explanation
"""


#The copyright for Fashion-MNIST is held by Zalando SE.
#Fashion-MNIST is licensed under the MIT License.
#You can learn more about the Fashion-MNIST dataset  
#from https://github.com/zalandoresearch/fashion-mnist
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.fashion_mnist.load_data()
print("Done")

#Convert the dataset into the format needed for the classifier
train_images = train_images.astype('float32')
test_images = test_images.astype('float32')
train_labels = train_labels.astype('int32')
test_labels = test_labels.astype('int32')

print(train_images.shape)
print(train_labels.shape)
print(test_images.shape)
print(test_labels.shape)

HEIGHT=28
WIDTH=28
NCLASSES=10
IMGNO=12

#Take a look at a sample image from the dataset
import matplotlib.pyplot as plt
plt.imshow(train_images[IMGNO].reshape(HEIGHT, WIDTH));

tf.logging.set_verbosity(tf.logging.INFO)

#define a training input function
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={'image': train_images},
    y=train_labels,
    num_epochs=None,  
    shuffle=True,  
    batch_size=600,
    queue_capacity=5000
  )

#define an input function for evaluation of the accuracy metric using a test dataset
test_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={'image': test_images},
    y=test_labels,
    num_epochs=1,
    shuffle=False,
    queue_capacity=5000
  )

#create a Deep Neural Network based classifier using 3 hidden layers, 100 neurons each,
#and classifying the input into 1 of 10 classes (i.e. categories). 
model = tf.estimator.DNNClassifier(
  feature_columns=[tf.feature_column.numeric_column('image', shape=[HEIGHT, WIDTH])],
  hidden_units=[100, 100, 100],
  n_classes = NCLASSES,
  model_dir = 'gs://{}/fashion/trained_{}'.format(BUCKET, MODEL_TYPE)
)

"""
Explanation: Exploring the data
Let's download  Fashion MNIST data and examine the shape. Take note of the numbers you will get. You will use them throughout this notebook.
End of explanation
"""


#Train the model
model.train(input_fn = train_input_fn, steps = 1000)

#Evaluate accuracy of the trained model
accuracy_score = model.evaluate(input_fn=test_input_fn)["accuracy"]

"""
Explanation: Check your understanding
If the previous cell executed successfully, it should have logged an output similar to the following:
<pre>
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_task_type': 'worker', '_train_distribute': None, '_is_chief': True, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x7f1d5e26d810>, '_evaluation_master': '', '_save_checkpoints_steps': None, '_keep_checkpoint_every_n_hours': 10000, '_service': None, '_num_ps_replicas': 0, '_tf_random_seed': None, '_master': '', '_num_worker_replicas': 1, '_task_id': 0, '_log_step_count_steps': 100, '_model_dir': 'gs://qwiklabs-gcp-27eb45524d98e9a5/fashion/trained_dnn', '_global_id_in_cluster': 0, '_save_summary_steps': 100}
</pre>

Go ahead and run the next code cell to begin training, and then return back to answer the following question:
Quiz: Remember that the <code>train_input_fn</code> method sets the <code>num_epochs</code> parameter, i.e. the number of epochs for training to be <code>None</code>. This means that the duration of training depends on the number of steps. Recall that earlier in this notebook you learned that the shape of the training dataset is 60000x28x28 meaning that there are 60000 training examples. If the number of training steps is set to be 1000 when training the model, and the train_input_fn uses a batch size of 600, how many epochs of training does the deep neural net get?
End of explanation
"""


from google.datalab.ml import TensorBoard
TensorBoard().start('gs://{}/fashion/trained_{}'.format(BUCKET, MODEL_TYPE))

for pid in TensorBoard.list()['pid']:
  TensorBoard().stop(pid)
  print 'Stopped TensorBoard with pid {}'.format(pid)

"""
Explanation: DO NOT PROCEED UNTIL YOU CAN SEE THE ACCURACY SCORE
If the training finished successfully, you should see an output above similar to the following:
<pre>
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at ...
INFO:tensorflow:Saving dict for global step 1000: accuracy = ..., average_loss = ..., global_step = ..., loss = ...
</pre>

Due to random seeds, your accuracy may vary. In the upcoming labs you will see methods to improve the performance of your image classifier. 
Monitoring training with TensorBoard
Use this cell to launch tensorboard
End of explanation
"""


