0% found this document useful (0 votes)
19 views15 pages

Dog vs Cat Image Classifier Guide

The Dog vs Cat Classifier is a deep learning project using TensorFlow/Keras to classify images as either dogs or cats, employing transfer learning with EfficientNetB0. It features a structured project layout, data loading and augmentation, model training with callbacks, evaluation metrics, and inference scripts for single and batch image predictions, along with a minimal Flask API and Streamlit app for demonstration. The project is designed for Python 3.9+ and includes a requirements file for necessary packages.

Uploaded by

chinnapamarthi18
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views15 pages

Dog vs Cat Image Classifier Guide

The Dog vs Cat Classifier is a deep learning project using TensorFlow/Keras to classify images as either dogs or cats, employing transfer learning with EfficientNetB0. It features a structured project layout, data loading and augmentation, model training with callbacks, evaluation metrics, and inference scripts for single and batch image predictions, along with a minimal Flask API and Streamlit app for demonstration. The project is designed for Python 3.9+ and includes a requirements file for necessary packages.

Uploaded by

chinnapamarthi18
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Dog vs Cat Classifier — Complete Project (Guide +

Code)
This is a ready-to-run deep learning project that classifies images as Dog or Cat using TensorFlow/Keras
with transfer learning (EfficientNetB0 by default). It includes:

• Clear folder structure


• Data loading & augmentation
• Model building (transfer learning)
• Training with callbacks
• Evaluation (metrics, confusion matrix)
• Inference script for single images & a batch
• Minimal Flask API and Streamlit app for quick demo

Python version: 3.9+ recommended

1) Project Structure

cat-dog-classifier/
├─ data/
│ ├─ train/
│ │ ├─ cat/ (e.g., [Link] ...)
│ │ └─ dog/ (e.g., [Link] ...)
│ ├─ val/
│ │ ├─ cat/
│ │ └─ dog/
│ └─ test/
│ ├─ cat/
│ └─ dog/
├─ src/
│ ├─ [Link]
│ ├─ [Link]
│ ├─ [Link]
│ ├─ [Link]
│ ├─ [Link]
│ ├─ infer_batch.py
│ ├─ app_flask.py
│ └─ app_streamlit.py
├─ [Link]
├─ [Link]
└─ .gitignore

1
You can split your dataset into train/val/test using your own script or tools; for the
popular Kaggle Dogs vs. Cats dataset, place images accordingly.

2) [Link]

tensorflow>=2.12
numpy
pandas
matplotlib
scikit-learn
Pillow
opencv-python
tqdm
flask
streamlit

3) src/[Link]

import os

# Paths
PROJECT_ROOT = [Link]([Link](__file__))
DATA_DIR = [Link](PROJECT_ROOT, 'data')
TRAIN_DIR = [Link](DATA_DIR, 'train')
VAL_DIR = [Link](DATA_DIR, 'val')
TEST_DIR = [Link](DATA_DIR, 'test')
OUTPUT_DIR = [Link](PROJECT_ROOT, 'outputs')
MODELS_DIR = [Link](OUTPUT_DIR, 'models')
LOGS_DIR = [Link](OUTPUT_DIR, 'logs')
PLOTS_DIR = [Link](OUTPUT_DIR, 'plots')

# Create dirs if missing


for d in [OUTPUT_DIR, MODELS_DIR, LOGS_DIR, PLOTS_DIR]:
[Link](d, exist_ok=True)

# Data settings
IMG_SIZE = (224, 224)
BATCH_SIZE = 32
NUM_CLASSES = 2
CLASS_NAMES = ['cat', 'dog'] # Ensure subfolders match these

# Training settings

2
EPOCHS = 20
BASE_LR = 1e-3
PATIENCE_EARLYSTOP = 5
PATIENCE_LR = 3
MODEL_NAME = 'efficientnet_b0_cat_dog.h5'
RANDOM_SEED = 42

4) src/[Link]

import os
import numpy as np
import [Link] as plt
from [Link] import confusion_matrix, classification_report
import itertools

def plot_training(history, out_path=None):


acc = [Link]('accuracy', [])
val_acc = [Link]('val_accuracy', [])
loss = [Link]('loss', [])
val_loss = [Link]('val_loss', [])

[Link]()
[Link](acc, label='train_acc')
[Link](val_acc, label='val_acc')
[Link]('Epoch')
[Link]('Accuracy')
[Link]()
if out_path:
[Link](out_path.replace('.png', '_acc.png'), bbox_inches='tight')
[Link]()

