add code blocks for practical 3b; cnn fashion dataset.

This commit is contained in:
K
2026-05-03 23:14:08 +05:30
parent 0c674d02f9
commit 811033a359
+233
View File
@@ -0,0 +1,233 @@
# Practical-3b (Convolutional Neural Network - MNIST Fashion Dataset)
Problem Statement: Convolutional Neural Network (CNN): Use MNIST Fashion Dataset and create a classifier to classify fashion clothing into categories.
> [!NOTE]
> Download dataset directly from [source](https://www.kaggle.com/datasets/zalando-research/fashionmnist).
> Dataset available in [Datasets](../Datasets/fashionmnist.zip) directory.
> In the code, dataset is downloaded directly from Keras/TensorFlow in 2nd step (Load Dataset)
---
## Pre-requisities
1. Install packages using `pip`: `pip install tensorflow keras numpy matplotlib seaborn scikit-learn` (`tensorflow` requires Python 3.9 - 3.12)
## Steps
---
## Code
### 1. Import Libraries:
```python3
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Conv2D, AvgPool2D, GlobalAveragePooling2D, Dense
from tensorflow.keras.utils import to_categorical
from sklearn.metrics import confusion_matrix, classification_report
```
### 2. Load Dataset:
```python3
# Fashion MNIST is built into Keras, downloads automatically on first run
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
'''
import numpy as np
import gzip
import os
def load_fashion_mnist(path):
"""Load Fashion MNIST from local .gz files (Kaggle Zalando format)."""
files = {
'X_train': 'train-images-idx3-ubyte.gz',
'y_train': 'train-labels-idx1-ubyte.gz',
'X_test': 't10k-images-idx3-ubyte.gz',
'y_test': 't10k-labels-idx1-ubyte.gz',
}
with gzip.open(os.path.join(path, files['X_train'])) as f:
X_train = np.frombuffer(f.read(), np.uint8, offset=16).reshape(-1, 28, 28)
with gzip.open(os.path.join(path, files['y_train'])) as f:
y_train = np.frombuffer(f.read(), np.uint8, offset=8)
with gzip.open(os.path.join(path, files['X_test'])) as f:
X_test = np.frombuffer(f.read(), np.uint8, offset=16).reshape(-1, 28, 28)
with gzip.open(os.path.join(path, files['y_test'])) as f:
y_test = np.frombuffer(f.read(), np.uint8, offset=8)
return (X_train, y_train), (X_test, y_test)
# Replace the Keras load line with:
(X_train, y_train), (X_test, y_test) = load_fashion_mnist('./fashion-mnist/')
'''
print("Training set shape:", X_train.shape) # (60000, 28, 28)
print("Test set shape: ", X_test.shape) # (10000, 28, 28)
print("Classes:", np.unique(y_train))
```
### 3. Exploratory Data Analysis (EDA):
```python3
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
# Class distribution
unique, counts = np.unique(y_train, return_counts=True)
plt.figure(figsize=(10, 4))
plt.bar([class_names[i] for i in unique], counts)
plt.xticks(rotation=45, ha='right')
plt.title("Training Set Class Distribution")
plt.ylabel("Count")
plt.tight_layout()
plt.show()
# Sample images (one per class)
plt.figure(figsize=(15, 3))
for i, cls in enumerate(class_names):
idx = np.where(y_train == i)[0][0] # index of first image for this class
plt.subplot(1, 10, i + 1)
plt.imshow(X_train[idx], cmap='gray')
plt.title(cls, fontsize=7)
plt.axis('off')
plt.suptitle("Sample Image per Class")
plt.tight_layout()
plt.show()
```
### 4. Preprocess Data:
```python3
# Reshape to add channel dimension: (samples, 28, 28) -> (samples, 28, 28, 1)
X_train = X_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0 # normalize to [0,1]
X_test = X_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0
# One-hot encode labels: e.g. class 3 of 10 -> [0,0,0,1,0,0,0,0,0,0]
y_train_cat = to_categorical(y_train, num_classes=10)
y_test_cat = to_categorical(y_test, num_classes=10)
print("X_train shape:", X_train.shape)
print("y_train_cat shape:", y_train_cat.shape)
```
### 5. Build the CNN Model:
```python3
model = Sequential()
model.add(Input(shape=(28, 28, 1))) # input: 28x28 grayscale image
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu', padding='same')) # 64 filters, extract features
model.add(AvgPool2D(pool_size=(2, 2))) # downsample to 14x14
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', padding='same')) # 32 filters, refine features
model.add(AvgPool2D(pool_size=(2, 2))) # downsample to 7x7
model.add(GlobalAveragePooling2D()) # average each feature map to single value
model.add(Dense(10, activation='softmax')) # output: probability for each of 10 classes
model.summary()
```
### 6. Compile the Model:
```python3
# categorical_crossentropy: standard loss for multi-class one-hot classification
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
```
### 7. Train the Model:
```python3
# validation_data uses test set to monitor performance after each epoch
history = model.fit(X_train, y_train_cat, epochs=10, validation_data=(X_test, y_test_cat))
```
### 8. Evaluate the Model on Test Data:
```python3
loss, accuracy = model.evaluate(X_test, y_test_cat)
print(f"Test Loss: {loss:.4f}")
print(f"Test Accuracy: {accuracy*100:.2f}%")
```
### 9. Plot Training vs Validation Accuracy:
```python3
plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Model Accuracy Over Epochs')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.show()
```
### 10. Plot Training vs Validation Loss:
```python3
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Model Loss Over Epochs')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.show()
```
### 11. Confusion Matrix and Classification Report:
```python3
y_pred = np.argmax(model.predict(X_test), axis=1) # predicted class index
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(10, 8))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=class_names, yticklabels=class_names)
plt.title('Confusion Matrix')
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()
print("\nClassification Report:\n")
print(classification_report(y_test, y_pred, target_names=class_names))
```
### 12. Visualize Sample Predictions:
```python3
# batch predict all test images, then pick 10 random ones to display
all_preds = np.argmax(model.predict(X_test), axis=1)
random_indices = np.random.choice(len(X_test), 10, replace=False)
plt.figure(figsize=(20, 4))
for i, idx in enumerate(random_indices):
plt.subplot(2, 5, i + 1)
plt.imshow(X_test[idx].reshape(28, 28), cmap='gray')
predicted = class_names[all_preds[idx]]
actual = class_names[y_test[idx]]
color = 'green' if predicted == actual else 'red' # green = correct, red = wrong
plt.title(f"P: {predicted}\nA: {actual}", fontsize=8, color=color)
plt.axis('off')
plt.suptitle("Sample Predictions (Green=Correct, Red=Wrong)")
plt.tight_layout()
plt.show()
```
---
## Miscellaneous
- [Dataset source](https://www.kaggle.com/datasets/zalando-research/fashionmnist)
---