OpenMV-Image-Classification/.ipynb_checkpoints/openmv clasification training-checkpoint.ipynb
2024-09-14 19:47:15 -04:00

1.4 MiB
Raw Blame History

None <html lang="en"> <head> </head>

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:

In [1]:
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.

In [2]:
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
No description has been provided for this image

 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
Out[2]:
<keras.src.callbacks.history.History at 0x7f0f06a4f5b0>
In [3]:
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
In [4]:
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

In [5]:
# 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)
No description has been provided for this image

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.

In [6]:
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

In [7]:
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:

In [8]:
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()
No description has been provided for this image

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:

In [ ]:
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:

In [ ]:
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.

In [ ]:
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:

In [ ]:
# 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:

In [ ]:
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:

In [ ]:
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:

In [ ]:
# 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:

In [ ]:
evaluate_model(tflite_model_quant_file, model_type="Quantized")
</html>