[Link]()
[Link](loss, label='train_loss')
[Link](val_loss, label='val_loss')
[Link]('Epoch')
[Link]('Loss')
[Link]()
if out_path:
[Link](out_path.replace('.png', '_loss.png'), bbox_inches='tight')
[Link]()

def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion

3
matrix', out_path=None):
if normalize:
cm = [Link]('float') / [Link](axis=1)[:, [Link]]

[Link]()
[Link](cm, interpolation='nearest', cmap=[Link])
[Link](title)
[Link]()
tick_marks = [Link](len(classes))
[Link](tick_marks, classes, rotation=45)
[Link](tick_marks, classes)

fmt = '.2f' if normalize else 'd'


thresh = [Link]() / 2.
for i, j in [Link](range([Link][0]), range([Link][1])):
[Link](j, i, format(cm[i, j], fmt),
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")

[Link]('True label')
[Link]('Predicted label')
plt.tight_layout()
if out_path:
[Link](out_path, bbox_inches='tight')
[Link]()

def print_classification_report(y_true, y_pred, target_names):


print(classification_report(y_true, y_pred, target_names=target_names))

5) src/[Link]

import os
import random
import numpy as np
import tensorflow as tf
from tensorflow import keras
from [Link] import layers
from [Link] import image_dataset_from_directory

from config import (TRAIN_DIR, VAL_DIR, MODELS_DIR, LOGS_DIR, PLOTS_DIR,


IMG_SIZE, BATCH_SIZE, EPOCHS, BASE_LR, PATIENCE_EARLYSTOP,
PATIENCE_LR, MODEL_NAME, RANDOM_SEED)
from utils import plot_training

4
# Reproducibility
[Link]['PYTHONHASHSEED'] = str(RANDOM_SEED)
[Link](RANDOM_SEED)
[Link](RANDOM_SEED)
[Link].set_seed(RANDOM_SEED)

# 1) Load datasets
train_ds = image_dataset_from_directory(
TRAIN_DIR,
validation_split=None,
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int',
shuffle=True,
)

val_ds = image_dataset_from_directory(
VAL_DIR,
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int',
shuffle=False,
)

# 2) Performance tweaks
AUTOTUNE = [Link]
train_ds = train_ds.prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.prefetch(buffer_size=AUTOTUNE)

# 3) Data augmentation pipeline


augment = [Link]([
[Link]('horizontal'),
[Link](0.1),
[Link](0.1),
], name='augmentation')

# 4) Build model with transfer learning (EfficientNetB0)


base_model = [Link].EfficientNetB0(
include_top=False,
input_shape=IMG_SIZE + (3,),
weights='imagenet'
)
base_model.trainable = False # first stage: freeze

inputs = [Link](shape=IMG_SIZE + (3,))


x = augment(inputs)
x = [Link].preprocess_input(x)

5
x = base_model(x, training=False)
x = layers.GlobalAveragePooling2D()(x)
x = [Link](0.3)(x)
outputs = [Link](1, activation='sigmoid')(x) # binary
model = [Link](inputs, outputs, name='cat_dog_efficientnetb0')

[Link](
optimizer=[Link](learning_rate=BASE_LR),
loss='binary_crossentropy',
metrics=['accuracy']
)

callbacks = [
[Link](
filepath=[Link](MODELS_DIR, MODEL_NAME),
save_best_only=True,
monitor='val_accuracy',
mode='max'
),
[Link](
monitor='val_accuracy',
patience=PATIENCE_EARLYSTOP,
restore_best_weights=True
),
[Link](
monitor='val_loss',
factor=0.5,
patience=PATIENCE_LR
),
[Link](log_dir=LOGS_DIR)
]

history = [Link](
train_ds,
epochs=EPOCHS,
validation_data=val_ds,
callbacks=callbacks
)

# Optional fine-tuning: unfreeze top layers


base_model.trainable = True
for layer in base_model.layers[:-20]: # fine-tune last ~20 layers
[Link] = False

[Link](
optimizer=[Link](learning_rate=BASE_LR * 0.1),
loss='binary_crossentropy',
metrics=['accuracy']

6
)

history_ft = [Link](
train_ds,
epochs=max(5, EPOCHS // 2),
validation_data=val_ds,
callbacks=callbacks
)

# Save final model


[Link]([Link](MODELS_DIR, MODEL_NAME))

# Plot training curves


plot_training(history, out_path=[Link](PLOTS_DIR, 'training_curves.png'))
plot_training(history_ft, out_path=[Link](PLOTS_DIR,
'training_curves_ft.png'))

print('Training complete. Best model saved to:', [Link](MODELS_DIR,


MODEL_NAME))

6) src/[Link]

