In [1]:
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt
In [2]:
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
In [3]:
train_images, test_images = train_images / 255.0, test_images / 255.0
In [4]:
# Build CNN Model
model = models.Sequential()
# Convolutional Layer 1
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
# Convolutional Layer 2
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# Convolutional Layer 3
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# Flatten Layer
model.add(layers.Flatten())
# Fully Connected Layer
model.add(layers.Dense(64, activation='relu'))
# Dropout Layer (prevent overfitting)
model.add(layers.Dropout(0.5))
# Output Layer
model.add(layers.Dense(10, activation='softmax'))
F:\xvdd0\Lib\site-packages\keras\src\layers\convolutional\base_conv.py:113: 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__(activity_regularizer=activity_regularizer, **kwargs)
In [5]:
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
WARNING:tensorflow:TensorFlow GPU support is not available on native Windows for TensorFlow >= 2.11. Even if CUDA/cuDNN are installed, GPU will not be used. Please use WSL2 or the TensorFlow-DirectML plugin.
In [6]:
history = model.fit(train_images, train_labels,
epochs=15,
batch_size=64,
validation_split=0.2)
Epoch 1/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 26s 28ms/step - accuracy: 0.3029 - loss: 1.8678 - val_accuracy: 0.4695 - val_loss: 1.4836 Epoch 2/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 15s 24ms/step - accuracy: 0.4554 - loss: 1.5084 - val_accuracy: 0.5360 - val_loss: 1.3135 Epoch 3/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 17s 27ms/step - accuracy: 0.5113 - loss: 1.3629 - val_accuracy: 0.5670 - val_loss: 1.2429 Epoch 4/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 14s 23ms/step - accuracy: 0.5478 - loss: 1.2703 - val_accuracy: 0.5835 - val_loss: 1.1754 Epoch 5/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 15s 24ms/step - accuracy: 0.5768 - loss: 1.1988 - val_accuracy: 0.6105 - val_loss: 1.0919 Epoch 6/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 14s 22ms/step - accuracy: 0.5969 - loss: 1.1422 - val_accuracy: 0.6371 - val_loss: 1.0124 Epoch 7/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 16s 26ms/step - accuracy: 0.6170 - loss: 1.0894 - val_accuracy: 0.6556 - val_loss: 0.9737 Epoch 8/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 17s 26ms/step - accuracy: 0.6334 - loss: 1.0474 - val_accuracy: 0.6451 - val_loss: 1.0127 Epoch 9/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 18s 29ms/step - accuracy: 0.6444 - loss: 1.0104 - val_accuracy: 0.6652 - val_loss: 0.9519 Epoch 10/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 16s 26ms/step - accuracy: 0.6605 - loss: 0.9723 - val_accuracy: 0.6712 - val_loss: 0.9183 Epoch 11/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 22s 36ms/step - accuracy: 0.6710 - loss: 0.9360 - val_accuracy: 0.6782 - val_loss: 0.9232 Epoch 12/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 19s 30ms/step - accuracy: 0.6806 - loss: 0.9139 - val_accuracy: 0.6778 - val_loss: 0.9368 Epoch 13/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 15s 24ms/step - accuracy: 0.6940 - loss: 0.8751 - val_accuracy: 0.6781 - val_loss: 0.9337 Epoch 14/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 16s 25ms/step - accuracy: 0.6993 - loss: 0.8602 - val_accuracy: 0.6981 - val_loss: 0.8790 Epoch 15/15 625/625 ━━━━━━━━━━━━━━━━━━━━ 14s 23ms/step - accuracy: 0.7079 - loss: 0.8305 - val_accuracy: 0.7035 - val_loss: 0.8670
In [7]:
model.summary()
Model: "sequential"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ conv2d (Conv2D) │ (None, 30, 30, 32) │ 896 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d (MaxPooling2D) │ (None, 15, 15, 32) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_1 (Conv2D) │ (None, 13, 13, 64) │ 18,496 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_1 (MaxPooling2D) │ (None, 6, 6, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_2 (Conv2D) │ (None, 4, 4, 64) │ 36,928 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ flatten (Flatten) │ (None, 1024) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense (Dense) │ (None, 64) │ 65,600 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout (Dropout) │ (None, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_1 (Dense) │ (None, 10) │ 650 │ └─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 367,712 (1.40 MB)
Trainable params: 122,570 (478.79 KB)
Non-trainable params: 0 (0.00 B)
Optimizer params: 245,142 (957.59 KB)
In [8]:
# Build Improved CNN Model
model = models.Sequential()
# Input layer (recommended format)
model.add(layers.Input(shape=(32, 32, 3)))
# Block 1
model.add(layers.Conv2D(32, (3, 3), padding='same', activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(0.25))
# Block 2
model.add(layers.Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(0.25))
# Block 3
model.add(layers.Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(0.5))
# Fully Connected
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dropout(0.5))
# Output Layer
model.add(layers.Dense(10, activation='softmax'))
In [9]:
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
In [10]:
history = model.fit(train_images, train_labels,
epochs=20,
batch_size=64,
validation_split=0.2)
Epoch 1/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 78s 112ms/step - accuracy: 0.2913 - loss: 1.9281 - val_accuracy: 0.4267 - val_loss: 1.6238 Epoch 2/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 78s 124ms/step - accuracy: 0.4169 - loss: 1.5614 - val_accuracy: 0.5375 - val_loss: 1.2908 Epoch 3/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 69s 111ms/step - accuracy: 0.5077 - loss: 1.3634 - val_accuracy: 0.4519 - val_loss: 1.8444 Epoch 4/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 79s 126ms/step - accuracy: 0.5648 - loss: 1.2265 - val_accuracy: 0.6506 - val_loss: 1.0009 Epoch 5/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 93s 144ms/step - accuracy: 0.6098 - loss: 1.1151 - val_accuracy: 0.6329 - val_loss: 1.0250 Epoch 6/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 85s 136ms/step - accuracy: 0.6439 - loss: 1.0282 - val_accuracy: 0.6840 - val_loss: 0.8579 Epoch 7/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 80s 128ms/step - accuracy: 0.6654 - loss: 0.9657 - val_accuracy: 0.6670 - val_loss: 0.9727 Epoch 8/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 74s 118ms/step - accuracy: 0.6831 - loss: 0.9177 - val_accuracy: 0.6676 - val_loss: 0.9951 Epoch 9/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 71s 114ms/step - accuracy: 0.6960 - loss: 0.8833 - val_accuracy: 0.7327 - val_loss: 0.7645 Epoch 10/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 72s 116ms/step - accuracy: 0.7108 - loss: 0.8416 - val_accuracy: 0.7317 - val_loss: 0.7950 Epoch 11/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 72s 115ms/step - accuracy: 0.7226 - loss: 0.8083 - val_accuracy: 0.7275 - val_loss: 0.8434 Epoch 12/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 73s 117ms/step - accuracy: 0.7323 - loss: 0.7823 - val_accuracy: 0.6812 - val_loss: 0.9672 Epoch 13/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 74s 118ms/step - accuracy: 0.7403 - loss: 0.7654 - val_accuracy: 0.7474 - val_loss: 0.7464 Epoch 14/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 74s 119ms/step - accuracy: 0.7473 - loss: 0.7390 - val_accuracy: 0.7528 - val_loss: 0.7215 Epoch 15/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 73s 117ms/step - accuracy: 0.7542 - loss: 0.7251 - val_accuracy: 0.7566 - val_loss: 0.7216 Epoch 16/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 71s 114ms/step - accuracy: 0.7576 - loss: 0.7070 - val_accuracy: 0.7880 - val_loss: 0.6241 Epoch 17/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 74s 118ms/step - accuracy: 0.7650 - loss: 0.6877 - val_accuracy: 0.7829 - val_loss: 0.6402 Epoch 18/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 72s 115ms/step - accuracy: 0.7707 - loss: 0.6713 - val_accuracy: 0.7962 - val_loss: 0.6018 Epoch 19/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 91s 145ms/step - accuracy: 0.7778 - loss: 0.6531 - val_accuracy: 0.7882 - val_loss: 0.6310 Epoch 20/20 625/625 ━━━━━━━━━━━━━━━━━━━━ 88s 141ms/step - accuracy: 0.7772 - loss: 0.6498 - val_accuracy: 0.7941 - val_loss: 0.6105
In [11]:
model.summary()
Model: "sequential_1"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ conv2d_3 (Conv2D) │ (None, 32, 32, 32) │ 896 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ batch_normalization │ (None, 32, 32, 32) │ 128 │ │ (BatchNormalization) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_4 (Conv2D) │ (None, 30, 30, 32) │ 9,248 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_2 (MaxPooling2D) │ (None, 15, 15, 32) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout_1 (Dropout) │ (None, 15, 15, 32) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_5 (Conv2D) │ (None, 15, 15, 64) │ 18,496 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ batch_normalization_1 │ (None, 15, 15, 64) │ 256 │ │ (BatchNormalization) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_6 (Conv2D) │ (None, 13, 13, 64) │ 36,928 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_3 (MaxPooling2D) │ (None, 6, 6, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout_2 (Dropout) │ (None, 6, 6, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ conv2d_7 (Conv2D) │ (None, 6, 6, 128) │ 73,856 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ batch_normalization_2 │ (None, 6, 6, 128) │ 512 │ │ (BatchNormalization) │ │ │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling2d_4 (MaxPooling2D) │ (None, 3, 3, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout_3 (Dropout) │ (None, 3, 3, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ flatten_1 (Flatten) │ (None, 1152) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_2 (Dense) │ (None, 128) │ 147,584 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout_4 (Dropout) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_3 (Dense) │ (None, 10) │ 1,290 │ └─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 866,688 (3.31 MB)
Trainable params: 288,746 (1.10 MB)
Non-trainable params: 448 (1.75 KB)
Optimizer params: 577,494 (2.20 MB)
In [12]:
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print(test_accuracy)
313/313 ━━━━━━━━━━━━━━━━━━━━ 6s 17ms/step - accuracy: 0.7926 - loss: 0.6299 0.7925999760627747
In [13]:
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['Train', 'Validation'])
plt.show()
In [14]:
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(['Train', 'Validation'])
plt.show()
In [15]:
pip install scikit-learn
Requirement already satisfied: scikit-learn in f:\xvdd0\lib\site-packages (1.7.2) Requirement already satisfied: numpy>=1.22.0 in f:\xvdd0\lib\site-packages (from scikit-learn) (2.3.5) Requirement already satisfied: scipy>=1.8.0 in f:\xvdd0\lib\site-packages (from scikit-learn) (1.16.3) Requirement already satisfied: joblib>=1.2.0 in f:\xvdd0\lib\site-packages (from scikit-learn) (1.5.2) Requirement already satisfied: threadpoolctl>=3.1.0 in f:\xvdd0\lib\site-packages (from scikit-learn) (3.5.0) Note: you may need to restart the kernel to use updated packages.
In [16]:
from sklearn.metrics import confusion_matrix, classification_report
import seaborn as sns
import numpy as np
In [17]:
# Predict classes
predictions = model.predict(test_images)
predicted_labels = np.argmax(predictions, axis=1)
# Flatten true labels
true_labels = test_labels.flatten()
313/313 ━━━━━━━━━━━━━━━━━━━━ 4s 11ms/step
In [18]:
cm = confusion_matrix(true_labels, predicted_labels)
plt.figure(figsize=(10,8))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['airplane','automobile','bird','cat','deer',
'dog','frog','horse','ship','truck'],
yticklabels=['airplane','automobile','bird','cat','deer',
'dog','frog','horse','ship','truck'])
plt.xlabel("Predicted Label")
plt.ylabel("True Label")
plt.title("Confusion Matrix")
plt.show()
In [19]:
print(classification_report(true_labels, predicted_labels,
target_names=['airplane','automobile','bird','cat','deer',
'dog','frog','horse','ship','truck']))
precision recall f1-score support
airplane 0.75 0.84 0.80 1000
automobile 0.94 0.87 0.90 1000
bird 0.82 0.59 0.69 1000
cat 0.66 0.59 0.62 1000
deer 0.72 0.81 0.76 1000
dog 0.71 0.73 0.72 1000
frog 0.84 0.83 0.83 1000
horse 0.80 0.86 0.83 1000
ship 0.80 0.94 0.86 1000
truck 0.90 0.87 0.89 1000
accuracy 0.79 10000
macro avg 0.79 0.79 0.79 10000
weighted avg 0.79 0.79 0.79 10000
In [20]:
plt.figure(figsize=(12,5))
plt.subplot(1,2,1)
plt.plot(history.history['accuracy'], label='Trainin g Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Accuracy Progress')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
Out[20]:
<matplotlib.legend.Legend at 0x1c5f7560410>
In [21]:
plt.subplot(1,2,2)
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Loss Reduction')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.tight_layout()
plt.show()
In [22]:
class_names = ['airplane','automobile','bird','cat','deer',
'dog','frog','horse','ship','truck']
In [23]:
plt.figure(figsize=(8,8))
for i in range(9):
plt.subplot(3,3,i+1)
plt.imshow(train_images[i])
plt.title(class_names[train_labels[i][0]])
plt.axis('off')
plt.show()
In [24]:
plt.figure(figsize=(8,8))
for i in range(6):
plt.subplot(3,2,i+1)
plt.imshow(test_images[i])
pred = predicted_labels[i]
true = true_labels[i]
plt.title(f"Pred: {class_names[pred]}\nTrue: {class_names[true]}")
plt.axis('off')
plt.show()
In [26]:
model.save("cnn_cifar10_model.keras")
In [ ]: