API Reference

This page documents the public Python API exposed by the ccexam package.


Data (src.data)

get_loaders

from src.data import get_loaders

train_loader, test_loader = get_loaders(
    dataset: str = "mnist",
    batch_size: int = 64,
    data_dir: str = "datasets",
    num_workers: int = 2,
    download: bool = True,
)

Returns (train_loader, test_loader) as torch.utils.data.DataLoader objects for a registered dataset. Dataset files are downloaded automatically on first use.

Example

from src.data import get_loaders

train_loader, test_loader = get_loaders(dataset="svhn", batch_size=128)
for images, labels in train_loader:
    ...

Data modules

Each dataset has a dedicated data module that can also be used directly:

Class

Dataset

Default normalization

MNISTDataModule

MNIST

mean=0.1307, std=0.3081

USPSDataModule

USPS

mean=0.2471, std=0.2994

SVHNDataModule

SVHN

mean=(0.4377, 0.4438, 0.4728), std=(0.1980, 0.2010, 0.1970)

All modules expose .train_loader(), .val_loader(), and .test_loader() methods.


Models (src.models)

All model classes are torch.nn.Module subclasses callable with an image batch tensor.

MNISTNet

CNN for 28×28 grayscale MNIST digits. Two convolutional blocks followed by a two-layer classifier head (128 hidden units, 10 outputs).

from src.models import MNISTNet

model = MNISTNet()
logits = model(batch)  # batch shape: (N, 1, 28, 28)

USPSNet

Same architecture as MNISTNet, adapted for 16×16 grayscale USPS digits.

from src.models import USPSNet

model = USPSNet()
logits = model(batch)  # batch shape: (N, 1, 16, 16)

SVHNNet

Deeper CNN for 32×32 RGB SVHN digits. Three convolutional blocks with batch normalization, followed by a dropout-regularized classifier head.

from src.models import SVHNNet

model = SVHNNet(num_classes=10, dropout=0.3)
logits = model(batch)  # batch shape: (N, 3, 32, 32)

Parameter

Default

Description

num_classes

10

Number of output classes

dropout

0.3

Dropout probability in the classifier head


Training (src.training)

train

from src.training import train

metrics = train(dataset: str = "mnist", **kwargs) -> dict

Convenience entry point. Selects the correct data module and model from DATASET_REGISTRY and runs training.

Keyword argument

Default

Description

epochs

1

Number of training epochs

lr

1e-3

Learning rate (Adam optimizer)

batch_size

64

Mini-batch size

checkpoint_path

registry default

Where to save the .pth checkpoint

data_dir

"datasets"

Root directory for dataset downloads

device

auto

"cpu", "cuda", or "mps"

loss_fn

CrossEntropyLoss

Custom torch.nn loss instance

Returns a dict with keys loss, accuracy, val_loss, val_accuracy, epochs, checkpoint_path.

Example

from src.training import train

metrics = train(dataset="usps", epochs=5, batch_size=128)
print(metrics["accuracy"])

DATASET_REGISTRY

Maps dataset names to DatasetSpec objects (data module class, model class, default checkpoint path).

Key

Model

Default checkpoint (file location)

CLI / API argument

"mnist"

MNISTNet

src/weights/mnist.pth

weights/mnist.pth

"usps"

USPSNet

src/weights/usps.pth

weights/usps.pth

"svhn"

SVHNNet

src/weights/svhn.pth

weights/svhn.pth

Paths are resolved relative to src/ via SRC_ROOT. Pass only the weights/<name>.pth portion when using --checkpoint-path or checkpoint_path=.


Evaluation (src.evaluation)

evaluate

from src.evaluation import evaluate

evaluate(
    inference: BaseInference,
    dataloader: Iterable,
    metrics: dict[str, Callable[[Any, Any], float]] | None = None,
) -> dict

Run a trained model over every batch in dataloader and report classification metrics together with the average inference speed. Runs under torch.no_grad.