import os
import numpy as np
import tensorflow as tf
from [Link] import image_dataset_from_directory
from [Link] import confusion_matrix

from config import (TEST_DIR, MODELS_DIR, IMG_SIZE, BATCH_SIZE, CLASS_NAMES,


MODEL_NAME, PLOTS_DIR)
from utils import plot_confusion_matrix, print_classification_report

# 1) Load test dataset

test_ds = image_dataset_from_directory(
TEST_DIR,
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int',
shuffle=False
)

# 2) Load trained model


model_path = [Link](MODELS_DIR, MODEL_NAME)

7
model = [Link].load_model(model_path)

# 3) Predict
probs = [Link](test_ds)
preds = ([Link]() >= 0.5).astype(int)

# 4) Collect ground-truth labels


true_labels = []
for _, y in test_ds.unbatch():
true_labels.append(int([Link]()))
true_labels = [Link](true_labels)

# 5) Metrics & confusion matrix


cm = confusion_matrix(true_labels, preds)
plot_confusion_matrix(cm, classes=CLASS_NAMES, normalize=False,
title='Confusion Matrix',
out_path=[Link](PLOTS_DIR, 'confusion_matrix.png'))

print_classification_report(true_labels, preds, target_names=CLASS_NAMES)

acc = (true_labels == preds).mean()


print(f"Test Accuracy: {acc:.4f}")

7) src/[Link] (single image inference)

import os
import sys
import numpy as np
import tensorflow as tf
from PIL import Image

from config import IMG_SIZE, MODELS_DIR, MODEL_NAME, CLASS_NAMES

model = [Link].load_model([Link](MODELS_DIR, MODEL_NAME))

def load_image(path):
img = [Link](path).convert('RGB').resize(IMG_SIZE)
arr = [Link](img)
arr = [Link].preprocess_input(arr)
return np.expand_dims(arr, 0)

if __name__ == '__main__':

8
if len([Link]) < 2:
print('Usage: python [Link] path/to/[Link]')
[Link](1)

img_path = [Link][1]
x = load_image(img_path)
prob = float([Link](x)[0][0])
label = CLASS_NAMES[1] if prob >= 0.5 else CLASS_NAMES[0]
confidence = prob if prob >= 0.5 else 1 - prob
print(f'Prediction: {label} (confidence={confidence:.3f})')

8) src/infer_batch.py (batch inference on a folder)

import os
import glob
import csv
import numpy as np
import tensorflow as tf
from PIL import Image

from config import IMG_SIZE, MODELS_DIR, MODEL_NAME, CLASS_NAMES, OUTPUT_DIR

model = [Link].load_model([Link](MODELS_DIR, MODEL_NAME))

def load_image(path):
img = [Link](path).convert('RGB').resize(IMG_SIZE)
arr = [Link](img)
arr = [Link].preprocess_input(arr)
return np.expand_dims(arr, 0)

def predict_folder(folder):
results = []
for fp in [Link]([Link](folder, '*')):
if [Link]().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
x = load_image(fp)
prob = float([Link](x, verbose=0)[0][0])
label_idx = 1 if prob >= 0.5 else 0
conf = prob if prob >= 0.5 else 1 - prob
[Link](([Link](fp), CLASS_NAMES[label_idx], conf))
return results

9
if __name__ == '__main__':
import sys
if len([Link]) < 2:
print('Usage: python infer_batch.py path/to/folder_of_images')
[Link](1)

folder = [Link][1]
rows = predict_folder(folder)

out_csv = [Link](OUTPUT_DIR, 'batch_predictions.csv')


with open(out_csv, 'w', newline='') as f:
writer = [Link](f)
[Link](['filename', 'prediction', 'confidence'])
[Link](rows)

print('Saved predictions to', out_csv)

9) src/app_flask.py (simple REST API)

from flask import Flask, request, jsonify


import io
from PIL import Image
import numpy as np
import tensorflow as tf

from config import IMG_SIZE, MODELS_DIR, MODEL_NAME, CLASS_NAMES

app = Flask(__name__)
model = [Link].load_model([Link](MODELS_DIR, MODEL_NAME))

def preprocess(img: [Link]):


img = [Link]('RGB').resize(IMG_SIZE)
arr = [Link](img)
arr = [Link].preprocess_input(arr)
return np.expand_dims(arr, 0)

