🖼️ Project 1: Image Classifier

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

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

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!