Seyed Masoud Hosseini · Overview · Study log · Weekly summaries · Ideas · Search · Transcript · RSS feed
Neural Networks: Zero to Hero · Lecture 6 of 10 · 56:21
Lecture 6: Building a WaveNet
Study guide
What this lecture covers
The lecture answers how to make the makemore character-level model deeper without simply widening a single hidden layer. It replaces the flat multi-layer perceptron from earlier lectures with a hierarchical, tree-like architecture that progressively fuses pairs of characters, arriving at something structurally similar to DeepMind's WaveNet. It follows directly from the MLP and BatchNorm work in the earlier makemore lectures (the manual backprop lecture is treated as a self-contained aside).
Along the way, the existing custom layers (Linear, BatchNorm1d, Tanh) are reorganized into reusable, PyTorch-like building blocks, including new Embedding and FlattenConsecutive modules and a Sequential container. After watching, you can explain why context is fused gradually instead of all at once, restructure a flat network into a hierarchical one, and recognize a subtle BatchNorm bug that appears when moving from two-dimensional to three-dimensional tensors.
Key ideas
- Progressive fusion: instead of flattening all context characters into one big vector before the first layer, WaveNet-style architectures fuse two characters at a time, then pairs of pairs, and so on, preserving structure longer.
- PyTorch-like containers: a custom
Sequentialmodule holds a list of layers and applies them in order, mirroringtorch.nn.Sequential. - Matrix multiply over extra batch dimensions: PyTorch's matmul operates on the last dimension and treats all leading dimensions as batch dimensions, which is what makes grouped, parallel processing of character pairs possible.
FlattenConsecutive: a custom layer that reshapes(B, T, C)into(B, T/n, C*n), fusingnconsecutive elements into the last dimension instead of flattening everything at once.- BatchNorm dimensionality bug: applying the two-dimensional BatchNorm implementation to three-dimensional input silently computes per-position statistics instead of per-channel ones; fixing it means reducing over dimensions
(0, 1)instead of just0. - Model state and bugs: forgetting to set a layer's
trainingflag correctly, or leaving a module in a stale mode, can silently corrupt results, as shown when a single-example forward pass hits BatchNorm in training mode. - Convolutions as an efficiency trick: sliding this same tree structure over an input sequence using convolutions computes the same result as looping in Python, but faster, because it reuses shared intermediate nodes and moves the loop into fast kernels.
Walkthrough
Intro and motivation (0:00)
The lecture explains the goal: take more than three characters of context and process them through a deeper network that fuses information gradually, rather than squashing everything into one hidden layer at once. This is connected to the 2016 WaveNet paper's hierarchical, tree-like prediction structure.
Starter code walkthrough (0:01:40)
The code picks up from the earlier MLP lecture, reusing the custom Linear, BatchNorm1d, and Tanh layer classes built to mimic torch.nn's API. The dataset and initial training loop are unchanged, reaching a validation loss around 2.10.
Fixing the loss plot and simplifying the forward pass (0:06:56)
The noisy per-step loss plot is smoothed by reshaping the loss list into rows and averaging. The embedding lookup and the flattening/concatenation step are then extracted into dedicated Embedding and Flatten modules so the entire forward pass becomes a single call through a Sequential model.
Pytorchifying the code: layers, containers, and a bug (0:09:16)
After introducing the Sequential container, a bug appears: sampling from the model with a single example produces gibberish because BatchNorm was left in training mode and computed a variance over one example, which is undefined. The fix highlights how easy it is to introduce bugs by not tracking a layer's train/eval state.
Implementing the WaveNet-style architecture (0:21:36)
The context length is increased from 3 to 8 characters. A naive flat model with the larger context already improves validation loss to about 2.02. The lecture then builds the FlattenConsecutive layer, which reshapes (B, T, C) into (B, T/n, C*n) by fusing n consecutive character embeddings, and stacks multiple Linear, BatchNorm1d, Tanh blocks with this flattening between them to build the tree-like structure, matching parameter count to the earlier flat model for a fair comparison.
Fixing the BatchNorm1d bug for 3D inputs (0:38:50)
Once the network processes three-dimensional tensors, the existing BatchNorm1d computes per-position statistics (1 x 4 x 68) instead of per-channel statistics, because it only reduces over dimension 0. The fix reduces over dimensions (0, 1) when the input is three-dimensional, correctly treating both the batch and the group position as batch dimensions. Retraining with the fix gives a small improvement, from 2.029 to 2.022.
Scaling up and final results (0:46:07)
Increasing embedding size and hidden units within the same hierarchical architecture pushes validation loss down to about 1.993, though the lecture notes there is no systematic experimental harness yet, only manual guessing and checking.
Convolutions, torch.nn, and the development process (0:47:44)
The lecture connects the hand-built tree structure to convolutions: a convolution slides the same small network across an input sequence and reuses shared intermediate computations, which is what makes it efficient compared to independently forwarding every position. It closes with reflections on the deep learning development process (prototyping in notebooks, wrestling with tensor shapes, PyTorch's inconsistent documentation) and previews future topics: dilated causal convolutions, residual and skip connections, and recurrent architectures.
Before you watch
- Complete the earlier makemore MLP lecture that builds the
Linear,BatchNorm1d, andTanhlayers and the initial two-layer network, since this lecture's starter code builds directly on it. - Be comfortable with BatchNorm's training/eval mode distinction and running statistics from that lecture.
- Familiarity with
torch.viewand broadcasting rules will help with the shape reasoning throughout.
Check your understanding
- Why does fusing two characters at a time, rather than flattening all context characters immediately, allow the network to be made deeper productively?
- What change does
FlattenConsecutivemake to the tensor shape, and how does it differ from the originalFlattenlayer? - Why did the two-dimensional
BatchNorm1dimplementation silently produce incorrect per-position statistics once the input became three-dimensional, and what dimensions does the fix reduce over? - What caused the single-example sampling bug, and why does it relate to BatchNorm specifically?
- In what sense does a convolution over a sequence compute the same result as looping over each position with the tree-structured model, only faster?
Vocabulary
- hierarchical (adjective)
- Organized in levels, where smaller parts combine step by step into bigger ones.
The WaveNet-style network uses a hierarchical structure to process characters. - fuse (verb)
- To combine two or more things into one.
The network fuses pairs of characters before fusing pairs of pairs. - tree-structured (adjective)
- Arranged like a tree, with items branching and combining at each level.
The architecture is tree-structured rather than a single flat layer. - container (noun)
- An object that holds and organizes other components together.
Sequential is a container that runs its layers one after another. - module (noun)
- A reusable, self-contained piece of code that performs one job in a network.
Embedding and FlattenConsecutive are new custom modules. - batch dimension (noun)
- The dimension of a tensor that lists separate, independent examples.
Matmul treats extra leading dimensions as batch dimensions. - flatten (verb)
- To collapse a tensor's separate dimensions into a single one.
FlattenConsecutive fuses neighboring characters instead of flattening everything at once. - silently (adverb)
- Without giving any warning or error, even though something is wrong.
The old BatchNorm code silently computes the wrong statistics on 3D input. - training mode (noun)
- A network setting where layers like batchnorm use the current batch's own statistics.
Leaving the model in training mode broke the single-example sampling. - eval mode (noun)
- A network setting where layers use fixed, previously stored statistics instead of the current batch.
The model must be switched to eval mode before sampling one example. - gibberish (noun)
- Text or output that makes no sense at all.
The bug caused the model to sample gibberish. - convolution (noun)
- An operation that slides a small pattern-matching filter across an input.
A convolution can slide the same small network across the whole sequence. - dilated (adjective)
- Spread out with gaps between the positions a filter looks at.
Dilated causal convolutions are previewed as a future topic. - causal (adjective)
- Only depending on earlier positions, never on later ones.
A causal convolution never looks ahead at future characters. - skip connection (noun)
- A shortcut path in a network that lets information bypass some layers.
Skip connections are mentioned as a future architecture improvement. - kernel (noun)
- A fast, low-level routine that a library runs to perform a computation.
Convolutions move the loop into fast kernels instead of Python. - reflections (noun)
- Thoughtful comments looking back on what was learned or experienced.
The lecture closes with reflections on the messy development process. - validation loss (noun)
- The error measured on data the model was not trained on.
The validation loss dropped after fixing the BatchNorm bug. - parameter count (noun)
- The total number of learnable values in a model.
The hierarchical model matches the flat model's parameter count for a fair comparison. - smoothing (verb)
- Making a noisy plot easier to read by averaging nearby values.
Smoothing the loss plot makes the training trend clearer. - documentation (noun)
- Written material explaining how to use a piece of software.
The lecture complains about PyTorch's inconsistent documentation.
Chapters
- 0:00 intro
- 1:40 starter code walkthrough
- 6:56 let’s fix the learning rate plot
- 9:16 pytorchifying our code: layers, containers, torch.nn, fun bugs
- 17:11 overview: WaveNet
- 19:33 dataset bump the context size to 8
- 19:55 re-running baseline code on block_size 8
- 21:36 implementing WaveNet
- 37:41 training the WaveNet: first pass
- 38:50 fixing batchnorm1d bug
- 45:21 re-training WaveNet with bug fix
- 46:07 scaling up our WaveNet
- 46:58 experimental harness
- 47:44 WaveNet but with “dilated causal convolutions”
- 51:34 torch.nn
- 52:28 the development process of building deep neural nets
- 54:17 going forward
- 55:26 improve on my loss! how far can we improve a WaveNet on this data?
From the YouTube description
We take the 2-layer MLP from previous video and make it deeper with a tree-like structure, arriving at a convolutional neural network architecture similar to the WaveNet (2016) from DeepMind. In the WaveNet paper, the same hierarchical architecture is implemented more efficiently using causal dilated convolutions (not yet covered). Along the way we get a better sense of torch.nn and what it is and how it works under the hood, and what a typical deep learning development process looks like (a lot of reading of documentation, keeping track of multidimensional tensor shapes, moving between jupyter notebooks and repository code, ...).
Links:
- makemore on github: https://github.com/karpathy/makemore
- jupyter notebook I built in this video: https://github.com/karpathy/nn-zero-to-hero/blob/master/lectures/makemore/makemore_part5_cnn1.ipynb
- collab notebook: https://colab.research.google.com/drive/1CXVEmCO_7r7WYZGb5qnjfyxTvQa13g5X?usp=sharing
- my website: https://karpathy.ai
- my twitter: https://twitter.com/karpathy
- our Discord channel: https://discord.gg/3zy8kqD9Cp
Supplementary links:
- WaveNet 2016 from DeepMind https://arxiv.org/abs/1609.03499
- Bengio et al. 2003 MLP LM https://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf
Chapters:
intro
00:00:00 intro
00:01:40 starter code walkthrough
00:06:56 let’s fix the learning rate plot
00:09:16 pytorchifying our code: layers, containers, torch.nn, fun bugs
implementing wavenet
00:17:11 overview: WaveNet
00:19:33 dataset bump the context size to 8
00:19:55 re-running baseline code on block_size 8
00:21:36 implementing WaveNet
00:37:41 training the WaveNet: first pass
00:38:50 fixing batchnorm1d bug
00:45:21 re-training WaveNet with bug fix
00:46:07 scaling up our WaveNet
conclusions
00:46:58 experimental harness
00:47:44 WaveNet but with “dilated causal convolutions”
00:51:34 torch.nn
00:52:28 the development process of building deep neural nets
00:54:17 going forward
00:55:26 improve on my loss! how far can we improve a WaveNet on this data?
← Lecture 5: Becoming a Backprop Ninja · Lecture 7: Let's Build GPT From Scratch →