@[Link]('/predict', methods=['POST'])
def predict():
if 'file' not in [Link]:
return jsonify({'error': 'no file uploaded'}), 400
file = [Link]['file']
img = [Link]([Link]([Link]()))

10
x = preprocess(img)
prob = float([Link](x)[0][0])
idx = 1 if prob >= 0.5 else 0
conf = prob if prob >= 0.5 else 1 - prob
return jsonify({'prediction': CLASS_NAMES[idx], 'confidence': conf})

if __name__ == '__main__':
[Link](host='[Link]', port=5000, debug=True)

10) src/app_streamlit.py (quick UI demo)

import streamlit as st
import numpy as np
import tensorflow as tf
from PIL import Image
import os

from config import IMG_SIZE, MODELS_DIR, MODEL_NAME, CLASS_NAMES

st.set_page_config(page_title='Dog vs Cat Classifier', page_icon='🐶🐱')

@st.cache_resource
def load_model():
return [Link].load_model([Link](MODELS_DIR, MODEL_NAME))

model = load_model()

[Link]('🐶🐱 Dog vs Cat Classifier')

file = st.file_uploader('Upload an image', type=['jpg', 'jpeg', 'png'])

if file:
img = [Link](file).convert('RGB').resize(IMG_SIZE)
[Link](img, caption='Uploaded Image', use_column_width=True)

arr = [Link](img)
arr = [Link].preprocess_input(arr)
x = np.expand_dims(arr, 0)

prob = float([Link](x)[0][0])
label_idx = 1 if prob >= 0.5 else 0
conf = prob if prob >= 0.5 else 1 - prob

11
[Link](f'Prediction: **{CLASS_NAMES[label_idx].title()}**')
[Link](f'Confidence: {conf:.3f}')

11) [Link]

# Dog vs Cat Classifier

A TensorFlow/Keras-based image classifier for dogs vs. cats using transfer


learning (EfficientNetB0).

## Setup

```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r [Link]

Data
Place images under data/train , data/val , and data/test with subfolders cat and dog .

Example:

data/
train/
cat/ [Link] ...
dog/ [Link] ...
val/
cat/
dog/
test/
cat/
dog/

You can create val and test splits using any splitter tool or a quick Python script.

Train

python -m [Link]

12
Evaluate

python -m [Link]

Predict (single image)

python -m [Link] path/to/[Link]

Batch Inference (folder)

python -m src.infer_batch path/to/folder

Run Flask API

python -m src.app_flask
# POST an image to [Link]

Run Streamlit App

streamlit run src/app_streamlit.py

Notes
• Default image size is 224x224; adjust in [Link] if needed.
• Fine-tuning is enabled after initial training; change layer freezing for speed/accuracy trade-offs.
• Swap backbones easily (e.g., ResNet50, MobileNetV2) — see below.

---

## 12) Swapping the Backbone (e.g., ResNet50)

In `src/[Link]`, replace EfficientNetB0 with ResNet50:

```python
base_model = [Link].ResNet50(
include_top=False,
input_shape=IMG_SIZE + (3,),
weights='imagenet'
)

13
preprocess = [Link].preprocess_input
...
x = preprocess(x)
...

Keep the rest identical. Adjust fine-tuning slices (e.g., [:-30] ).

13) Tips for Best Results


• Balanced data: Keep cat/dog counts similar.
• Augmentation: Increase if overfitting; decrease if underfitting.
• Batch size: 16–64 depending on GPU RAM.
• Learning rate: Start 1e-3; reduce on plateau.
• Early stopping: Prevents overfitting; monitor val_accuracy .
• Confusion matrix: Inspect which class is misclassified more often.
• Mixed precision (if on GPU):
[Link].mixed_precision.set_global_policy("mixed_float16") for speed.

14) (Optional) Quick Split Script


If you only have a single folder with cat.* and dog.* images, this script creates train/val/test
splits.

# save as tools/split_dataset.py, run: python tools/split_dataset.py /path/to/


images
import os, shutil, random, sys

[Link](42)

src = [Link][1]
out = [Link]([Link](src), 'data')
for split in ['train', 'val', 'test']:
for cls in ['cat', 'dog']:
[Link]([Link](out, split, cls), exist_ok=True)

cats = [f for f in [Link](src) if [Link]('cat')]


dogs = [f for f in [Link](src) if [Link]('dog')]

for label, files in [('cat', cats), ('dog', dogs)]:


