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()
No description has been provided for this image
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()
No description has been provided for this image
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()
No description has been provided for this image
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>
No description has been provided for this image
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()
No description has been provided for this image
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()
No description has been provided for this image
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()
No description has been provided for this image
In [26]:
model.save("cnn_cifar10_model.keras")
In [ ]: