This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

Notebooks · lib/nn

The pieces a transformer is made of

A transformer block is four things: a matrix multiply, a normalization, a pointwise nonlinearity, and a softmax. This module has the forward pass of each, and of the pieces around the blocks: the embedding lookup and the cross-entropy. Training needs each of them backwards as well, and that comes from value_and_grad over the forward pass; the tests check the gradient it generates for every piece against central differences on the forward, which is the only way to know a gradient is right.

The choices here follow the nanogpt speedrun rather than the 2017 paper, because that is what a fast implementation looks like now:

  • RMSNorm with no learnable gain. Divide each row by the root mean square of its entries. There is nothing to train and nothing to store.
  • ReLU squared instead of GELU. max(x, 0)^2. Its derivative is 2 max(x, 0), which is continuous, and it costs one compare and one multiply.
  • Linear layers with no bias. The bias is redundant after a normalization and it is one more thing to move.

A row of X is a token and a column is a feature, so X is T by D for a sequence of T tokens in D dimensions, or B by T by D for a batch of B sequences: every def works along the last axis (the features) or the last two (the positions and the features), and reads T and D from its arguments.

The backward passes written by hand before value_and_grad existed are in lib/nn_adjoints, kept as references: its tests hold them to the generated ones, and the study/idioms ports that write a backward pass by hand, to compare it with the generated one, call them.

Used with import nn.

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

This program declares a record type (AttentionCase), and records run only in compiled C for now, so the Run buttons here are off. Open it in the workbench and use its C tab to compile it.

Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.

[1]lines 37–392