Start
03/09/2026
Close
∞
Handwritten Digit Recognition Challenge
Classify handwritten digits from images
Challenge Rewards:
knowledgeParticipants
33
Submissions
30
Handwritten Digit Recognition Baseline Source Code
Challenge participants: Build robust models to classify hand-written digit images into digits (0-9).
Table of Contents
- Quick Start
- Introduction
- Requirements
- Project Structure
- Detailed Tutorial
- Submission Guidelines
- License
Quick Start
Clone the repository:
git clone [email protected]:AIOZAI/handwritten_digit_baseline.git
or, download directly: Handwritten Digit Baseline
Then, navigate into the project directory and follow the steps below:
# 1. Install dependencies (Add any other libraries your code imports to requirements.txt)
pip install -r requirements.txt
# 2. Start developing your solution. Follow the tutorial below to implement your AI model.
# 3. Verify Your Submission
python preflight.py
Note: You need to implement your Handwritten Digit Recognition solution following the tutorial guide.
Introduction
The Handwritten Digit Recognition Challenge is an AI competition where you predict the digit in a hand-written digit image. It's a multi-class classification problem.
In this challenge, participants will be provided with:
-
Model Access: Handwritten Digit Baseline
- Code baseline to develop solutions.
- Dependencies: Add every dependency you import in
requirements.txt.
-
Dataset Access: Handwritten Digit Dataset
- Training dataset to train your AI models (includes
ground_truth.csv). - Testing dataset to predict labels for generating the submission file.
- Training dataset to train your AI models (includes
Goal: Classify each digit image into one of 10 categories: 0 through 9.
Requirements
System Requirements
- Python 3.10+
Dependencies
Install all required packages:
pip install -r requirements.txt
Project Structure
Your AI library should follow this structure:
repository/
├── my_ai_lib/ # Your AI library
│ ├── __init__.py # Required: Exposes run() — do not touch
│ ├── schemas.py # Required: Locked input/output schema for this challenge
│ ├── model.py # load_model() <- load your weights here
│ ├── pipeline.py # preprocess/predict/postprocess <- your logic
│ └── run.py # Required: Main workflow function — do not touch
├── models/ # Model weights directory
├── preflight.py # Demo script to verify output format
├── requirements.txt # Add every dependency you import
└── README.md # Documentation
What you may and may not change
| Part | Rule |
|---|---|
my_ai_lib package name | Locked — DO NOT EDIT. AIOZ AI imports my_ai_lib.run(...). Do not rename the folder or remove from .run import run. |
TaskInput / TaskOutput in schemas.py | Locked — DO NOT EDIT. |
run() in run.py | Locked — DO NOT EDIT. It is the entrypoint AIOZ AI calls; do not rename or remove it. |
load_model / preprocess / predict / postprocess | Yours. Fill in these stages with your logic in model.py and pipeline.py. |
requirements.txt | Yours. Add every dependency you import. |
Detailed Tutorial
Step 1: Initialize Your AI Library
1.1 Define my_ai_lib/__init__.py
from .run import run
This file exposes the run() function from run.py as an attribute of my_ai_lib, so you can call it as my_ai_lib.run().
1.2 Define Input/Output Objects in my_ai_lib/schemas.py
Note: In this template, schemas.py is pre-defined and locked. Do not edit it.
from aioz_ainode_adapter.schemas import FileObject, InputObject, OutputObject
class TaskInput(InputObject):
input_folder: str
class TaskOutput(OutputObject):
output_file: FileObject
Step 2: Understanding AIOZ Schema Objects
InputObject(base fields yourTaskInputinherits):device: one ofcpu,cuda,gpu(defaultcuda).model_storage_directory: where your weights live — read this path, do not hard-code one.
- This challenge adds one input field:
input_folder: str. OutputObject: this challenge returnsoutput_file: FileObject.FileObject:data(a localPath, an open binary file, or a URL) +name.
Step 3: Implement the Main Workflow
3.1 Implement Your AI Logic (my_ai_lib/model.py & my_ai_lib/pipeline.py)
Modify my_ai_lib/model.py and my_ai_lib/pipeline.py to add your custom logic.
- load_model: Load your weights from
model_storage_directory. - preprocess: Read all images from the
input_folder. - predict: Run your loaded model on the images to generate predictions.
- postprocess: Save predictions to
result.csvand return its path.
3.2 Implement the Required run() Function (my_ai_lib/run.py)
Note: In this template, run() is pre-defined to link your pipeline stages. Do not edit it.
def run(input_obj: TaskInput) -> TaskOutput:
"""Mandatory entrypoint — DO NOT RENAME IT."""
task_input = TaskInput.model_validate(input_obj.model_dump()) # validate the input
model = load_model(task_input.model_storage_directory, task_input.device)
samples = preprocess(task_input.input_folder)
predictions = predict(model, samples)
output_path = postprocess(predictions)
output = open(output_path, "rb")
output_file = FileObject(data=output, name=os.path.basename(output.name))
return TaskOutput(output_file=output_file)
Critical: The
run()function name is mandatory and cannot be changed.
Step 4: Create Demo Script
The template includes a preflight script (preflight.py) to test your implementation end-to-end and verify the output schema.
Run this command to test your implementation:
python preflight.py
Expected console output:
✅ my_ai_lib.run found
✅ locked schema is intact
Input: type='InputObj' device='cuda' model_storage_directory='.../models' input_folder='sample_input/'
Output: type='OutputObj' output_file=FileObject(type='FileObj', data=..., name='result.csv')
✅ run() returned a valid TaskOutput with a file
Step 5: Add Model Weights
Place your trained model files in the models/ directory:
models/
├── model.pth # Your trained model
├── config.json # Model configuration
└── etc.
Step 6: Format Your Prediction Output (For Submission)
Your model must output predictions in a specific format for grading. Implement the logic to generate this file in the postprocess function of my_ai_lib/pipeline.py.
Requirements:
- Process test dataset (images in test data folder)
- Generate predictions for each image
- Save results as
result.csv(e.g., inside anoutput/directory)
Implementation Example in pipeline.py:
import csv
from pathlib import Path
from typing import List, Tuple
def postprocess(predictions: List[Tuple[str, int]], output_path: Path = Path("result.csv")) -> Path:
"""Turn predictions into your output file and return its path.
Placeholder: write the predictions to result.csv.
"""
with output_path.open("w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["id", "digit"])
writer.writerows(predictions)
return output_path
Important: The
result.csvmust match the challenge's sample submission format exactly.
Notes
- Use relative imports for your own modules (
from .lib import helper) so your code runs inside the sandbox. - Let exceptions propagate — AIOZ AI reports them; do not catch and hide them.
- Run
python preflight.pybefore every submission.
Submission Guidelines
Submission Format
The submission file has two fields:
- id: The unique identifier for each image.
- digit: The target class (0-9).
Example:
id,digit
000039d3a3924cba84e8098d6bdd6951.png,0
0019e9a6ca414f7ab1456c0f0b578e64.png,3
License
This repository is licensed under the MIT License.