faizan commited on
Commit
fd17037
·
0 Parent(s):

feat: complete Phase 0 - project setup

Browse files

- Add requirements.txt with pinned versions (PyTorch, MLflow, Gradio, etc.)
- Configure .gitignore for Python, notebooks, models, and MLflow
- Initialize experiment_log.md template
- Create scripts/README.md documentation
- Verify all dependencies install correctly in ai_engg environment
- Confirm CUDA available (PyTorch 2.0.1+cu117)
- Data files present and verified

Tasks completed: 0.1, 0.2, 0.3, 0.4

.github/copilot-instructions.md ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AI Coding Agent Instructions
2
+
3
+ ## Project Overview
4
+ MNIST handwritten digit recognition project focusing on CNN-based image classification with emphasis on data quality, SE best practices, and Hugging Face deployment.
5
+
6
+ ## Directory Structure
7
+ ```
8
+ data/raw/ # Original MNIST binary files (.idx*-ubyte)
9
+ data/processed/ # Cleaned/augmented data (to be populated)
10
+ notebooks/ # Jupyter notebooks for exploration & development
11
+ scripts/ # Reusable Python modules
12
+ docs/ # Project documentation
13
+ ```
14
+
15
+ ## Development Environment
16
+ - **Python**: 3.10 (conda environment: `ai_engg`)
17
+ - **Activate**: `conda activate ai_engg`
18
+ - **Linting**: `ruff check . --fix`
19
+ - Install dependencies: `pip install numpy matplotlib torch torchvision`
20
+
21
+ ## Workflow Protocol
22
+ 1. **Pre-Flight**: Verify `ai_engg` env is active, `git status` is clean
23
+ 2. **Spec-First**: Read `planning.md` and relevant spec files before coding
24
+ 3. **Anti-Redundancy**: Search `scripts/` for existing utilities before building new ones
25
+ 4. **Atomic Commits**: One task = one logic block = one commit
26
+ 5. **Commit Format**: `type: brief summary` (e.g., `feat: add data augmentation`)
27
+
28
+ ## Data Handling
29
+ - MNIST data is in raw binary IDX format (not standard image files)
30
+ - Use `MnistDataloader` class from [data/raw/read-mnist-dataset.ipynb](data/raw/read-mnist-dataset.ipynb) as reference for loading
31
+ - Images: 28x28 grayscale, Labels: 0-9 digits
32
+ - Training: 60,000 samples, Test: 10,000 samples
33
+
34
+ ## Code Conventions
35
+ - Place reusable data loading/preprocessing code in `scripts/`
36
+ - Exploratory work and model training in `notebooks/`
37
+ - Use type hints and docstrings for all functions in scripts
38
+ - Follow modular design: separate data, model, training, and evaluation logic
39
+
40
+ ## Key Patterns
41
+ ```python
42
+ # Example: Loading MNIST data
43
+ from scripts.data_loader import MnistDataloader
44
+ loader = MnistDataloader(train_images, train_labels, test_images, test_labels)
45
+ (x_train, y_train), (x_test, y_test) = loader.load_data()
46
+ ```
47
+
48
+ ## Deployment Target
49
+ - Final model deploys to **Hugging Face Spaces**
50
+ - Prepare inference pipeline compatible with Gradio or Streamlit interface
51
+
52
+ ## Documentation Requirements
53
+ - Document data quality issues and preprocessing steps
54
+ - Include visualizations for data exploration
55
+ - Track experiments with clear metrics (accuracy, precision, recall)
56
+ - Update `planning.md` with task status (mark ✅ when complete)
57
+
58
+ ## Code Quality Checklist
59
+ - No unused imports
60
+ - Proper docstrings on all functions
61
+ - Run `ruff check . --fix` before committing
62
+ - Implementation matches spec exactly
63
+
64
+ ## Pending Setup
65
+ - [ ] Create `requirements.txt` with pinned versions
66
+ - [ ] Populate `docs/DEVELOPMENT_WORKFLOW.md` with build/test commands
67
+ - [ ] Set up data augmentation pipeline in `data/processed/`
.gitignore ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+ .Python
7
+ *.so
8
+ *.egg
9
+ *.egg-info/
10
+ dist/
11
+ build/
12
+
13
+ # Jupyter Notebook
14
+ .ipynb_checkpoints/
15
+ *.ipynb_checkpoints
16
+
17
+ # Data (keep raw, ignore processed)
18
+ data/processed/*.parquet
19
+ data/processed/*.npy
20
+ data/processed/*.npz
21
+
22
+ # Models
23
+ *.pt
24
+ *.pth
25
+ models/*.pt
26
+ models/*.pth
27
+ !models/.gitkeep
28
+
29
+ # MLflow
30
+ mlruns/
31
+ mlartifacts/
32
+
33
+ # Experiments
34
+ experiments/
35
+ runs/
36
+ !experiments/.gitkeep
37
+
38
+ # Environment
39
+ .env
40
+ .venv/
41
+ venv/
42
+ env/
43
+ ENV/
44
+
45
+ # IDE
46
+ .vscode/
47
+ .idea/
48
+ *.swp
49
+ *.swo
50
+ *~
51
+
52
+ # OS
53
+ .DS_Store
54
+ Thumbs.db
55
+
56
+ # Docker
57
+ *.log
docs/experiment_log.md ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Experiment Log
2
+
3
+ ## Overview
4
+ This document tracks all experiments conducted during the MNIST digit classification project. Each experiment includes configuration, results, and insights.
5
+
6
+ ---
7
+
8
+ ## Experiment Template
9
+
10
+ ```markdown
11
+ ## Experiment N: [Name]
12
+ **Date:** YYYY-MM-DD
13
+ **Branch:** feature/[branch-name]
14
+ **MLflow Run ID:** [run_id]
15
+ **Objective:** [What we're trying to achieve]
16
+
17
+ ### Configuration
18
+ - **Architecture:** [Model description]
19
+ - **Hyperparameters:**
20
+ - Learning rate: X
21
+ - Batch size: X
22
+ - Epochs: X
23
+ - Optimizer: X
24
+ - [Other params]
25
+
26
+ ### Results
27
+ - **Training Accuracy:** X.XX%
28
+ - **Validation Accuracy:** X.XX%
29
+ - **Test Accuracy:** X.XX% (if evaluated)
30
+ - **Training Time:** X minutes
31
+ - **Best Epoch:** X
32
+
33
+ ### Metrics
34
+ | Metric | Train | Val | Test |
35
+ |--------|-------|-----|------|
36
+ | Accuracy | X.XX% | X.XX% | X.XX% |
37
+ | Precision | X.XX | X.XX | X.XX |
38
+ | Recall | X.XX | X.XX | X.XX |
39
+ | Loss | X.XXX | X.XXX | X.XXX |
40
+
41
+ ### Insights
42
+ - What worked well?
43
+ - What didn't work?
44
+ - Unexpected findings?
45
+ - Next steps?
46
+
47
+ ### Artifacts
48
+ - Model checkpoint: `models/[filename].pt`
49
+ - Training curves: `experiments/plots/[filename].png`
50
+ - MLflow link: http://localhost:5000/#/experiments/[experiment_id]/runs/[run_id]
51
+
52
+ ---
53
+ ```
54
+
55
+ ## Experiments
56
+
57
+ *Experiments will be logged below as they are conducted.*
58
+
59
+ ---
60
+
61
+ ## Summary
62
+
63
+ | Exp # | Date | Model | Val Acc | Test Acc | Notes |
64
+ |-------|------|-------|---------|----------|-------|
65
+ | - | - | - | - | - | Experiments to be added |
planning.md ADDED
@@ -0,0 +1,1727 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Planning Document: MNIST Handwritten Digit Recognition
2
+
3
+ ## Current Status
4
+
5
+ **Current Phase:** Phase 1 - Data Pipeline & Quality Analysis
6
+ **Last Updated:** December 28, 2025
7
+ **Status:** 🟡 STARTING - Project scaffolding in progress
8
+
9
+ ### Quick Summary
10
+
11
+ **Project Goal:**
12
+ Develop production-ready CNN for MNIST digit classification (28×28 grayscale → 0-9 labels) emphasizing:
13
+ - Data quality analysis throughout pipeline
14
+ - Software engineering best practices
15
+ - Deployment to Hugging Face Spaces
16
+
17
+ **Deliverables:**
18
+ - 20-30 page report documenting complete workflow
19
+ - Functional Jupyter notebook validating solution
20
+ - Deployed model on Hugging Face with interactive interface
21
+
22
+ **Current Progress:**
23
+ - ✅ Environment setup (conda env `ai_engg`, Python 3.10)
24
+ - ✅ Raw MNIST data available (60k train, 10k test, IDX format)
25
+ - ✅ Workflow conventions defined
26
+ - ⬜ Planning document (this file) - in progress
27
+ - ⬜ Code implementation - not started
28
+
29
+ ---
30
+
31
+ ## Phase Status Overview
32
+
33
+ | Phase | Tasks | Status | Key Milestone | Est. Time |
34
+ |-------|-------|--------|---------------|-----------|
35
+ | 0: Setup | 4 | ⬜ | Dependencies + project structure | 1-2h |
36
+ | 1: Data Pipeline | 6 | ⬜ | Quality analysis + augmentation | 6-8h |
37
+ | 2: Model Development | 5 | ⬜ | Trained CNN with >98% accuracy | 8-10h |
38
+ | 3: Deployment | 4 | ⬜ | Live Hugging Face Space | 4-6h |
39
+ | 4: Documentation | 3 | ⬜ | Final 20-30 page report | 6-8h |
40
+
41
+ **Total Estimated Time:** 25-34 hours
42
+
43
+ ---
44
+
45
+ ## Critical Context
46
+
47
+ ### Project Constraints
48
+ - **Dataset:** MNIST (60,000 train, 10,000 test) - no external data allowed
49
+ - **Framework:** PyTorch (specified in environment setup)
50
+ - **Architecture:** CNN required (not simpler models)
51
+ - **Deployment:** Hugging Face Spaces (free tier)
52
+ - **Evaluation Metrics:** Accuracy, precision, recall (per spec)
53
+
54
+ ### Success Criteria
55
+ - **Functional:** Model achieves ≥98% test accuracy (baseline: 97-98%)
56
+ - **SE Quality:** Code passes `ruff` linting, has tests, modular design
57
+ - **Documentation:** Complete 20-30 page report covering all requirements
58
+ - **Production:** Working Hugging Face Space accepting digit images
59
+
60
+ ### Data Specifics
61
+ - **Format:** IDX binary (not standard images) - requires custom loader
62
+ - **Preprocessing:** Normalization (0-255 → 0-1), reshape for CNN
63
+ - **Augmentation:** Rotation, translation, scaling to improve robustness
64
+ - **Quality:** High quality dataset, but must document analysis process
65
+
66
+ ---
67
+
68
+ ## Phase 0: Project Setup (Pre-Flight)
69
+
70
+ > **Purpose:** Establish development infrastructure before coding begins
71
+
72
+ **Status:** ⬜ NOT STARTED
73
+ **Priority:** CRITICAL (blocks all other work)
74
+ **Estimated Time:** 1-2 hours
75
+
76
+ ---
77
+
78
+ ### **Task 0.1:** Create requirements.txt with pinned versions
79
+ **Status:** ✅ COMPLETE
80
+ **Priority:** CRITICAL
81
+ **Objective:** Lock dependency versions for reproducibility
82
+
83
+ **Implementation:**
84
+ - [ ] Create `requirements.txt` with core dependencies:
85
+ ```
86
+ numpy==1.24.3
87
+ matplotlib==3.7.1
88
+ torch==2.0.1
89
+ torchvision==0.15.2
90
+ jupyter==1.0.0
91
+ scikit-learn==1.3.0
92
+ ruff==0.0.270
93
+ pytest==7.4.0
94
+ mlflow==2.9.2
95
+ gradio==3.50.0
96
+ pillow==10.0.0
97
+ ```
98
+ - [ ] Test installation: `pip install -r requirements.txt`
99
+ - [ ] Verify imports work in Python REPL
100
+ - [ ] Document installation in README.md (create if needed)
101
+
102
+ **Success Criteria:**
103
+ - requirements.txt exists and installs without errors
104
+ - All imports verified working
105
+
106
+ **Estimated Time:** 20 minutes
107
+
108
+ ---
109
+
110
+ ### **Task 0.2:** Configure .gitignore
111
+ **Status:** ✅ COMPLETE
112
+ **Priority:** HIGH
113
+ **Objective:** Prevent committing generated files and large binaries
114
+
115
+ **Implementation:**
116
+ - [ ] Create `.gitignore` with standard Python patterns:
117
+ ```
118
+ # Python
119
+ __pycache__/
120
+ *.pyc
121
+ *.pyo
122
+ .ipynb_checkpoints/
123
+ *.egg-info/
124
+
125
+ # Data (keep raw, ignore processed)
126
+ data/processed/*.parquet
127
+ data/processed/*.npy
128
+ *.pt
129
+ *.pth
130
+
131
+ # Experiments
132
+ experiments/
133
+ runs/
134
+ mlruns/
135
+
136
+ # Environment
137
+ .env
138
+ .venv/
139
+ venv/
140
+ ```
141
+ - [ ] Test: create dummy files and verify git ignores them
142
+ - [ ] Commit .gitignore
143
+
144
+ **Success Criteria:**
145
+ - Generated files don't appear in `git status`
146
+ - Raw data and source code still tracked
147
+
148
+ **Estimated Time:** 15 minutes
149
+
150
+ ---
151
+
152
+ ### **Task 0.3:** Initialize project documentation
153
+ **Status:** ✅ COMPLETE
154
+ **Priority:** MEDIUM
155
+ **Objective:** Create documentation templates for tracking work
156
+
157
+ **Implementation:**
158
+ - [ ] Create `docs/experiment_log.md` with template:
159
+ ```markdown
160
+ # Experiment Log
161
+
162
+ ## Experiment 1: Baseline CNN
163
+ **Date:** YYYY-MM-DD
164
+ **Branch:** feature/baseline-cnn
165
+ **Objective:** Establish baseline performance
166
+ **Architecture:** [describe]
167
+ **Hyperparameters:** [list]
168
+ **Results:** [metrics]
169
+ **Insights:** [what learned]
170
+ ```
171
+ - [ ] Create `scripts/README.md` documenting utility modules
172
+ - [ ] Update `.github/copilot-instructions.md` with planning.md reference
173
+ - [ ] Commit documentation templates
174
+
175
+ **Success Criteria:**
176
+ - Templates exist and are usable
177
+ - Copilot instructions point to planning.md
178
+
179
+ **Estimated Time:** 20 minutes
180
+
181
+ ---
182
+
183
+ ### **Task 0.4:** Verify data integrity
184
+ **Status:** ✅ COMPLETE
185
+ **Priority:** HIGH
186
+ **Objective:** Ensure MNIST files are complete and uncorrupted
187
+
188
+ **Implementation:**
189
+ - [ ] Check file sizes match expected:
190
+ - `train-images-idx3-ubyte` or `.gz`: ~47 MB
191
+ - `train-labels-idx1-ubyte` or `.gz`: ~60 KB
192
+ - `t10k-images-idx3-ubyte` or `.gz`: ~7.8 MB
193
+ - `t10k-labels-idx1-ubyte` or `.gz`: ~10 KB
194
+ - [ ] Extract `.gz` files if compressed: `gunzip data/raw/*.gz`
195
+ - [ ] Verify magic numbers using reference loader from notebook
196
+ - [ ] Document data provenance in `data/raw/README.md`
197
+
198
+ **Success Criteria:**
199
+ - All files present and correct size
200
+ - Magic numbers verified (2051 for images, 2049 for labels)
201
+ - Data source documented
202
+
203
+ **Estimated Time:** 15 minutes
204
+
205
+ ---
206
+
207
+ ### **Task 0.5:** Setup MLflow experiment tracking
208
+ **Status:** ⬜ NOT STARTED
209
+ **Priority:** HIGH
210
+ **Objective:** Configure MLflow for experiment tracking and model registry
211
+
212
+ **Implementation:**
213
+ - [ ] Create `mlruns/` directory (git-ignored for artifacts)
214
+ - [ ] Create `scripts/mlflow_setup.py`:
215
+ ```python
216
+ import mlflow
217
+ from pathlib import Path
218
+
219
+ # Set tracking URI to local directory
220
+ MLFLOW_TRACKING_URI = Path("mlruns").resolve().as_uri()
221
+ mlflow.set_tracking_uri(MLFLOW_TRACKING_URI)
222
+
223
+ # Create experiment
224
+ EXPERIMENT_NAME = "mnist-digit-classification"
225
+
226
+ def setup_mlflow():
227
+ """Initialize MLflow experiment"""
228
+ try:
229
+ experiment_id = mlflow.create_experiment(EXPERIMENT_NAME)
230
+ except:
231
+ experiment_id = mlflow.get_experiment_by_name(EXPERIMENT_NAME).experiment_id
232
+
233
+ mlflow.set_experiment(EXPERIMENT_NAME)
234
+ return experiment_id
235
+ ```
236
+ - [ ] Update `.gitignore` to include:
237
+ ```
238
+ mlruns/
239
+ mlartifacts/
240
+ ```
241
+ - [ ] Create launch script `scripts/launch_mlflow_ui.sh`:
242
+ ```bash
243
+ #!/bin/bash
244
+ mlflow ui --backend-store-uri mlruns --port 5000
245
+ ```
246
+ - [ ] Make executable: `chmod +x scripts/launch_mlflow_ui.sh`
247
+ - [ ] Test: Run `./scripts/launch_mlflow_ui.sh` and access http://localhost:5000
248
+
249
+ **Success Criteria:**
250
+ - MLflow UI launches without errors
251
+ - Experiment "mnist-digit-classification" visible
252
+ - Tracking URI configured correctly
253
+
254
+ **Estimated Time:** 30 minutes
255
+
256
+ ---
257
+
258
+ ## Phase 1: Data Pipeline & Quality Analysis
259
+
260
+ > **Purpose:** Build robust data loading and preprocessing pipeline with comprehensive quality analysis
261
+
262
+ **Status:** ⬜ NOT STARTED
263
+ **Prerequisites:** Phase 0 complete
264
+ **Estimated Time:** 6-8 hours
265
+
266
+ ---
267
+
268
+ ### **Task 1.1:** Extract MnistDataloader to reusable module
269
+ **Status:** ⬜ NOT STARTED
270
+ **Priority:** CRITICAL
271
+ **Objective:** Move data loader from notebook to `scripts/` for reuse
272
+
273
+ **Implementation:**
274
+ - [ ] Create `scripts/data_loader.py`
275
+ - [ ] Extract `MnistDataloader` class from `data/raw/read-mnist-dataset.ipynb`
276
+ - [ ] Add type hints:
277
+ ```python
278
+ from typing import Tuple
279
+ import numpy as np
280
+ from numpy.typing import NDArray
281
+
282
+ class MnistDataloader:
283
+ def __init__(
284
+ self,
285
+ training_images_filepath: str,
286
+ training_labels_filepath: str,
287
+ test_images_filepath: str,
288
+ test_labels_filepath: str
289
+ ) -> None:
290
+ ...
291
+
292
+ def load_data(self) -> Tuple[
293
+ Tuple[list[NDArray[np.uint8]], list[int]],
294
+ Tuple[list[NDArray[np.uint8]], list[int]]
295
+ ]:
296
+ ...
297
+ ```
298
+ - [ ] Add docstrings (class and methods)
299
+ - [ ] Handle file not found errors gracefully
300
+ - [ ] Test loading: verify shapes (60000, 28, 28) and (10000, 28, 28)
301
+
302
+ **Success Criteria:**
303
+ - Module imports successfully: `from scripts.data_loader import MnistDataloader`
304
+ - Loads data without errors
305
+ - Returns correct shapes and data types
306
+
307
+ **Estimated Time:** 45 minutes
308
+
309
+ ---
310
+
311
+ ### **Task 1.2:** Build data exploration notebook
312
+ **Status:** ⬜ NOT STARTED
313
+ **Priority:** HIGH
314
+ **Objective:** Visual and statistical exploration of MNIST dataset
315
+
316
+ **Implementation:**
317
+ - [ ] Create `notebooks/01_data_exploration.ipynb`
318
+ - [ ] Load data using new `MnistDataloader` module
319
+ - [ ] Visualizations:
320
+ - Grid of sample images (10×10) with labels
321
+ - One sample per digit class (0-9) side-by-side
322
+ - Pixel intensity histograms (overall and per-class)
323
+ - Image dimension verification (all 28×28)
324
+ - [ ] Statistical analysis:
325
+ - Class balance: count per digit (should be ~6000 each for training)
326
+ - Pixel value range: min/max (should be 0-255)
327
+ - Missing values check (should be zero)
328
+ - Mean/std pixel intensity per class
329
+ - [ ] Document findings in markdown cells
330
+
331
+ **Expected Findings:**
332
+ - MNIST is well-balanced (~6000 samples per digit in training)
333
+ - No missing values or corrupted images
334
+ - Some digits harder to distinguish (4/9, 3/8, 5/6)
335
+
336
+ **Deliverables:**
337
+ - [ ] Notebook with visualizations and analysis
338
+ - [ ] Summary of data quality findings
339
+
340
+ **Success Criteria:**
341
+ - Clear visualizations rendering correctly
342
+ - Statistical properties documented
343
+ - Findings support data quality section of report
344
+
345
+ **Estimated Time:** 1.5 hours
346
+
347
+ ---
348
+
349
+ ### **Task 1.3:** Implement data quality analysis module
350
+ **Status:** ⬜ NOT STARTED
351
+ **Priority:** HIGH
352
+ **Objective:** Systematic quality checks for report documentation
353
+
354
+ **Implementation:**
355
+ - [ ] Create `scripts/data_quality.py` with functions:
356
+ ```python
357
+ def check_missing_values(images, labels) -> dict:
358
+ """Check for NaN or missing values"""
359
+
360
+ def check_outliers(images) -> dict:
361
+ """Identify pixels outside 0-255 range"""
362
+
363
+ def check_class_balance(labels) -> dict:
364
+ """Compute samples per class and imbalance ratio"""
365
+
366
+ def check_image_dimensions(images) -> dict:
367
+ """Verify all images are 28x28"""
368
+
369
+ def generate_quality_report(train_data, test_data) -> dict:
370
+ """Run all checks and return comprehensive report"""
371
+ ```
372
+ - [ ] Create unit tests: `tests/test_data_quality.py`
373
+ - [ ] Run quality checks on train and test sets
374
+ - [ ] Save report as JSON: `data/quality_report.json`
375
+
376
+ **Success Criteria:**
377
+ - All quality check functions implemented with tests
378
+ - Report confirms high data quality (no issues for MNIST)
379
+ - JSON report available for documentation
380
+
381
+ **Estimated Time:** 1.5 hours
382
+
383
+ ---
384
+
385
+ ### **Task 1.4:** Create preprocessing pipeline
386
+ **Status:** ⬜ NOT STARTED
387
+ **Priority:** CRITICAL
388
+ **Objective:** Normalize and prepare data for CNN input
389
+
390
+ **Implementation:**
391
+ - [ ] Create `scripts/preprocessing.py`:
392
+ ```python
393
+ import torch
394
+ from torch.utils.data import Dataset, DataLoader
395
+
396
+ class MnistDataset(Dataset):
397
+ def __init__(self, images, labels, transform=None):
398
+ """
399
+ Args:
400
+ images: List of 28x28 numpy arrays
401
+ labels: List of integer labels (0-9)
402
+ transform: Optional torchvision transforms
403
+ """
404
+ self.images = images
405
+ self.labels = labels
406
+ self.transform = transform
407
+
408
+ def __getitem__(self, idx):
409
+ image = self.images[idx]
410
+ label = self.labels[idx]
411
+
412
+ # Normalize to [0, 1]
413
+ image = image.astype(np.float32) / 255.0
414
+
415
+ # Add channel dimension: (28, 28) -> (1, 28, 28)
416
+ image = torch.tensor(image).unsqueeze(0)
417
+ label = torch.tensor(label, dtype=torch.long)
418
+
419
+ if self.transform:
420
+ image = self.transform(image)
421
+
422
+ return image, label
423
+ ```
424
+ - [ ] Test pipeline:
425
+ - Verify normalization (values in [0, 1])
426
+ - Check tensor shapes: images (B, 1, 28, 28), labels (B,)
427
+ - Test DataLoader batching
428
+ - [ ] Document preprocessing steps in docstrings
429
+
430
+ **Success Criteria:**
431
+ - MnistDataset works with PyTorch DataLoader
432
+ - Data properly normalized and shaped for CNN
433
+ - No data leakage (train/test separate)
434
+
435
+ **Estimated Time:** 1 hour
436
+
437
+ ---
438
+
439
+ ### **Task 1.5:** Implement data augmentation
440
+ **Status:** ⬜ NOT STARTED
441
+ **Priority:** HIGH
442
+ **Objective:** Generate augmented training data for robustness
443
+
444
+ **Implementation:**
445
+ - [ ] Create `scripts/augmentation.py`:
446
+ ```python
447
+ from torchvision import transforms
448
+
449
+ def get_augmentation_pipeline():
450
+ """Return composition of augmentation transforms"""
451
+ return transforms.Compose([
452
+ transforms.RandomRotation(degrees=15), # ±15° rotation
453
+ transforms.RandomAffine(
454
+ degrees=0,
455
+ translate=(0.1, 0.1), # ±10% translation
456
+ scale=(0.9, 1.1) # 90-110% zoom
457
+ ),
458
+ # Note: already normalized in Dataset
459
+ ])
460
+ ```
461
+ - [ ] Test augmentations visually:
462
+ - Create `notebooks/02_augmentation_demo.ipynb`
463
+ - Show original vs augmented images side-by-side
464
+ - Verify labels remain correct
465
+ - Check augmentation doesn't distort digits beyond recognition
466
+ - [ ] Document augmentation rationale:
467
+ - Why these parameters? (realistic handwriting variations)
468
+ - Expected impact on generalization
469
+ - Trade-offs (training time vs accuracy)
470
+
471
+ **Design Decision:**
472
+ Apply augmentations **on-the-fly** during training (not pre-generate). Reasons:
473
+ - Infinite variations per epoch
474
+ - Saves disk space
475
+ - Standard PyTorch practice
476
+
477
+ **Success Criteria:**
478
+ - Augmentation pipeline integrates with MnistDataset
479
+ - Visual verification shows realistic variations
480
+ - Documented in experiment log
481
+
482
+ **Estimated Time:** 1.5 hours
483
+
484
+ ---
485
+
486
+ ### **Task 1.6:** Create train/validation split
487
+ **Status:** ⬜ NOT STARTED
488
+ **Priority:** CRITICAL
489
+ **Objective:** Split 60k training data into train/val sets
490
+
491
+ **Implementation:**
492
+ - [ ] Add split function to `scripts/preprocessing.py`:
493
+ ```python
494
+ from sklearn.model_selection import train_test_split
495
+
496
+ def create_train_val_split(
497
+ images,
498
+ labels,
499
+ val_size: float = 0.15,
500
+ random_state: int = 42
501
+ ):
502
+ """
503
+ Split data into train and validation sets.
504
+
505
+ Args:
506
+ val_size: Fraction for validation (default 15% = 9000 samples)
507
+ random_state: Seed for reproducibility
508
+
509
+ Returns:
510
+ (train_images, train_labels, val_images, val_labels)
511
+ """
512
+ return train_test_split(
513
+ images, labels,
514
+ test_size=val_size,
515
+ random_state=random_state,
516
+ stratify=labels # Maintain class balance
517
+ )
518
+ ```
519
+ - [ ] Test split:
520
+ - Verify sizes: 51000 train, 9000 val (for 15% split)
521
+ - Check class balance maintained in both sets
522
+ - Verify no data leakage (no overlap)
523
+ - [ ] Document split strategy in `docs/experiment_log.md`
524
+
525
+ **Success Criteria:**
526
+ - Train/val split maintains class balance
527
+ - Reproducible (same split every run with fixed seed)
528
+ - Documented split rationale
529
+
530
+ **Estimated Time:** 30 minutes
531
+
532
+ ---
533
+
534
+ ## Phase 2: Model Development & Training
535
+
536
+ > **Purpose:** Design, implement, and train CNN architecture with rigorous evaluation
537
+
538
+ **Status:** ⬜ NOT STARTED
539
+ **Prerequisites:** Phase 1 complete (data pipeline working)
540
+ **Estimated Time:** 8-10 hours
541
+
542
+ ---
543
+
544
+ ### **Task 2.1:** Design baseline CNN architecture
545
+ **Status:** ⬜ NOT STARTED
546
+ **Priority:** CRITICAL
547
+ **Objective:** Implement simple but effective CNN for MNIST
548
+
549
+ **Implementation:**
550
+ - [ ] Create `scripts/models.py`:
551
+ ```python
552
+ import torch.nn as nn
553
+
554
+ class BaselineCNN(nn.Module):
555
+ """
556
+ Baseline CNN for MNIST classification.
557
+
558
+ Architecture:
559
+ Conv1: 1 -> 32 filters, 3x3, ReLU, MaxPool(2x2)
560
+ Conv2: 32 -> 64 filters, 3x3, ReLU, MaxPool(2x2)
561
+ Flatten
562
+ FC1: 64*7*7 -> 128, ReLU, Dropout(0.5)
563
+ FC2: 128 -> 10 (output logits)
564
+
565
+ Expected parameters: ~100k
566
+ Expected accuracy: 98-99%
567
+ """
568
+ def __init__(self):
569
+ super().__init__()
570
+ self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
571
+ self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
572
+ self.pool = nn.MaxPool2d(2, 2)
573
+ self.fc1 = nn.Linear(64 * 7 * 7, 128)
574
+ self.fc2 = nn.Linear(128, 10)
575
+ self.dropout = nn.Dropout(0.5)
576
+
577
+ def forward(self, x):
578
+ # Implementation here
579
+ ...
580
+ ```
581
+ - [ ] Document architecture choices:
582
+ - Why 2 conv layers? (balance simplicity vs capacity)
583
+ - Why 32→64 filters? (standard progression)
584
+ - Why dropout 0.5? (prevent overfitting)
585
+ - [ ] Test model:
586
+ - Verify forward pass with dummy input (1, 1, 28, 28)
587
+ - Check output shape (1, 10)
588
+ - Count parameters: `sum(p.numel() for p in model.parameters())`
589
+
590
+ **Design Rationale:**
591
+ - Start simple: baseline must work before trying complex architectures
592
+ - Proven pattern: 2 conv layers sufficient for MNIST
593
+ - Dropout critical: MNIST is small, overfitting likely
594
+
595
+ **Success Criteria:**
596
+ - Model instantiates without errors
597
+ - Forward pass produces correct output shape
598
+ - Architecture documented with justification
599
+
600
+ **Estimated Time:** 1 hour
601
+
602
+ ---
603
+
604
+ ### **Task 2.2:** Implement training pipeline
605
+ **Status:** ⬜ NOT STARTED
606
+ **Priority:** CRITICAL
607
+ **Objective:** Build robust training loop with logging
608
+
609
+ **Implementation:**
610
+ - [ ] Create `scripts/train.py`:
611
+ ```python
612
+ import torch
613
+ import torch.nn as nn
614
+ import torch.optim as optim
615
+ from typing import Dict, List
616
+
617
+ def train_epoch(
618
+ model,
619
+ train_loader,
620
+ criterion,
621
+ optimizer,
622
+ device
623
+ ) -> Dict[str, float]:
624
+ """Train for one epoch, return metrics"""
625
+ model.train()
626
+ total_loss = 0.0
627
+ correct = 0
628
+ total = 0
629
+
630
+ for images, labels in train_loader:
631
+ images, labels = images.to(device), labels.to(device)
632
+
633
+ optimizer.zero_grad()
634
+ outputs = model(images)
635
+ loss = criterion(outputs, labels)
636
+ loss.backward()
637
+ optimizer.step()
638
+
639
+ total_loss += loss.item()
640
+ _, predicted = outputs.max(1)
641
+ correct += predicted.eq(labels).sum().item()
642
+ total += labels.size(0)
643
+
644
+ return {
645
+ 'loss': total_loss / len(train_loader),
646
+ 'accuracy': 100.0 * correct / total
647
+ }
648
+
649
+ def validate(model, val_loader, criterion, device) -> Dict[str, float]:
650
+ """Evaluate on validation set"""
651
+ # Similar structure, no gradient computation
652
+ ...
653
+
654
+ def train_model(
655
+ model,
656
+ train_loader,
657
+ val_loader,
658
+ num_epochs: int = 10,
659
+ learning_rate: float = 0.001,
660
+ device: str = 'cuda' if torch.cuda.is_available() else 'cpu'
661
+ ) -> Dict[str, List[float]]:
662
+ """Full training loop with history tracking"""
663
+ ...
664
+ ```
665
+ - [ ] Add learning rate scheduling:
666
+ ```python
667
+ scheduler = optim.lr_scheduler.ReduceLROnPlateau(
668
+ optimizer, mode='min', patience=3, factor=0.5
669
+ )
670
+ ```
671
+ - [ ] Implement early stopping (patience=5 epochs)
672
+ - [ ] Save checkpoints:
673
+ - Best model (lowest val loss): `models/best_model.pt`
674
+ - Last model: `models/last_model.pt`
675
+ - [ ] Log training history to JSON: `experiments/training_history.json`
676
+
677
+ **Success Criteria:**
678
+ - Training loop runs without errors
679
+ - Validation accuracy improves over epochs
680
+ - Checkpoints saved correctly
681
+ - History available for plotting
682
+
683
+ **Estimated Time:** 2 hours
684
+
685
+ ---
686
+
687
+ ### **Task 2.2b:** Integrate MLflow tracking
688
+ **Status:** ⬜ NOT STARTED
689
+ **Priority:** HIGH
690
+ **Objective:** Add MLflow logging to training pipeline
691
+
692
+ **Implementation:**
693
+ - [ ] Update `scripts/train.py` to log with MLflow:
694
+ ```python
695
+ import mlflow
696
+ from scripts.mlflow_setup import setup_mlflow
697
+
698
+ def train_model(
699
+ model,
700
+ train_loader,
701
+ val_loader,
702
+ num_epochs: int = 10,
703
+ learning_rate: float = 0.001,
704
+ device: str = 'cuda' if torch.cuda.is_available() else 'cpu'
705
+ ) -> Dict[str, List[float]]:
706
+ """Full training loop with MLflow tracking"""
707
+
708
+ # Initialize MLflow
709
+ setup_mlflow()
710
+
711
+ with mlflow.start_run():
712
+ # Log hyperparameters
713
+ mlflow.log_params({
714
+ 'num_epochs': num_epochs,
715
+ 'learning_rate': learning_rate,
716
+ 'batch_size': train_loader.batch_size,
717
+ 'optimizer': 'Adam',
718
+ 'architecture': model.__class__.__name__,
719
+ 'device': device
720
+ })
721
+
722
+ # Training loop
723
+ for epoch in range(num_epochs):
724
+ train_metrics = train_epoch(...)
725
+ val_metrics = validate(...)
726
+
727
+ # Log metrics
728
+ mlflow.log_metrics({
729
+ 'train_loss': train_metrics['loss'],
730
+ 'train_accuracy': train_metrics['accuracy'],
731
+ 'val_loss': val_metrics['loss'],
732
+ 'val_accuracy': val_metrics['accuracy']
733
+ }, step=epoch)
734
+
735
+ # Save best model
736
+ if val_metrics['loss'] < best_val_loss:
737
+ best_val_loss = val_metrics['loss']
738
+ torch.save(model.state_dict(), 'models/best_model.pt')
739
+
740
+ # Log model to MLflow
741
+ mlflow.pytorch.log_model(
742
+ model,
743
+ "model",
744
+ registered_model_name="mnist-cnn-baseline"
745
+ )
746
+
747
+ # Log final artifacts
748
+ mlflow.log_artifact('models/best_model.pt')
749
+ mlflow.log_artifact('experiments/training_history.json')
750
+
751
+ return history
752
+ ```
753
+ - [ ] Test MLflow logging:
754
+ - Run short training (2-3 epochs)
755
+ - Check MLflow UI for logged params, metrics, and artifacts
756
+ - Verify model appears in model registry
757
+ - [ ] Document MLflow workflow in `docs/experiment_log.md`
758
+
759
+ **Success Criteria:**
760
+ - All hyperparameters logged automatically
761
+ - Metrics tracked per epoch in MLflow UI
762
+ - Models saved to MLflow model registry
763
+ - Training curves visible in MLflow UI
764
+
765
+ **Estimated Time:** 1.5 hours
766
+
767
+ ---
768
+
769
+ ### **Task 2.3:** Train baseline model
770
+ **Status:** ⬜ NOT STARTED
771
+ **Priority:** CRITICAL
772
+ **Objective:** Train baseline CNN and establish performance benchmark
773
+
774
+ **Implementation:**
775
+ - [ ] Create `notebooks/03_train_baseline.ipynb`
776
+ - [ ] Configure training:
777
+ ```python
778
+ config = {
779
+ 'batch_size': 64,
780
+ 'num_epochs': 15,
781
+ 'learning_rate': 0.001,
782
+ 'optimizer': 'Adam',
783
+ 'weight_decay': 1e-5,
784
+ 'device': 'cuda' if available else 'cpu'
785
+ }
786
+ ```
787
+ - [ ] Train model with augmentation
788
+ - [ ] Track metrics:
789
+ - Training loss/accuracy per epoch
790
+ - Validation loss/accuracy per epoch
791
+ - Best validation accuracy achieved
792
+ - Training time per epoch
793
+ - [ ] Visualize training curves (loss and accuracy)
794
+ - [ ] Test on test set (use ONLY ONCE to avoid overfitting to test)
795
+
796
+ **Expected Results:**
797
+ - Validation accuracy: 98-99% (typical for MNIST CNN)
798
+ - Training time: ~2-5 min per epoch on CPU, <1 min on GPU
799
+ - Convergence: plateaus after 10-12 epochs
800
+
801
+ **Deliverables:**
802
+ - [ ] Trained model checkpoint: `models/baseline_cnn_best.pt`
803
+ - [ ] Training history: `experiments/baseline_training.json`
804
+ - [ ] Notebook with training curves and analysis
805
+
806
+ **Success Criteria:**
807
+ - Validation accuracy ≥ 98.0%
808
+ - No severe overfitting (train/val gap < 2%)
809
+ - Reproducible (fixed random seeds)
810
+
811
+ **Estimated Time:** 2-3 hours (includes training time)
812
+
813
+ ---
814
+
815
+ ### **Task 2.4:** Comprehensive model evaluation
816
+ **Status:** ⬜ NOT STARTED
817
+ **Priority:** HIGH
818
+ **Objective:** Compute all required metrics for report
819
+
820
+ **Implementation:**
821
+ - [ ] Create `scripts/evaluate.py`:
822
+ ```python
823
+ from sklearn.metrics import (
824
+ accuracy_score,
825
+ precision_recall_fscore_support,
826
+ confusion_matrix,
827
+ classification_report
828
+ )
829
+
830
+ def evaluate_model(model, test_loader, device) -> Dict:
831
+ """Compute all evaluation metrics"""
832
+ model.eval()
833
+ all_preds = []
834
+ all_labels = []
835
+
836
+ with torch.no_grad():
837
+ for images, labels in test_loader:
838
+ images = images.to(device)
839
+ outputs = model(images)
840
+ _, predicted = outputs.max(1)
841
+ all_preds.extend(predicted.cpu().numpy())
842
+ all_labels.extend(labels.numpy())
843
+
844
+ # Compute metrics
845
+ accuracy = accuracy_score(all_labels, all_preds)
846
+ precision, recall, f1, _ = precision_recall_fscore_support(
847
+ all_labels, all_preds, average='macro'
848
+ )
849
+ conf_matrix = confusion_matrix(all_labels, all_preds)
850
+
851
+ # Per-class metrics
852
+ per_class = classification_report(
853
+ all_labels, all_preds,
854
+ target_names=[str(i) for i in range(10)],
855
+ output_dict=True
856
+ )
857
+
858
+ return {
859
+ 'accuracy': accuracy,
860
+ 'precision': precision,
861
+ 'recall': recall,
862
+ 'f1_score': f1,
863
+ 'confusion_matrix': conf_matrix.tolist(),
864
+ 'per_class_metrics': per_class
865
+ }
866
+ ```
867
+ - [ ] Create `notebooks/04_model_evaluation.ipynb`
868
+ - [ ] Generate visualizations:
869
+ - Confusion matrix heatmap (seaborn)
870
+ - Per-class precision/recall bar charts
871
+ - Misclassified examples (show images + predictions)
872
+ - [ ] Perform error analysis:
873
+ - Which digit pairs confused most? (e.g., 4/9, 3/8)
874
+ - Are errors systematic or random?
875
+ - Visualize top-10 worst predictions
876
+ - [ ] Save evaluation report: `experiments/evaluation_report.json`
877
+
878
+ **Success Criteria:**
879
+ - All required metrics computed (accuracy, precision, recall)
880
+ - Confusion matrix shows strong diagonal (high accuracy per class)
881
+ - Error analysis identifies patterns
882
+ - Visualizations ready for report
883
+
884
+ **Estimated Time:** 2 hours
885
+
886
+ ---
887
+
888
+ ### **Task 2.5:** Experiment with improvements (leveraging MLflow)
889
+ **Status:** ⬜ NOT STARTED
890
+ **Priority:** MEDIUM
891
+ **Objective:** Systematic hyperparameter tuning using MLflow experiment tracking
892
+
893
+ **Potential Experiments:**
894
+ 1. **Deeper architecture**: Add 3rd conv layer (64→128 filters)
895
+ 2. **Batch normalization**: Add after each conv layer
896
+ 3. **Different optimizer**: Try SGD with momentum vs Adam
897
+ 4. **Learning rate tuning**: Grid search [0.0001, 0.001, 0.01]
898
+ 5. **Regularization**: Try different dropout rates [0.3, 0.5, 0.7]
899
+
900
+ **Implementation:**
901
+ - [ ] Create `notebooks/05_hyperparameter_tuning.ipynb`
902
+ - [ ] Use MLflow for systematic tracking:
903
+ ```python
904
+ import mlflow
905
+ from itertools import product
906
+
907
+ # Define search space
908
+ learning_rates = [0.0001, 0.001, 0.01]
909
+ dropout_rates = [0.3, 0.5, 0.7]
910
+ batch_sizes = [32, 64, 128]
911
+
912
+ # Grid search
913
+ for lr, dropout, batch_size in product(learning_rates, dropout_rates, batch_sizes):
914
+ with mlflow.start_run(run_name=f"lr{lr}_drop{dropout}_bs{batch_size}"):
915
+ # Train and log
916
+ ...
917
+ ```
918
+ - [ ] Use MLflow UI to compare experiments:
919
+ - Sort runs by validation accuracy
920
+ - Visualize parameter impact
921
+ - Identify best configuration
922
+ - [ ] Document findings in `docs/experiment_log.md`
923
+
924
+ **Decision Rule:**
925
+ Only pursue if baseline achieves ≥98% but want to push to 99%+. MLflow makes this more efficient than manual tracking.
926
+
927
+ **Success Criteria:**
928
+ - All experiments logged in MLflow with comparable metrics
929
+ - Best model identified through MLflow comparison
930
+ - Clear documentation of what worked/didn't work
931
+
932
+ **Estimated Time:** 2-3 hours
933
+
934
+ ---
935
+
936
+ ## Phase 3: Deployment to Hugging Face
937
+
938
+ > **Purpose:** Package model for production and deploy to Hugging Face Spaces
939
+
940
+ **Status:** ⬜ NOT STARTED
941
+ **Prerequisites:** Phase 2 complete (trained model achieving ≥98% accuracy)
942
+ **Estimated Time:** 4-6 hours
943
+
944
+ ---
945
+
946
+ ### **Task 3.1:** Create inference module
947
+ **Status:** ⬜ NOT STARTED
948
+ **Priority:** CRITICAL
949
+ **Objective:** Build clean inference interface for deployment
950
+
951
+ **Implementation:**
952
+ - [ ] Create `scripts/inference.py`:
953
+ ```python
954
+ import torch
955
+ from PIL import Image
956
+ import numpy as np
957
+
958
+ class DigitClassifier:
959
+ """Production inference wrapper"""
960
+
961
+ def __init__(self, model_path: str, device: str = 'cpu'):
962
+ self.device = device
963
+ self.model = self.load_model(model_path)
964
+ self.model.eval()
965
+
966
+ def load_model(self, path: str):
967
+ """Load model from checkpoint"""
968
+ from scripts.models import BaselineCNN
969
+ model = BaselineCNN()
970
+ model.load_state_dict(torch.load(path, map_location=self.device))
971
+ return model.to(self.device)
972
+
973
+ def preprocess(self, image: Image.Image) -> torch.Tensor:
974
+ """
975
+ Preprocess image for model input.
976
+ Accepts PIL Image or numpy array.
977
+ Handles resizing, normalization, etc.
978
+ """
979
+ # Convert to grayscale if RGB
980
+ if image.mode != 'L':
981
+ image = image.convert('L')
982
+
983
+ # Resize to 28x28 if needed
984
+ if image.size != (28, 28):
985
+ image = image.resize((28, 28), Image.Resampling.LANCZOS)
986
+
987
+ # Convert to tensor and normalize
988
+ img_array = np.array(image).astype(np.float32) / 255.0
989
+ img_tensor = torch.tensor(img_array).unsqueeze(0).unsqueeze(0)
990
+ return img_tensor.to(self.device)
991
+
992
+ def predict(self, image: Image.Image) -> dict:
993
+ """
994
+ Predict digit from image.
995
+
996
+ Returns:
997
+ {
998
+ 'digit': int (0-9),
999
+ 'confidence': float (0-1),
1000
+ 'probabilities': list of 10 floats
1001
+ }
1002
+ """
1003
+ img_tensor = self.preprocess(image)
1004
+
1005
+ with torch.no_grad():
1006
+ outputs = self.model(img_tensor)
1007
+ probabilities = torch.softmax(outputs, dim=1)[0]
1008
+ confidence, predicted = torch.max(probabilities, dim=0)
1009
+
1010
+ return {
1011
+ 'digit': int(predicted.item()),
1012
+ 'confidence': float(confidence.item()),
1013
+ 'probabilities': probabilities.cpu().numpy().tolist()
1014
+ }
1015
+ ```
1016
+ - [ ] Test inference module:
1017
+ - Load test set images
1018
+ - Verify predictions match evaluation results
1019
+ - Test with various image formats (PNG, JPG, different sizes)
1020
+ - Test edge cases (blank image, non-digit image)
1021
+
1022
+ **Success Criteria:**
1023
+ - Clean API: `classifier.predict(image)` → results
1024
+ - Handles various input formats gracefully
1025
+ - Fast inference (<100ms per image on CPU)
1026
+
1027
+ **Estimated Time:** 1.5 hours
1028
+
1029
+ ---
1030
+
1031
+ ### **Task 3.2:** Build Gradio interface
1032
+ **Status:** ⬜ NOT STARTED
1033
+ **Priority:** CRITICAL
1034
+ **Objective:** Create interactive web UI for digit recognition
1035
+
1036
+ **Implementation:**
1037
+ - [ ] Create `app.py`:
1038
+ ```python
1039
+ import gradio as gr
1040
+ from scripts.inference import DigitClassifier
1041
+ from PIL import Image
1042
+
1043
+ # Initialize classifier
1044
+ classifier = DigitClassifier('models/baseline_cnn_best.pt')
1045
+
1046
+ def predict_digit(image):
1047
+ """Gradio interface function"""
1048
+ if image is None:
1049
+ return "Please draw or upload a digit", None
1050
+
1051
+ # Convert to PIL Image
1052
+ if isinstance(image, np.ndarray):
1053
+ image = Image.fromarray(image.astype('uint8'))
1054
+
1055
+ # Get prediction
1056
+ result = classifier.predict(image)
1057
+
1058
+ # Format output
1059
+ label = f"Predicted Digit: {result['digit']}"
1060
+ confidence = f"Confidence: {result['confidence']:.2%}"
1061
+
1062
+ # Create probability chart
1063
+ probs = {str(i): result['probabilities'][i] for i in range(10)}
1064
+
1065
+ return f"{label}\n{confidence}", probs
1066
+
1067
+ # Create Gradio interface
1068
+ demo = gr.Interface(
1069
+ fn=predict_digit,
1070
+ inputs=gr.Image(
1071
+ sources=['upload', 'canvas'],
1072
+ type='pil',
1073
+ label="Draw or upload a digit (0-9)",
1074
+ image_mode='L' # Grayscale
1075
+ ),
1076
+ outputs=[
1077
+ gr.Textbox(label="Prediction"),
1078
+ gr.BarPlot(label="Confidence per Digit")
1079
+ ],
1080
+ title="MNIST Digit Classifier",
1081
+ description="Draw a digit (0-9) or upload an image. Model trained on MNIST dataset.",
1082
+ examples=[
1083
+ # Add example images from test set
1084
+ ],
1085
+ theme="default"
1086
+ )
1087
+
1088
+ if __name__ == "__main__":
1089
+ demo.launch()
1090
+ ```
1091
+ - [ ] Test locally: `python app.py`
1092
+ - Test drawing on canvas
1093
+ - Test uploading images
1094
+ - Verify probability bars update correctly
1095
+ - Test responsive design (mobile/desktop)
1096
+ - [ ] Add example images:
1097
+ - Extract 10 images from test set (one per digit)
1098
+ - Save as `examples/digit_0.png`, etc.
1099
+ - Include in interface for quick testing
1100
+
1101
+ **Success Criteria:**
1102
+ - Interface launches locally without errors
1103
+ - Users can draw or upload digits
1104
+ - Predictions display clearly with confidence scores
1105
+ - Responsive and intuitive UX
1106
+
1107
+ **Estimated Time:** 2 hours
1108
+
1109
+ ---
1110
+
1111
+ ### **Task 3.3:** Deploy to Hugging Face Spaces
1112
+ **Status:** ⬜ NOT STARTED
1113
+ **Priority:** HIGH
1114
+ **Objective:** Make model publicly accessible via Hugging Face
1115
+
1116
+ **Implementation:**
1117
+ - [ ] Create Hugging Face account (if needed): https://huggingface.co/join
1118
+ - [ ] Create new Space:
1119
+ - Name: `mnist-digit-classifier`
1120
+ - SDK: Gradio
1121
+ - Hardware: CPU (free tier sufficient)
1122
+ - [ ] Prepare deployment files:
1123
+ ```
1124
+ .
1125
+ ├── app.py # Gradio interface
1126
+ ├── requirements.txt # Deployment dependencies
1127
+ ├── models/
1128
+ │ └── baseline_cnn_best.pt # Model checkpoint
1129
+ ├── scripts/
1130
+ │ ├── models.py # Model architecture
1131
+ │ └── inference.py # Inference wrapper
1132
+ └── README.md # Space documentation
1133
+ ```
1134
+ - [ ] Create deployment `requirements.txt`:
1135
+ ```
1136
+ torch==2.0.1
1137
+ torchvision==0.15.2
1138
+ gradio==3.50.0
1139
+ pillow==10.0.0
1140
+ numpy==1.24.3
1141
+ ```
1142
+ - [ ] Write Space README.md:
1143
+ ```markdown
1144
+ ---
1145
+ title: MNIST Digit Classifier
1146
+ emoji: 🔢
1147
+ colorFrom: blue
1148
+ colorTo: purple
1149
+ sdk: gradio
1150
+ sdk_version: 3.50.0
1151
+ app_file: app.py
1152
+ pinned: false
1153
+ ---
1154
+
1155
+ # MNIST Digit Classifier
1156
+
1157
+ CNN model for handwritten digit recognition (0-9).
1158
+
1159
+ ## Model Details
1160
+ - Architecture: 2-layer CNN
1161
+ - Accuracy: XX.X% on MNIST test set
1162
+ - Training data: 60,000 handwritten digits
1163
+
1164
+ ## Usage
1165
+ Draw a digit or upload an image to get predictions.
1166
+ ```
1167
+ - [ ] Deploy:
1168
+ - Initialize git repo: `git init`
1169
+ - Add Hugging Face remote
1170
+ - Push code: `git push`
1171
+ - Monitor build logs for errors
1172
+ - [ ] Test deployed Space:
1173
+ - Visit Space URL
1174
+ - Test drawing interface
1175
+ - Verify predictions match local testing
1176
+ - Check loading time (<10s initial load)
1177
+
1178
+ **Success Criteria:**
1179
+ - Space builds successfully
1180
+ - Public URL accessible: `https://huggingface.co/spaces/<username>/mnist-digit-classifier`
1181
+ - Interface works identically to local version
1182
+ - Model makes accurate predictions
1183
+
1184
+ **Estimated Time:** 1.5 hours
1185
+
1186
+ ---
1187
+
1188
+ ### **Task 3.4:** Document deployment
1189
+ **Status:** ⬜ NOT STARTED
1190
+ **Priority:** MEDIUM
1191
+ **Objective:** Create usage guide for deployed model
1192
+
1193
+ **Implementation:**
1194
+ - [ ] Update Space README with:
1195
+ - Model architecture details
1196
+ - Training methodology
1197
+ - Performance metrics (accuracy, precision, recall)
1198
+ - Example usage (screenshots)
1199
+ - Limitations (works best on centered digits)
1200
+ - Citation/attribution
1201
+ - [ ] Create `docs/deployment_guide.md`:
1202
+ - How to run locally
1203
+ - How to deploy to other platforms
1204
+ - API documentation (if adding API endpoint)
1205
+ - Troubleshooting common issues
1206
+ - [ ] Add Space URL to main project README
1207
+ - [ ] Take screenshots for report
1208
+
1209
+ **Success Criteria:**
1210
+ - Clear documentation for users and developers
1211
+ - README includes all necessary information
1212
+ - Screenshots captured for report
1213
+
1214
+ **Estimated Time:** 45 minutes
1215
+
1216
+ ---
1217
+
1218
+ ### **Task 3.5:** Create Docker container
1219
+ **Status:** ⬜ NOT STARTED
1220
+ **Priority:** HIGH
1221
+ **Objective:** Containerize application for reproducible deployment
1222
+
1223
+ **Implementation:**
1224
+ - [ ] Create `Dockerfile`:
1225
+ ```dockerfile
1226
+ # Use official Python runtime as base
1227
+ FROM python:3.10-slim
1228
+
1229
+ # Set working directory
1230
+ WORKDIR /app
1231
+
1232
+ # Install system dependencies
1233
+ RUN apt-get update && apt-get install -y \
1234
+ build-essential \
1235
+ && rm -rf /var/lib/apt/lists/*
1236
+
1237
+ # Copy requirements and install Python dependencies
1238
+ COPY requirements.txt .
1239
+ RUN pip install --no-cache-dir -r requirements.txt
1240
+
1241
+ # Copy application code
1242
+ COPY scripts/ ./scripts/
1243
+ COPY models/ ./models/
1244
+ COPY app.py .
1245
+
1246
+ # Expose Gradio port
1247
+ EXPOSE 7860
1248
+
1249
+ # Run application
1250
+ CMD ["python", "app.py"]
1251
+ ```
1252
+ - [ ] Create `.dockerignore`:
1253
+ ```
1254
+ __pycache__
1255
+ *.pyc
1256
+ .git
1257
+ .gitignore
1258
+ data/
1259
+ notebooks/
1260
+ experiments/
1261
+ mlruns/
1262
+ *.md
1263
+ .venv/
1264
+ venv/
1265
+ ```
1266
+ - [ ] Build Docker image:
1267
+ ```bash
1268
+ docker build -t mnist-classifier:latest .
1269
+ ```
1270
+ - [ ] Test container locally:
1271
+ ```bash
1272
+ docker run -p 7860:7860 mnist-classifier:latest
1273
+ ```
1274
+ - Access http://localhost:7860
1275
+ - Verify inference works
1276
+ - Check resource usage
1277
+ - [ ] Document Docker usage in `README.md`
1278
+
1279
+ **Success Criteria:**
1280
+ - Docker image builds without errors
1281
+ - Container runs application successfully
1282
+ - Inference works identically to local setup
1283
+ - Image size reasonable (<1GB)
1284
+
1285
+ **Estimated Time:** 1.5 hours
1286
+
1287
+ ---
1288
+
1289
+ ### **Task 3.6:** Create docker-compose setup
1290
+ **Status:** ⬜ NOT STARTED
1291
+ **Priority:** MEDIUM
1292
+ **Objective:** Multi-container setup with MLflow UI for complete dev environment
1293
+
1294
+ **Implementation:**
1295
+ - [ ] Create `docker-compose.yml`:
1296
+ ```yaml
1297
+ version: '3.8'
1298
+
1299
+ services:
1300
+ mnist-app:
1301
+ build: .
1302
+ ports:
1303
+ - "7860:7860"
1304
+ volumes:
1305
+ - ./models:/app/models
1306
+ environment:
1307
+ - PYTHONUNBUFFERED=1
1308
+
1309
+ mlflow:
1310
+ image: ghcr.io/mlflow/mlflow:v2.9.2
1311
+ ports:
1312
+ - "5000:5000"
1313
+ volumes:
1314
+ - ./mlruns:/mlflow/mlruns
1315
+ command: mlflow server --host 0.0.0.0 --port 5000 --backend-store-uri /mlflow/mlruns
1316
+ ```
1317
+ - [ ] Test multi-container setup:
1318
+ ```bash
1319
+ docker-compose up -d
1320
+ ```
1321
+ - Access app: http://localhost:7860
1322
+ - Access MLflow: http://localhost:5000
1323
+ - [ ] Create management scripts:
1324
+ - `scripts/docker_start.sh`: Start containers
1325
+ - `scripts/docker_stop.sh`: Stop containers
1326
+ - `scripts/docker_logs.sh`: View logs
1327
+ - [ ] Document docker-compose workflow in `docs/deployment_guide.md`
1328
+
1329
+ **Success Criteria:**
1330
+ - Both services start successfully
1331
+ - Can access app and MLflow UI simultaneously
1332
+ - Volumes persist data correctly
1333
+ - Easy startup/shutdown
1334
+
1335
+ **Estimated Time:** 1 hour
1336
+
1337
+ ---
1338
+
1339
+ ## Phase 4: Final Documentation & Report
1340
+
1341
+ > **Purpose:** Compile comprehensive 20-30 page report and finalize deliverables
1342
+
1343
+ **Status:** ⬜ NOT STARTED
1344
+ **Prerequisites:** Phases 1-3 complete
1345
+ **Estimated Time:** 6-8 hours
1346
+
1347
+ ---
1348
+
1349
+ ### **Task 4.1:** Write technical report
1350
+ **Status:** ⬜ NOT STARTED
1351
+ **Priority:** CRITICAL
1352
+ **Objective:** Create final 20-30 page report covering all requirements
1353
+
1354
+ **Report Structure:**
1355
+ ```markdown
1356
+ # MNIST Handwritten Digit Recognition: A Data Quality-Focused Approach
1357
+
1358
+ ## Executive Summary (1 page)
1359
+ - Project overview
1360
+ - Key achievements
1361
+ - Final model performance
1362
+
1363
+ ## 1. Introduction (2 pages)
1364
+ - Problem statement
1365
+ - Objectives
1366
+ - Approach overview
1367
+
1368
+ ## 2. Data Pipeline (4-5 pages)
1369
+ - MNIST dataset description
1370
+ - IDX format handling
1371
+ - Data loading implementation
1372
+ - **Data Quality Analysis** (detailed):
1373
+ - Missing values check
1374
+ - Outlier detection
1375
+ - Class balance analysis
1376
+ - Visual inspection results
1377
+ - Preprocessing steps (normalization)
1378
+ - Train/validation/test split strategy
1379
+
1380
+ ## 3. Data Augmentation (3-4 pages)
1381
+ - Motivation and rationale
1382
+ - Augmentation techniques:
1383
+ - Random rotation (±15°)
1384
+ - Random translation (±10%)
1385
+ - Random scaling (90-110%)
1386
+ - Implementation details
1387
+ - Visual examples (before/after)
1388
+ - Impact on model performance (with/without augmentation)
1389
+
1390
+ ## 4. Model Architecture (3-4 pages)
1391
+ - CNN design rationale
1392
+ - Architecture details:
1393
+ - Layer specifications
1394
+ - Parameter counts
1395
+ - Activation functions
1396
+ - Architectural diagram
1397
+ - Design trade-offs and alternatives considered
1398
+
1399
+ ## 5. Training Methodology (3-4 pages)
1400
+ - Training configuration (hyperparameters)
1401
+ - Loss function and optimizer selection
1402
+ - Learning rate scheduling
1403
+ - Early stopping and regularization
1404
+ - Training curves (loss and accuracy)
1405
+ - Convergence analysis
1406
+
1407
+ ## 6. Evaluation & Results (4-5 pages)
1408
+ - **Metrics** (as required):
1409
+ - Accuracy: X.X%
1410
+ - Precision (macro): X.X%
1411
+ - Recall (macro): X.X%
1412
+ - Confusion matrix analysis
1413
+ - Per-class performance
1414
+ - Error analysis:
1415
+ - Most common misclassifications
1416
+ - Challenging digit pairs
1417
+ - Failure case examples
1418
+ - Comparison to baselines/literature
1419
+
1420
+ ## 7. Software Engineering Practices (3-4 pages)
1421
+ - **Code organization**:
1422
+ - Modular design (scripts/ structure)
1423
+ - Separation of concerns
1424
+ - **Version control**:
1425
+ - Git workflow
1426
+ - Commit conventions
1427
+ - Branch strategy
1428
+ - **Code quality**:
1429
+ - Linting (ruff)
1430
+ - Type hints and docstrings
1431
+ - Testing (if implemented)
1432
+ - **Experiment tracking**:
1433
+ - MLflow setup and workflow
1434
+ - Experiment comparison methodology
1435
+ - Model registry and versioning
1436
+ - **Documentation**:
1437
+ - Inline comments
1438
+ - Module documentation
1439
+ - README files
1440
+
1441
+ ## 8. Deployment (3-4 pages)
1442
+ - **Containerization**:
1443
+ - Docker setup and rationale
1444
+ - Multi-stage builds (if applicable)
1445
+ - Container orchestration (docker-compose)
1446
+ - **MLflow integration**:
1447
+ - Model serving from registry
1448
+ - Experiment reproducibility
1449
+ - **Hugging Face Spaces**:
1450
+ - Platform setup and configuration
1451
+ - Interface design (Gradio)
1452
+ - Inference pipeline
1453
+ - Usage examples and screenshots
1454
+ - Performance considerations (latency, resource usage)
1455
+ - **Deployment alternatives**:
1456
+ - Local Docker deployment
1457
+ - Docker vs Hugging Face comparison
1458
+
1459
+ ## 9. Challenges & Lessons Learned (1-2 pages)
1460
+ - Technical challenges encountered
1461
+ - Solutions implemented
1462
+ - Insights gained
1463
+ - Future improvements
1464
+
1465
+ ## 10. Conclusion (1 page)
1466
+ - Summary of achievements
1467
+ - Key takeaways
1468
+ - Potential extensions
1469
+
1470
+ ## References
1471
+ - MNIST dataset citation
1472
+ - Framework documentation (PyTorch)
1473
+ - Relevant papers/tutorials
1474
+
1475
+ ## Appendix
1476
+ - A: Code snippets (key functions)
1477
+ - B: Additional visualizations
1478
+ - C: Experiment log summary
1479
+ ```
1480
+
1481
+ **Implementation:**
1482
+ - [ ] Draft each section using content from notebooks and experiment log
1483
+ - [ ] Include all visualizations (plots, diagrams, screenshots)
1484
+ - [ ] Ensure data quality analysis is comprehensive (major focus)
1485
+ - [ ] Proofread for clarity and technical accuracy
1486
+ - [ ] Format professionally (LaTeX or polished Markdown)
1487
+
1488
+ **Success Criteria:**
1489
+ - Report is 20-30 pages (excluding appendix)
1490
+ - All required topics covered with sufficient depth
1491
+ - Data quality analysis prominent
1492
+ - SE practices clearly documented
1493
+ - Professional presentation quality
1494
+
1495
+ **Estimated Time:** 5-6 hours (spread over multiple sessions)
1496
+
1497
+ ---
1498
+
1499
+ ### **Task 4.2:** Create final validation notebook
1500
+ **Status:** ⬜ NOT STARTED
1501
+ **Priority:** CRITICAL
1502
+ **Objective:** Single notebook demonstrating complete solution
1503
+
1504
+ **Implementation:**
1505
+ - [ ] Create `notebooks/99_final_solution.ipynb`
1506
+ - [ ] Structure:
1507
+ ```
1508
+ 1. Setup & Imports
1509
+ 2. Data Loading
1510
+ 3. Data Quality Analysis (with outputs)
1511
+ 4. Preprocessing & Augmentation Demo
1512
+ 5. Model Definition
1513
+ 6. Training (or load pre-trained)
1514
+ 7. Evaluation (all metrics)
1515
+ 8. Visualizations (confusion matrix, examples)
1516
+ 9. Inference Examples
1517
+ 10. Summary
1518
+ ```
1519
+ - [ ] Requirements:
1520
+ - Runs end-to-end without errors
1521
+ - Clear markdown explanations
1522
+ - All outputs visible (no need to re-run)
1523
+ - Reproduces key results from report
1524
+ - [ ] Test notebook:
1525
+ - Restart kernel and run all cells
1526
+ - Verify no missing imports or path issues
1527
+ - Check output matches report
1528
+
1529
+ **Success Criteria:**
1530
+ - Notebook validates entire solution
1531
+ - Can be run by evaluators to verify results
1532
+ - Well-documented with markdown cells
1533
+ - All cells execute successfully
1534
+
1535
+ **Estimated Time:** 2 hours
1536
+
1537
+ ---
1538
+
1539
+ ### **Task 4.3:** Finalize project documentation
1540
+ **Status:** ⬜ NOT STARTED
1541
+ **Priority:** MEDIUM
1542
+ **Objective:** Ensure all documentation is complete and polished
1543
+
1544
+ **Implementation:**
1545
+ - [ ] Update main `README.md`:
1546
+ ```markdown
1547
+ # MNIST Digit Classifier
1548
+
1549
+ CNN-based handwritten digit recognition with emphasis on data quality.
1550
+
1551
+ ## Quick Links
1552
+ - 🚀 [Live Demo](https://huggingface.co/spaces/...)
1553
+ - 📄 [Full Report](docs/final_report.pdf)
1554
+ - 📓 [Solution Notebook](notebooks/99_final_solution.ipynb)
1555
+
1556
+ ## Project Structure
1557
+ [Describe directories]
1558
+
1559
+ ## Setup
1560
+ [Installation instructions]
1561
+
1562
+ ## Usage
1563
+ [How to run training, evaluation, inference]
1564
+
1565
+ ## Results
1566
+ [Key metrics summary]
1567
+
1568
+ ## Citation
1569
+ [If applicable]
1570
+ ```
1571
+ - [ ] Review all documentation files:
1572
+ - `docs/DEVELOPMENT_WORKFLOW.md` - accurate?
1573
+ - `docs/experiment_log.md` - complete?
1574
+ - `scripts/README.md` - describes all modules?
1575
+ - `.github/copilot-instructions.md` - up to date?
1576
+ - [ ] Clean up repository:
1577
+ - Remove temporary files
1578
+ - Archive experiment artifacts
1579
+ - Organize `experiments/` directory
1580
+ - Verify `.gitignore` working correctly
1581
+ - [ ] Final git commit:
1582
+ - Commit message: `docs: finalize project documentation`
1583
+ - Tag release: `git tag v1.0.0`
1584
+
1585
+ **Success Criteria:**
1586
+ - All documentation files complete and accurate
1587
+ - README provides clear project overview
1588
+ - Repository clean and organized
1589
+ - Easy for others to understand and reproduce
1590
+
1591
+ **Estimated Time:** 1 hour
1592
+
1593
+ ---
1594
+
1595
+ ## Next Steps
1596
+
1597
+ **Immediate Actions (Start Here):**
1598
+ 1. Complete Phase 0: Project Setup (1-2 hours)
1599
+ - Create requirements.txt
1600
+ - Configure .gitignore
1601
+ - Initialize documentation
1602
+ - Verify data integrity
1603
+
1604
+ 2. Start Phase 1: Data Pipeline (6-8 hours)
1605
+ - Extract MnistDataloader to module
1606
+ - Build data exploration notebook
1607
+ - Implement quality analysis
1608
+
1609
+ **Decision Points:**
1610
+ - **After Task 2.3** (baseline training): If accuracy ≥98%, proceed to deployment. If <98%, debug before continuing.
1611
+ - **After Task 2.4** (evaluation): Decide whether to pursue Task 2.5 (improvements) or move to deployment.
1612
+ - **After Task 3.3** (deployment): If deployment issues, can document locally and note limitations in report.
1613
+
1614
+ **Risk Mitigation:**
1615
+ - **Time constraint**: Focus on baseline (skip Task 2.5) if time limited
1616
+ - **Deployment issues**: Have local demo ready as backup
1617
+ - **Model underperformance**: Document honestly and analyze why
1618
+
1619
+ ---
1620
+
1621
+ ## Metrics & Success Criteria
1622
+
1623
+ **Model Performance Targets:**
1624
+ - Minimum: ≥ 97% test accuracy (acceptable baseline)
1625
+ - Target: ≥ 98% test accuracy (standard CNN performance)
1626
+ - Stretch: ≥ 99% test accuracy (competitive)
1627
+
1628
+ **Code Quality Targets:**
1629
+ - Zero `ruff` linting errors
1630
+ - Type hints on all functions in `scripts/`
1631
+ - Docstrings on all public functions
1632
+ - Modular design (no monolithic files >500 lines)
1633
+
1634
+ **Documentation Targets:**
1635
+ - Report: 20-30 pages covering all required topics
1636
+ - Data quality analysis: ≥3 pages with visualizations
1637
+ - SE practices section: clearly demonstrates best practices
1638
+ - Final notebook: executable and reproducible
1639
+
1640
+ **Deployment Targets:**
1641
+ - Hugging Face Space live and accessible
1642
+ - Inference latency: <500ms per prediction
1643
+ - Interface intuitive (can be used without instructions)
1644
+
1645
+ ---
1646
+
1647
+ ## Workflow Reference
1648
+
1649
+ **Standard Task Workflow:**
1650
+ 1. **Review**: Read task requirements, check dependencies
1651
+ 2. **Design**: Plan implementation approach
1652
+ 3. **Implement**: Write code with tests
1653
+ 4. **Run**: Execute and validate results
1654
+ 5. **Assess**: Analyze outcomes, document findings
1655
+ 6. **Commit**: Save progress with clear message
1656
+
1657
+ **Commit Message Format:**
1658
+ ```
1659
+ type: brief summary (50 chars max)
1660
+
1661
+ Detailed description if needed (wrap at 72 chars).
1662
+ Include rationale, trade-offs, and any important context.
1663
+
1664
+ Related tasks: #1.2, #2.3
1665
+ ```
1666
+
1667
+ **Types:** `feat`, `fix`, `docs`, `refactor`, `test`, `chore`
1668
+
1669
+ **Branch Strategy:**
1670
+ - `main`: stable code only
1671
+ - `feature/<task-name>`: for each major task
1672
+ - Merge to main after task completion and validation
1673
+
1674
+ ---
1675
+
1676
+ ## Resources
1677
+
1678
+ **Documentation:**
1679
+ - [MNIST Official](http://yann.lecun.com/exdb/mnist/)
1680
+ - [PyTorch Tutorials](https://pytorch.org/tutorials/)
1681
+ - [Hugging Face Spaces Docs](https://huggingface.co/docs/hub/spaces)
1682
+ - [Gradio Documentation](https://gradio.app/docs/)
1683
+
1684
+ **Project Files:**
1685
+ - Planning: [planning.md](planning.md) (this file)
1686
+ - Workflow: [docs/DEVELOPMENT_WORKFLOW.md](docs/DEVELOPMENT_WORKFLOW.md)
1687
+ - Experiments: [docs/experiment_log.md](docs/experiment_log.md)
1688
+ - Problem: [docs/problem_statement.md](docs/problem_statement.md)
1689
+
1690
+ **Code Reference:**
1691
+ - Data loader: [data/raw/read-mnist-dataset.ipynb](data/raw/read-mnist-dataset.ipynb)
1692
+ - AI instructions: [.github/copilot-instructions.md](.github/copilot-instructions.md)
1693
+
1694
+ ---
1695
+
1696
+ ## Notes
1697
+
1698
+ **Critical Success Factors:**
1699
+ 1. **Data quality analysis is paramount** - this is a key differentiator per spec
1700
+ 2. **SE best practices must be demonstrable** - not just good code, but documented practices
1701
+ 3. **Report quality matters** - 20-30 pages well-written, not just verbose
1702
+ 4. **Reproducibility** - others must be able to run and verify results
1703
+
1704
+ **Common Pitfalls to Avoid:**
1705
+ - ❌ Training on test set (data leakage)
1706
+ - ❌ Not fixing random seeds (non-reproducible)
1707
+ - ❌ Overfitting to validation set (test multiple times)
1708
+ - ❌ Skipping data quality analysis (required!)
1709
+ - ❌ Poor documentation (hard to evaluate)
1710
+
1711
+ **Time Management:**
1712
+ - Baseline is sufficient - don't over-optimize
1713
+ - Data quality and documentation are as important as model performance
1714
+ - Leave buffer for report writing (6-8 hours)
1715
+ - Test deployment early (can be time sink if issues)
1716
+
1717
+ **Questions/Uncertainties:**
1718
+ - [ ] Preferred report format? (PDF, Markdown, LaTeX)
1719
+ - [ ] Should tests be included? (Not required, but good practice)
1720
+ - [ ] Team submission or individual? (Affects documentation scope)
1721
+ - [ ] Evaluation rubric available? (Would inform priorities)
1722
+
1723
+ ---
1724
+
1725
+ **Last Updated:** December 28, 2025
1726
+ **Status:** Phase 0 - Ready to begin
1727
+ **Next Task:** Task 0.1 - Create requirements.txt
requirements.txt ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Core dependencies for MNIST digit classification project
2
+ # Python 3.10 (conda environment: ai_engg)
3
+
4
+ # Core ML libraries
5
+ numpy==1.24.3
6
+ matplotlib==3.7.1
7
+ torch==2.0.1
8
+ torchvision==0.15.2
9
+ scikit-learn==1.3.0
10
+
11
+ # Experiment tracking
12
+ mlflow==2.9.2
13
+
14
+ # Deployment
15
+ gradio==3.50.0
16
+ pillow==10.0.0
17
+
18
+ # Development
19
+ jupyter==1.0.0
20
+ ruff==0.0.270
21
+ pytest==7.4.0
22
+
23
+ # Additional utilities
24
+ pandas==2.0.3
25
+ seaborn==0.12.2
scripts/README.md ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Scripts Directory
2
+
3
+ This directory contains reusable Python modules for the MNIST digit classification project.
4
+
5
+ ## Modules
6
+
7
+ ### Data Processing
8
+ - **`data_loader.py`** - MNIST data loading from IDX binary format
9
+ - `MnistDataloader` class for loading train/test data
10
+
11
+ - **`preprocessing.py`** - Data preprocessing and PyTorch Dataset
12
+ - `MnistDataset` - PyTorch Dataset with normalization
13
+ - `create_train_val_split()` - Split training data into train/val
14
+
15
+ - **`data_quality.py`** - Data quality analysis functions
16
+ - Quality checks: missing values, outliers, class balance
17
+ - `generate_quality_report()` - Comprehensive quality report
18
+
19
+ - **`augmentation.py`** - Data augmentation pipeline
20
+ - `get_augmentation_pipeline()` - Transform composition for training
21
+
22
+ ### Model
23
+ - **`models.py`** - CNN architectures
24
+ - `BaselineCNN` - 2-layer CNN baseline model
25
+
26
+ - **`train.py`** - Training pipeline
27
+ - `train_epoch()` - Single epoch training
28
+ - `validate()` - Validation evaluation
29
+ - `train_model()` - Complete training loop with MLflow logging
30
+
31
+ - **`evaluate.py`** - Model evaluation
32
+ - `evaluate_model()` - Comprehensive metrics computation
33
+ - Accuracy, precision, recall, confusion matrix
34
+
35
+ - **`inference.py`** - Production inference
36
+ - `DigitClassifier` - Inference wrapper for deployment
37
+
38
+ ### Experiment Tracking
39
+ - **`mlflow_setup.py`** - MLflow configuration
40
+ - `setup_mlflow()` - Initialize MLflow experiment
41
+ - Tracking URI and experiment management
42
+
43
+ ### Utilities
44
+ - **`launch_mlflow_ui.sh`** - Launch MLflow UI server
45
+ - **`docker_start.sh`** - Start Docker containers
46
+ - **`docker_stop.sh`** - Stop Docker containers
47
+ - **`docker_logs.sh`** - View Docker container logs
48
+
49
+ ## Usage
50
+
51
+ All modules are designed to be imported and used in notebooks or other scripts:
52
+
53
+ ```python
54
+ # Example: Load data
55
+ from scripts.data_loader import MnistDataloader
56
+
57
+ loader = MnistDataloader(
58
+ training_images_filepath='data/raw/train-images.idx3-ubyte',
59
+ training_labels_filepath='data/raw/train-labels.idx1-ubyte',
60
+ test_images_filepath='data/raw/t10k-images.idx3-ubyte',
61
+ test_labels_filepath='data/raw/t10k-labels.idx1-ubyte'
62
+ )
63
+ (x_train, y_train), (x_test, y_test) = loader.load_data()
64
+ ```
65
+
66
+ ## Development Guidelines
67
+
68
+ - All functions include type hints
69
+ - All public functions have docstrings
70
+ - Follow naming conventions (snake_case for functions, PascalCase for classes)
71
+ - Run `ruff check . --fix` before committing
72
+ - Add unit tests in `tests/` directory for critical functions