RSS Amplifier

Hands On "AI Engineering" · Jul 13, 2026

Week 19-20 : Neural Networks from Scratch (Days 127-140)

0
Sign in to vote or save

This page did not load. You can still read it on the original site — the toolbar below keeps your place in the directory.

Introduction

Introduction

Most “from scratch” neural network repos stop at a script that prints accuracy. That’s useful for learning, but it’s not a system engineers can iterate on: there’s no stable API surface, no durable run metadata, no clear separation between reusable core logic and orchestration, and no way to observe what the system is doing while it works.

This project turns Days 127-140 into a single production-style application: a NumPy-first core package, a FastAPI backend that exposes both Learning and Product endpoints, a React dashboard, and a Postgres-backed run ledger. You’ll walk away with a practical blueprint for integrating neural network lesson code into an operable service without losing the educational “glass box” properties.

System Overview

The stack is intentionally small and explicit:

  • React dashboard (Vite build served by Nginx, port 3000) — one integrated workbench: a stepper for Days 127–131 and a Product view for experiments and runs.

  • FastAPI backend (port 8000)/api/v1/week1920/learn/... for curriculum-backed demos, /api/v1/ml/... for persisted experiments, runs, artifacts, and live metrics.

  • week1920_python core package — the “engine room”: perceptron training, activation primitives, MLP forward passes, backprop trainer, MNIST forward model, plus a minimal losses/metrics surface.

  • Persistence — Postgres (async SQLAlchemy + Alembic) for experiment and run metadata; Docker volumes for artifacts and cache directories.

The curriculum topics don’t show up as separate apps. They show up as modules that the system can execute: perceptron training is a callable unit, activations expose gradient checks, backprop is a bounded training job, and MNIST is operationalized as a forward pipeline (with training staged for later days).

Engine / Core System Design

The core package owns math and algorithms; the backend owns HTTP, input validation, and orchestration. That separation is what keeps the “lesson logic” reusable while letting the system behave like a service.

At the core layer, the “day modules” are not scripts. They’re importable functions and classes that can be dispatched from either the Learning API or a Product workflow. The engine layer is minimal on purpose: it standardizes conventions (shapes, seeds, bounded defaults) and provides a stable surface for orchestration.

Two details matter for correctness and operability:

1) A consistent parameter convention

The core uses a consistent dense-layer convention ((fan_in, fan_out) weights and Z = A @ W + b) across MLP and MNIST. That makes later training code predictable and keeps “shape debugging” localized.

2) Non-blocking orchestration

Learning endpoints can still do “real work” (training or dataset access), but the backend must remain responsive while that happens. This repo moves CPU-heavy work into asyncio.to_thread(...) so the event loop isn’t blocked by NumPy loops or dataset preprocessing.

backend/app/routes/week1920_lab.py (excerpt)
@week1920_router.post(”/learn/day130/backprop/train”)
async def learn_day130_backprop_train(epochs: int = 200, lr: float = 0.05, seed: int = 0):
    epochs = min(epochs, settings.WEEK1920_MAX_EPOCHS_LEARN)
def _run_sync():
        X, y = get_xor_data()
        y2 = y.reshape(-1, 1).astype(float)
        net = Trainer(layer_sizes=[2, 4, 4, 1], hidden_activation=”relu”, seed=seed)
        result = net.train(X, y2, epochs=epochs, lr=lr)
        preds = net.predict(X)
        accuracy = float(np.mean((preds >= 0.5).astype(int).flatten() == y2.flatten()))
return {”final_loss”: result[”final_loss”], “accuracy”: accuracy}
return await asyncio.to_thread(_run_sync)

Data Flow Diagram Reference

API Design

The API is split into two surfaces that behave differently:

  • Learning endpoints are stateless, bounded, and “demo-first.”

  • Product endpoints are stateful: they create experiments, record runs, and surface artifacts/metrics for the dashboard.

Representative endpoints:

GET /api/v1/week1920/learn/day127/perceptron?dataset=xor&max_epochs=50
Response: {
  lesson: "day127",
  dataset: "xor",
  accuracy: number,
  training: { converged: boolean, epochs_run: number, training_errors: number[] }
}

Runs the perceptron training loop with bounded epochs to demonstrate separability limits.

POST /api/v1/week1920/learn/day130/backprop/train?epochs=200&lr=0.05
Response: {
  lesson: "day130",
  epochs: number,
  lr: number,
  final_loss: number,
  loss_history_tail: number[],
  accuracy: number
}

Executes a bounded XOR backprop training run; designed to stay responsive by pushing CPU work off the event loop.

POST /api/v1/ml/experiments
Request:  { name: string, dataset_profile: "mnist", model_backend: "numpy_scratch", task_type: "mnist" }
Response: { id: uuid, name: string, created_at: string, architecture_json: object }

Creates a durable experiment record that will own many runs.

GET /api/v1/ml/metrics/live
Response: {
  server_time: string,
  experiments_count: number,
  runs_summary: { running: number, pending: number, completed: number, failed: number },
  latest_runs: [{ id: uuid, run_type: string, status: string, elapsed_seconds: number|null }]
}

A lightweight polling endpoint for the dashboard; it must remain fast even when learning routes are active.

In FastAPI, the pattern is consistent: validate inputs, then delegate to core modules or background jobs. The Product layer uses repositories to persist metadata, and services to execute work.

backend/app/routes/week1920_lab.py (excerpt)
@ml_router.post(”/experiments”, response_model=ExperimentOut)
async def create_experiment(payload: ExperimentCreate, db: AsyncSession = Depends(get_db)):
    repo = ExperimentRepository(db)
    exp = await repo.create_experiment(
        name=payload.name,
        dataset_profile=payload.dataset_profile,
        model_backend=payload.model_backend,
        objective_metric=payload.objective_metric,
        task_type=payload.task_type,
        architecture_json=payload.architecture_json or {”layers”: [784, 128, 64, 10]},
)
return ExperimentOut.model_validate(exp)

Subscribe to access Github

Github Link:

https://github.com/sysdr/aiml-p/tree/main/week_19_20_aiml_integrated_project

Implementation Guide

Read more

Read on aieworks.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.