1.4 MiB
Post-training integer quantization¶
Overview¶
Integer quantization is an optimization strategy that converts 32-bit floating-point numbers (such as weights and activation outputs) to the nearest 8-bit fixed-point numbers. This results in a smaller model and increased inferencing speed, which is valuable for low-power devices such as the OpenMV camera
Setup¶
In order to quantize both the input and output tensors, we need to use APIs added in TensorFlow 2.3:
import os import logging os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' logging.getLogger('tensorflow').setLevel(logging.ERROR) import matplotlib.pyplot as plt import numpy as np import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.models import Sequential
Generate a TensorFlow Model¶
We'll build a simple model to classify a few playing cards.
batch_size = 58 img_height = 120 img_width = 120 train_ds = tf.keras.utils.image_dataset_from_directory( "images/", #color_mode='grayscale', validation_split=0.2, subset="training", seed=123, image_size=(img_height, img_width), batch_size=batch_size) val_ds = tf.keras.utils.image_dataset_from_directory( "images/", #color_mode='grayscale', validation_split=0.2, subset="validation", seed=123, image_size=(img_height, img_width), batch_size=batch_size) # print info on the classes in the dataset class_names = train_ds.class_names num_classes = len(class_names) print("number of classes:", num_classes) plt.figure(figsize=(10, 10)) for images, labels in train_ds.take(3): for i in range(9): ax = plt.subplot(3, 3, i + 1) plt.imshow(images[i].numpy().astype("uint8")) plt.title(class_names[labels[i]]) plt.axis("off")
Found 97 files belonging to 5 classes. Using 78 files for training.
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR I0000 00:00:1726357209.971252 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.016076 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.016287 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.017355 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.017543 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.017701 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.082813 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.083011 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355 I0000 00:00:1726357210.083177 177727 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
Found 97 files belonging to 5 classes. Using 19 files for validation. number of classes: 5
479/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9829 - loss: 0.0583
516/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9828 - loss: 0.0585
553/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9827 - loss: 0.0587
590/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9827 - loss: 0.0589
627/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9826 - loss: 0.0591
664/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9826 - loss: 0.0593
700/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9825 - loss: 0.0594
736/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9825 - loss: 0.0596
772/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9825 - loss: 0.0597
808/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9824 - loss: 0.0598
844/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9824 - loss: 0.0599
881/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9824 - loss: 0.0600
918/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9824 - loss: 0.0600
956/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9823 - loss: 0.0601
993/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9823 - loss: 0.0602
1030/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9823 - loss: 0.0603
1067/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9823 - loss: 0.0604
1105/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9823 - loss: 0.0605
1143/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9822 - loss: 0.0606
1181/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0606
1218/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0607
1256/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0608
1295/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0608
1334/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0609
1373/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0609
1412/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0610
1451/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9822 - loss: 0.0610
1489/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0611
1528/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0611
1566/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0612
1603/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0612
1641/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0613
1679/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0613
1718/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0614
1756/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0614
1795/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9821 - loss: 0.0614
1833/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9820 - loss: 0.0615
1870/1875 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.9820 - loss: 0.0615
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 3s 2ms/step - accuracy: 0.9820 - loss: 0.0615 - val_accuracy: 0.9797 - val_loss: 0.0668
<keras.src.callbacks.history.History at 0x7f0f06a4f5b0>
image_list = [] # Initialize an empty list to store the images label_list = [] # Initialize an empty list to store the labels for images, labels in val_ds: # Take the first batch for i in range(len(images)): image_list.append(images[i].numpy()) # Convert to NumPy and store in the list label_list.append(labels[i].numpy()) # Convert to NumPy and store in the list # Convert the list of NumPy arrays into a single NumPy array image_array = np.array(image_list) test_labels = np.array(label_list) # Now apply astype and normalization test_images = image_array.astype(np.float32) / 255.0 image_list = [] # Initialize an empty list to store the images label_list = [] # Initialize an empty list to store the labels for images, labels in train_ds: # Take the first batch for i in range(len(images)): image_list.append(images[i].numpy()) # Convert to NumPy and store in the list label_list.append(labels[i].numpy()) # Convert to NumPy and store in the list # Convert the list of NumPy arrays into a single NumPy array image_array = np.array(image_list) train_labels = np.array(label_list) # Now apply astype and normalization train_images = image_array.astype(np.float32) / 255.0
image_list = [] # Initialize an empty list to store the images label_list = [] # Initialize an empty list to store the labels for images, labels in train_ds: # Take the first batch for i in range(len(images)): image_list.append(images[i].numpy()) # Convert to NumPy and store in the list label_list.append(labels[i].numpy()) # Convert to NumPy and store in the list # Convert the list of NumPy arrays into a single NumPy array image_array = np.array(image_list) train_labels = np.array(label_list) # Now apply astype and normalization train_images = image_array.astype(np.float32) / 255.0 first_image = train_images[0] print(np.min(first_image), np.max(first_image))
0.2882355 0.99411756
In this step we will do a little data augmentation so that the model does not overfit
# Augment training data data_augmentation = keras.Sequential( [ layers.RandomFlip("horizontal", input_shape=(img_height, img_width, 3)), layers.RandomRotation(0.4), layers.RandomZoom(0.1), ] ) # Visualize Change plt.figure(figsize=(10, 10)) for images, _ in train_ds.take(1): for i in range(9): augmented_images = data_augmentation(images) ax = plt.subplot(3, 3, i + 1) plt.imshow(augmented_images[0].numpy().astype("uint8")) plt.axis("off")
/home/brickman/miniconda3/envs/openmv_train/lib/python3.10/site-packages/keras/src/layers/preprocessing/tf_data_layer.py:19: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead. super().__init__(**kwargs)
Let's set up our model architecture and decide whether we want to use transfer learning or build the model from scratch. Transfer learning may include more overhead for the edge device but is better with less data, making it faster to build and train.
Choose whether you want to use transfer learning by setting the transfer_learning
parameter to True
or False
.
transfer_learning = True if transfer_learning: # Load the pre-trained MobileNetV2 model (excluding the top classification layer) base_model = tf.keras.applications.MobileNetV2(input_shape=(img_height, img_width, 3), include_top=False, # Do not include the final classification layer weights='imagenet') # Use weights pre-trained on ImageNet base_model.trainable = False # Freeze the base model so its weights won't be updated during training # Create the model model = Sequential([ data_augmentation, base_model, # Add the pre-trained MobileNetV2 layers.GlobalAveragePooling2D(), # Use global average pooling instead of flattening layers.Dense(128, activation='relu'), # Add a fully connected layer layers.Dropout(0.2), # Dropout to reduce overfitting layers.Dense(num_classes, name="outputs", activation='softmax') # Final classification layer (for 10 classes) ]) else: model = Sequential([ layers.InputLayer(input_shape(img_height, img_width, 3), batch_size=1), # Proper InputLayer with batch_size=1 data_augmentation, layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(128, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Dropout(0.2), layers.Flatten(), layers.Dense(24, activation='relu'), layers.Dense(48, activation='relu'), layers.Dense(num_classes, name="outputs", activation='softmax') ]) # compile the model model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) # give a nice summary of the model architecture model.summary()
/tmp/ipykernel_177727/819969002.py:5: UserWarning: `input_shape` is undefined or non-square, or `rows` is not in [96, 128, 160, 192, 224]. Weights for input shape (224, 224) will be loaded as the default. base_model = tf.keras.applications.MobileNetV2(input_shape=(img_height, img_width, 3),
Model: "sequential_1"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ sequential (Sequential) │ (None, 120, 120, 3) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ mobilenetv2_1.00_224 │ (None, 4, 4, 1280) │ 2,257,984 │ │ (Functional) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ global_average_pooling2d │ (None, 1280) │ 0 │ │ (GlobalAveragePooling2D) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 128) │ 163,968 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout (Dropout) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ outputs (Dense) │ (None, 5) │ 645 │ └─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 2,422,597 (9.24 MB)
Trainable params: 164,613 (643.02 KB)
Non-trainable params: 2,257,984 (8.61 MB)
Training Model¶
Now that we have setup are model's architecture lets train our model
epochs = 100 history = model.fit( train_images, train_labels, epochs=epochs, validation_data=(test_images, test_labels) )
Epoch 1/100
/home/brickman/miniconda3/envs/openmv_train/lib/python3.10/site-packages/keras/src/backend/tensorflow/nn.py:635: UserWarning: "`sparse_categorical_crossentropy` received `from_logits=True`, but the `output` argument was produced by a Softmax activation and thus does not represent logits. Was this intended? output, from_logits = _get_logits( W0000 00:00:1726357216.800337 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.819953 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.821099 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.828785 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.830769 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.832719 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.834030 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.836192 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.837501 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.855066 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.962140 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.963683 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.966329 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.968056 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.989936 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.991655 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.993431 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.996330 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357216.999003 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.002068 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.005231 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.008253 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.011157 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.013318 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.015547 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.018033 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.021012 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.023248 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.026339 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.029253 177813 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 47ms/step - accuracy: 0.2181 - loss: 2.0655
W0000 00:00:1726357217.334963 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.336193 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.337305 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.338814 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.340084 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.341282 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.342461 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.343583 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.344710 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.345837 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.346965 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.348335 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.349593 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.350913 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.352279 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.353686 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.355036 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.356617 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.357905 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.359370 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.360732 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.362069 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.363444 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.364888 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.366474 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.367893 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.369443 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357217.370858 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced
3/3 ━━━━━━━━━━━━━━━━━━━━ 4s 398ms/step - accuracy: 0.2373 - loss: 2.0153 - val_accuracy: 0.4737 - val_loss: 1.2687 Epoch 2/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.7404 - loss: 0.6928 - val_accuracy: 0.6316 - val_loss: 0.8260 Epoch 3/100
W0000 00:00:1726357218.034327 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.035458 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.036568 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.038225 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.039556 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.040762 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.041962 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.043101 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.044236 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.045447 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.046593 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.048033 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.049332 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.050737 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.052219 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.053743 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.055201 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.056975 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.058376 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.059985 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.061481 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.062938 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.064427 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.066005 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.067798 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.069361 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.071101 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726357218.072682 177812 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.8503 - loss: 0.4061 - val_accuracy: 0.5789 - val_loss: 0.6591 Epoch 4/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.8076 - loss: 0.4528 - val_accuracy: 0.6842 - val_loss: 0.7452 Epoch 5/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9445 - loss: 0.2263 - val_accuracy: 0.7895 - val_loss: 0.5651 Epoch 6/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 38ms/step - accuracy: 0.8965 - loss: 0.2498 - val_accuracy: 0.8421 - val_loss: 0.4142 Epoch 7/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.8848 - loss: 0.2633 - val_accuracy: 0.8421 - val_loss: 0.4038 Epoch 8/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9509 - loss: 0.2042 - val_accuracy: 0.8421 - val_loss: 0.3523 Epoch 9/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.8798 - loss: 0.2198 - val_accuracy: 0.8421 - val_loss: 0.3389 Epoch 10/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9534 - loss: 0.1349 - val_accuracy: 0.8421 - val_loss: 0.3604 Epoch 11/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9716 - loss: 0.0719 - val_accuracy: 0.7895 - val_loss: 0.3791 Epoch 12/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9186 - loss: 0.1475 - val_accuracy: 0.8947 - val_loss: 0.3160 Epoch 13/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.9250 - loss: 0.1747 - val_accuracy: 0.8947 - val_loss: 0.2067 Epoch 14/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9406 - loss: 0.1366 - val_accuracy: 0.9474 - val_loss: 0.1961 Epoch 15/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9445 - loss: 0.1685 - val_accuracy: 0.8947 - val_loss: 0.2783 Epoch 16/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9534 - loss: 0.1124 - val_accuracy: 0.8947 - val_loss: 0.2823 Epoch 17/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9819 - loss: 0.1058 - val_accuracy: 0.8947 - val_loss: 0.2889 Epoch 18/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9897 - loss: 0.0564 - val_accuracy: 0.8947 - val_loss: 0.3029 Epoch 19/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.9264 - loss: 0.1349 - val_accuracy: 0.8947 - val_loss: 0.2102 Epoch 20/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9637 - loss: 0.0832 - val_accuracy: 0.9474 - val_loss: 0.1600 Epoch 21/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0557 - val_accuracy: 0.9474 - val_loss: 0.1391 Epoch 22/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9431 - loss: 0.1461 - val_accuracy: 0.8947 - val_loss: 0.1811 Epoch 23/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9665 - loss: 0.0685 - val_accuracy: 0.9474 - val_loss: 0.1729 Epoch 24/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9612 - loss: 0.0803 - val_accuracy: 0.9474 - val_loss: 0.1309 Epoch 25/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9716 - loss: 0.0867 - val_accuracy: 0.9474 - val_loss: 0.1322 Epoch 26/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0355 - val_accuracy: 0.9474 - val_loss: 0.1303 Epoch 27/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9367 - loss: 0.1395 - val_accuracy: 0.9474 - val_loss: 0.1509 Epoch 28/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 38ms/step - accuracy: 0.9794 - loss: 0.0619 - val_accuracy: 0.8421 - val_loss: 0.2339 Epoch 29/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9651 - loss: 0.0518 - val_accuracy: 0.8421 - val_loss: 0.2864 Epoch 30/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9534 - loss: 0.1049 - val_accuracy: 0.8947 - val_loss: 0.2026 Epoch 31/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0255 - val_accuracy: 0.9474 - val_loss: 0.1675 Epoch 32/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9637 - loss: 0.0935 - val_accuracy: 0.9474 - val_loss: 0.1276 Epoch 33/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9819 - loss: 0.0436 - val_accuracy: 0.9474 - val_loss: 0.1064 Epoch 34/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9794 - loss: 0.0587 - val_accuracy: 0.9474 - val_loss: 0.1186 Epoch 35/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0234 - val_accuracy: 0.9474 - val_loss: 0.1543 Epoch 36/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9897 - loss: 0.0388 - val_accuracy: 0.8421 - val_loss: 0.2616 Epoch 37/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9716 - loss: 0.0450 - val_accuracy: 0.8421 - val_loss: 0.3819 Epoch 38/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9716 - loss: 0.0580 - val_accuracy: 0.8421 - val_loss: 0.2887 Epoch 39/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0327 - val_accuracy: 0.9474 - val_loss: 0.1340 Epoch 40/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0443 - val_accuracy: 1.0000 - val_loss: 0.1000 Epoch 41/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9819 - loss: 0.0453 - val_accuracy: 1.0000 - val_loss: 0.0908 Epoch 42/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9936 - loss: 0.0317 - val_accuracy: 0.9474 - val_loss: 0.1173 Epoch 43/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 1.0000 - loss: 0.0393 - val_accuracy: 0.8947 - val_loss: 0.2235 Epoch 44/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9897 - loss: 0.0439 - val_accuracy: 0.8947 - val_loss: 0.2219 Epoch 45/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9819 - loss: 0.0424 - val_accuracy: 0.9474 - val_loss: 0.1414 Epoch 46/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9819 - loss: 0.0419 - val_accuracy: 0.8947 - val_loss: 0.1344 Epoch 47/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0116 - val_accuracy: 0.9474 - val_loss: 0.1197 Epoch 48/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9872 - loss: 0.0355 - val_accuracy: 1.0000 - val_loss: 0.0458 Epoch 49/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0174 - val_accuracy: 1.0000 - val_loss: 0.0609 Epoch 50/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9897 - loss: 0.0796 - val_accuracy: 1.0000 - val_loss: 0.0605 Epoch 51/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9637 - loss: 0.1125 - val_accuracy: 1.0000 - val_loss: 0.0857 Epoch 52/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0073 - val_accuracy: 0.8421 - val_loss: 0.2956 Epoch 53/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0133 - val_accuracy: 0.8421 - val_loss: 0.5120 Epoch 54/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0175 - val_accuracy: 0.8421 - val_loss: 0.5815 Epoch 55/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9794 - loss: 0.0523 - val_accuracy: 0.8421 - val_loss: 0.2835 Epoch 56/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 28ms/step - accuracy: 0.9819 - loss: 0.0399 - val_accuracy: 0.9474 - val_loss: 0.0811 Epoch 57/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9936 - loss: 0.0282 - val_accuracy: 1.0000 - val_loss: 0.0485 Epoch 58/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0518 - val_accuracy: 0.9474 - val_loss: 0.0833 Epoch 59/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0224 - val_accuracy: 0.8947 - val_loss: 0.1869 Epoch 60/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9819 - loss: 0.0641 - val_accuracy: 0.8947 - val_loss: 0.1960 Epoch 61/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9936 - loss: 0.0185 - val_accuracy: 0.8947 - val_loss: 0.2296 Epoch 62/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0176 - val_accuracy: 0.8947 - val_loss: 0.2455 Epoch 63/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9897 - loss: 0.0347 - val_accuracy: 0.9474 - val_loss: 0.1655 Epoch 64/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 37ms/step - accuracy: 1.0000 - loss: 0.0240 - val_accuracy: 0.9474 - val_loss: 0.0992 Epoch 65/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9819 - loss: 0.0640 - val_accuracy: 0.8947 - val_loss: 0.1745 Epoch 66/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9936 - loss: 0.0290 - val_accuracy: 0.8947 - val_loss: 0.1984 Epoch 67/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9716 - loss: 0.0526 - val_accuracy: 0.8947 - val_loss: 0.1530 Epoch 68/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0082 - val_accuracy: 0.8947 - val_loss: 0.1839 Epoch 69/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9936 - loss: 0.0211 - val_accuracy: 0.8947 - val_loss: 0.1748 Epoch 70/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9819 - loss: 0.0434 - val_accuracy: 1.0000 - val_loss: 0.0406 Epoch 71/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9936 - loss: 0.0144 - val_accuracy: 1.0000 - val_loss: 0.0327 Epoch 72/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9819 - loss: 0.0381 - val_accuracy: 1.0000 - val_loss: 0.0354 Epoch 73/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0129 - val_accuracy: 1.0000 - val_loss: 0.0431 Epoch 74/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9819 - loss: 0.0261 - val_accuracy: 0.9474 - val_loss: 0.0838 Epoch 75/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9936 - loss: 0.0191 - val_accuracy: 0.9474 - val_loss: 0.0921 Epoch 76/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 1.0000 - loss: 0.0163 - val_accuracy: 0.9474 - val_loss: 0.0705 Epoch 77/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0398 - val_accuracy: 1.0000 - val_loss: 0.0305 Epoch 78/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0062 - val_accuracy: 1.0000 - val_loss: 0.0220 Epoch 79/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 1.0000 - loss: 0.0081 - val_accuracy: 1.0000 - val_loss: 0.0310 Epoch 80/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9897 - loss: 0.0317 - val_accuracy: 1.0000 - val_loss: 0.0296 Epoch 81/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0135 - val_accuracy: 1.0000 - val_loss: 0.0430 Epoch 82/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0453 - val_accuracy: 1.0000 - val_loss: 0.0502 Epoch 83/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 1.0000 - loss: 0.0103 - val_accuracy: 1.0000 - val_loss: 0.0567 Epoch 84/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 1.0000 - loss: 0.0137 - val_accuracy: 0.9474 - val_loss: 0.0686 Epoch 85/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0110 - val_accuracy: 0.9474 - val_loss: 0.0707 Epoch 86/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9534 - loss: 0.0879 - val_accuracy: 1.0000 - val_loss: 0.0606 Epoch 87/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 1.0000 - loss: 0.0065 - val_accuracy: 1.0000 - val_loss: 0.0367 Epoch 88/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 1.0000 - loss: 0.0108 - val_accuracy: 1.0000 - val_loss: 0.0265 Epoch 89/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 1.0000 - loss: 0.0051 - val_accuracy: 1.0000 - val_loss: 0.0277 Epoch 90/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9897 - loss: 0.0246 - val_accuracy: 1.0000 - val_loss: 0.0157 Epoch 91/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 1.0000 - loss: 0.0144 - val_accuracy: 1.0000 - val_loss: 0.0152 Epoch 92/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0042 - val_accuracy: 1.0000 - val_loss: 0.0228 Epoch 93/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9897 - loss: 0.0215 - val_accuracy: 1.0000 - val_loss: 0.0461 Epoch 94/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0045 - val_accuracy: 0.9474 - val_loss: 0.0861 Epoch 95/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0142 - val_accuracy: 0.8947 - val_loss: 0.1580 Epoch 96/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 1.0000 - loss: 0.0039 - val_accuracy: 0.8947 - val_loss: 0.1995 Epoch 97/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0465 - val_accuracy: 0.8947 - val_loss: 0.1079 Epoch 98/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9936 - loss: 0.0257 - val_accuracy: 0.9474 - val_loss: 0.1108 Epoch 99/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9936 - loss: 0.0122 - val_accuracy: 0.8947 - val_loss: 0.2087 Epoch 100/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0078 - val_accuracy: 0.8947 - val_loss: 0.2261
Visualize training results¶
Create plots of the loss and accuracy on the training and validation sets:
acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(15, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show()
Convert to a TensorFlow Lite model¶
Convert using integer-only quantization¶
To quantize the variable data (such as model input/output and intermediates between layers), you need to provide a RepresentativeDataset
. This is a generator function that provides a set of input data that's large enough to represent typical values. It allows the converter to estimate a dynamic range for all the variable data. (The dataset does not need to be unique compared to the training or evaluation dataset.)
To support multiple inputs, each representative data point is a list and elements in the list are fed to the model according to their indices.
To quantize the input and output tensors, and make the converter throw an error if it encounters an operation it cannot quantize, convert the model again with some additional parameters:
def representative_data_gen(): for input_value in tf.data.Dataset.from_tensor_slices(train_images).batch(1).take(100): yield [input_value] converter = tf.lite.TFLiteConverter.from_keras_model(model) converter._experimental_disable_per_channel_quantization_for_dense_layers = True converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_data_gen converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.target_spec.supported_types = [tf.int8] converter.inference_input_type = tf.uint8 converter.inference_output_type = tf.uint8 tflite_model_quant = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmpurjcrmlo/assets
INFO:tensorflow:Assets written to: /tmp/tmpurjcrmlo/assets
Saved artifact at '/tmp/tmpurjcrmlo'. The following endpoints are available: * Endpoint 'serve' args_0 (POSITIONAL_ONLY): TensorSpec(shape=(None, 120, 120, 3), dtype=tf.float32, name='keras_tensor_158') Output Type: TensorSpec(shape=(None, 5), dtype=tf.float32, name=None) Captures: 131556059225376: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556070830352: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556070832640: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556070827712: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556070831936: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556070830176: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061018800: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061017744: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061014400: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061009472: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061012288: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061010704: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061005248: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061009296: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061013520: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061005952: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061284832: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061282896: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061282544: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061285008: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061293104: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061292048: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061294688: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061284480: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061292576: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061297680: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061121168: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061119232: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061121520: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061121344: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061126976: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061125920: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061128384: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061124512: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061127152: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061134368: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061130848: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061130496: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061131552: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061130320: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061129968: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060929664: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060930720: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060926848: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060929488: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060936704: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060935648: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060932128: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060934240: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060936880: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556060934592: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059257088: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059259728: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059255680: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059257616: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059265888: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059264832: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059261312: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059253744: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059266064: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061130144: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059321744: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059322800: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059318928: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059321568: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059328784: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059327728: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059330368: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059319280: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059328256: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059324384: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059353456: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059353104: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059350640: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059353280: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059360672: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059359616: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059362080: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059358208: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059360848: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059364896: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061775472: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061775296: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061776704: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061777232: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061784448: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061783392: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061785856: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061781984: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556059364016: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061781632: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061907248: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061905312: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061787968: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061907424: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061915696: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061914640: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061917280: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061907776: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061915168: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061920272: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061743760: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061741824: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061744112: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061743936: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061749568: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061748512: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061750976: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061747104: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061749744: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061756960: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061753440: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061753088: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061754144: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061752912: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061752560: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062486144: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062487200: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062483328: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062485968: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062493360: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062492304: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062488784: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062490896: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062493536: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556062491248: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061631888: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061633648: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061631536: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061632064: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061640336: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061639280: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061641744: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061629424: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061640512: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061628192: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061484608: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061485664: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061481792: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061484432: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061491648: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061490592: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061493232: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061482144: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061491120: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556061487248: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066710048: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066709696: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066707232: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066709872: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066717264: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066716208: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066718672: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066714800: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066717440: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066721488: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066182944: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066185056: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066181184: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066184704: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066191920: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066190864: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066193328: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066189456: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066192096: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066189104: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065756256: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066190688: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066195968: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065755200: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066196496: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065762240: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065764880: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065760832: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065762768: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065771040: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065761184: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065766464: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065768224: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556065766992: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066720432: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066615264: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066616144: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066617728: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066615616: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066611920: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066610160: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066612800: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066616496: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066614560: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066613504: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066531760: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066532816: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066528944: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066531584: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066538976: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066537920: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066540384: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066536512: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066539152: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066536864: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066268384: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066271024: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066266976: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066268912: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066277184: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066276128: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066278592: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066265040: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066277360: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066611216: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066365808: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066365456: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066362992: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066365632: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066372848: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066371792: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066374432: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066363344: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066372320: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556066377424: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057320784: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057318320: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057317440: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057320960: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057328000: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057326944: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057329408: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057325536: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057328176: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057332224: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057367120: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057366768: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057331344: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057368880: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057376096: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057375040: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057377504: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057373632: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057376272: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057373280: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057384208: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057384560: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057381552: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057382976: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057379616: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057390192: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057392832: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057388784: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057390720: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057398992: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057389136: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057394416: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057396176: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057449040: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057331168: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057455024: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057456080: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057452208: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057454848: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057463648: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057679648: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057678944: TensorSpec(shape=(), dtype=tf.resource, name=None) 131556057682464: TensorSpec(shape=(), dtype=tf.resource, name=None)
/home/brickman/miniconda3/envs/openmv_train/lib/python3.10/site-packages/tensorflow/lite/python/convert.py:983: UserWarning: Statistics for quantized inputs were expected, but not specified; continuing anyway. warnings.warn( WARNING: All log messages before absl::InitializeLog() is called are written to STDERR W0000 00:00:1726357234.059892 177727 tf_tfl_flatbuffer_helpers.cc:392] Ignored output_format. W0000 00:00:1726357234.059913 177727 tf_tfl_flatbuffer_helpers.cc:395] Ignored drop_control_dependency. fully_quantize: 0, inference_type: 6, input_inference_type: UINT8, output_inference_type: UINT8
The internal quantization remains the same as above, but you can see the input and output tensors are now integer format:
interpreter = tf.lite.Interpreter(model_content=tflite_model_quant) input_type = interpreter.get_input_details()[0]['dtype'] print('input: ', input_type) output_type = interpreter.get_output_details()[0]['dtype'] print('output: ', output_type)
input: <class 'numpy.uint8'> output: <class 'numpy.uint8'>
Now you have an integer quantized model that uses integer data for the model's input and output tensors, so it's compatible with integer-only hardware such as the Edge TPU.
Save the models as files¶
You'll need a .tflite
file to deploy your model on other devices. So let's save the converted model to a file and then load it when we run inferences below.
import pathlib tflite_models_dir = pathlib.Path("models/") tflite_models_dir.mkdir(exist_ok=True, parents=True) # Save the quantized model: tflite_model_quant_file = tflite_models_dir/"model_quant.tflite" tflite_model_quant_file.write_bytes(tflite_model_quant)
2876048
Run the TensorFlow Lite model¶
Now we'll run inferences using the TensorFlow Lite Interpreter
to confirm our model's accuracy.
First, we need a function that runs inference with the model and images, and then return the predictions:
# Helper function to run inference on a TFLite model def run_tflite_model(tflite_file, test_image_indices): global test_images # Initialize the interpreter interpreter = tf.lite.Interpreter(model_path=str(tflite_file)) interpreter.allocate_tensors() input_details = interpreter.get_input_details()[0] output_details = interpreter.get_output_details()[0] predictions = np.zeros((len(test_image_indices),), dtype=int) for i, test_image_index in enumerate(test_image_indices): test_image = test_images[test_image_index] # Check if the input type is quantized, then rescale input data to uint8 if input_details['dtype'] == np.uint8: input_scale, input_zero_point = input_details["quantization"] test_image = test_image / input_scale + input_zero_point test_image = np.expand_dims(test_image, axis=0).astype(input_details["dtype"]) interpreter.set_tensor(input_details["index"], test_image) interpreter.invoke() output = interpreter.get_tensor(output_details["index"])[0] predictions[i] = output.argmax() return predictions
Testing the model on one image¶
Now we'll test the performance of the model.
Let's create another function to print our predictions:
import matplotlib.pylab as plt # Change this to test a different image test_image_index = 18 ## Helper function to test the models on one image def test_model(tflite_file, test_image_index): global test_labels predictions = run_tflite_model(tflite_file, [test_image_index]) plt.imshow(test_images[test_image_index]) template = " Model \n True: {true}, Predicted: {predict}" _ = plt.title(template.format(true= str(class_names[test_labels[test_image_index]]), predict=str(class_names[predictions[0]]))) plt.grid(False)
And test the model on an image:
test_model(tflite_model_quant_file, test_image_index)
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
Evaluate the model on all images¶
Now let's run the model using all the test images we loaded at the beginning:
# Helper function to evaluate a TFLite model on all images def evaluate_model(tflite_file, model_type): global test_images global test_labels test_image_indices = range(test_images.shape[0]) predictions = run_tflite_model(tflite_file, test_image_indices) accuracy = (np.sum(test_labels== predictions) * 100) / len(test_images) print('%s model accuracy is %.4f%% (Number of test samples=%d)' % ( model_type, accuracy, len(test_images)))
Evaluate the model:
evaluate_model(tflite_model_quant_file, model_type="Quantized")
Quantized model accuracy is 84.2105% (Number of test samples=19)