[Link](files)
n = len(files)
train_n = int(0.7*n)
val_n = int(0.15*n)

14
splits = [
('train', files[:train_n]),
('val', files[train_n:train_n+val_n]),
('test', files[train_n+val_n:])
]
for split, names in splits:
for name in names:
[Link]([Link](src, name), [Link](out, split, label,
name))

print('Done. Created train/val/test under', out)

15) Explanation Summary


• Why transfer learning? Pretrained models learned generic visual features on ImageNet; they adapt
quickly to cats vs. dogs with fewer images and less compute.
• Pipeline: Load data → Augment → Preprocess → Feature extractor (frozen) → Classifier head →
Fine-tune top layers → Evaluate → Deploy.
• Metrics: Accuracy + classification report to capture precision/recall per class.

This template is production-friendly, easy to extend, and suitable for academic reports and demos.

15

Common questions

Powered by AI

Callbacks in the Dog vs Cat Classifier project are used to optimize training by automating responses to model actions like 'ModelCheckpoint' for saving the best model, 'EarlyStopping' to halt training when no improvement is seen, and 'ReduceLROnPlateau' for adjusting learning rates. These tools are significant as they enhance efficiency, prevent overfitting, and ensure the model saved is the best version, reducing manual monitoring and improving model robustness .

Transfer learning using EfficientNetB0 enhances performance by leveraging pre-trained weights from large datasets like ImageNet, providing a strong feature extraction foundation. This approach allows the classifier to converge faster and perform better with limited data compared to training from scratch. It reduces computational requirements and accelerates training time by only fine-tuning the network's top layers for specific tasks like distinguishing cats from dogs, making it preferred for efficiency and effectiveness .

The confusion matrix in the Dog vs Cat Classifier project is used to visualize the model's performance by displaying true vs. predicted classifications for each category. It offers insights into the types of errors made by the model, such as false positives or false negatives. This helps identify which class ('cat' or 'dog') is being misclassified more often, guiding further model adjustments and improvements .

The project's script for batch inference simplifies the prediction process by automatically processing multiple images within a specified folder, predicting each image's category and confidence, and saving results to a CSV file. This streamlines large-scale data handling, saving time and ensuring consistency. Practical applications include batch processing for dataset evaluation, bulk image analysis for business analytics, and integration into automated workflows where large image sets require classification .

The Flask API in the Dog vs Cat Classifier project is utilized to create a simple RESTful web service that allows users to upload images for prediction. This API reads, preprocesses the image, and uses the pre-trained model to return predictions. Its advantages for deployment include easy setup for serving the model over the web, facilitating integration with other systems or apps, and enabling scalability for handling multiple requests concurrently .

Data augmentation in the Dog vs Cat Classifier project serves to artificially expand the training dataset and improve model generalization. It is implemented using a pipeline that includes random horizontal flips, rotations, and zooms. This augmentation helps model performance by allowing it to learn robust features and become less sensitive to image variations, reducing overfitting and increasing the model's ability to generalize to unseen data .

The Dog vs Cat Classifier project's folder structure includes key components such as 'data/' for dataset organization into train/val/test splits, 'src/' housing scripts for configuration, training, evaluation, prediction, and utilities, and others like 'outputs/' for storing models and logs. Each component serves a specific function: 'data/' organizes input data for model training and testing; 'src/' contains the core logic for model deployment and analysis; 'outputs/' stores results and models. This structure ensures modular, organized code management enhancing functionality and maintainability .

Reproducibility in the project is ensured by setting random seeds for libraries like numpy, random, and TensorFlow, ensuring consistent performance across different runs. This is important because it allows for verifiable and reliable results, crucial in machine learning where small changes can significantly impact outcomes, aiding in debugging, tuning, and comparing model iterations .

The Streamlit app in the Dog vs Cat Classifier project provides a user-friendly interface by allowing users to upload images directly via a web interface for immediate classification, displaying results with confidence scores. Its benefits over traditional command-line execution include accessibility to non-technical users, quicker visual feedback, and enhanced interaction by eliminating command-line prerequisites, making the classification process more intuitive and engaging .

Fine-tuning in transfer learning is crucial for the Dog vs Cat Classifier project as it involves selectively retraining higher layers of the pre-trained model with new data, allowing it to adapt to specific features of the target dataset. This enhances model performance by improving accuracy beyond what is achieved by transfer learning alone. It offers flexibility by allowing adjustments for specific nuances of the cat vs. dog classification task, tailoring the model to better capture unique distinctions .

You might also like