Deep learning from scratch

Build a deep learning framework from nothing, then use it to understand how machines hear and speak: 23 stages in three parts, from the maths to a speech model.

What this is

A path for a developer who wants to understand deep learning by building it. You write a small PyTorch-like framework on NumPy, one module at a time, then use it to read a real speech system: how audio becomes numbers, how a model recognises a speaker, and how a text-to-speech model turns a written description into a voice.

Who it is for

You program in Python and have met machine learning before: you know roughly what a loss and a gradient are. You have not built a framework, and you have not worked with audio.

What you will build

A NumPy framework with tensors, layers, losses, a data loader, autograd, optimisers, convolutions, attention and a transformer, then profiling, quantization, a KV cache and benchmarks. On the way it runs six historical milestones, from Rosenblatt's perceptron (1958) to a transformer (2017).

What you need first

Python, NumPy and school algebra; stage 1 covers the rest of the maths, with a reading for each piece. A computer with Python 3.10 or later. TrenTorch needs no GPU. The audio stages read code in the Alaap repo; running its demo needs the environment its README describes.

How long it takes

About 91 h in all: each TrenTorch module about 1.5 hours, the rest as each stage states. At five hours a week, about 18 weeks.

How to use it

Take the stages in order. Try each exit check before you open its answer, and if you cannot answer it, stay on the stage. Mark a stage done when you pass. Your progress stays in this browser; nothing is sent anywhere.

Set up

TrenTorch is an open framework you build yourself, module by module, in NumPy: its own take on the TinyTorch curriculum. Clone it and start the first module (the README has the Windows version):

git clone https://github.com/TrenTorch/TrenTorch.git
cd TrenTorch/TrenTorch_CLI
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt && pip install -e .
tren setup
tren module start 01

Alaap is an open research system for voice design: a written character description becomes a persistent voice identity that can speak any dialogue. Part 3 quotes its study guide and its architecture diagrams, which are in the architecture tab.

The path

Part 1 · FoundationsStage 1 · mathsThe maths you need,…Stage 2 · Alaap guideSound as dataStage 3 · Alaap guideSource and filterPart 2 · PyTorch from scratchStage 4 · bothTensors, built by handStage 5 · bothActivations and layersStage 6 · TrenTorchLossesStage 7 · TrenTorchThe data pipelineStage 8 · bothAutogradStage 9 · bothOptimisers and the…Stage 10 · Alaap guideThe same things, in…Stage 11 · TrenTorchConvolutions, and…Stage 12 · TrenTorchTokens and embeddingsStage 13 · TrenTorchAttention and…Stage 14 · TrenTorchMaking it runPart 3 · Audio MLStage 15 · Alaap guideA speech system, end…Stage 16 · Alaap guideThe rest of soundStage 17 · Alaap guideSpeaker identityStage 18 · Alaap guideIs the space navigable?Stage 19 · Alaap guideHow a TTS model…Stage 20 · Alaap guideDescription to voiceStage 21 · Alaap guideEvaluation, and why…Stage 22 · Alaap guideThe roads not takenStage 23 · bothCapstone
The whole path. Green is part 1, blue part 2, amber part 3. Select a stage to open it.

How each stage is laid out

After this you can

the capability, stated as something you can do

Why it matters

where the idea shows up in real models

TrenTorch module

what you build, its objectives, and its reflection questions

From the Alaap guide

what to read and do, quoted from Alaap's study guide; paths such as alaap/acoustics.py are files in the Alaap repo

Exit check

one question with a short model answer; if you cannot answer it, do not move on

Part 1 · Foundations

about 13 h across 3 stages

No framework yet. The maths every later stage leans on, and what sound is as numbers. The two sound stages need no PyTorch, so you can also run them alongside part 2.

Stage 1

The maths you need, and where it is used

