Project Overview
Difficulty: Beginner
Goal: Build a model that classifies images of clothing items
Dataset: Fashion MNIST (70,000 grayscale images)
Time Required: 2-3 hours
What You'll Learn
- Loading and preprocessing image data
- Building a neural network for image classification
- Training and evaluating a model
- Making predictions on new images
- Visualizing results
Step 1: Setup and Data Loading
# Import required libraries
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
# Load Fashion MNIST dataset (built into TensorFlow!)
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
# Class names for the clothing items
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
# Explore the data
print(f"Training set: {train_images.shape}") # (60000, 28, 28)
print(f"Test set: {test_images.shape}") # (10000, 28, 28)
print(f"Image shape: {train_images[0].shape}") # (28, 28)
print(f"Label: {train_labels[0]} = {class_names[train_labels[0]]}")
# Visualize some examples
plt.figure(figsize=(10, 10))
for i in range(25):
plt.subplot(5, 5, i + 1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.binary)
plt.xlabel(class_names[train_labels[i]])
plt.tight_layout()
plt.savefig('fashion_samples.png')
plt.show()
Step 2: Data Preprocessing
# Normalize pixel values to 0-1 range
train_images = train_images / 255.0
test_images = test_images / 255.0
# Verify preprocessing
print(f"Min pixel value: {train_images.min()}") # 0.0
print(f"Max pixel value: {train_images.max()}") # 1.0
# Check a single image
plt.figure(figsize=(5, 5))
plt.imshow(train_images[0], cmap='gray')
plt.colorbar()
plt.title(f'Label: {class_names[train_labels[0]]}')
plt.show()
Step 3: Build the Neural Network
# Create the model architecture
model = keras.Sequential([
# Flatten layer: converts 28x28 image to 784 pixel array
keras.layers.Flatten(input_shape=(28, 28)),
# Hidden layer: 128 neurons with ReLU activation
keras.layers.Dense(128, activation='relu'),
# Dropout: prevents overfitting (randomly drops 20% of connections)
keras.layers.Dropout(0.2),
# Output layer: 10 neurons (one for each class)
keras.layers.Dense(10, activation='softmax')
])
# Display model architecture
model.summary()
# Compile the model
model.compile(
optimizer='adam', # Optimization algorithm
loss='sparse_categorical_crossentropy', # Loss function
metrics=['accuracy'] # Metric to track
)
print("\nModel ready for training!")
Model Architecture Explained
- Input: 28×28 = 784 pixels
- Hidden: 128 neurons learn patterns
- Dropout: Prevents overfitting
- Output: 10 probabilities (one per class)
Step 4: Train the Model
# Train the model
print("Training started...")
history = model.fit(
train_images,
train_labels,
epochs=10, # Number of training cycles
validation_split=0.2, # Use 20% for validation
verbose=1
)
print("\nTraining complete!")
# Plot training history
plt.figure(figsize=(12, 4))
# Accuracy plot
plt.subplot(1, 2, 1)
plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
# Loss plot
plt.subplot(1, 2, 2)
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.savefig('training_history.png')
plt.show()
Step 5: Evaluate the Model
# Evaluate on test set
test_loss, test_accuracy = model.evaluate(test_images, test_labels, verbose=0)
print(f"\nTest Accuracy: {test_accuracy * 100:.2f}%")
print(f"Test Loss: {test_loss:.4f}")
# Make predictions
predictions = model.predict(test_images)
# Examine a single prediction
sample_idx = 0
prediction = predictions[sample_idx]
predicted_label = np.argmax(prediction)
true_label = test_labels[sample_idx]
print(f"\nSample Prediction:")
print(f"Predicted: {class_names[predicted_label]} ({prediction[predicted_label]*100:.2f}%)")
print(f"True label: {class_names[true_label]}")
print(f"Correct: {predicted_label == true_label}")
Step 6: Visualize Predictions
# Function to plot predictions
def plot_image_prediction(i, predictions_array, true_label, img):
predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue' # Correct prediction
else:
color = 'red' # Wrong prediction
plt.xlabel(f"{class_names[predicted_label]} {100*np.max(predictions_array):.0f}% ({class_names[true_label]})",
color=color)
def plot_value_array(i, predictions_array, true_label):
predictions_array, true_label = predictions_array[i], true_label[i]
plt.grid(False)
plt.xticks(range(10))
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
# Plot several predictions
num_rows = 5
num_cols = 3
num_images = num_rows * num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2*num_cols, 2*i+1)
plot_image_prediction(i, predictions, test_labels, test_images)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_value_array(i, predictions, test_labels)
plt.tight_layout()
plt.savefig('predictions_grid.png')
plt.show()
Step 7: Use the Model (Real Application)
# Function to predict a single image
def predict_single_image(model, image, class_names):
"""Predict class of a single image"""
# Add batch dimension
img_array = np.expand_dims(image, 0)
# Make prediction
predictions = model.predict(img_array)
predicted_class = np.argmax(predictions[0])
confidence = predictions[0][predicted_class]
return class_names[predicted_class], confidence
# Test with random images from test set
for i in range(5):
idx = np.random.randint(0, len(test_images))
img = test_images[idx]
true_label = test_labels[idx]
predicted_class, confidence = predict_single_image(model, img, class_names)
plt.figure(figsize=(4, 4))
plt.imshow(img, cmap='gray')
plt.title(f"Predicted: {predicted_class} ({confidence*100:.1f}%)\n"
f"Actual: {class_names[true_label]}")
plt.axis('off')
plt.show()
print(f"Image {i+1}: Predicted {predicted_class} with {confidence*100:.1f}% confidence")
print(f" Actual: {class_names[true_label]}")
print(f" {'✓ Correct!' if predicted_class == class_names[true_label] else '✗ Wrong'}\n")
Step 8: Save and Load Model
# Save the trained model
model.save('fashion_classifier_model.h5')
print("Model saved as 'fashion_classifier_model.h5'")
# Later, load the model
loaded_model = keras.models.load_model('fashion_classifier_model.h5')
print("Model loaded successfully!")
# Verify it works
test_loss, test_accuracy = loaded_model.evaluate(test_images, test_labels, verbose=0)
print(f"Loaded model accuracy: {test_accuracy * 100:.2f}%")
Complete Project Code
# Complete Fashion MNIST Classifier
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
# 1. Load data
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
# 2. Preprocess
train_images = train_images / 255.0
test_images = test_images / 255.0
# 3. Build model
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
# 4. Compile
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 5. Train
history = model.fit(train_images, train_labels,
epochs=10, validation_split=0.2)
# 6. Evaluate
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print(f"Test Accuracy: {test_accuracy * 100:.2f}%")
# 7. Save
model.save('fashion_classifier.h5')
print("Project complete! You've built your first image classifier!")
Challenge Extensions
- 🎯 Add more hidden layers - does accuracy improve?
- 🎯 Try different optimizers (SGD, RMSprop)
- 🎯 Experiment with different neuron counts (64, 256)
- 🎯 Add data augmentation (rotation, flip)
- 🎯 Build a CNN (Convolutional Neural Network) version
- 🎯 Create a web interface to upload and classify images
Expected Results
Typical Performance
- Training Accuracy: ~92-95%
- Test Accuracy: ~88-91%
- Training Time: ~2-3 minutes on CPU
Note: If test accuracy is much lower than training accuracy, the model may be overfitting!