<jupyter_start><jupyter_text>Prepare the data<jupyter_code>import tensorflow as tf
from tensorflow import keras
import numpy as np

# Model / data parameters
num_classes = 10
input_shape = (28, 28, 1)

# Fetch the dataset
data = (train_X, train_Y), (test_X, test_Y) = tf.keras.datasets.mnist.load_data()
# data = (train_X, train_Y), (test_X, test_Y) = tf.keras.datasets.fashion_mnist.load_data()
print(f"Training size={len(train_X)}, test size={len(test_X)}")

print(f"Type of train_X: {type(train_X)}")
train_X.shape
# re-shape and normalize
# train_X = train_X.reshape(60000, 784)
# test_X = test_X.reshape(10000, 784)

# Scale images to the [0, 1] range
train_X = train_X.astype("float32") / 255
test_X = test_X.astype("float32") / 255
# Make sure images have shape (28, 28, 1)
train_X = np.expand_dims(train_X, -1)
test_X = np.expand_dims(test_X, -1)

# convert class vectors to binary class matrices
train_Y = keras.utils.to_categorical(train_Y, num_classes)
test_Y = keras.utils.to_categorical(test_Y, num_classes)

train_X.shape
from typing import Tuple

def heldout_split(train_data: Tuple, fraction=0.0)-> Tuple:
    (train_X, train_Y) = train_data
    if fraction <= 0:
        return (train_X, train_Y), None
    else:
        total_size = len(train_X)
        train_size = total_size - int(total_size * fraction)

        # Further break training data into train / validation sets
        (train_X, valid_X) = train_X[:train_size], train_X[train_size:] 
        (train_Y, valid_Y) = train_Y[:train_size], train_Y[train_size:]

        return (train_X, train_Y), (valid_X, valid_Y)
train_set, heldout_set = heldout_split((train_X, train_Y), fraction=0.1)
train_X, train_Y = train_set
heldout_X, heldout_Y = heldout_set

# Print training set shape
print("train_X shape:", train_X.shape, "train_Y shape:", train_Y.shape)

# Print the number of training, validation, and test datasets
print(train_X.shape[0], 'train set')
print(heldout_X.shape[0], 'validation set')
print(test_X.shape[0], 'test set')

model = tf.keras.Sequential()

# Must define the input shape in the first layer of the neural network
# model.add(tf.keras.Input(shape=input_shape))
# model.add(tf.keras.layers.Flatten(input_shape=(784,1)))
# model.add(tf.keras.layers.Dense(10, activation='softmax'))

model = keras.Sequential(
    [
        keras.Input(shape=input_shape),
        keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
        keras.layers.MaxPooling2D(pool_size=(2, 2)),
        keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
        keras.layers.MaxPooling2D(pool_size=(2, 2)),
        keras.layers.Flatten(),
        keras.layers.Dropout(0.5),
        keras.layers.Dense(num_classes, activation="softmax"),
    ]
)

# Take a look at the model summary
model.summary()
#Compile the model:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

import keras
import keras.callbacks
from keras.callbacks import ModelCheckpoint

checkpointer = ModelCheckpoint(filepath='model.weights.best.hdf5', verbose = 1, save_best_only=True )
model.fit(train_X,
         train_Y,
         batch_size=64,
         epochs=5,
         validation_data=(heldout_X, heldout_Y),
         callbacks=[checkpointer]
         )<jupyter_output>Train on 54000 samples, validate on 6000 samples
Epoch 1/5
53952/54000 [============================>.] - ETA: 0s - loss: 0.1095 - accuracy: 0.9664
Epoch 00001: val_loss improved from inf to 0.05402, saving model to model.weights.best.hdf5
54000/54000 [==============================] - 32s 595us/sample - loss: 0.1094 - accuracy: 0.9664 - val_loss: 0.0540 - val_accuracy: 0.9852
Epoch 2/5
53888/54000 [============================>.] - ETA: 0s - loss: 0.0814 - accuracy: 0.9751
Epoch 00002: val_loss improved from 0.05402 to 0.04324, saving model to model.weights.best.hdf5
54000/54000 [==============================] - 32s 585us/sample - loss: 0.0813 - accuracy: 0.9751 - val_loss: 0.0432 - val_accuracy: 0.9877
Epoch 3/5
53952/54000 [============================>.] - ETA: 0s - loss: 0.0663 - accuracy: 0.9801
Epoch 00003: val_loss improved from 0.04324 to 0.03947, saving model to model.weights.best.hdf5
54000/54000 [==============================] - 32s 584us/sample - loss: 0.0663 - accuracy:[...]
{'fraction_non_alphanumeric': 0.1658091674462114, 'fraction_numerical': 0.06898971000935454, 'mean_word_length': 4.407079646017699, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 8, 'https://': 0, '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': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '186439', 'license': 'MIT', 'n_tokens_mistral': 1725, 'n_tokens_neox': 1524, 'n_words': 354, 'path': 'notebooks/examples/mnist/keras_mnist.ipynb', 'repo_name': 'jmetzz/sandbox-thinc.ai', 'size': '4276'}