handwritten_digit_baseline

Handwritten Digit Recognition Challenge

Baseline source code for Handwritten Digit Recognition Challenge

MIT
Image Classification
PyTorch
Scikit-learn
English
by @AIOZAI
27
0

Last updated: 9 days ago


Handwritten Digit Recognition Baseline Source Code

License Python System

Challenge participants: Build robust models to classify hand-written digit images into digits (0-9).

Table of Contents

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.

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

PartRule
my_ai_lib package nameLocked — 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.pyLocked — DO NOT EDIT.
run() in run.pyLocked — DO NOT EDIT. It is the entrypoint AIOZ AI calls; do not rename or remove it.
load_model / preprocess / predict / postprocessYours. Fill in these stages with your logic in model.py and pipeline.py.
requirements.txtYours. 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 your TaskInput inherits):
    • device: one of cpu, cuda, gpu (default cuda).
    • 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 returns output_file: FileObject.
  • FileObject: data (a local Path, 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.csv and 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 an output/ 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.csv must 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.py before 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.