<jupyter_start><jupyter_text>Instructions0. If you haven't already, follow [the setup instructions here](https://jennselby.github.io/MachineLearningCourseNotes/setting-up-python3) to get all necessary software installed.0. Read through the code in the following sections:    * [MNIST Data](MNIST-Data)    * [Convolutional Neural Network Model](Convolutional-Neural-Network-Model)    * [Train Model](Train-Model)    * [Validation](Validation)0. Complete the [Exercise](Exercise)<jupyter_code># allow matplotlib graphics to display in the notebook
%matplotlib inline
import matplotlib.pyplot

# import numpy, for image dimension manipulation
import numpy

# import validation methods from scikit-learn
from sklearn.metrics import precision_recall_fscore_support, accuracy_score

# import the dataset and neural network layers from keras
from keras.datasets import mnist
from keras.models import Sequential, Model
from keras.layers.convolutional import Conv2D
from keras.layers import Dense, Flatten
from keras.optimizers import SGD
from keras.utils import to_categorical<jupyter_output>Using TensorFlow backend.<jupyter_text>MNIST Data[MNIST](https://en.wikipedia.org/wiki/MNIST_database) is a famous dataset of images of handwritten numbers. The goal is to be able to figure out which number is in the image.<jupyter_code># constants to describe the MNIST images
NUM_ROWS = 28 
NUM_COLUMNS = 28
NUM_COLORS = 1
IMG_SHAPE = (NUM_ROWS, NUM_COLUMNS, NUM_COLORS)

# constant to describe the MNIST output labels
# there are ten different numbers, 0-9
NUM_CLASSES = 10
# load the data
((images_train, labels_train), (images_test, labels_test)) = mnist.load_data()<jupyter_output><empty_output><jupyter_text>Let's take a look at one particular image and its label, to better understand the dataset.<jupyter_code>matplotlib.pyplot.imshow(images_train[17], cmap='gray')
labels_train[17]<jupyter_output><empty_output><jupyter_text>Convolutional Neural Network Model<jupyter_code>model = Sequential()

# convolutional layers
model.add(Conv2D(input_shape=IMG_SHAPE,
                 filters=8, kernel_size=3, strides=2, padding='same'))
model.add(Conv2D(filters=8, kernel_size=3, strides=2, padding='same'))

# dense layers to consolidate information
model.add(Flatten())
model.add(Dense(units=8, activation='tanh'))

# output layer to make the final decision on which number it is
model.add(Dense(units=NUM_CLASSES, activation='softmax'))<jupyter_output><empty_output><jupyter_text>Train Model<jupyter_code># keras requires a color dimension, so we need to expand each image to have one
images_3d_train = numpy.expand_dims(images_train, axis=3)

# the labels need to be one-hot encoded, to match the ten outputs of our model
labels_onehot_train = to_categorical(labels_train)

# set up the model to be ready for training
model.compile(optimizer=SGD(), loss='categorical_crossentropy')

# fit the model to the training data
model.fit(images_3d_train, labels_onehot_train, epochs=2)<jupyter_output>Epoch 1/2
60000/60000 [==============================] - 9s 153us/step - loss: 1.4788
Epoch 2/2
60000/60000 [==============================] - 9s 142us/step - loss: 1.5431<jupyter_text>Validation<jupyter_code># keras requires a color dimension, so we need to expand each image to have one
images_3d_test = numpy.expand_dims(images_test, axis=3)

# get the predictions from the model
predictions_test_onehot = model.predict(images_3d_test)

# get the index that has the highest probability
predictions_test = numpy.argmax(predictions_test_onehot, axis=1)
# get the overall accuracy
accuracy_score(y_true=labels_test, y_pred=predictions_test)
# get precision, recall, f-score, and number of examples of each digit
# can you see which digits are easiest for the model, and which are hardest?
precision_recall_fscore_support(y_true=labels_test, y_pred=predictions_test)<jupyter_output>/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sklearn/metrics/classification.py:1437: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.
  'precision', 'predicted', average, warn_for)
{'fraction_non_alphanumeric': 0.09884281581485053, 'fraction_numerical': 0.020973963355834138, 'mean_word_length': 6.52994555353902, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 22, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '472142', 'license': 'MIT', 'n_tokens_mistral': 1364, 'n_tokens_neox': 1281, 'n_words': 382, 'path': 'Examples/ConvolutionalNeuralNetworkTuningTutorial.ipynb', 'repo_name': 'FlyN-Nick/advancedML', 'size': '4148'}