Parameter

Type

Description

inference

BaseInference

Inference instance from InferenceFactory.create(...). Its underlying model is used for batch prediction.

dataloader

Iterable

Yields (images, labels) batches — typically a DataModule.test_loader().

metrics

dict | None

Mapping of metric name to (y_true, y_pred) -> float. Defaults to DEFAULT_METRICS (precision and recall, macro-averaged).

Returns a dict with:

  • "precision" — macro-averaged precision

  • "recall" — macro-averaged recall

  • "speed_ms" — average forward-pass time in milliseconds per sample (data-loading time excluded)

Example

from src.data import DATA_MODULES
from src.evaluation import evaluate
from src.inference import InferenceFactory

inference = InferenceFactory.create("svhn", checkpoint_path="weights/svhn.pth", device="cpu")
test_loader = DATA_MODULES["svhn"](data_dir="datasets", batch_size=256).test_loader()

results = evaluate(inference, test_loader)
print(results)  # {"precision": 0.91, "recall": 0.90, "speed_ms": 1.42}

CLI usage

src.evaluation is also runnable as a module to evaluate a registered dataset on its test set:

python -m src.evaluation --dataset svhn --checkpoint-path weights/svhn.pth --device cpu

Argument

Default

Description

--dataset

mnist

One of mnist, usps, svhn

--checkpoint-path

registry default

Checkpoint to load

--batch-size

256

Evaluation batch size

--data-dir

datasets

Root directory containing the datasets

--num-workers

0

DataLoader worker count

--device

cpu

cpu, cuda, or mps

--log-level

INFO

Logging level


DEFAULT_METRICS

Module-level dict of the default metric callables used when metrics=None is passed to evaluate. Override or extend to add metrics like F1 or accuracy:

from src.evaluation import DEFAULT_METRICS, evaluate
from sklearn.metrics import f1_score

custom = {**DEFAULT_METRICS, "f1": lambda y, p: f1_score(y, p, average="macro")}
results = evaluate(inference, test_loader, metrics=custom)

Inference (src.inference)

run_inference

from src.inference import run_inference

run_inference(
    model: str,
    input_path: str | Path,
    checkpoint_path: str | Path | None = None,
    device: str | None = None,
) -> int | list[int]

Run inference on one image or a folder of images.

Parameter

Type

Description

model

str

Dataset alias: "mnist", "usps", "svhn"

input_path

str | Path

Path to a single image file or a directory of images

checkpoint_path

str | Path | None

Override the default checkpoint file (optional)

device

str | None

Torch device, e.g. "cpu", "cuda", "mps". Auto-detected if None

Returns a single int label when input_path is a file, or a list[int] (sorted by filename) when it is a directory.

Example

from src.inference import run_inference

label = run_inference(model="usps", input_path="digit.png")
print(label)  # e.g. 7

labels = run_inference(model="mnist", input_path="folder/")
print(labels)  # e.g. [3, 1, 4, 1, 5]

InferenceFactory

from src.inference import InferenceFactory

predictor = InferenceFactory.create(model_name: str, **kwargs)
predictor.predict(image)  # -> int

Creates a configured Inference instance for the given model name. Accepts the same keyword arguments as run_inference (device, checkpoint_path, etc.).


INFERENCE_REGISTRY

Dictionary mapping model/dataset names to InferenceSpec objects that define the model class, default checkpoint path, image size, and normalization constants.

Key

Model class

Image size

Channels

"mnist" / "model-a"

MNISTNet

28×28

Grayscale

"usps" / "model-b"

USPSNet

16×16

Grayscale

"svhn" / "model-c"

SVHNNet

32×32

RGB


write_results

from src.inference import write_results

write_results(results: dict[Path, int], output_path: str | Path) -> Path

Write a {image_path: label} dictionary to a .csv or .txt file. The output file is never overwritten — a numbered copy is created instead (predictions_1.csv, …).