about 8 h

    After this you can Do by hand the maths the path leans on: matrix shapes, the chain rule, logarithms and softmax, cross-entropy, cosine similarity, and what an FFT bin measures.

    Why it matters Every later stage uses some of it, and the table says which. With it fresh, the code reads as the maths it is.

    The maths, piece by piece

    Work down the table. If a row is already easy, do its task on paper and move on; if not, read the lesson beside it. Each reading is a free lesson from AI Engineering from Scratch.

    TopicBe able toUsed in stageRead
    Vectors, matrices and shapesMultiply a (32, 80) matrix by an (80, 256) one, and say the result's shape before you compute it.4, 8, 13Vectors, matrices, operations
    Tensor operations
    Derivatives and the chain ruleDifferentiate a composition of three functions, then write the gradients of y = x @ W for x and for W.8, 9Calculus for ML
    Chain rule and autodiff
    Logarithms and probabilitySay why training adds log-probabilities instead of multiplying probabilities, and compute softmax without overflow.6, 20Probability and distributions
    Numerical stability
    Cross-entropyCompute the cross-entropy between a predicted distribution and a one-hot target, and say what it measures.6, 13Information theory
    Distances and directionsCompute a cosine similarity, and say what the first principal component of a cloud of points points along.17, 18Norms and distances
    Dimensionality reduction
    Complex numbers and the Fourier transformSay what one FFT bin measures, and why n real samples give n / 2 + 1 useful bins.2, 16Complex numbers
    Fourier transform

    Exit check A softmax outputs p = (0.7, 0.2, 0.1) and the correct class is the first. What is the cross-entropy loss, and its gradient with respect to the logits?

    Show the answer

    The loss is minus ln 0.7, about 0.36. The gradient is p minus the one-hot target: (-0.3, 0.2, 0.1). It is largest where the prediction is most wrong, which is why this pairing keeps training.

    Stage 2

    Sound as data: sampling and Nyquist

    about 2 h
    • Alaap guide 2.1

    After this you can Say what a sample rate buys you, find the Nyquist cliff on a real spectrum, and explain why analysing audio at the wrong rate shifts every frequency.

    Why it matters Alaap's audio lives at four sample rates: corpus 24 kHz, WavLM 16 kHz, MioCodec 44.1 kHz, Sarvam 22.05 kHz. Mixing them up once reversed an experiment's result.

    continuous sampled resampled what survives sample skip it air pressure a continuous wave 24 kHz corpus 24 000 readings a second Nyquist: 12 kHz half the sample rate low-pass, then keep 2 of every 3 16 kHz for WavLM content up to 8 kHz without the filter 10 kHz folds to 6 kHz
    The cliff is the filter. A sample rate represents only frequencies below half of itself. Resampling down must remove what no longer fits, or it comes back at the wrong frequency as aliasing.

    From the Alaap guide, Part 2: Sound as data 12 h

    After this you can read alaap/acoustics.py and say what every function measures and how it could be wrong.

    Guide 2.1 Sampling and the time domain 2 h

    Sample rate, Nyquist, bit depth, why 16 kHz / 22.05 kHz / 24 kHz / 44.1 kHz all appear here.

    Intuition a waveform is a very long list of air-pressure readings. Nyquist says you can represent frequencies up to half your sample rate and nothing above.

    Why it matters the Alaap project's audio lives at four sample rates, corpus 24 kHz, WavLM 16 kHz, MioCodec 44.1 kHz, Sarvam 22.05 kHz, and analysing one at another's rate puts every frequency off by a ratio. That happened in S21 phase B and reversed a result.

    Do: load a clip at 24 kHz, resample to 16 kHz, plot both spectra. Find the cliff.

    Exit check A clip recorded at 24 kHz is resampled to 16 kHz. What happens to a component at 10 kHz, and why?

    Show the answer

    It is removed. At 16 kHz the Nyquist limit is 8 kHz, so the resampler's low-pass filter cuts everything above it. Without the filter, the 10 kHz energy would alias down to 6 kHz. That cut is the cliff on the plot.

    Stage 3

    Source and filter: what describes a voice

    about 3 h
    • Alaap guide 2.3

    After this you can Separate the glottal buzz (F0) from the vocal-tract tube (formants), and put each of Alaap's measurements on one side.

    Why it matters Alaap's identity axes follow this split. f0_mean measures the source; vtl_cm and the formants measure the filter. spectral_tilt was meant to measure the source's shape but partly reads pitch.

    source filter what you hear Alaap measures excites vocal folds a buzz at F0 vocal tract a tube with resonances speech buzz shaped by tube f0_mean the source vtl_cm, formants the filter spectral_tilt meant for source, reads F0
    Change the buzz and it is the same person; change the tube and it is not. Every identity axis Alaap keeps sits on one side of this split. Spectral tilt straddles it, and it caused the trouble.

    Guide 2.3 The source–filter model 3 h

    Glottal source (pitch, F0) vs vocal-tract filter (formants). Why they are separable and why that separation is the whole basis of describing a voice.

    Intuition the vocal folds make a buzz at F0. The mouth and throat are a tube that resonates at certain frequencies, formants. Change the buzz, same person. Change the tube, different person.

    This is the single most important idea in Part 2. f0_mean measures the source; vtl_cm and the formants measure the filter; spectral_tilt is supposed to measure the source's spectral shape and, as S21 found, partly measures the buzz rate instead.

    Also in the architecture 8 · The attribute taxonomy

    Exit check Two recordings of the same person, one speaking and one singing higher. Which measurements should move, and which should not?

    Show the answer

    F0 goes up, because it belongs to the source. Vocal-tract length and the formant pattern should not move: the tube is the same person. A measurement of the tube that moves with F0, as spectral tilt partly did, is confounded.

    Part 2 · PyTorch from scratch

    about 31.5 h across 11 stages

    Build a deep learning framework on NumPy, one TrenTorch module at a time: tensors, layers, losses, data, autograd, optimisers, convolutions, embeddings and attention, then the tools that make a model run fast. Halfway through, map every piece to real PyTorch.

    Stage 4

    Tensors, built by hand

    about 1.5 h
    • Alaap guide 1.1
    • TrenTorch 01 Tensor Foundation

    After this you can Build a Tensor class on NumPy and predict the shape, dtype and memory of any operation before running it.

    Why it matters Every model file is tensor shapes. Once you have built a tensor yourself, you read them without guessing.

    data view operation result view flat buffer float32, contiguous shape + strides (32, 80) · (80, 1) transpose same buffer, new strides broadcast add (32, 80) + (80,) matmul (32, 80) @ (80, 256) (32, 80) no copy of the (80,) (32, 256) inner dims must match
    A tensor is a buffer plus a way of reading it. Shape and strides decide what an index means, so transpose and view are free, and broadcasting repeats a smaller tensor without copying it.
    TrenTorch 01

    Tensor Foundation

    Building Blocks of ML Module source

    Build the foundational Tensor class that powers all machine learning operations.

    You have built
    Nothing - this is our foundation!
    You build
    A complete Tensor class with arithmetic, matrix operations, and shape manipulation
    It enables
    Foundation for activations, layers, and all future neural network components
    Build it tren module start 01, work in the notebook, then tren module test 01 and tren module complete 01. It exports trentorch.core.tensor; the source is TrenTorch_CLI/data/src/01_tensor/01_tensor.py.

    Learning objectives

    1. Implement a complete Tensor class with fundamental operations
    2. Understand tensors as the universal data structure in ML
    3. Master broadcasting, matrix multiplication, and shape manipulation
    4. Test tensor operations with immediate validation

    Inside the module

    • Why Tensors Matter in ML Systems
    • Core Operations We'll Implement
    • Broadcasting: Making Tensors Work Together
    • Tensor Class Architecture
    • Tensor Creation and Initialization
    • Why Element-wise Operations Matter
    • Element-wise Addition: The Foundation
    • Subtraction, Multiplication, and Division
    • Why Matrix Multiplication Matters
    • Matrix Multiplication Visualization
    • Computational Complexity and Performance
    • Chained Matrix Multiplications
    • Shape Validation for Matrix Multiplication
    • Why Shape Manipulation Matters
    NumPy Arrays → Tensor → Activations (Module 02)
    (raw data)   (ML ops)  (intelligence)
    Reflection questions from the module (5)
    1. Memory Layout and Cache Performance. How does row-major vs column-major storage affect cache performance in tensor operations?
    2. Batch Processing and Scaling. If you double the number of samples in a batch, what happens to memory usage? What about
    3. Data Type Precision and Memory. What's the memory difference between float64 and float32 for a (1000, 1000) tensor?
    4. Production Scale Memory. A large-scale model has 175 billion parameters. How much RAM is needed just to store the weights?
    5. Hardware Awareness. Why do parallel processors strongly prefer operations on large tensors over many small ones?

    From the Alaap guide, Part 1: PyTorch and tensors 20 h

    This is TrenTorch's job. Below is the exit checklist, not a substitute syllabus.

    After this you can read any model file in the Alaap repo without guessing what a line does.

    Guide 1.1 The tensor

    Shapes, dtypes, devices, broadcasting, view/reshape/permute, indexing.

    Intuition a tensor is a numpy array that remembers where it came from. That memory is autograd.

    Exit check A (32, 1, 80) tensor is added to an (80,) tensor. What is the result's shape, and what did broadcasting do?

    Show the answer

    (32, 1, 80). The (80,) tensor is treated as (1, 1, 80), repeated along the first two axes without copying memory, then added element by element.

    Stage 5

    Activations and layers

    about 3 h
    • Alaap guide 1.3
    • TrenTorch 02 Activations
    • TrenTorch 03 Layers
    • Unlocks milestone 01
    • Unlocks milestone 02

    After this you can Build Linear, ReLU, softmax and dropout as modules, and say what each one's parameters and buffers are.

    Why it matters nn.Module, train() and eval() appear in every Alaap experiment. Dropout is the smallest layer that behaves differently in the two modes.

    input parameters no parameters mode-dependent mode last layer x (batch, 784) Linear W (784, 256), b (256) ReLU max(0, z) Dropout p = 0.5 train: drop, scale x2 eval() passes everything softmax (output) subtract the max first
    A layer is parameters plus a rule, and some rules depend on the mode. Linear owns weights. ReLU and softmax own nothing. Dropout behaves differently under train() and eval(), so Alaap calls eval() before every measurement.
    TrenTorch 02

    Activations

    Intelligence Through Nonlinearity Module source

    Add the secret ingredient that makes neural networks intelligent - nonlinearity.

    You have built
    Tensor with data manipulation and basic operations
    You build
    Activation functions that add nonlinearity to transformations
    It enables
    Neural networks with the ability to learn complex patterns
    Build it tren module start 02, work in the notebook, then tren module test 02 and tren module complete 02. It exports trentorch.core.activations; the source is TrenTorch_CLI/data/src/02_activations/02_activations.py.

    Learning objectives

    1. Implement 5 core activation functions (Sigmoid, ReLU, Tanh, GELU, Softmax)
    2. Understand how nonlinearity enables neural network intelligence
    3. Test activation behaviors and output ranges
    4. Connect activations to real neural network components

    Inside the module

    • Why Nonlinearity Matters
    • The Five Essential Activations
    • Implementation Pattern
    • Sigmoid - The Probability Gatekeeper
    • Mathematical Definition
    • Visual Behavior
    • ASCII Visualization
    • ReLU - The Sparsity Creator
    • Mathematical Definition
    • Visual Behavior
    • ASCII Visualization
    • Tanh - The Zero-Centered Alternative
    • Mathematical Definition
    • Visual Behavior
    Tensor → Activations → Layers
    (data)   (intelligence) (architecture)
    Reflection questions from the module (5)
    1. Computational Cost Comparison. ReLU is the most popular activation function in hidden layers. Given what you implemented, why is ReLU computationally cheaper than Sigmoid or GELU?
    2. Numerical Stability. Look at your Softmax implementation. Why did we subtract the maximum value before computing exponentials?
    3. Sparsity and Efficiency. ReLU creates "sparsity" by zeroing negative values. Why might having many zero activations be beneficial for computation?
    4. Activation Selection for Different Stages. Why do we typically use different activations for hidden stages vs. output stages of a computation?
    5. The "Dying ReLU" Problem. If ReLU outputs 0 for some inputs, those inputs get no signal passed through -- they effectively "die." What situations might cause this, and why is it a problem?
    TrenTorch 03

    Layers

    Building Blocks of Neural Networks Module source

    Build Linear layers and Dropout for multi-layer neural networks.

    You have built
    Tensor class (Module 01) with all operations and activations (Module 02)
    You build
    Linear layers and Dropout regularization
    It enables
    Multi-layer neural networks, trainable parameters, and forward passes
    Build it tren module start 03, work in the notebook, then tren module test 03 and tren module complete 03. It exports trentorch.core.layers; the source is TrenTorch_CLI/data/src/03_layers/03_layers.py.

    Learning objectives

    1. Implement Linear layers with proper weight initialization
    2. Add Dropout for regularization during training
    3. Understand parameter management and counting
    4. Test individual layer components

    Inside the module

    • Linear Layer Mathematics
    • Weight Initialization
    • Parameter Counting
    • Key Design Principles:
    • Layer Base Class - Foundation for All Layers
    • Linear Layer - The Foundation of Neural Networks
    • Why Linear Layers Matter
    • Data Flow Visualization
    • Memory Layout
    • Edge Case Tests: Linear Layer
    • Parameter Collection Tests: Linear Layer
    • Dropout Layer - Preventing Overfitting
    • Why Dropout Matters
    • Dropout in Action
    Tensor → Activations → Layers → Networks
    (data)   (intelligence) (building blocks) (architectures)
    Reflection questions from the module (5)
    1. Parameter Scaling and Memory. Consider three different network architectures for MNIST (28x28 = 784 input features, 10 output classes):
    2. Dropout Training vs Inference. You have a Dropout layer with p=0.5 in your network. During training, we scale surviving values by 1/(1-p) = 2.0.
    3. Weight Initialization Trade-offs. We initialize weights with scale = sqrt(1/in_features) (LeCun-style). For Linear(1000, 10), how does this compare to Linear(10, 1000)?
    4. Layer Ordering Effects. In a typical layer block, we compose: Linear -> Activation -> Dropout. What happens if you change the order to: Linear -> Dropout -> Activation?
    5. Production Deployment Memory. You're deploying a 3-layer network (784->256->128->10) to a mobile device with 10MB free memory.

    Unlocks TrenTorch milestone 01 · Perceptron (1958) Build Rosenblatt's first neural network (forward pass). Needs modules 01-03. Run it with tren milestone run 01.

    Unlocks TrenTorch milestone 02 · XOR Crisis (1969) Experience the XOR limitation that triggered AI Winter. Needs modules 01-03. Run it with tren milestone run 02.

    Guide 1.3 nn.Module

    __init__ vs forward, parameters vs buffers, train()/eval(), state_dict.

    Why it matters here model.eval() and torch.no_grad() appear in every experiment in the Alaap repo. Know exactly what each turns off, they are not the same thing.

    Exit check Dropout with p = 0.5 scales surviving activations by 2 during training. What does it do at eval time, and why the scaling?

    Show the answer

    Nothing: at eval every unit passes through unscaled. Scaling by 1/(1-p) during training keeps the expected activation the same in both modes, so the next layer sees the same magnitudes whether or not dropout is on.

    Stage 6

    Losses: measuring how wrong

    about 1.5 h
    • TrenTorch 04 Losses

    After this you can Build MSE and cross-entropy, compute softmax stably, and say why cross-entropy's gradient survives where squared error's saturates.

    Why it matters The mixture density network in stage 20 trains on negative log-likelihood; cross-entropy is its one-component version.

    model output probabilities loss gradient backward backward logits z any real numbers softmax p = exp(z - max) / sum cross-entropy -log p[target] p - onehot large while wrong sigmoid + MSE the alternative vanishes when saturated
    Cross-entropy's gradient survives saturation. Paired with softmax, the log cancels the exponential and the gradient is p minus the target.
    TrenTorch 04

    Losses

    Measuring How Wrong We Are Module source

    Implement loss functions that measure prediction quality for training.

    You have built
    Tensors (data), Activations (intelligence), Layers (architecture)
    You build
    Loss functions that measure prediction quality
    It enables
    The feedback signal needed for training
    Build it tren module start 04, work in the notebook, then tren module test 04 and tren module complete 04. It exports trentorch.core.losses; the source is TrenTorch_CLI/data/src/04_losses/04_losses.py.

    Learning objectives

    1. Implement MSELoss for regression problems
    2. Implement CrossEntropyLoss for classification problems
    3. Implement BinaryCrossEntropyLoss for binary classification
    4. Understand numerical stability in loss computation
    5. Test all loss functions with realistic examples

    Inside the module

    • The Three Essential Loss Functions
    • Mean Squared Error (MSE)
    • Cross-Entropy Loss
    • Binary Cross-Entropy
    • Log-Softmax: The Numerically Stable Foundation
    • Why Log-Softmax Matters
    • The Log-Sum-Exp Trick Visualization
    • MSELoss: Measuring Continuous Prediction Quality
    • When to Use MSE
    • How MSE Shapes Learning
    • Why Square the Errors?
    • MSE vs Other Regression Losses
    • CrossEntropyLoss: Measuring Classification Confidence
    • When to Use Cross-Entropy
    Layers → Losses → Autograd
    (predictions) (error measurement) (learning signals)
    Reflection questions from the module (6)
    1. Memory and Performance. Loss Function Selection for Large Vocabulary
    2. Loss Function Performance Bottleneck. Performance Analysis
    3. Numerical Stability. Debugging Exploding Loss
    4. Production Considerations. Real-Time Inference Latency
    5. Class Imbalance in Medical Diagnosis. Handling Class Imbalance
    6. Batch Size and Loss Computation. Systems Thinking

    Exit check With softmax and cross-entropy together, what is the gradient with respect to the logits?

    Show the answer

    p minus the one-hot target. It stays large while the prediction is wrong, however confident, so this pairing does not stall the way sigmoid plus squared error does.

    Stage 7

    The data pipeline

    about 1.5 h
    • TrenTorch 05 DataLoader

    After this you can Build a Dataset and a DataLoader that shuffle, batch and collate, and reason about what a batch costs in memory.

    Why it matters Alaap streams clips from corpora it never downloads whole. How data reaches the model decides what an experiment can afford.

    stored each epoch each step to the model Dataset __len__, __getitem__ shuffle indices a permutation, not data take a batch batch_size indices collate stack into one tensor memory per batch batch x sample bytes
    Shuffle the indices, not the data. A DataLoader permutes a list of integers, fetches only the batch it needs, and stacks it. The whole dataset never has to fit in memory.
    TrenTorch 05

    DataLoader

    Efficient Data Pipeline Module source

    Build data loading infrastructure for efficient ML training.

    You have built
    Tensor operations, activations, layers, and losses
    You build
    Dataset abstraction, DataLoader with batching/shuffling, and real dataset support
    It enables
    Efficient data pipelines that will feed hungry neural networks with properly formatted batches
    Build it tren module start 05, work in the notebook, then tren module test 05 and tren module complete 05. It exports trentorch.core.dataloader; the source is TrenTorch_CLI/data/src/05_dataloader/05_dataloader.py.

    Learning objectives

    1. Understand the data pipeline: individual samples → batches → training
    2. Implement Dataset abstraction and TensorDataset for tensor-based data
    3. Build DataLoader with intelligent batching, shuffling, and memory-efficient iteration
    4. Experience data pipeline performance characteristics firsthand
    5. Create download functions for real computer vision datasets

    Inside the module

    • The Data Pipeline Journey
    • Why This Pipeline Matters
    • The Dataset Abstraction
    • Dataset Base Class Implementation
    • Understanding TensorDataset Structure
    • Why TensorDataset is Powerful
    • Real-World Usage Patterns
    • TensorDataset Implementation
    • Understanding Batching: From Samples to Tensors
    • The Shuffling Process
    • DataLoader as a Systems Component
    • The DataLoader Algorithm
    • DataLoader Implementation
    • Why Augmentation Matters
    Losses → DataLoader → Autograd → Optimizers → Training
    (Module 04)  (Module 05)  (Module 06)  (Module 07)  (Module 08)
    Reflection questions from the module (5)
    1. The Batch Memory Budget. You're loading a large image dataset. Each image is a tensor of shape (3, 224, 224) stored as float32 (4 bytes per value). Your batch size is 256.
    2. To Shuffle or Not to Shuffle?. You're training on a medical dataset where samples are ordered by patient (first 1000 samples = Patient A, next 1000 = Patient B, etc.). Consider these scenarios:
    3. Data Loading Bottlenecks. Your program reports these timings per batch:
    4. Memory Explosion with Large Datasets. You're training on 100GB of high-resolution medical scans. Your DataLoader code:
    5. The Shuffle Memory Trap. You implement shuffling like this:

    Exit check Samples are stored ordered by speaker. What goes wrong if you train without shuffling?

    Show the answer

    Each batch holds one speaker, so gradients chase that speaker and then the next: training oscillates, and the model forgets earlier speakers. Shuffling makes each batch a fair sample of the whole set.

    Stage 8

    Autograd: the gradient engine

    about 1.5 h
    • Alaap guide 1.2
    • TrenTorch 06 Autograd

    After this you can Build reverse-mode automatic differentiation: record the forward pass as a graph, then walk it backward with each operation's gradient rule.

    Why it matters The Alaap guide's Part 1 promises you will know what backward() does, and what no_grad() and detach() switch off. You learn it here by building it.

    forward, recorded backward, replayed x, W requires_grad MatmulBackward saves x and W ReluBackward saves the mask loss loss.backward() grad = 1 seed grad x mask chain rule W.grad, x.grad x.T @ g, g @ W.T
    The graph is a tape recorded on the way forward. Each operation saves what its gradient rule needs; backward() walks the tape in reverse and multiplies by each local derivative. no_grad() stops the recording, which is why it saves memory.
    TrenTorch 06

    Autograd

    The Gradient Engine Module source

    Build the autograd system that computes gradients automatically.

    You have built
    Tensor operations, activations, layers, losses, and DataLoader
    You build
    The autograd system that computes gradients automatically
    It enables
    The ability to optimize neural networks.
    Build it tren module start 06, work in the notebook, then tren module test 06 and tren module complete 06. It exports trentorch.core.autograd; the source is TrenTorch_CLI/data/src/06_autograd/06_autograd.py.

    Learning objectives

    1. Enhance Tensor with automatic differentiation capabilities
    2. Build computation graphs that track operations for gradient flow
    3. Implement backward() method for reverse-mode differentiation
    4. Create Function classes for operation-specific gradient rules
    5. Test gradient correctness with mathematical validation

    Inside the module

    • The Challenge
    • The Solution: Computational Graphs
    • Computational Graph Example
    • Memory Layout During Backpropagation
    • The Function Architecture
    • Function Base Class - The Foundation of Autograd
    • Operation Functions - Implementing Gradient Rules
    • Understanding Broadcasting in Gradients
    • AddBackward - Gradient Rules for Addition
    • MulBackward - Gradient Rules for Element-wise Multiplication
    • SubBackward - Gradient Rules for Subtraction
    • DivBackward - Gradient Rules for Division
    • MatmulBackward - Gradient Rules for Matrix Multiplication
    • SumBackward - Gradient Rules for Reduction Operations
    Modules 01-05 → Autograd → Optimizers → Training
    (forward pass)  (Module 06)  (Module 07)  (Module 08)
    Reflection questions from the module (5)
    1. Computational Graph Memory. A 10-layer neural network processes a single sample. Each layer performs matrix multiplication (matmul) and addition (bias). How much memory does the computation graph use compared to just storing the weights?
    2. Gradient Accumulation. A weight matrix is shared between two computation paths in a network (like a tied-weights architecture). Why does gradient accumulation (`grad = grad + new_grad`) save memory during training? What's the trade-off?
    3. Backward Pass Cost. A forward pass through a 3-layer MLP takes 10ms. Is the backward pass faster, slower, or the same speed as the forward pass? Why?
    4. Graph Retention. You're training a language model that processes sequences of varying lengths. When should you call `.zero_grad()`? What happens if you forget?
    5. Production Pattern. PyTorch and TensorFlow use `requires_grad` flags instead of always tracking gradients for every tensor. Why? What's the performance benefit of making gradient tracking opt-in?

    Guide 1.2 Autograd

    requires_grad, the graph, backward(), torch.no_grad(), why .detach() exists.

    Intuition the graph is built forward as a side effect of computing, then walked backward. Nothing is symbolic; it is a recorded tape.

    Exit check y = x @ W. Given the gradient of the loss with respect to y, what are the gradients for x and W?

    Show the answer

    grad_x = grad_y @ W.T and grad_W = x.T @ grad_y. Two matmuls backward for one forward, so the backward pass costs about twice the forward.

    Stage 9

    Optimisers and the training loop

    about 3 h
    • Alaap guide 1.4
    • TrenTorch 07 Optimizers
    • TrenTorch 08 Training
    • Unlocks milestone 03

    After this you can Build SGD and Adam, write the full loop (zero_grad, forward, loss, backward, step), and train a network from scratch.

    Why it matters This is the first real checkpoint: a small network trained from scratch, with every line and every gradient explained.

    one step next batch each epoch zero_grad() clear last step forward model(batch) loss criterion(out, y) backward() fills .grad optimizer.step() SGD or Adam update schedule, clip lr decay, global norm eval() + no_grad() validate, checkpoint
    Every training script is these five lines. Adam keeps two running averages per parameter, so with the weights it holds three copies, against two for SGD with momentum. Evaluation switches both the layer mode and gradient recording off.
    TrenTorch 07

    Optimizers

    Sophisticated Learning Algorithms Module source

    Build SGD, Adam, and AdamW optimizers for neural network training.

    You have built
    Tensor with gradients (Modules 01-06)
    You build
    SGD, Adam, and AdamW optimizers with sophisticated momentum and adaptive learning
    It enables
    Modern optimization algorithms that power state-of-the-art neural networks
    Build it tren module start 07, work in the notebook, then tren module test 07 and tren module complete 07. It exports trentorch.core.optimizers; the source is TrenTorch_CLI/data/src/07_optimizers/07_optimizers.py.

    Learning objectives

    1. Implement SGD with momentum for stable gradient descent
    2. Build Adam optimizer with adaptive learning rates
    3. Create AdamW optimizer with decoupled weight decay
    4. Understand memory and computational trade-offs in optimization algorithms

    Inside the module

    • The Optimization Challenge
    • Our Optimizer Toolkit
    • The Mathematics Behind Movement
    • Understanding Momentum: The Physics of Optimization
    • Adam: Adaptive Learning for Each Parameter
    • AdamW: Fixing Weight Decay
    • Implementation Strategy
    • Gradient Extraction - Handling Tensor vs NumPy Gradients
    • Why SGD Works
    • The Oscillation Problem
    • Momentum Solution
    • The Parameter Scaling Problem
    • Adam's Adaptive Solution
    • Bias Correction: The Cold Start Problem
    Gradients → Optimizers → Training
    (Module 06)  (Module 07)  (Module 08)
    Reflection questions from the module (5)
    1. Memory vs Performance. You've implemented SGD (2x memory) and Adam (3x memory). For a model with 10 billion parameters at float32 (4 bytes each):
    2. Learning Rate Sensitivity. SGD uses a fixed learning rate for all parameters, while Adam adapts per-parameter.
    3. Optimizer State Management. Adam and AdamW maintain momentum buffers (m, v) that persist across training steps.
    4. Weight Decay Trade-offs. AdamW decouples weight decay from gradient updates.
    5. Production Scale: Memory Requirements. For training a GPT-scale model with 1 billion parameters, calculate the memory requirements:
    TrenTorch 08

    Training

    Complete Learning Loops Module source

    Build complete training loops with checkpointing and scheduling.

    You have built
    Tensors, activations, layers, losses, DataLoader, gradients, and optimizers
    You build
    Complete training loops with checkpointing, scheduling, and gradient management
    It enables
    Full model training pipeline for the MLP milestone
    Build it tren module start 08, work in the notebook, then tren module test 08 and tren module complete 08. It exports trentorch.core.training; the source is TrenTorch_CLI/data/src/08_training/08_training.py.

    Learning objectives

    1. Implement a complete Trainer class with train/eval modes
    2. Build learning rate scheduling and gradient clipping
    3. Create checkpointing for model persistence
    4. Test training loops with immediate validation
    5. Understand gradient accumulation patterns

    Inside the module

    • Training Loop Mathematics
    • Train vs Eval Modes
    • Learning Rate Scheduling: Adaptive Training Speed
    • Gradient Clipping: Preventing Training Explosions
    • The Trainer Class: Orchestrating Complete Training
    • Trainer.__init__ - Setting Up the Training System
    • Trainer.train_epoch - The Core Learning Loop
    • Trainer.evaluate - Measuring Model Performance
    • Trainer.save_checkpoint - Persisting Training State
    • Trainer.load_checkpoint - Resuming Training
    • Building a Complete Training Pipeline
    • Training Memory Breakdown
    • Key Systems Insights
    • 1. Memory Trade-offs
    DataLoader → Autograd → Optimizers → Training → Convolutions
    (Module 05)  (Module 06)  (Module 07)  (Module 08)  (Module 09)
    Reflection questions from the module (5)
    1. Memory Trade-offs. If you have a model with 1 million parameters and use Adam optimizer, what's the total training memory required?
    2. Gradient Clipping. Why do we clip gradients by *global norm* rather than clipping each gradient independently?
    3. Learning Rate Scheduling. Why does cosine annealing start with high learning rate and end with low learning rate?
    4. Checkpointing Strategy. You're training for 100 epochs with 1GB checkpoints. How often should you save?
    5. Train vs Eval Modes. Why is it crucial to set model.training = False during evaluation?

    Unlocks TrenTorch milestone 03 · MLP Revival (1986) Train MLPs to solve XOR + recognize digits. Needs modules 01-08. Run it with tren milestone run 03.

    Guide 1.4 The training loop

    Dataset/DataLoader, loss, optimiser, zero_grad, LR schedules.

    Exit check What happens if you forget zero_grad() between steps?

    Show the answer

    Gradients accumulate, so each update applies the sum of every earlier gradient. Steps grow and training diverges. Accumulating on purpose gives a large effective batch, as long as you zero every N steps.

    Stage 10

    The same things, in real PyTorch

    about 3 h
    • Alaap guide 1.5

    After this you can Map every TrenTorch piece to its PyTorch name, and pass Part 1's exit checklist on a real Alaap model: WavLM's hidden states.

    Why it matters TrenTorch taught the mechanism, and Alaap is written in PyTorch. This stage closes the gap. It also covers out-of-memory that is system RAM, not VRAM.

    you built, in TrenTorch you read, in PyTorch is is is is Tensor trentorch.core.tensor torch.Tensor .to(device), dtype Function, backward trentorch.core.autograd autograd, no_grad, detach the same tape Linear, Dropout trentorch.core.layers nn.Module, eval() parameters vs buffers Trainer, DataLoader trentorch.core.training optim, utils.data the loop you wrote
    Every PyTorch line in Alaap maps to something you built. The differences are devices, dtypes and scale; the mechanism is the one you wrote on NumPy.

    Guide 1.5 The things that bite

    • CPU vs CUDA, and .to(device) on both model and data
    • memory: activations dominate, not weights
    • float32 vs bfloat16
    • why a model that "fits in VRAM" still OOMs

    The Alaap repo's own version of that lesson: loading two models in one process segfaults on a 15.7 GB box while the 6 GB GPU sits at 614 MiB. It is system RAM, not VRAM. See HANDOFF.md §8b.

    Do in the Alaap repo, no training required:
    import torch, torchaudio
    m = torchaudio.pipelines.WAVLM_BASE_PLUS.get_model().eval()
    x = torch.randn(1, 16000)          # 1 second at 16 kHz
    with torch.no_grad():
        hs, _ = m.extract_features(x, num_layers=12)
    print(len(hs), hs[0].shape)
    

    Then explain, out loud: why 12 tensors? What are the three dimensions of each? Why no_grad()?

    Check Why does hs[0].shape[1] change when you change the input length, and what is the ratio? (This is the frame rate, and it is the first properly "audio" idea.)

    Exit check model.eval() and torch.no_grad() are both used in every Alaap experiment. What does each switch off?

    Show the answer

    eval() changes layer behaviour: dropout stops dropping and batch norm uses its running statistics. no_grad() stops recording the graph, so no activations are kept for backward and memory falls. They are independent, and inference wants both.

    Stage 11

    Convolutions, and batch normalisation

    about 1.5 h
    • TrenTorch 09 Convolutions
    • Unlocks milestone 04

    After this you can Build Conv2d, pooling and BatchNorm2d, and see a convolution as one small filter slid along an axis.

    Why it matters ECAPA-TDNN, Alaap's independent identity judge, is a 1-D convolution along time over audio frames, with dilation, then attentive pooling. This module teaches that mechanism.

    audio frames TDNN / ECAPA pooling embedding 80 mel bands one column per 10 ms Conv1d over time kernel 5, one filter slid dilated Conv1d wider context, same cost BatchNorm per channel attentive stats weighted mean and std fixed-length vector any length in, one out
    ECAPA-TDNN is convolution along time. The same small filter slides over frames of audio, dilation widens what it sees, and pooling over time turns an utterance of any length into one vector.
    TrenTorch 09

    Convolutions

    Processing Images with Spatial Operations Module source

    Implement Conv2d, MaxPool2d, and AvgPool2d for image processing.

    You have built
    Complete training pipeline with MLPs, optimizers, and data loaders
    You build
    Spatial operations - Conv2d, MaxPool2d, AvgPool2d for image processing
    It enables
    Convolutional Neural Networks (CNNs) for computer vision
    Build it tren module start 09, work in the notebook, then tren module test 09 and tren module complete 09. It exports trentorch.core.spatial; the source is TrenTorch_CLI/data/src/09_convolutions/09_convolutions.py.

    Learning objectives

    1. Implement Conv2d with explicit loops to understand O(N²M²K²) complexity
    2. Build pooling operations (Max and Average) for spatial reduction
    3. Understand receptive fields and spatial feature extraction
    4. Analyze memory vs computation trade-offs in spatial operations

    Inside the module

    • The Two Core Spatial Operations
    • Visual Example: How Convolution Works
    • Why Spatial Operations Transform ML
    • Understanding Convolution Step by Step
    • The Mathematical Formula
    • Pooling: Spatial Summarization
    • Why This Complexity Matters
    • Key Properties That Enable Deep Learning
    • Conv2d: Detecting Patterns with Sliding Windows
    • The Six Nested Loops of Convolution
    • Shared Input Validation
    • Conv2d Implementation - Building the Core of Computer Vision
    • Implementation Strategy: Decomposed Helpers
    • Step 1: Output Shape Formula
    Training Pipeline → Spatial Operations → CNN (Milestone 03)
        (MLPs)            (Conv/Pool)        (Computer Vision)
    Reflection questions from the module (5)
    1. Conv2d Memory Footprint. A Conv2d layer with 64 filters (3×3) processes a (224×224×3) image.
    2. Spatial Locality and CPU Performance. Why are CNNs faster on CPUs than fully-connected networks of similar parameter count?
    3. Im2col Trade-off. When is this trade-off worthwhile?
    4. Pooling's Systems Benefits. MaxPool2d reduces spatial dimensions (e.g., 224×224 → 112×112).
    5. Mobile ML Deployment. Why do mobile ML models prefer depthwise-separable convolutions over standard Conv2d?

    Unlocks TrenTorch milestone 04 · CNN Revolution (1998) Build LeNet for image recognition. Needs modules 01-09. Run it with tren milestone run 04.

    Exit check Batch normalisation has two separate effects. Name them.

    Show the answer

    First, it normalises each channel to zero mean and unit variance over the batch, which steadies and speeds up training. Second, batch statistics are noisy, so it adds regularising noise. At eval it uses running statistics instead of batch ones, which is why eval() matters.

    Stage 12

    Tokens and embeddings

    about 3 h
    • TrenTorch 10 Tokenization
    • TrenTorch 11 Embeddings

    After this you can Build a character and a BPE tokenizer, an embedding table, and positional encodings, and say where the embedding numbers physically come from.

    Why it matters Modern TTS turns audio into tokens with a codec and generates them with a language model. The tokens differ from text tokens; the machinery is the same.

    text tokens lookup into the model row index add same idea "warm voice" characters BPE tokenizer ids [812, 4431] embedding table (vocab, d) weights + position learned or sinusoidal (tokens, d) one row per token audio, via a codec 25 Hz content tokens
    An embedding is a row of a weight matrix. A token id picks the row; gradient descent wrote the numbers. A codec does for audio what the tokenizer does for text, which is why TTS can be a language model.
    TrenTorch 10

    Tokenization

    Converting Text to Numbers Module source

    Build tokenization systems that convert text to numerical representations.

    You have built
    Neural networks, layers, training loops, and data loading
    You build
    Text tokenization systems (character and BPE-based)
    It enables
    Text processing for language models and NLP tasks
    Build it tren module start 10, work in the notebook, then tren module test 10 and tren module complete 10. It exports trentorch.core.tokenization; the source is TrenTorch_CLI/data/src/10_tokenization/10_tokenization.py.

    Learning objectives

    1. Implement character-based tokenization for simple text processing
    2. Build a BPE (Byte Pair Encoding) tokenizer for efficient text representation
    3. Understand vocabulary management and encoding/decoding operations
    4. Create the foundation for text processing in neural networks

    Inside the module

    • The Text-to-Numbers Challenge
    • The Four-Step Process
    • Why This Matters
    • Character-Level Tokenization
    • Word-Level Tokenization
    • Subword Tokenization (BPE)
    • Strategy Comparison
    • Tokenization Class Architecture
    • Base Tokenizer Interface
    • Counting Byte Pairs
    • Merging a Byte Pair
    • Tokenization Pipeline
    • Why This Integration Matters
    • Memory Profiling: Actual Tokenizer Memory Usage
    DataLoader → Tokenization → Embeddings
    (batching)   (text→numbers)  (learnable representations)
    Reflection questions from the module (4)
    1. Vocabulary Size and Storage. You implemented tokenizers with different vocabulary sizes.
    2. Sequence Length Trade-offs. Your character tokenizer produces longer sequences than BPE. For the text "machine learning" (16 characters):
    3. Tokenization Coverage and Robustness. Your BPE tokenizer handles unknown words by decomposing into subwords.
    4. Production Scale Considerations. A production language model serves 1 million requests per day, each with average 500 tokens.
    TrenTorch 11

    Embeddings

    Converting Tokens to Learnable Representations Module source

    Build embedding layers that convert tokens into dense, learnable vectors.

    You have built
    Tensors, layers, tokenization (discrete text processing)
    You build
    Embedding lookups and positional encodings for sequence modeling
    It enables
    Foundation for attention mechanisms and transformer architectures
    Build it tren module start 11, work in the notebook, then tren module test 11 and tren module complete 11. It exports trentorch.core.embeddings; the source is TrenTorch_CLI/data/src/11_embeddings/11_embeddings.py.

    Learning objectives

    1. Implement embedding layers for token-to-vector conversion
    2. Understand learnable vs fixed positional encodings
    3. Build both sinusoidal and learned position encodings
    4. Analyze embedding memory requirements and lookup performance

    Inside the module

    • The Token-to-Vector Challenge
    • The Four-Layer Embedding System
    • Why This Matters
    • Token Embedding Lookup Process
    • Positional Encoding Strategies
    • Strategy Comparison
    • Gradient Computation for Embedding Lookups
    • Learned Positional Encoding
    • Implementing Learned Positional Encoding
    • Sinusoidal Positional Encoding
    • Computing the Sinusoidal Table
    • Implementing Sinusoidal Positional Encodings
    • Complete Embedding System Architecture
    • EmbeddingLayer Initialization
    Tokenization → Embeddings → Positional Encoding → Attention
    (discrete)     (dense)      (position-aware)     (context-aware)
    Reflection questions from the module (4)
    1. Memory Scaling. You implemented an embedding layer with vocab_size=50,000 and embed_dim=512.
    2. Lookup Complexity. Your embedding layer performs table lookups for token indices.
    3. Positional Encoding Trade-offs. You implemented both learned and sinusoidal positional encodings.
    4. Production Implications. Your complete EmbeddingLayer combines token and positional embeddings.

    Exit check Where do the numbers in an embedding table come from?

    Show the answer

    They are ordinary weights: a (vocabulary x dimension) matrix, initialised randomly and updated by gradient descent. Looking up a token is selecting a row, which is the same as multiplying a one-hot vector by the matrix.

    Stage 13

    Attention and transformers

    about 3 h
    • TrenTorch 12 Attention
    • TrenTorch 13 Transformers
    • Unlocks milestone 05

    After this you can Build scaled dot-product and multi-head attention, then a full transformer block, and generate text with it.

    Why it matters WavLM and Alaap's acoustic language model are transformers. Their layers encode different things, so the WavLM layer you pool changes what you measure.

    input projections scores output x (n, d) Q = x Wq what I look for K = x Wk what I offer V = x Wv what I pass on Q K^T / sqrt(d_k) (n, n): the O(n^2) mask, softmax rows sum to 1 weights @ V (n, d), per head
    Every token scores every other token. The n by n score matrix is where attention's quadratic memory comes from, and the square root of d_k keeps those scores out of softmax's flat tails.
    TrenTorch 12

    Attention

    Learning to Focus Module source

    Build scaled dot-product and multi-head attention mechanisms.

    You have built
    Tensor, activations, layers, losses, autograd, optimizers, training, dataloaders, spatial layers, tokenization, and embeddings
    You build
    Scaled dot-product attention and multi-head attention mechanisms
    It enables
    Transformer architectures, GPT-style language models, and sequence-to-sequence processing
    Build it tren module start 12, work in the notebook, then tren module test 12 and tren module complete 12. It exports trentorch.core.attention; the source is TrenTorch_CLI/data/src/12_attention/12_attention.py.

    Learning objectives

    1. Implement scaled dot-product attention with explicit O(n²) complexity
    2. Build multi-head attention for parallel processing streams
    3. Understand attention weight computation and interpretation
    4. Experience attention's quadratic memory scaling firsthand
    5. Test attention mechanisms with masking and sequence processing

    Inside the module

    • The Attention Intuition
    • Why Attention Changed Everything
    • The Mathematical Foundation
    • The Three Components Visualized
    • The Attention Process Step by Step
    • Dimensions and Shapes
    • Why O(n²) Complexity?
    • The Attention Matrix Visualization
    • Understanding the Algorithm Visually
    • Helper: Computing Attention Scores
    • Helper: Scaling Scores
    • Helper: Applying Causal Mask
    • Bringing It Together: Scaled Dot-Product Attention
    • Understanding Multi-Head Architecture
    Embeddings → Attention → Transformers → Language Models
    (representations) (focus mechanism) (complete architecture) (text generation)
    Reflection questions from the module (5)
    1. Quadratic Complexity and Memory. For sequence length 1024, how much memory does attention's O(n^2) use? What about length 2048?
    2. Attention vs FFN Bottleneck. In production transformers, attention is often the memory bottleneck, not the FFN (feed-forward network). Why?
    3. Multi-Head Trade-offs. 8 attention heads vs 1 head with 8x dimensions - same parameters, different performance. What's the systems difference?
    4. Masking Costs. Causal masking (for autoregressive models) zeros out half the attention matrix. Do we save computation or just correctness?
    5. The Quadratic Memory Challenge. Your implementation computes the full (seq_len x seq_len) attention matrix. Why is this the primary memory bottleneck?
    TrenTorch 13

    Transformers

    Complete Transformer Architecture Module source

    Build TransformerBlock, GPT architecture, and autoregressive generation.

    You have built
    Tokenization, embeddings, attention mechanisms, and all foundational components
    You build
    TransformerBlock, complete GPT architecture, and autoregressive generation
    It enables
    Full language model training and text generation capabilities
    Build it tren module start 13, work in the notebook, then tren module test 13 and tren module complete 13. It exports trentorch.core.transformers; the source is TrenTorch_CLI/data/src/13_transformers/13_transformers.py.

    Learning objectives

    1. Implement complete TransformerBlock with attention, MLP, and layer normalization
    2. Build full GPT architecture with multiple transformer blocks
    3. Add autoregressive text generation capability
    4. Understand parameter scaling in large language models
    5. Test transformer components and generation pipeline

    Inside the module

    • The Transformer Revolution
    • Complete GPT Architecture Overview
    • Why Transformers Dominate
    • The Building Blocks We'll Implement
    • Layer Normalization: The Stability Engine
    • Residual Connections: The Gradient Highway
    • Feed-Forward Network (MLP): The Thinking Layer
    • The Complete Transformer Block Data Flow
    • Understanding Layer Normalization
    • Understanding the Multi-Layer Perceptron (MLP)
    • Understanding the Complete Transformer Block
    • Understanding the Complete GPT Architecture
    • The Language Modeling Pipeline
    • The Scaling Laws Revolution
    Tokenization + Embeddings + Attention → Transformers → Language Generation
    (text→numbers)  (learnable vectors) (sequence modeling)  (complete models)
    Reflection questions from the module (4)
    1. Attention Memory Complexity. You implemented multi-head attention that computes attention matrices of size (batch, heads, seq_len, seq_len).
    2. Residual Connection Benefits. Your TransformerBlock uses residual connections (x + attention_output, x + mlp_output).
    3. Parameter Scaling Analysis. Your GPT model combines embeddings, transformer blocks, and output projection.
    4. Autoregressive Generation Efficiency. Your generate() method processes the full sequence for each new token.

    Unlocks TrenTorch milestone 05 · Transformer Era (2017) Prove attention with reversal, copy, and mixed sequence tasks. Needs modules 01-08, 11-13. Run it with tren milestone run 05.

    Exit check Why divide QK^T by the square root of d_k?

    Show the answer

    With unit-variance entries, a dot product of d_k terms has variance d_k, so scores grow with dimension. Large scores push softmax into saturation where its gradients vanish. Dividing by the square root of d_k keeps the variance near one.

    Stage 14

    Making it run: inference, measured

    about 9 h
    • TrenTorch 14 Profiling
    • TrenTorch 15 Quantization
    • TrenTorch 16 Compression
    • TrenTorch 17 Acceleration
    • TrenTorch 18 Memoization
    • TrenTorch 19 Benchmarking
    • Unlocks milestone 06

    After this you can Profile a model, quantize and prune it, fuse and vectorise its hot paths, cache attention keys and values, and benchmark the result with confidence intervals.

    Why it matters A trained model is only useful once it runs fast and cheaply enough. A speech service is judged on p95 latency and cost per minute under load, and these modules teach you to measure and move both.

    measure shrink speed up prove profile FLOPs, memory, where time goes quantize float32 to int8, x4 smaller prune, distil fewer weights fuse, vectorise fewer memory trips KV cache reuse past keys, values benchmark p95 latency, CI a speech service over HTTP, $/min
    Measure, shrink, speed up, prove. A speech service is judged on its p95 latency and cost per minute under load, so every change to the model is measured before and after.
    TrenTorch 14

    Profiling

    Measuring What Matters Module source

    Build profiling tools for parameters, FLOPs, memory, and latency.

    You have built
    Complete ML stack from tensors to transformers (Modules 01-13)
    You build
    Comprehensive profiling system for parameters, FLOPs, memory, and latency
    It enables
    Data-driven optimization decisions and performance analysis
    Build it tren module start 14, work in the notebook, then tren module test 14 and tren module complete 14. It exports trentorch.perf.profiling; the source is TrenTorch_CLI/data/src/14_profiling/14_profiling.py.

    Learning objectives

    1. Implement a complete Profiler class for model analysis
    2. Count parameters and FLOPs accurately for different architectures
    3. Measure memory usage and latency with statistical rigor
    4. Create production-quality performance analysis tools

    Inside the module

    • The Profiling Workflow Visualization
    • From Implementation to Optimization: The Profiling Foundation
    • Parameter Counting: Model Size Detective Work
    • FLOP Counting: Computational Cost Analysis
    • Memory Profiling: The Three Types of Memory
    • Latency Measurement: Dealing with Reality
    • The Profiler Architecture
    • Why Helper Functions Matter
    • Why Parameter Counting Matters
    • FLOP Counting Visualization
    • FLOP Counting Strategy
    • Memory Usage Breakdown
    • Memory Measurement Strategy
    • Latency Measurement Challenges
    All Modules (01-13) → Profiling (14)
    (implementations)     (measurement)
    Reflection questions from the module (4)
    1. FLOP Analysis. You implemented a profiler that counts FLOPs for different operations. For a Linear layer with 1000 input features and 500 output features:
    2. Memory Scaling. Your profiler measures memory usage for models and activations. A transformer model has 125M parameters (500MB at FP32). During training with batch size 16:
    3. Performance Bottlenecks. You built tools to identify compute vs memory bottlenecks. A model achieves 10 GFLOP/s on hardware with 100 GFLOP/s peak.
    4. Profiling Trade-offs. Your profiler adds measurement overhead to understand performance. If profiling adds 5x overhead but reveals a 50% speedup opportunity:
    TrenTorch 15

    Quantization

    Reduced Precision for Efficiency Module source

    Reduce model precision from FP32 to INT8 while preserving accuracy.

    You have built
    Complete ML pipeline with profiling (Module 14)
    You build
    INT8 quantization system with calibration and memory savings
    It enables
    4x memory reduction and 2-4x speedup for production deployment
    Build it tren module start 15, work in the notebook, then tren module test 15 and tren module complete 15. It exports trentorch.perf.quantization; the source is TrenTorch_CLI/data/src/15_quantization/15_quantization.py.

    Learning objectives

    1. Implement INT8 quantization with proper scaling
    2. Build quantization-aware training for minimal accuracy loss
    3. Apply post-training quantization to existing models
    4. Measure actual memory and compute savings
    5. Understand quantization error and mitigation strategies

    Inside the module

    • The Precision Paradox
    • The Growing Memory Crisis
    • The Quantization Solution
    • Real-World Impact You'll Achieve
    • Understanding the Core Challenge
    • The Quantization Mapping
    • The Magic Formula
    • The Two Critical Parameters
    • Visual Example: Weight Quantization
    • Quantization Error Analysis
    • Why INT8 is the Sweet Spot
    • Our Implementation Strategy
    • What We're About to Build
    • Why We Need Quantized Layers
    Profiling (14) → Quantization (15)
    (measure memory)   (reduce precision)
    Reflection questions from the module (5)
    1. Memory Architecture Impact. You implemented INT8 quantization that reduces each parameter from 4 bytes to 1 byte.
    2. Quantization Error Analysis. Your quantization maps a continuous range to 256 discrete values (INT8).
    3. Hardware Efficiency. Modern processors have specialized INT8 instructions (like AVX-512 VNNI).
    4. Calibration Strategy Trade-offs. Your calibration process finds optimal scales using sample data.
    5. Production Deployment. In mobile/edge deployment scenarios:
    TrenTorch 16

    Compression

    Pruning and Model Compression Module source

    Build pruning, knowledge distillation, and low-rank approximation techniques.

    You have built
    Complete optimization pipeline with profiling (14) and quantization (15)
    You build
    Pruning (magnitude & structured), knowledge distillation, and low-rank approximation
    It enables
    Compressed models that maintain accuracy while using dramatically less storage and memory
    Build it tren module start 16, work in the notebook, then tren module test 16 and tren module complete 16. It exports trentorch.perf.compression; the source is TrenTorch_CLI/data/src/16_compression/16_compression.py.

    Learning objectives

    1. Implement magnitude-based and structured pruning
    2. Build knowledge distillation for model compression
    3. Create low-rank approximations of weight matrices
    4. Measure compression ratios and sparsity levels
    5. Understand structured vs unstructured sparsity trade-offs

    Inside the module

    • Note on Sequential Usage in This Module
    • Why Compression Matters in ML Systems
    • The Compression Landscape
    • Magnitude-Based Pruning: The Simple Approach
    • Structured Pruning: Hardware-Friendly Compression
    • Knowledge Distillation: Learning from Teachers
    • Low-Rank Approximation: Matrix Compression
    • Understanding Sparsity
    • How Magnitude Pruning Works
    • Why Global Thresholding Works
    • Why Structured Pruning Matters
    • Channel Importance Ranking
    • Hardware Benefits of Structured Sparsity
    • The Intuition Behind Low-Rank Approximation
    Profiling (14) → Quantization (15) → Compression (16) → Advanced Optimization
    (measure size)   (reduce precision)  (remove weights)   (next modules)
    Reflection questions from the module (5)
    1. Compression Trade-offs. You implemented magnitude pruning that removes 90% of weights from a 10M parameter model.
    2. Structured vs Unstructured Sparsity. Your structured pruning removes entire channels, while magnitude pruning creates scattered zeros.
    3. Knowledge Distillation Efficiency. A teacher model has 100M parameters, student has 10M parameters, both achieve 85% accuracy.
    4. Low-Rank Decomposition. You approximate a (512, 256) weight matrix with rank 64 using SVD.
    5. Pruning Strategy Selection. For deploying on a mobile device with 50MB model limit and 100ms latency requirement:
    TrenTorch 17

    Acceleration

    Hardware-Aware Optimization Module source

    Master vectorization and kernel fusion for hardware-efficient execution.

    You have built
    Complete neural network foundation with tensors (01), layers (03), autograd (06), training (08), and CNNs (09)
    You build
    Acceleration techniques including vectorization and operation fusion
    It enables
    Hardware-efficient execution for production deployment
    Build it tren module start 17, work in the notebook, then tren module test 17 and tren module complete 17. It exports trentorch.perf.acceleration; the source is TrenTorch_CLI/data/src/17_acceleration/17_acceleration.py.

    Learning objectives

    1. Implement vectorized operations for maximum throughput
    2. Create fused operations to reduce memory bandwidth
    3. Understand the relationship between compute and memory bandwidth
    4. Analyze acceleration trade-offs in production systems

    Inside the module

    • The Two Enemies of Performance
    • The Roofline Model - Your Performance Compass
    • Why This Module Matters
    • The SIMD Revolution
    • Memory Access Patterns: The Hidden Performance Killer
    • Matrix Multiplication: The King of Vectorization
    • The Memory Bandwidth Crisis
    • Understanding GELU: The Smooth Activation
    • Kernel Fusion Strategy
    • Why Cache Awareness Matters
    • Memory Efficiency Analysis
    • 1. Arithmetic Intensity Analysis
    • 2. Kernel Fusion Memory Benefits
    • 3. Production Optimization Strategy
    Layers (03) → Training (08) → CNNs (09) → Acceleration (17)
    (building blocks) (learning)   (spatial)  (speed up)
    Reflection questions from the module (3)
    1. Arithmetic Intensity Analysis. You implemented vectorized matrix multiplication and fused GELU.
    2. Kernel Fusion Memory Benefits. Your fused_gelu combines 7 operations into a single expression.
    3. Production Optimization Strategy. Based on your decision framework analysis:
    TrenTorch 18

    Memoization

    Computational Reuse for Inference Module source

    Implement KV caching for 10-15x faster transformer text generation.

    You have built
    Complete transformer architecture (Module 13) and profiling tools (Module 14)
    You build
    Memoization system that eliminates redundant computation through caching
    It enables
    Production-grade inference optimization using computational reuse
    Build it tren module start 18, work in the notebook, then tren module test 18 and tren module complete 18. It exports trentorch.perf.memoization; the source is TrenTorch_CLI/data/src/18_memoization/18_memoization.py.

    Learning objectives

    1. Understand memoization as a general optimization pattern (cache results, avoid recomputation)
    2. Apply memoization to transformers through KV caching
    3. Implement KVCache with efficient memory management and O(1) updates
    4. Build cache-aware attention that reuses previously computed keys and values
    5. Measure dramatic speedup gains (10-15x) and understand memory trade-offs

    Inside the module

    • The Core Inefficiency
    • Computational Complexity Analysis
    • Real-World Impact
    • Cache-Optimized Generation
    • Memory vs Compute Trade-off
    • Core Requirements
    • Cache Architecture Visualization
    • Update Operation Flow
    • Integration Strategy
    • Generation Flow Comparison
    • The Challenge
    • Using KV Cache in Practice
    • Performance Expectations
    • Production Considerations
    Profiling (14) → Quantization (15) → Acceleration (17) → Memoization (18)
    (measure O(n²))  (reduce precision)   (vectorize)        (cache K,V → O(n))
    Reflection questions from the module (5)
    1. Cache Size Calculation. A 12-layer transformer has 12 attention heads per layer, 64-dimensional embeddings per head,
    2. Speed vs Memory Trade-off. Your KVCache makes generation 10× faster but uses several GB of RAM.
    3. Batch Inference Scaling. Batch size 1 generates at 500 tokens/sec, using 50 MB cache. With KV cache, each sequence in a batch gets its own cache storage.
    4. Cache Eviction for Long Conversations. Your `KVCache` has `max_seq_len=2048`. A chatbot conversation reaches 2048 tokens - the cache is full!
    5. Production Reality - Multi-User Serving. ChatGPT serves millions of users. Each user's conversation needs its own KV cache.
    TrenTorch 19

    Benchmarking

    TorchPerf Olympics Preparation Module source

    Build the benchmarking infrastructure for the capstone competition.

    You have built
    Complete ML framework with profiling, acceleration, quantization, and compression
    You build
    TorchPerf benchmarking system for fair model comparison and performance evaluation
    It enables
    Systematic optimization combination and competitive performance evaluation
    Build it tren module start 19, work in the notebook, then tren module test 19 and tren module complete 19. It exports trentorch.perf.benchmarking; the source is TrenTorch_CLI/data/src/19_benchmarking/19_benchmarking.py.

    Learning objectives

    1. Implement professional benchmarking infrastructure with statistical rigor
    2. Learn to combine optimization techniques strategically (order matters!)
    3. Build the TorchPerf class - a standardized performance evaluation framework
    4. Understand ablation studies and systematic performance evaluation

    Inside the module

    • Benchmarking as a Systems Engineering Discipline
    • Central Limit Theorem in Practice
    • Multi-Objective Optimization Theory
    • Measurement Uncertainty and Error Propagation
    • Benchmark Architecture Overview
    • BenchmarkResult - Statistical Analysis Container
    • Why Statistical Analysis Matters
    • Statistical Properties We Track
    • Timing Challenges in Practice
    • Why perf_counter() Matters
    • Timing Best Practices
    • Benchmark Class - Core Measurement Engine
    • Benchmark Architecture Overview
    • Why Warmup Runs Matter
    Individual Optimizations (M14-18) → Benchmarking (M19) → Module 20 (Capstone)
    (techniques)                        (evaluation)         (application)
    Reflection questions from the module (5)
    1. Statistical Confidence in Measurements. You implemented BenchmarkResult with confidence intervals for measurements.
    2. Measurement Overhead Analysis. Your precise_timer context manager has microsecond precision, but models run for milliseconds.
    3. Benchmark Configuration Trade-offs. The BenchmarkSuite class uses configurable warmup_runs and measurement_runs parameters
    4. MLPerf Compliance Metrics. You implemented MLPerf-style standardized benchmarks with target thresholds.
    5. Optimization Comparison Analysis. Your analyze_optimization_techniques() generates recommendations for different use cases.

    Unlocks TrenTorch milestone 06 · MLPerf Benchmarks (2018) Optimize and benchmark your neural networks. Needs modules 01-08, 14-19. Run it with tren milestone run 06.

    Also in the architecture 1 · System context

    Exit check Why does a KV cache make autoregressive generation faster, and what does it cost?

    Show the answer

    Without it, each new token recomputes keys and values for the whole prefix, so generation is quadratic. The cache stores them and computes only the new token's, making each step linear. The cost is memory per sequence, which grows with length and limits how many users one GPU serves.

    Part 3 · Audio ML

    about 46.5 h across 9 stages

    Use what you built to read a real speech system, Alaap: spectrograms, speaker embeddings, neural codecs, text-to-speech as a language model, and evaluation that does not fool you. The text is quoted from Alaap's own study guide and architecture.

    Stage 15

    A speech system, end to end: what Alaap does

    about 2 h

      After this you can Say what Alaap does in one sentence, and trace one written description through its architecture to audio.

      Why it matters Every later stage fills in one idea: a frozen TTS model driven by a learned speaker vector. Learn that shape first.

      From the Alaap guide, Part 0: Orientation 2 hours, do this first

      After this you can describe what Alaap does, and run it.

      Read in this order, and nothing else yet:
      1. learning/architecture.html, open it in a browser. Diagrams 1–5.
      2. README.md
      3. RESEARCH/00-EXECUTIVE-VERDICT.md
      Do
      envs/qwen3/Scripts/python.exe scripts/demo_script_render.py
      

      Four minutes. Then listen to demo_out/audio/. No number in the Alaap repo substitutes for that.

      Check Why is the TTS model never trained? What would break if it were?

      Architecture: 1 · System context Open in the architecture tab

      The product promise in one picture. A person writes a sentence describing a character; a voice that has never existed comes back, and it stays that same voice across every line of a script.

      input alaap output description“a warm, low-pitched mentor” script400 lines of dialogue direction, per lineemotion · rate mapperdescription → vector identity storevector + seed clip rendererFROZEN TTS gatesdrift · CER · unique watermarkAudioSeal, every file audio, per lineOGG/Vorbis manifest.jsongame-engine ready
      The frozen box is the whole idea. The TTS model is never trained. All the learning lives in the mapper, which produces a speaker vector the frozen model already knows how to consume. Watermarking is not a launch task, it happens on render #1 (invariant I7, EU Art. 50(2)).
      Involves
      description, script, per-line direction, mapper, identity store, frozen TTS renderer, gates, watermark, per-line audio and manifest
      Topics
      • system context
      • frozen model
      • product contract
      Learn it in
      Stage 15, A speech system, end to end: what Alaap does · Stage 23, Capstone: Alaap, from scratch

      Also in the architecture 2 · The two-tower thesis · 3 · The mint pipeline, in full · 4 · The render pipeline · 5 · The gate stack

      Exit check Why is the TTS model never trained, and what would break if it were?

      Show the answer

      All the learning is in the mapper, which produces a vector the frozen model already knows how to consume. Train the TTS and the vector space moves under every stored identity: every minted voice drifts, and the independent drift and consistency judges stop meaning anything.

      Stage 16

      The rest of sound: frequency, and how estimators lie

      about 7 h
      • Alaap guide 2.2
      • Alaap guide 2.4

      After this you can Read a spectrogram's time and frequency resolution from its parameters, and read alaap/acoustics.py, saying what each function measures and how it can be wrong.

      Why it matters These estimators produce every attribute Alaap captions. If measure() is wrong, the caption, the mapper and the adherence score are wrong together, and nothing complains.

      waveform one window one column the picture samples 24 kHz n_fft = 2048 85 ms, Hann window FFT 1025 bins, 11.7 Hz each spectrogram time x frequency hop = 512 slide 21 ms, repeat the trade long window: sharp Hz, blurry time
      The STFT is an FFT on a sliding window. Every parameter is a trade between time and frequency resolution, and both numbers appear inside spectral_tilt.

      Guide 2.2 The frequency domain 3 h

      DFT/FFT, window functions, the STFT, the spectrogram, mel scale, MFCCs.

      Intuition the STFT is "run an FFT on a sliding window". Every parameter is a trade: a long window gives fine frequency resolution and blurry time; a short one, the reverse.

      Read any good DSP intro; Smith's Mathematics of the DFT if you want rigour.

      Do in the Alaap repo:

      import librosa, numpy as np
      S = np.abs(librosa.stft(wav, n_fft=2048, hop_length=512))
      

      n_fft=2048 at 24 kHz gives what frequency resolution? What time resolution? Both numbers appear in spectral_tilt and both matter.

      Guide 2.4 The estimators, and how each one lies 4 h

      Read alaap/acoustics.py top to bottom. Every docstring is a lesson someone paid for.

      function the trap
      f0_track pYIN; octave errors on creaky voice
      voiced_mask an energy+ZCR VAD, not a periodicity detector; structurally capped near 0.60 and bimodal
      formants LPC order and analysis rate; run at ~2× max formant, not native
      vocal_tract_length never average through F2, it is vowel-dependent
      spectral_tilt OLS over linear FFT bins puts 43% of leverage on 27 bins
      speaking_rate needs text; silently NaN without it; g2p-en does not raise on Devanagari

      Read the project skill .claude/skills/speech-feature-pitfalls/SKILL.md, it is the compressed version of everything above, written from real failures here.

      Check Why does a 250 Hz voice read a flatter spectral tilt than a 90 Hz voice with an identical spectral envelope? (Answer in experiments/S21-spectral-tilt/RESULTS.md.)

      Also in the architecture 8 · The attribute taxonomy · 6 · Reversibility, the property that makes captions checkable

      Exit check At 24 kHz with n_fft = 2048 and hop 512, what are the frequency and time resolutions?

      Show the answer

      Frequency: 24000 / 2048, about 11.7 Hz per bin. Time: 512 / 24000, about 21 ms between frames, with each window 85 ms long. Finer frequency costs blurrier time, and the reverse.

      Stage 17

      Speaker identity: embeddings that recognise people

      about 5 h
      • Alaap guide 3.1
      • Alaap guide 3.2

      After this you can Explain how a speaker embedding is made, why it is invariant to channel, and why verification thresholds must be fitted in-domain.

      Why it matters ECAPA is trained to ignore channel and quality, so it recognises you down a bad line. For the same reason Alaap uses it as the independent judge of identity, never of quality.

      train keep training only utterance thousands of speakers ECAPA-TDNN conv + pooling penultimate layer a fixed-length vector speaker classifier thrown away cosine(a, b) same or different? in-domain calibration C_same 0.70, C_diff 0.20
      Train to tell speakers apart, then drop the classifier. The layer before it is the embedding, and it inherits whatever training made it ignore: channel and quality. That is why it judges identity and never quality.

      From the Alaap guide, Part 3: Speaker identity 10 h

      After this you can read the three papers the whole architecture rests on, and explain why a speaker embedding is not just "an embedding".

      Guide 3.1 From i-vectors to ECAPA 3 h

      Read
      • Snyder et al., "X-Vectors: Robust DNN Embeddings for Speaker Recognition", ICASSP 2018
      • Desplanques et al., "ECAPA-TDNN: Emphasized Channel Attention, Propagation and Aggregation in TDNN Based Speaker Verification", Interspeech 2020

      Intuition train a network to tell speakers apart; throw away the classifier; the penultimate layer is now a speaker embedding. Everything downstream inherits whatever that training made it invariant to.

      Why it matters here, and it is a rule, not a detail

      ECAPA is trained to be INVARIANT to channel and quality, so it can recognise you down a bad phone line. That is exactly why it must never be used to measure quality. It is the project's independent judge for identity, and nothing else.

      Guide 3.2 Cosine, EER, and calibration 2 h

      Cosine similarity, thresholds, EER, and why a threshold from a paper does not transfer.

      Do read alaap/metrics.py's CALIBRATION and E4's results. C_same = 0.6988, C_diff = 0.2011. Then answer: why must these be fit in-domain? (E4 measured that doing so halves EER.)

      Also in the architecture 12 · Module map

      Exit check Why does fitting C_same and C_diff in-domain halve the equal error rate?

      Show the answer

      Cosine scores depend on corpus, channel and language. A threshold taken from a paper sits in the wrong place for Alaap's audio and trades errors badly. Fitted on Alaap's own same-speaker and different-speaker pairs, it sits where the two distributions cross.

      Stage 18

      Is the space navigable?

      about 5 h
      • Alaap guide 3.3
      • Alaap guide 3.4

      After this you can Argue, from three papers, that a speaker embedding space can be sampled and interpolated, and say what goes wrong in sparse regions and past the shell.

      Why it matters The project rests on this: if the space could not be navigated, Tower A would not be worth training.

      Guide 3.3 Is the space navigable? 3 h

      This is the intellectual core of the project. Three papers, all in SOURCES.md:

      arXiv:1806.04558 §3.6, Jia et al., NeurIPS 2018 random unit-hypersphere vectors → MOS 3.65, "as natural as real speakers". The manifold is navigable.
      arXiv:2111.05095 §6.2, TacoSpawn discriminative d-vector spaces resist parametric priors (g2s 0.35 vs s2s 0.20). Learned spaces do not.
      arXiv:2207.04834 §5.1.1, Meyer et al. the collapse and its fix. Per-dim rescaling: GVD −6.50 → −0.14. Dimension ranges span three orders of magnitude.

      Intuition for the third one: if one dimension ranges over ±80 and another over ±0.5, then an unweighted MSE loss is entirely about the first dimension. Every voice collapses onto the same one. Rescale per dimension or the model learns nothing.

      Guide 3.4 Moving through the space 2 h

      Interpolation vs extrapolation; SLERP vs LERP; sparse regions.

      arXiv:2106.05762 1,225 pairwise interpolations, WER 6.42–7.35%. Interpolation works.
      arXiv:2310.03538 "extrapolation is not particularly meaningful"
      arXiv:2508.19210 SLERP not LERP, preserves unit norm
      arXiv:2005.08601 sparse-region averaging costs +60% relative WER

      Check Why does mint(novelty=0.7) produce voices closer to the centre of the space, not further from it? (S9. It is not obvious, and the experiment retracted a claim over it.)

      Architecture: 7 · Speaker-space geometry Open in the architecture tab

      You cannot treat a speaker embedding space as isotropic. This is invariant I1, and ignoring it collapses every identity onto one voice.

      raw vectors Z(N, 2048) or (N, 128)per-dim ranges span 3 OOM mean-centre79.5% of every vectoris a shared constant (E3) per-dim rescaleGVD -6.50 to -0.14arXiv:2207.04834 PCA basisthe working spacefull dims = best (S9b) encode() /decode() the shell real speakers sit at a radius SLERP, not LERP preserves the norm arXiv:2508.19210 why this is not decorationAveraging two speaker vectors in a sparse region costs +60% relative WER(10.94% vs 6.83%, Interspeech 2020). "Elderly" and "raspy" ARE sparse regions.Extrapolation past the shell is "not particularly meaningful" (ICASSP 2024).So: interpolate, stay on the shell, and never average unweighted.
      Interpolation between real speakers is well supported, 1,225 pairwise interpolations held WER at 6.42–7.35% (Interspeech 2021). Extrapolation is not. That is why novelty defaults to 0.0 and why the mapper blends anchors rather than inventing points.
      Involves
      raw vectors, mean-centring, per-dimension rescale, PCA basis, the shell, SLERP
      Topics
      • anisotropy (I1)
      • interpolation versus extrapolation
      • sparse regions
      Learn it in
      Stage 18, Is the space navigable?

      Also in the architecture 2 · The two-tower thesis

      Exit check Why SLERP rather than linear interpolation between two speaker vectors?

      Show the answer

      Real speakers sit on a shell at roughly constant norm. A straight line between two points on a sphere cuts inside it, where the norm shrinks and the voice drifts toward the average. SLERP stays on the shell.

      Stage 19

      How a TTS model actually works

      about 10 h
      • Alaap guide 4.1
      • Alaap guide 4.2
      • Alaap guide 4.3
      • Alaap guide 4.4

      After this you can Read the model card of any open TTS system and predict whether it can serve Alaap's architecture.

      Why it matters Codecs turn audio into integers. That is why modern TTS is a language model, and why Alaap can decode forty voices for the price of one.

      in frozen acoustic LM codec out text tokens what to say speaker vector who says it transformer predicts codec tokens content tokens FSQ [8,8,8,5,5] codec decoder tokens + identity waveform 44.1 kHz
      Once audio is integers, a language model can write it. Content tokens are generated once and decoded through any speaker vector, which is why forty voices cost the same language-model time as one.

      From the Alaap guide, Part 4: How a TTS model actually works 10 h

      After this you can read the model card of any open TTS system and predict whether it can serve this architecture.

      Guide 4.1 The shape of the field 2 h

      Autoregressive vs non-autoregressive; two-stage (text→tokens→waveform) vs end-to-end.

      Read Kim et al., "VITS: Conditional Variational Autoencoder with Adversarial Learning for End-to-End Text-to-Speech", 2021. It is the clean end-to-end baseline everything else is a reaction to.

      Guide 4.2 Neural audio codecs 3 h the key unlock

      Read
      • Zeghidour et al., "SoundStream: An End-to-End Neural Audio Codec", 2021
      • Défossez et al., "High Fidelity Neural Audio Compression" (EnCodec), 2022
      • Mentzer et al., "Finite Scalar Quantization: VQ-VAE Made Simple", 2023, FSQ, which is what MioCodec uses

      Intuition a codec learns to turn a waveform into a short sequence of integers and back. Once audio is integers, a language model can generate it. That is why modern TTS is a language model.

      Why FSQ specifically: it replaces a learned codebook with a fixed grid, quantise each of 5 dimensions to [8,8,8,5,5] levels, giving 12 800 combinations, no codebook collapse, no auxiliary losses.

      And the trap, which cost the Alaap project a week: two FSQ codecs with the same levels share no codebook. Every index is valid in both. Nothing raises. You get fluent speech saying different words. Diagram 10 in architecture.html.

      Guide 4.3 Self-supervised speech representations 2 h

      Read Chen et al., "WavLM: Large-Scale Self-Supervised Pre-Training for Full Stack Speech Processing", 2022. HuBERT if you want the predecessor.

      Intuition train on unlabelled audio by masking and predicting. Different layers end up encoding different things, early layers pitch and speaker, middle layers phonetic content.

      Why it matters here the naturalness gate is distance to the real-speech manifold in WavLM features, and which layer you pool changes what you measure. Layer 0 correlates with F0 at −0.578, which is the DNSMOS trap in disguise. See S20b and S23.

      Guide 4.4 Flow matching and diffusion, enough to argue 3 h

      Read Lipman et al., "Flow Matching for Generative Modeling", 2023. Skim the maths; get the picture.

      Intuition diffusion learns to reverse noise step by step. Flow matching learns a velocity field that transports noise to data along a straight-ish path, fewer steps, same destination.

      The one A/B that matters here, from SOURCES.md:

      arXiv:2406.08812, Interspeech 2024, flow matching wins fidelity (FAD 3.559 vs 5.244) and loses adherence (SRCC 0.60 vs 0.74). A hybrid is best. The trade is bidirectional, which is why the Alaap project's S3 plans MDN first.

      Architecture: 10 · Inside MioCodec, the content / identity split Open in the architecture tab

      This split is what makes the Indic experiments cheap. It is also where the project's most expensive bug lived.

      audio 44.1 kHz encode()return_content=Truereturn_global=True content tokens25 Hz, WHAT is said global embedding(128,), WHO says it decode()both args 1-D audio the bug that cost a weekTwo FSQ codecs, both with levels [8,8,8,5,5] = 12 800 entries, SHARE NO CODEBOOK.Every index is accepted. Nothing raises. The output is fluent, natural Hindi, saying completely different words. A fluent listener passed it, because they wereasked "does this sound right?" instead of "does this say X?"
      Why forty voices cost the same LM time as one. Content tokens are generated once and decoded through every speaker vector: L LM generations + N×L codec decodes, not N×L LM generations. That is the two-tower split being real in the weights, and it makes voice comparisons exact, since every voice says an identical waveform of content.
      Involves
      MioCodec encode, content tokens at 25 Hz, global embedding (128), decode
      Topics
      • neural codecs
      • FSQ
      • content and identity split
      Learn it in
      Stage 19, How a TTS model actually works

      Also in the architecture 9 · Two backends, one interface · 4 · The render pipeline · 2 · The two-tower thesis

      Exit check Two FSQ codecs both use levels [8, 8, 8, 5, 5]. Why can you not feed one's tokens to the other's decoder?

      Show the answer

      Equal levels give the same 12,800 valid indices, but each codec learned its own mapping from index to sound. Every index is accepted and nothing raises, so you get fluent speech saying different words.

      Stage 20

      Description to voice

      about 5 h
      • Alaap guide 5.1
      • Alaap guide 5.2
      • Alaap guide 5.3

      After this you can Read the mapper code and the paper it copies, and explain why the mapper blends top_k = 2 anchors.

      Why it matters One description fits many valid voices. A mixture density network predicts a family of them instead of one point.

      description encoder MDN head speaker space sample train "a warm low voice" free text sentence encoder MiniLM 10 Gaussians weights, means, spreads sample a vector a family, not a point negative log-likelihood of the real speaker a plain regressor predicts the blurred mean
      One description, many valid voices. A mixture density network outputs a distribution over speaker vectors and is trained by the likelihood of the real one; a regressor would average them into one central voice.

      From the Alaap guide, Part 5: Description → voice 5 h

      After this you can read the mapper code and the paper it copies, and explain the design choice in top_k=2.

      Guide 5.1 Mixture Density Networks 2 h

      Read Bishop, "Mixture Density Networks", 1994 (tech report, ~20 pages, very readable).

      Intuition a normal regressor predicts one output per input. But one description ("a warm low voice") corresponds to many valid voices. An MDN predicts a mixture of Gaussians instead of a point, so the model can say "any of these".

      Why it matters it is the difference between one voice per description and a family. The reference implementation is MDNLayer(256, 256, num_gaussians=10, dim_wise=True).

      Guide 5.2 PromptTTS++ 2 h the reference implementation

      Read Shimizu et al., "PromptTTS++: Controlling Speaker Identity in Prompt-Based Text-to-Speech Using Natural Language Descriptions", 2024. Then the code: line/promptttspp, Apache-2.0, weights downloadable.

      This is the only open working implementation of exactly the contract Alaap needs: natural-language description → speaker embedding → frozen TTS.

      Guide 5.3 Data-Speech and measure-first captions 1 h

      Read Lyth & King, "Natural language guidance of high-fidelity text-to-speech with synthetic annotations", 2024 (the Parler-TTS / Data-Speech line).

      Do compare against alaap/acoustics.py: Data-Speech computes 9 columns from 5 tools, equal-width bins. Alaap uses percentile bins and adds six attributes Data-Speech has not got. Read Binner's docstring for why percentile, it is a real finding about skewed corpora.

      Check Why does Binner regress HNR on log-F0 before binning it? (39.9% of HNR variance was pitch, a measurement artefact, and it made "a high, harsh voice" impossible to satisfy.)

      Architecture: 3 · The mint pipeline, in full Open in the architecture tab

      Every box here is real code in alaap/mapper.py and alaap/service.py. This is the path a description takes to become a stored identity.

      descriptionfree text target_bins_from_textprose → bin labels TextEncoderMiniLM sentence emb. retrieve()hybrid: bins + cosine anchor corpusreal speakers, measured+ their vectors blend top_k = 2SLERP, unit norm novelty · εdefault 0.0 speaker vectorcandidate gates, all must pass uniqueness≥ 0.30 · 0.45vs every accepted voice render a probefrozen TTS3 lines drift≥ 0.40intended vs re-extracted consistency≥ 0.43across sentences, ECAPA CERASR intelligibilitywords still correct? IdentityStore.put()vector + seed clip + backend_id + version + params
      Two things here are counter-intuitive and both were measured. top_k = 2 rather than 1: blending two anchors beats pure retrieval, but blending four contracts toward the centroid and loses diversity. novelty = 0.0: pushing minted vectors away from real anchors makes them more central, not less (S9). And the store keeps a seed clip as well as a vector, invariant I2, because an encoder change orphaned every stored vector once already.
      Involves
      bin labels from text, MiniLM text encoder, hybrid retrieval, top_k = 2 SLERP blend, novelty, four gates, IdentityStore
      Topics
      • retrieval
      • interpolation
      • gating
      • identity storage
      Learn it in
      Stage 15, A speech system, end to end: what Alaap does · Stage 18, Is the space navigable? · Stage 20, Description to voice

      Also in the architecture 11 · The Direction channel

      Exit check Why an MDN rather than a regressor that predicts one speaker vector?

      Show the answer

      Trained with squared error on a one-to-many mapping, a regressor predicts the average of every valid voice, which is a blurred central voice. An MDN predicts mixture weights, means and spreads, so sampling gives distinct plausible voices.

      Stage 21

      Evaluation, and why most of it is wrong

      about 5 h
      • Alaap guide 6.1
      • Alaap guide 6.2
      • Alaap guide 6.3
      • Alaap guide 6.4

      After this you can Design a measurement that will not fool you: the right diversity statistic, the right judge, and a listening test with its discard rule written first.

      Why it matters This part has more hard-won knowledge, and less published literature behind it, than any other part of the project.

      voices similarity spectrum the number n voices speaker vectors similarity matrix (n, n), cosine eigenvalues normalised to sum 1 exp(entropy) effective voices the trap a fraction of n is not a count
      Vendi counts distinct things. Forty voices that are really twenty distinct ones score about twenty. Normalised Vendi divides by n, so the same fraction over different set sizes means different counts.

      From the Alaap guide, Part 6: Evaluation, and why most of it is wrong 5 h

      After this you can design a measurement that will not fool you. This is the part of the project with the highest ratio of hard-won knowledge to published literature.

      Guide 6.1 The MOS-predictor trap 1.5 h

      Read Reddy et al. DNSMOS (2021) and Saeki et al. UTMOS (2022), then RESEARCH/06-evaluation-harness.md §5.2.

      correlation with mean F0
      humans −0.059
      DNSMOS −0.788
      UTMOSv2 −0.722

      They also move less than 0.1 on prosodic corruption that costs humans 1.84 MOS points. For a project whose point is spanning the pitch range, a MOS gate systematically rejects high-pitched voices for a reason humans do not share. Invariant I9.

      Guide 6.2 Diversity: the Vendi score 1 h

      Read Friedman & Dieng, "The Vendi Score: A Diversity Evaluation Metric for Machine Learning", 2023.

      Intuition the exponential of the entropy of the eigenvalues of a similarity matrix. If you have 40 items that are really 20 distinct things, Vendi × n ≈ 20, "effective voices".

      The trap the Alaap repo hit: normalised Vendi is a fraction of the maximum for a set of that size. 0.361 over 95 items and 0.362 over 38 are not the same thing, they are ~34 and ~14 effective voices. S9 retracted a published claim over this.

      Guide 6.3 Intelligibility 0.5 h

      WER/CER, ASR as a judge, and why CER not WER for Indic scripts.

      Guide 6.4 Listening tests 2 h read the skill, it is better than the literature

      Read .claude/skills/listening-tests/SKILL.md, then experiments/S14-rate-control/RESULTS-S14c.md as a worked failure.

      The compressed lessons:

      • Comparative, not single-stimulus, when the baseline is itself imperfect
      • Positive and negative controls, always
      • Write the discard condition down before sending the set, then honour it
      • Compute the false-positive rate of that condition. S14c's fired on a coin flip
      • Ask "does this say X?", never "does this sound right?"

      Check Design a test for "does the rate knob sound processed?" without letting the listener answer on clip length. (There is a real tension here; S14b and S14c both failed it in opposite ways.)

      Architecture: 5 · The gate stack Open in the architecture tab

      Five gates, four of them calibrated on a corpus rather than chosen. Each answers a different question, and the project spent nineteen experiments not noticing that none of them asked about naturalness.

      identity content quality drift ≥ 0.40is the rendered voice the onewe asked for? consistency ≥ 0.43same person acrossdifferent sentences? uniqueness ≥ 0.300.45 on MioCodecis this a voice we alreadyhave? ← moved by S11 CERdoes it say the words?ASR transcript vs promptminting costs −0.012 CER naturalness < 75WavLM layer 7 distanceto the real-speech manifoldreal ≈ 50 · renders ≈ 97 the trap this avoidsDNSMOS correlates with mean F0 at r = −0.788; UTMOSv2 at −0.722.Humans correlate at −0.059. A MOS gate would reject high-pitched voicesfor a reason humans do not share, fighting the diversity axis directly.Invariant I9. RESEARCH/06 §5.2.
      The naturalness gate is a proposal, not a gate. It has never rejected anything, the floor of 75 was chosen, not measured. Everything to its left has blocked renders. Note also that drift/consistency/uniqueness/CER all pass on audio a listener calls synthetic (S19): they are identity and intelligibility gates, and the absence of a quality gate was invisible for nineteen experiments precisely because nothing was named one.
      Involves
      drift, consistency, uniqueness, CER, naturalness (WavLM layer 7)
      Topics
      • calibrated thresholds
      • MOS-predictor trap (I9)
      • evaluation
      Learn it in
      Stage 15, A speech system, end to end: what Alaap does · Stage 21, Evaluation, and why most of it is wrong

      Also in the architecture 6 · Reversibility, the property that makes captions checkable · 13 · Experiment lineage

      Exit check Why would a MOS predictor make a bad naturalness gate for Alaap?

      Show the answer

      DNSMOS correlates with mean pitch at r = -0.788; human ratings correlate at -0.059. It rejects high-pitched voices for a reason listeners do not share, and works against the diversity the project exists to create.

      Stage 22

      The roads not taken

      about 6 h

        After this you can Argue the backend choice instead of inheriting it: what each rejected system is, why it was rejected, and what would change the answer.

        Why it matters Licences and model shapes decide more of this project than benchmarks do. Five licence chains checked, five mis-declared.

        From the Alaap guide, Part 7: The roads not taken 6 h

        After this you can argue about backend choice rather than inherit it.

        For each: what it is, why it was rejected, and what would change the answer.

        system why not what would change it
        CosyVoice 2/3 speaker vector exists but use_spk_embedding: False, no spk2info.pt shipped. Best-shaped control surface though, separate instruct_text, speed, <strong>, [laughter] it is the documented fallback if the Direction channel had failed
        F5-TTS flow-matching, strong; but IndicF5 is a fine-tune of it under CC-BY-NC-4.0 despite an MIT card a clean-licence Indic fine-tune
        Zonos / ZONOS2 v0.1 encoder derives from VoxBlink2 (CC-BY-NC-SA); ZONOS2 is 15.34 GB bf16, does not fit 12 GB. Ships SLERP blending + additive emotion vectors, the same ideas as here more VRAM, and a licence trace
        IndexTTS-2 licence bars using it or its outputs to improve any AI model; "Use" includes running nothing, it is structurally incompatible with a training project
        XTTS-v2 code MPL-2.0, weights CPML; Coqui defunct, the fork cannot relicense nothing
        Indic Parler-TTS zero speaker-embedding code. Identity is a name token in the same string as style a fork that exposes a vector
        Kokoro-82M tiny and good; ref_s[:,:128]→decoder, [128:]→prosody is an undocumented free timbre/prosody split worth revisiting for a small/fast tier

        Read RESEARCH/03-tts-backends-english.md and RESEARCH/04-indic-track.md in full. They are the most reusable thing in the repo: primary-source verification of a dozen systems.

        Do pick one rejected system and write a one-page case for reopening it. Then check whether RESEARCH/08-licensing-propagation.md already kills your case.

        Check Why does invariant I4 say a licence declaration is "a claim, not evidence"? How many chains were mis-declared out of how many checked?

        Also in the architecture 9 · Two backends, one interface

        Exit check Why does invariant I4 call a licence declaration a claim, not evidence?

        Show the answer

        Because derived models inherit their parents' terms, and the declaration on the derived model is often wrong: every one of the five Indic chains checked was mis-declared upstream. Only tracing the chain to the training data is evidence.

        Stage 23

        Capstone: Alaap, from scratch

        about 1.5 h
        • Alaap guide, closing ideas
        • TrenTorch 20 Capstone

        After this you can Put the whole stack together: a model you trained, served and benchmarked, and the five ideas that cost the project longest to learn.

        Why it matters Alaap becomes a system you trained, instead of an assembly of other people's models.

        in what you built it from out description stage 12: tokens mapper (MDN) stages 6, 9, 20 identity store stage 18: the shell frozen TTS stages 13, 19 gates stages 17, 21 service over HTTP stage 14 audio, per line stages 2, 3, 16
        Every box, and the stage that taught it. The system context from stage 15 again. Now you can say how each part works, because you built or read every one.
        TrenTorch 20

        Capstone

        Benchmarking & Submission Module source

        Demonstrate your framework with benchmarks and generate a submission.

        You have built
        Complete ML framework with profiling (M14), quantization (M15), compression (M16), acceleration (M17), memoization (M18), and benchmarking (M19)
        You build
        Professional benchmark submission workflow with standardized reporting
        It enables
        Shareable, reproducible results demonstrating framework performance
        Build it tren module start 20, work in the notebook, then tren module test 20 and tren module complete 20. It exports trentorch.olympics; the source is TrenTorch_CLI/data/src/20_capstone/20_capstone.py.

        Learning objectives

        1. Use Module 19's benchmarking tools to measure model performance comprehensively
        2. Apply optimization techniques from Modules 14-18 to improve baseline models
        3. Generate standardized JSON submissions following industry best practices
        4. Validate submissions against a schema for reproducibility
        5. Compare baseline vs. optimized models with quantitative metrics
        6. Share your results with the TrenTorch community in a professional format

        Inside the module

        • The Reproducibility Crisis in ML
        • Industry Standard: Benchmarking Frameworks
        • What This Capstone Teaches You
        • The Three Pillars of Good Benchmarking
        • What Metrics Actually Matter?
        • Benchmark Report Components
        • Latency vs. Throughput: A Critical Distinction
        • Why Variance Matters
        • The Submission Schema: Enforcing Standards
        • Understanding SimpleMLP Parameter Counting
        • Why These Metrics?
        • Design Choice: Why num_runs=100?
        • Design Choice: Python Native Types
        • Understanding the Improvements Calculation
        Modules 01-13 → Optimization Suite (14-18) → Benchmarking (19) → Submission (20)
        (Framework)     (Performance Tools)            (Measurement)       (Results)

        The five ideas that took the Alaap project longest to learn

        If you remember nothing else:

        1. A suspiciously good or suspiciously bad number is a bug report about your setup. Recorded ~17 times here. Every single time.

        2. State the property before you read the result. Otherwise you will rationalise.

        3. An axis that fails to separate is a bug in the estimator until proven otherwise. Two "noise" axes turned out to be broken measurements.

        4. Effect size is not significance. A gap of 8 points with a standard error of 6 is nothing, and it will look like a finding.

        5. A metric is validated on a corpus, not in the abstract. Re-run the validation when the corpus, model, or codec changes.

        These are the three project skills in .claude/skills/, statistical-claims, speech-feature-pitfalls, listening-tests. Read them at week 1 and again at week 13; they will mean different things.

        Exit check A new result is suspiciously good. What do you do first?

        Show the answer

        Treat it as a bug report about the setup. Write down the property you expected before reading further, then check the measurement, the corpus and the comparison. The project recorded this about seventeen times, and each time it was the setup.