A professional, modular, and extensible implementation of a neural network for classifying handwritten digits from the MNIST dataset. This project demonstrates best practices in machine learning engineering, including proper code organization, testing, logging, and CI/CD integration.
Handwritten-Digit-Classification/
├── .github/
│ └── workflows/
│ └── ci.yml # GitHub Actions CI/CD pipeline
├── src/
│ └── mnist_classifier/
│ ├── __init__.py # Package initialization
│ ├── config.py # Configuration management
│ ├── data_loader.py # Data loading and preprocessing
│ ├── model.py # Neural network model definition
│ ├── trainer.py # Training logic and callbacks
│ ├── evaluator.py # Model evaluation and metrics
│ ├── visualization.py # Plotting and visualization utilities
│ └── cli.py # Command-line interface
├── tests/
│ ├── __init__.py
│ ├── test_config.py # Configuration tests
│ ├── test_data_loader.py # Data loading tests
│ ├── test_model.py # Model tests
│ └── test_trainer.py # Training tests
├── models/ # Saved models (gitignored)
├── results/
│ ├── plots/ # Generated visualizations
│ └── logs/ # Training logs and history
├── data/ # Dataset cache (gitignored)
├── train.py # Main training script
├── predict.py # Prediction script
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Development dependencies
├── setup.py # Package installation script
├── pytest.ini # Pytest configuration
├── .gitignore # Git ignore rules
├── LICENSE # MIT License
└── README.md # This file
git clone https://github.com/pyenthusiasts/Handwritten-Digit-Classification.git
cd Handwritten-Digit-Classification
pip install -r requirements.txt
For development with testing and code quality tools:
pip install -r requirements-dev.txt
Install as a Python package:
pip install -e .
This enables you to use the package from anywhere and provides command-line entry points.
python train.py
This will:
models/results/plots/results/logs/python predict.py --model-path models/best_model.h5 --num-samples 10
python train.py
python train.py \
--epochs 20 \
--batch-size 256 \
--learning-rate 0.001 \
--hidden-units 256 128 64 \
--dropout-rate 0.3
python train.py --early-stopping
python train.py --verbose
python predict.py --model-path models/best_model.h5 --num-samples 20
python predict.py \
--model-path models/best_model.h5 \
--show-misclassified \
--num-samples 10
python predict.py \
--model-path models/best_model.h5 \
--save-predictions \
--output-dir results/predictions
| Option | Description | Default |
|---|---|---|
--epochs |
Number of training epochs | 10 |
--batch-size |
Batch size for training | 128 |
--learning-rate |
Learning rate for optimizer | 0.001 |
--validation-split |
Fraction of data for validation | 0.2 |
--hidden-units |
Hidden layer sizes (space-separated) | 128 64 |
--dropout-rate |
Dropout rate for regularization | 0.2 |
--early-stopping |
Enable early stopping | False |
--no-callbacks |
Disable training callbacks | False |
--no-plots |
Disable plot generation | False |
--model-dir |
Directory to save models | models |
--results-dir |
Directory to save results | results |
--seed |
Random seed for reproducibility | 42 |
--verbose |
Enable verbose output | False |
| Option | Description | Default |
|---|---|---|
--model-path |
Path to trained model (required) | - |
--num-samples |
Number of samples to predict | 10 |
--show-misclassified |
Show only misclassified samples | False |
--save-predictions |
Save prediction visualizations | False |
--output-dir |
Directory to save outputs | results/predictions |
--verbose |
Enable verbose output | False |
from mnist_classifier import (
Config,
MNISTDataLoader,
MNISTModel,
ModelTrainer,
ModelEvaluator,
Visualizer,
)
# Create configuration
config = Config(
epochs=15,
batch_size=256,
hidden_units=(256, 128, 64),
dropout_rate=0.3
)
# Load data
data_loader = MNISTDataLoader(normalize=True, categorical=True)
(X_train, y_train), (X_test, y_test) = data_loader.load_data()
# Build and compile model
model = MNISTModel(config)
model.build()
model.compile()
# Train model
trainer = ModelTrainer(model, config)
history = trainer.train(X_train, y_train)
# Evaluate model
evaluator = ModelEvaluator(model)
metrics = evaluator.evaluate(X_test, y_test)
# Visualize results
visualizer = Visualizer(config)
visualizer.plot_training_history(history)
# Save model
model.save("my_model.h5")
ConfigConfiguration dataclass for all hyperparameters and settings.
MNISTDataLoaderHandles loading and preprocessing the MNIST dataset.
Methods:
load_data(): Load and preprocess dataget_data_shapes(): Get information about data dimensionsMNISTModelNeural network model wrapper.
Methods:
build(): Build the neural network architecturecompile(): Compile the model with optimizer and losssave(filepath): Save model to diskload(filepath): Load model from disksummary(): Print model architecturecount_parameters(): Get parameter countsModelTrainerHandles model training with callbacks and history tracking.
Methods:
train(X_train, y_train): Train the modelget_history(): Get training historyget_final_metrics(): Get final epoch metricsModelEvaluatorModel evaluation and metrics computation.
Methods:
evaluate(X_test, y_test): Evaluate on test setpredict(X): Generate predictionspredict_classes(X): Predict class labelsget_confusion_matrix(X_test, y_test): Compute confusion matrixget_classification_report(X_test, y_test): Generate detailed reportget_misclassified_samples(X_test, y_test): Find misclassified examplesget_top_k_accuracy(X_test, y_test, k): Compute top-k accuracyget_per_class_accuracy(X_test, y_test): Compute per-class accuracyVisualizerVisualization utilities for plots and reports.
Methods:
plot_training_history(history): Plot training curvesplot_confusion_matrix(cm): Plot confusion matrix heatmapplot_sample_predictions(images, true, pred): Plot sample predictionsplot_per_class_accuracy(per_class_acc): Plot per-class accuracy barsplot_misclassified_samples(images, true, pred): Plot misclassified samplescreate_summary_report(metrics): Generate text summary report# Clone the repository
git clone https://github.com/pyenthusiasts/Handwritten-Digit-Classification.git
cd Handwritten-Digit-Classification
# Install development dependencies
pip install -r requirements-dev.txt
# Install package in editable mode
pip install -e .
black src/ tests/ train.py predict.py
isort src/ tests/ train.py predict.py
flake8 src/ tests/ train.py predict.py --max-line-length=120
mypy src/
pytest
pytest --cov=src/mnist_classifier --cov-report=html
pytest tests/test_model.py -v
pytest -n auto
With default settings, the model typically achieves:
After training, you’ll find:
Models:
models/best_model.h5 - Best model based on validation accuracymodels/final_model.h5 - Model from final epochVisualizations:
results/plots/training_history.png - Training/validation curvesresults/plots/confusion_matrix.png - Confusion matrix heatmapresults/plots/per_class_accuracy.png - Per-class accuracy barsresults/plots/sample_predictions.png - Sample predictionsresults/plots/misclassified_samples.png - Misclassified examplesLogs:
results/logs/training_YYYYMMDD_HHMMSS.csv - Training metrics per epochresults/logs/history_YYYYMMDD_HHMMSS.json - Complete training historyresults/summary_report.txt - Summary report with all metricsContributions are welcome! Here’s how you can help:
# Click the 'Fork' button on GitHub
git clone https://github.com/your-username/Handwritten-Digit-Classification.git
cd Handwritten-Digit-Classification
git checkout -b feature/your-feature-name
pytestblack . and isort .flake8 .git add .
git commit -m "Add: description of your changes"
git push origin feature/your-feature-name
This project is licensed under the MIT License - see the LICENSE file for details.
If you use this project in your research or work, please cite:
@software{mnist_digit_classification,
title = {MNIST Digit Classification with Neural Network},
author = {MNIST Classifier Team},
year = {2024},
url = {https://github.com/pyenthusiasts/Handwritten-Digit-Classification}
}
Made with passion for clean code and machine learning