<jupyter_start><jupyter_text>Bring in dependencies<jupyter_code>import tensorflow as tf
import numpy as np
import sklearn
import pandas as pd<jupyter_output><empty_output><jupyter_text>Config<jupyter_code>from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))

np.set_printoptions(linewidth=5000)<jupyter_output><empty_output><jupyter_text>Bring in datasets<jupyter_code>( X_train_raw, y_train_raw ), ( X_test_raw, y_test_raw ) = tf.keras.datasets.mnist.load_data()<jupyter_output><empty_output><jupyter_text>Shuffle datasets<jupyter_code>X_train_shuffled, y_train_shuffled = sklearn.utils.shuffle(X_train_raw, y_train_raw, random_state=777)

X_test_shuffled, y_test_shuffled = sklearn.utils.shuffle(X_test_raw, y_test_raw, random_state=777)<jupyter_output><empty_output><jupyter_text>Normalize (X) example inputs<jupyter_code>X_train_normalized = X_train_shuffled / 255.0

X_test_normalized = X_test_shuffled / 255.0<jupyter_output><empty_output><jupyter_text>One-hot encode (y) label outputs<jupyter_code>y_train_one_hot_encoded = tf.keras.utils.to_categorical(y_train_shuffled)

y_test_one_hot_encoded = tf.keras.utils.to_categorical(y_test_shuffled)<jupyter_output><empty_output><jupyter_text>Sanity check modifications<jupyter_code>sample_index=1

X_train_shuffled[sample_index], X_train_normalized[sample_index], y_train_shuffled[sample_index], y_train_one_hot_encoded[sample_index]
sample_index=3

X_test_shuffled[sample_index], X_test_normalized[sample_index], y_test_shuffled[sample_index], y_test_one_hot_encoded[sample_index]<jupyter_output><empty_output><jupyter_text>Accept modified datasets, reshaping as needed<jupyter_code>X_train = tf.expand_dims(X_train_normalized, axis=-1)
y_train = y_train_one_hot_encoded

X_test = tf.expand_dims(X_test_normalized, axis=-1)
y_test = y_test_one_hot_encoded<jupyter_output><empty_output><jupyter_text>Create model architecture<jupyter_code>tf.random.set_seed(777)

model_001 = tf.keras.Sequential([
    tf.keras.layers.Conv2D(50, (3, 3), padding="same", activation=tf.keras.activations.relu),
    tf.keras.layers.MaxPool2D((2, 2)),
    
    tf.keras.layers.Conv2D(50, (3, 3), padding="same", activation=tf.keras.activations.relu),
    tf.keras.layers.MaxPool2D((2, 2)),
    
    tf.keras.layers.Conv2D(50, (3, 3), padding="same", activation=tf.keras.activations.relu),
    tf.keras.layers.MaxPool2D((2, 2)),
    
    tf.keras.layers.Conv2D(50, (3, 3), padding="same", activation=tf.keras.activations.relu),
    tf.keras.layers.MaxPool2D((2, 2)),
    
    tf.keras.layers.Flatten(),
    
    tf.keras.layers.Dense(50, activation=tf.keras.activations.relu),
    
    tf.keras.layers.Dense(len(y_train[0]), activation=tf.keras.activations.softmax)
    
])

model_001.compile(
    loss=tf.keras.losses.CategoricalCrossentropy(),
    optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
    metrics=[ "accuracy" ]
)

model_001.build(X_train.shape)

model_001.summary()

tf.keras.utils.plot_model(model_001, show_shapes=True)<jupyter_output>Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d_8 (Conv2D)           (60000, 28, 28, 50)       500       
                                                                 
 max_pooling2d_8 (MaxPooling  (60000, 14, 14, 50)      0         
 2D)                                                             
                                                                 
 conv2d_9 (Conv2D)           (60000, 14, 14, 50)       22550     
                                                                 
 max_pooling2d_9 (MaxPooling  (60000, 7, 7, 50)        0         
 2D)                                                             
                                                                 
 conv2d_10 (Conv2D)          (60000, 7, 7, 50)         22550     
                                                      [...]<jupyter_text>Train model<jupyter_code>def learning_rate_schedule(current_epoch, current_learning_rate):
    return current_learning_rate

model_001_history = model_001.fit(
    X_train,
    y_train,
    epochs=25,
    validation_data=(X_test, y_test),
    callbacks=[
        tf.keras.callbacks.LearningRateScheduler(schedule=learning_rate_schedule),
        tf.keras.callbacks.EarlyStopping(monitor="val_accuracy", patience=5, restore_best_weights=True)
    ]
)<jupyter_output>Epoch 1/25
1875/1875 [==============================] - 50s 26ms/step - loss: 0.1747 - accuracy: 0.9456 - val_loss: 0.0509 - val_accuracy: 0.9845 - lr: 0.0010
Epoch 2/25
1875/1875 [==============================] - 57s 30ms/step - loss: 0.0529 - accuracy: 0.9838 - val_loss: 0.0435 - val_accuracy: 0.9850 - lr: 0.0010
Epoch 3/25
1875/1875 [==============================] - 71s 38ms/step - loss: 0.0383 - accuracy: 0.9879 - val_loss: 0.0273 - val_accuracy: 0.9907 - lr: 0.0010
Epoch 4/25
1875/1875 [==============================] - 65s 35ms/step - loss: 0.0299 - accuracy: 0.9903 - val_loss: 0.0295 - val_accuracy: 0.9894 - lr: 0.0010
Epoch 5/25
1875/1875 [==============================] - 65s 35ms/step - loss: 0.0237 - accuracy: 0.9925 - val_loss: 0.0320 - val_accuracy: 0.9903 - lr: 0.0010
Epoch 6/25
1875/1875 [==============================] - 66s 35ms/step - loss: 0.0207 - accuracy: 0.9932 - val_loss: 0.0262 - val_accuracy: 0.9919 - lr: 0.0010
Epoch 7/25
1875/1875 [========================[...]<jupyter_text>Observe training history<jupyter_code>pd.DataFrame(model_001_history.history)
pd.DataFrame(model_001_history.history).plot()
pd.DataFrame(model_001_history.history["loss"]).plot()
pd.DataFrame(model_001_history.history["accuracy"]).plot()
pd.DataFrame(model_001_history.history["val_loss"]).plot()
pd.DataFrame(model_001_history.history["val_accuracy"]).plot()<jupyter_output><empty_output><jupyter_text>Evaluate results- The model weights from the 11th epoch were selected<jupyter_code>model_001.evaluate(X_test, y_test)<jupyter_output>313/313 [==============================] - 2s 5ms/step - loss: 0.0293 - accuracy: 0.9931
{'fraction_non_alphanumeric': 0.16076338347080704, 'fraction_numerical': 0.07536794436357755, 'mean_word_length': 3.663650075414781, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '406591', 'license': 'MIT', 'n_tokens_mistral': 2462, 'n_tokens_neox': 2130, 'n_words': 307, 'path': 'practiceInstances/005MnistHandwritingDigitRecognition/practice_5_mnist_handwriting_digit_recognition.ipynb', 'repo_name': 'pddivine/machineLearningPractice', 'size': '6183'}