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 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
2024-09-14 19:26:49.528256: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:485] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered 2024-09-14 19:26:49.544309: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:8454] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered 2024-09-14 19:26:49.549222: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1452] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered 2024-09-14 19:26:49.561671: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations. To enable the following instructions: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags. 2024-09-14 19:26:50.195875: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT
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:1726356412.152193 168090 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:1726356412.201034 168090 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:1726356412.201280 168090 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:1726356412.202348 168090 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:1726356412.202582 168090 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:1726356412.202769 168090 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:1726356412.292549 168090 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:1726356412.292752 168090 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:1726356412.292919 168090 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 2024-09-14 19:26:52.293158: I tensorflow/core/common_runtime/gpu/gpu_device.cc:2021] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 5600 MB memory: -> device: 0, name: NVIDIA GeForce RTX 3050, pci bus id: 0000:2d:00.0, compute capability: 8.6
Found 97 files belonging to 5 classes. Using 19 files for validation. number of classes: 5
2024-09-14 19:26:53.320173: I tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence
111/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9836 - loss: 0.0545
147/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9837 - loss: 0.0547
184/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9835 - loss: 0.0549
221/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9833 - loss: 0.0559
258/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9831 - loss: 0.0567
295/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9830 - loss: 0.0572
332/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9829 - loss: 0.0575
369/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9829 - loss: 0.0577
406/1875 ━━━━━━━━━━━━━━━━━━━━ 2s 1ms/step - accuracy: 0.9829 - loss: 0.0579
443/1875 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9829 - loss: 0.0581
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
2024-09-14 19:26:56.822115: I tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence
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
2024-09-14 19:26:59.222836: I tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence
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_168090/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( 2024-09-14 19:27:10.386696: I external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:531] Loaded cuDNN version 8907 W0000 00:00:1726356430.467248 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.485512 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.486658 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.495360 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.497357 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.499308 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.500620 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.502785 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.504102 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.521907 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.630649 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.632200 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.634857 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.636585 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.658563 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.660279 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.662139 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.665014 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.667685 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.670758 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.673827 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.676793 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.679584 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.681518 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.683228 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.685087 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.688047 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.690277 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.693367 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356430.695685 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 49ms/step - accuracy: 0.3849 - loss: 1.9038
W0000 00:00:1726356431.021783 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.022984 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.024083 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.025588 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.026889 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.028113 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.029282 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.030394 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.031506 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.032620 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.033733 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.035066 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.036302 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.037617 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.038987 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.040387 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.041732 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.043304 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.044593 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.046044 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.047401 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.048729 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.050096 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.051522 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.053092 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.054510 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.056059 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.057472 168193 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced
3/3 ━━━━━━━━━━━━━━━━━━━━ 4s 420ms/step - accuracy: 0.3976 - loss: 1.8413 - val_accuracy: 0.5263 - val_loss: 1.2608 Epoch 2/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.7404 - loss: 0.6882 - val_accuracy: 0.6316 - val_loss: 0.9502 Epoch 3/100 1/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.8438 - loss: 0.3935
W0000 00:00:1726356431.761672 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.762804 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.763902 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.765542 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.766898 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.768073 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.769267 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.770395 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.771519 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.772649 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.773785 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.775234 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.776535 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.777962 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.779436 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.780947 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.782382 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.784152 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.785550 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.787161 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.788645 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.790093 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.791588 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.793164 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.794950 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.796513 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.798257 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced W0000 00:00:1726356431.799823 168190 gpu_timer.cc:114] Skipping the delay kernel, measurement accuracy will be reduced
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.8464 - loss: 0.4116 - val_accuracy: 0.7368 - val_loss: 0.7621 Epoch 4/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9317 - loss: 0.2455 - val_accuracy: 0.6842 - val_loss: 0.6344 Epoch 5/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.8759 - loss: 0.3613 - val_accuracy: 0.6842 - val_loss: 0.6439 Epoch 6/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.9651 - loss: 0.1515 - val_accuracy: 0.6842 - val_loss: 0.6854 Epoch 7/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9214 - loss: 0.1634 - val_accuracy: 0.6842 - val_loss: 0.5383 Epoch 8/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9445 - loss: 0.2176 - val_accuracy: 0.7895 - val_loss: 0.4033 Epoch 9/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.9612 - loss: 0.1978 - val_accuracy: 0.7895 - val_loss: 0.3957 Epoch 10/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 37ms/step - accuracy: 0.9897 - loss: 0.0959 - val_accuracy: 0.7368 - val_loss: 0.4482 Epoch 11/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9573 - loss: 0.1609 - val_accuracy: 0.7368 - val_loss: 0.4644 Epoch 12/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 37ms/step - accuracy: 0.9897 - loss: 0.0862 - val_accuracy: 0.7895 - val_loss: 0.3869 Epoch 13/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9833 - loss: 0.0579 - val_accuracy: 0.8421 - val_loss: 0.3883 Epoch 14/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9819 - loss: 0.0622 - val_accuracy: 0.8421 - val_loss: 0.4512 Epoch 15/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9897 - loss: 0.0609 - val_accuracy: 0.8421 - val_loss: 0.4793 Epoch 16/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9612 - loss: 0.0720 - val_accuracy: 0.8421 - val_loss: 0.4097 Epoch 17/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9833 - loss: 0.0637 - val_accuracy: 0.7895 - val_loss: 0.3420 Epoch 18/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9612 - loss: 0.1100 - val_accuracy: 0.8421 - val_loss: 0.3505 Epoch 19/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9612 - loss: 0.0986 - val_accuracy: 0.8421 - val_loss: 0.3895 Epoch 20/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 37ms/step - accuracy: 0.9833 - loss: 0.0691 - val_accuracy: 0.8421 - val_loss: 0.4282 Epoch 21/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9651 - loss: 0.1071 - val_accuracy: 0.8421 - val_loss: 0.3757 Epoch 22/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9897 - loss: 0.0423 - val_accuracy: 0.7895 - val_loss: 0.2878 Epoch 23/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9794 - loss: 0.0693 - val_accuracy: 0.7895 - val_loss: 0.2836 Epoch 24/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0236 - val_accuracy: 0.7895 - val_loss: 0.3023 Epoch 25/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 38ms/step - accuracy: 0.9342 - loss: 0.1475 - val_accuracy: 0.8947 - val_loss: 0.2678 Epoch 26/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 37ms/step - accuracy: 0.9897 - loss: 0.0524 - val_accuracy: 0.8947 - val_loss: 0.3377 Epoch 27/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.9651 - loss: 0.1025 - val_accuracy: 0.8947 - val_loss: 0.2798 Epoch 28/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 37ms/step - accuracy: 0.9819 - loss: 0.0805 - val_accuracy: 0.8421 - val_loss: 0.2067 Epoch 29/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9897 - loss: 0.0397 - val_accuracy: 0.8421 - val_loss: 0.3344 Epoch 30/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9612 - loss: 0.0903 - val_accuracy: 0.7895 - val_loss: 0.3593 Epoch 31/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0145 - val_accuracy: 0.8947 - val_loss: 0.3727 Epoch 32/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9897 - loss: 0.0540 - val_accuracy: 0.8947 - val_loss: 0.3414 Epoch 33/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9716 - loss: 0.0738 - val_accuracy: 0.8421 - val_loss: 0.3185 Epoch 34/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.9534 - loss: 0.0842 - val_accuracy: 0.8421 - val_loss: 0.3502 Epoch 35/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9936 - loss: 0.0339 - val_accuracy: 0.8421 - val_loss: 0.3274 Epoch 36/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 1.0000 - loss: 0.0155 - val_accuracy: 0.8421 - val_loss: 0.3008 Epoch 37/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 1.0000 - loss: 0.0287 - val_accuracy: 0.8421 - val_loss: 0.2620 Epoch 38/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9691 - loss: 0.0764 - val_accuracy: 0.8947 - val_loss: 0.2829 Epoch 39/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0433 - val_accuracy: 0.8947 - val_loss: 0.3697 Epoch 40/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9897 - loss: 0.0567 - val_accuracy: 0.8947 - val_loss: 0.3053 Epoch 41/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9730 - loss: 0.0667 - val_accuracy: 0.8947 - val_loss: 0.2928 Epoch 42/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9936 - loss: 0.0212 - val_accuracy: 0.7895 - val_loss: 0.4014 Epoch 43/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9573 - loss: 0.0836 - val_accuracy: 0.7895 - val_loss: 0.5016 Epoch 44/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9353 - loss: 0.1166 - val_accuracy: 0.8947 - val_loss: 0.3694 Epoch 45/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 37ms/step - accuracy: 1.0000 - loss: 0.0143 - val_accuracy: 0.8947 - val_loss: 0.4014 Epoch 46/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9936 - loss: 0.0260 - val_accuracy: 0.8947 - val_loss: 0.4448 Epoch 47/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9637 - loss: 0.0920 - val_accuracy: 0.8947 - val_loss: 0.4216 Epoch 48/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9872 - loss: 0.0301 - val_accuracy: 0.8947 - val_loss: 0.4062 Epoch 49/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9897 - loss: 0.0180 - val_accuracy: 0.8947 - val_loss: 0.3476 Epoch 50/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0244 - val_accuracy: 0.8947 - val_loss: 0.3082 Epoch 51/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9819 - loss: 0.0436 - val_accuracy: 0.8947 - val_loss: 0.3227 Epoch 52/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0109 - val_accuracy: 0.8947 - val_loss: 0.3390 Epoch 53/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0081 - val_accuracy: 0.8947 - val_loss: 0.3357 Epoch 54/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 1.0000 - loss: 0.0131 - val_accuracy: 0.8947 - val_loss: 0.3251 Epoch 55/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0128 - val_accuracy: 0.8947 - val_loss: 0.3439 Epoch 56/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0110 - val_accuracy: 0.8947 - val_loss: 0.3746 Epoch 57/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0406 - val_accuracy: 0.8947 - val_loss: 0.4276 Epoch 58/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9651 - loss: 0.0715 - val_accuracy: 0.8947 - val_loss: 0.2093 Epoch 59/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 28ms/step - accuracy: 1.0000 - loss: 0.0119 - val_accuracy: 0.9474 - val_loss: 0.1279 Epoch 60/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9637 - loss: 0.0817 - val_accuracy: 0.8947 - val_loss: 0.2241 Epoch 61/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9509 - loss: 0.1228 - val_accuracy: 0.9474 - val_loss: 0.0986 Epoch 62/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0417 - val_accuracy: 0.8947 - val_loss: 0.3678 Epoch 63/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 1.0000 - loss: 0.0122 - val_accuracy: 0.8421 - val_loss: 0.7185 Epoch 64/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 0.9936 - loss: 0.0259 - val_accuracy: 0.7895 - val_loss: 0.7323 Epoch 65/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 0.9353 - loss: 0.1039 - val_accuracy: 0.8947 - val_loss: 0.2433 Epoch 66/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9716 - loss: 0.0363 - val_accuracy: 1.0000 - val_loss: 0.0542 Epoch 67/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0499 - val_accuracy: 1.0000 - val_loss: 0.0603 Epoch 68/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9872 - loss: 0.0598 - val_accuracy: 1.0000 - val_loss: 0.0431 Epoch 69/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9637 - loss: 0.0670 - val_accuracy: 0.8947 - val_loss: 0.3316 Epoch 70/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9833 - loss: 0.0394 - val_accuracy: 0.7368 - val_loss: 0.7130 Epoch 71/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9612 - loss: 0.0893 - val_accuracy: 0.7895 - val_loss: 0.4985 Epoch 72/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9612 - loss: 0.0572 - val_accuracy: 0.8947 - val_loss: 0.2079 Epoch 73/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9936 - loss: 0.0202 - val_accuracy: 0.8947 - val_loss: 0.1120 Epoch 74/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 0.9819 - loss: 0.0316 - val_accuracy: 0.8947 - val_loss: 0.1634 Epoch 75/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 1.0000 - loss: 0.0128 - val_accuracy: 0.9474 - val_loss: 0.1917 Epoch 76/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0289 - val_accuracy: 0.9474 - val_loss: 0.1438 Epoch 77/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0136 - val_accuracy: 0.9474 - val_loss: 0.1096 Epoch 78/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 0.9819 - loss: 0.0513 - val_accuracy: 1.0000 - val_loss: 0.0786 Epoch 79/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 0.9819 - loss: 0.0270 - val_accuracy: 0.9474 - val_loss: 0.0851 Epoch 80/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9819 - loss: 0.0416 - val_accuracy: 1.0000 - val_loss: 0.0736 Epoch 81/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 1.0000 - loss: 0.0119 - val_accuracy: 1.0000 - val_loss: 0.0757 Epoch 82/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step - accuracy: 0.9897 - loss: 0.0172 - val_accuracy: 0.9474 - val_loss: 0.0997 Epoch 83/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 36ms/step - accuracy: 1.0000 - loss: 0.0073 - val_accuracy: 0.8947 - val_loss: 0.1681 Epoch 84/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9897 - loss: 0.0184 - val_accuracy: 0.8947 - val_loss: 0.2357 Epoch 85/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0187 - val_accuracy: 0.8947 - val_loss: 0.2395 Epoch 86/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 1.0000 - loss: 0.0045 - val_accuracy: 0.8947 - val_loss: 0.2212 Epoch 87/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 0.9897 - loss: 0.0637 - val_accuracy: 0.8947 - val_loss: 0.1375 Epoch 88/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0052 - val_accuracy: 0.9474 - val_loss: 0.0707 Epoch 89/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - accuracy: 1.0000 - loss: 0.0045 - val_accuracy: 1.0000 - val_loss: 0.0522 Epoch 90/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0074 - val_accuracy: 1.0000 - val_loss: 0.0559 Epoch 91/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0221 - val_accuracy: 0.9474 - val_loss: 0.0867 Epoch 92/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 0.9819 - loss: 0.0324 - val_accuracy: 0.9474 - val_loss: 0.1309 Epoch 93/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0075 - val_accuracy: 0.8947 - val_loss: 0.1963 Epoch 94/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0144 - val_accuracy: 0.8947 - val_loss: 0.2724 Epoch 95/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step - accuracy: 1.0000 - loss: 0.0075 - val_accuracy: 0.8947 - val_loss: 0.3144 Epoch 96/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step - accuracy: 1.0000 - loss: 0.0081 - val_accuracy: 0.8947 - val_loss: 0.3045 Epoch 97/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0094 - val_accuracy: 0.8947 - val_loss: 0.2763 Epoch 98/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step - accuracy: 1.0000 - loss: 0.0055 - val_accuracy: 0.8947 - val_loss: 0.2239 Epoch 99/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step - accuracy: 1.0000 - loss: 0.0071 - val_accuracy: 0.8947 - val_loss: 0.1649 Epoch 100/100 3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - accuracy: 1.0000 - loss: 0.0057 - val_accuracy: 0.8947 - val_loss: 0.1196
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()
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)
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)
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)
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")