Module 01 · Part I · Foundations

Shapes and Linear Algebra

Scalars to Tensors, Matrix Multiplication by Hand, the Matrix Toolkit, Dot Products, Embeddings, Projections, and How Numbers Are Stored

By the end you can read any shape in the course, multiply matrices by hand, and explain what a projection keeps and throws away.

Builds onModule 0·
Check yourself ▸

Before you start, can you already…

  • ☐describe in one paragraph what happens between typing a prompt and seeing the next word, and know how to use the course. (Module 0)

If any is shaky, the linked module teaches it.

Open in Colab
5 Hours·Core·Foundational·0/7

A transformer is arithmetic on tables of numbers. This module gives you the toolkit to follow it: read a symbol such as and know what it holds, multiply matrices by hand, and say what a multiplication keeps and what it throws away.

1.1 Scalars, Vectors, Matrices, and TensorsRun this section

Everything a transformer reads, stores and produces comes in one of four arrangements, which differ in their number of : directions you can step along from one number to the next. Know a symbol's arrangement and the length of each axis, and you can follow most formulas before you know what they compute.

Scalar: One Number

A is a single number. It has no axes, because there is nothing to step along. The temperature that sets how random a model's output is (section 4.3), the step size used in training (section 2.4) and the loss that measures a model's error are all scalars. The course writes a scalar as a plain italic letter, and writes "xx is one real number" as x∈Rx \in \mathbb{R}.

Vector: A List

A is a list of numbers in a fixed order. It has one axis, and its length is how many numbers it holds:

x=[0.2, −1.7, 3.0, 0.5]∈R4\mathbf{x} = [0.2,\, -1.7,\, 3.0,\, 0.5] \in \mathbb{R}^{4}

Vectors are written in bold. The raised 44 is the length of the list, not a power. One index picks one entry: x3=3.0x_3 = 3.0 is the third number. The entry is written plain rather than bold because it is a scalar. Section 1.5 shows how every token of text becomes a vector like this one, only hundreds or thousands of numbers long.

Matrix: A Table

A matrix is a table of numbers with two axes, rows and columns. Take the three tokens of "the cat sat", give each a vector of four numbers, and stack the vectors as rows:

X=[0.2−1.73.00.51.10.4−0.32.2−0.60.91.50.0]∈R3×4X = \begin{bmatrix} 0.2 & -1.7 & 3.0 & 0.5 \\ 1.1 & 0.4 & -0.3 & 2.2 \\ -0.6 & 0.9 & 1.5 & 0.0 \end{bmatrix} \in \mathbb{R}^{3 \times 4}

A matrix's size is said rows first, so this is a "3 by 4" matrix holding 12 numbers. Matrices are written as capital letters. Two indices pick one entry, row first: X23=−0.3X_{23} = -0.3 is row 2, column 3. Row 2 on its own is the vector for "cat".

Some matrices hold data, like XX, one row per token. Others hold learned numbers, like the of section 1.6.

Tensor: A Stack of Tables

Add a third axis and you have a stack of matrices. A model processes several sentences at once, a , so the data entering a layer is a stack of matrices like XX, one per sentence:

X∈RB×N×dmodel\mathcal{X} \in \mathbb{R}^{B \times N \times d_{\text{model}}}

Here BB is the number of sentences in the batch, NN the number of tokens in each, and dmodeld_{\text{model}} the length of each token's vector. An array with any number of axes is called a tensor. Two sentences of three tokens with four numbers each make a 2 by 3 by 4 tensor, and multiplying the sizes gives the 24 numbers it holds. A color image is a tensor too: height by width by three color channels (section 25.2).

In code, torch.Tensor holds all four arrangements (a scalar has zero axes). In prose, "tensor" usually means three axes or more.

Figure 1.1
One number, a list, a table, a stack of tables

Choose how many axes the data has, change the sizes, and click any entry to see the indices that pick it out. In a stack, click a table’s edge or its b label to bring it forward.

Indices in the maths count from 1, as the course does. PyTorch counts from 0, so the same entry is one lower on every axis.
Predict, then try

A batch of 2 sentences, each 3 tokens long, each token 4 numbers. How many indices do you need to pick out one single number, and how many numbers does the whole tensor hold?

In words. The figure draws one boxed number, a row of boxes, a grid, and a stack of grids like sheets of paper; the depth of the stack is the third axis. Clicking a box shows the indices that reach it (none, one, two or three), and the readout multiplies the axis lengths to count the numbers.

Reading a Shape

The list of axis lengths is the shape. The course writes it as the raised part of R\mathbb{R}, and PyTorch prints it as a tuple from x.shape. Here are the four arrangements with sizes from GPT-2 Small, whose tokens are vectors of 768 numbers:

arrangementaxesexamplewrittenPyTorch shape
scalar0the loss()
vector1one tokenx∈R768\mathbf{x} \in \mathbb{R}^{768}(768,)
matrix2a sentence of NN tokensX∈RN×768X \in \mathbb{R}^{N \times 768}(N, 768)
tensor3a batch of BB sentencesX∈RB×N×768\mathcal{X} \in \mathbb{R}^{B \times N \times 768}(B, N, 768)

Sentences in a batch go through the same computation and never mix, so the course drops the batch axis and follows one sequence: attention in Module 6 works on an N×dmodelN \times d_{\text{model}} matrix, and the code puts BB in front of every shape.

The course counts indices from 1, as mathematics does. PyTorch counts from 0, so x3x_3 is x[2] in code and X23X_{23} is X[1, 2].

Some texts call the number of axes a tensor's "rank". This course reserves rank for something else (section 1.3) and says "number of axes".

1.2 Matrix Multiplication, Done by HandRun this section

Almost every line of a transformer is a matrix multiplication, so do one by hand until the rule is automatic.

Row ii of AA and column jj of BB, multiplied entry by entry and summed, give entry (i,j)(i, j) of ABAB. With nn the shared length:

(AB)ij=∑k=1nAikBkj(AB)_{ij} = \sum_{k=1}^{n} A_{ik} B_{kj}

The ∑\sum ("sum") lets kk run from 11 to nn and adds one term for each value. The row and column must pair up entry for entry, which is why the inner sizes have to agree.

Worked example. Multiply a 2 by 3 matrix by a 3 by 2 matrix: A=[120−103]A = \begin{bmatrix} 1 & 2 & 0 \\ -1 & 0 & 3 \end{bmatrix}, B=[210−114]B = \begin{bmatrix} 2 & 1 \\ 0 & -1 \\ 1 & 4 \end{bmatrix}. Entry (1,1)(1,1) is row 1 of AA with column 1 of BB: 1⋅2+2⋅0+0⋅1=21 \cdot 2 + 2 \cdot 0 + 0 \cdot 1 = 2. Entry (1,2)(1,2) is row 1 with column 2: 1⋅1+2⋅(−1)+0⋅4=−11 \cdot 1 + 2 \cdot (-1) + 0 \cdot 4 = -1. Entry (2,1)(2,1) is −1⋅2+0⋅0+3⋅1=1-1 \cdot 2 + 0 \cdot 0 + 3 \cdot 1 = 1, and entry (2,2)(2,2) is −1⋅1+0⋅(−1)+3⋅4=11-1 \cdot 1 + 0 \cdot (-1) + 3 \cdot 4 = 11. So AB=[2−1111]AB = \begin{bmatrix} 2 & -1 \\ 1 & 11 \end{bmatrix}, a 2 by 2 matrix.

Figure 1.2
Each entry of a product is one row times one column

Point at an entry of AB to see which row of A and which column of B make it. Edit any number in A or B and the product updates.

A is 2 × 3 and B is 3 × 2, so AB is 2 × 2. The inner size, 3, is the length of every row-column pairing.
Predict, then try

In the figure, before hovering, decide which row of AA and which column of BB produce the bottom-right entry of the result. Then check whether changing a number in the first row of AA can ever change the bottom row of the result.

In words. The figure shows two small editable matrices and their product. Pointing at an entry of the product highlights the row and column that produce it and spells out the sum.

Two facts follow. Order matters: ABAB and BABA usually differ, and often only one exists. And each row of ABAB depends on one row of AA only, so multiplying a one-token-per-row matrix by WW transforms every token separately, with the same WW.

What Operations Do to Shapes

Checking the shape of each output is the quickest way to follow a formula.

  • Entry by entry. Adding two tensors, or multiplying them entry by entry (), needs the same shape and keeps it.
  • By a scalar. Multiplying by a scalar scales every entry and keeps the shape.
  • Dot product. Two vectors of the same length give one scalar (section 1.4).
  • Along an axis. Summing or averaging along an axis removes it: the average of each row of XX is a vector of 3 numbers. Softmax (section 4.3) keeps the shape but also works along one axis, turning each row into probabilities separately.
  • Matrix multiplication. An mm by nn matrix times an nn by pp matrix needs the two inner sizes to agree, and gives an mm by pp matrix:
X⏟N×dmodel  W⏟dmodel×dk=Y⏟N×dk\underbrace{X}_{N \times d_{\text{model}}} \; \underbrace{W}_{d_{\text{model}} \times d_k} = \underbrace{Y}_{N \times d_k}

The shared dmodeld_{\text{model}} disappears: every token's dmodeld_{\text{model}} numbers become dkd_k numbers. That is the shape of every projection in section 1.6.

Worked example. Multiply the 3 by 4 matrix XX above by a 4 by 2 matrix WW. The inner sizes are both 4, so the product exists, and it is 3 by 2: three tokens, two numbers each. WW times XX is not defined at all, because a row of WW holds 2 numbers and a column of XX holds 3.

1.3 The Matrix ToolkitRun this section

These operations recur throughout the course; later sections use them without stopping.

Transpose

The A⊤A^\top swaps rows and columns: row ii of AA becomes column ii of A⊤A^\top, so a 3 by 2 matrix becomes 2 by 3, and (A⊤)ij=Aji(A^\top)_{ij} = A_{ji}. A row vector transposed is a column vector. One rule is used repeatedly: the transpose of a product reverses the order, (AB)⊤=B⊤A⊤(AB)^\top = B^\top A^\top.

Identity and Diagonal Matrices

The identity matrix II is square, with 1 on its diagonal (top-left to bottom-right) and 0 elsewhere. Like the number 1, it changes nothing: AI=IA=AAI = IA = A.

A diagonal matrix diag⁡(s)\operatorname{diag}(\mathbf{s}) has the entries of s\mathbf{s} on its diagonal and zeros elsewhere. On the right it scales each column of a matrix by one entry of s\mathbf{s}; on the left, each row. diag⁡(2,3)\operatorname{diag}(2, 3) doubles a vector's first entry and triples its second.

Inverse

The inverse A−1A^{-1} of a square matrix undoes it: A−1A=AA−1=IA^{-1}A = AA^{-1} = I. A matrix that squashes some direction to zero has none, because that information is gone. A diagonal matrix with no zeros is easy to invert: divide instead of multiply, so diag⁡(2,3)−1=diag⁡(12,13)\operatorname{diag}(2, 3)^{-1} = \operatorname{diag}(\tfrac{1}{2}, \tfrac{1}{3}). Sections 24.3 and 24.4 use this.

Element-Wise Product

The element-wise product A⊙BA \odot B multiplies entries in matching positions, so both matrices must have the same shape and the result does too. It is not matrix multiplication: [12]⊙[34]=[38]\begin{bmatrix} 1 & 2 \end{bmatrix} \odot \begin{bmatrix} 3 & 4 \end{bmatrix} = \begin{bmatrix} 3 & 8 \end{bmatrix}. Some papers write it ⊗\otimes.

Outer Product

For column vectors u\mathbf{u} (length mm) and v\mathbf{v} (length nn), the outer product uv⊤\mathbf{u}\mathbf{v}^\top is the mm by nn matrix with entry (i,j)=uivj(i, j) = u_i v_j. Every row is a multiple of v⊤\mathbf{v}^\top, so it is the simplest possible matrix. The reverse order, u⊤v\mathbf{u}^\top\mathbf{v}, is 1 by 1: the dot product. Sections 18.1 and 20.2 build matrices from sums of outer products.

Independent Directions and Rank

Vectors are linearly independent when none can be made by scaling and adding the others: [1,0,0][1, 0, 0] and [0,1,0][0, 1, 0] are, but [1,1,0][1, 1, 0] adds no new direction, being their sum. The of a matrix is the number of independent directions among its rows (equivalently, its columns), at most the smaller of its two sizes. Section 1.6 uses it to say how much of a token vector a projection keeps.

The Row-Vector Convention

This course writes a token's vector as a row (a 1 by dmodeld_{\text{model}} matrix), so a weight matrix multiplies it from the right: y=xW\mathbf{y} = \mathbf{x}W. PyTorch's nn.Linear stores the matrix transposed and computes xW⊤\mathbf{x}W^\top, the same thing. Sections 15.1 and 18.1 switch to column vectors, y=Rx\mathbf{y} = R\mathbf{x}, to match their papers, and say so.

1.4 Dot Products, Length, and AngleRun this section

Geometric Meaning of the Dot Product

The model compares two vectors with the (or inner product): multiply entry by entry and add. The same number is the product of the two lengths times the cosine of the angle between them.

⟨u,v⟩=u⊤v=∑i=1duivi=∥u∥2∥v∥2cos⁡(θ)\langle \mathbf{u}, \mathbf{v} \rangle = \mathbf{u}^\top \mathbf{v} = \sum_{i=1}^d u_i v_i = \|\mathbf{u}\|_2 \|\mathbf{v}\|_2 \cos(\theta)

∥u∥2\|\mathbf{u}\|_2 is the length of u\mathbf{u} (the square root of the sum of its squared entries) and θ\theta the angle between the vectors, which makes sense in any number of dimensions.

Architecture Flowchart
Diagram: Vector x_i; Dot product ⟨x_i, x_j⟩ = ||x_i|| · ||x_j|| · cos(θ); Vector x_j; Same direction (θ = 0°): cos = 1, largest positive score; Perpendicular (θ = 90°): cos = 0, score is zero; Opposite directions (θ = 180°): cos = −1, most negative score

In words. Vectors pointing the same way score high, perpendicular vectors score zero, and opposite vectors score negative. The angle sets the sign; the lengths set the size.

Perpendicular vectors are called orthogonal: neither has any component along the other.

Cosine Similarity vs. Unnormalized Dot Product

Divide out both lengths and only direction remains: cosine similarity, between −1-1 and 11.

CosineSim⁡(u,v)=u⊤v∥u∥2∥v∥2\operatorname{CosineSim}(\mathbf{u}, \mathbf{v}) = \frac{\mathbf{u}^\top \mathbf{v}}{\|\mathbf{u}\|_2 \|\mathbf{v}\|_2}

Attention uses the raw dot product, so a longer vector produces larger scores. Length becomes a second learned signal alongside direction, for example to make one token's scores sharper than another's. The cost is that raw dot products have no fixed range, which is why Module 2 scales them down.

1.5 Embeddings: From a Token to a VectorRun this section

A model cannot do arithmetic on text, so each (a word, part of a word, or a punctuation mark) becomes a vector of fixed length:

x∈Rdmodel\mathbf{x} \in \mathbb{R}^{d_{\text{model}}}

The length dmodeld_{\text{model}} is the model's width: 768768 in GPT-2 Small, 40964096 in LLaMA-3 8B and 12,28812{,}288 in GPT-3 175B, according to their published descriptions. Section 19.1 compares current models.

From Text to Vectors: The Embedding Lookup Walk-through

How "cat" becomes a vector of length dmodeld_{\text{model}}:

  1. Tokenization. A fixed dictionary, the VV, gives every token a whole-number ID from 00 to ∣V∣−1|V|-1, where ∣V∣|V| is the number of entries. Say "cat" gets ID 37973797.
  2. One-hot encoding. On paper, the ID can be written as a ei\mathbf{e}_i: a vector of length ∣V∣|V| that is 11 at position ii and 00 everywhere else.
  3. Row lookup. The WEW_E has one row per vocabulary entry and dmodeld_{\text{model}} columns (∣V∣×dmodel|V| \times d_{\text{model}}). The one-hot row ei⊤\mathbf{e}_i^\top times WEW_E picks out row ii, because every other row is multiplied by zero.
    x=ei⊤WE=WE[i,:]∈Rdmodel\mathbf{x} = \mathbf{e}_i^\top W_E = W_E[i, :] \in \mathbb{R}^{d_{\text{model}}}

Real code skips the multiplication and reads row ii straight from memory, which costs the same however large the vocabulary: , read "order one", meaning the cost does not grow with input size. In PyTorch this is nn.Embedding(vocab_size, d_model). The rows start random and are learned in , which nudges the model's numbers, its (or parameters), to make fewer mistakes on example text.

1.6 Linear Projections: One Vector Into ThreeRun this section

In attention, each token plays three roles: it looks for other tokens, it is found by them, and it hands information to those that find it. Rather than make one vector do all three jobs, the transformer makes three vectors from each token with three learned matrices:

qi=xiWQ(WQ∈Rdmodel×dk)\mathbf{q}_i = \mathbf{x}_i W^Q \quad (W^Q \in \mathbb{R}^{d_{\text{model}} \times d_k})
ki=xiWK(WK∈Rdmodel×dk)\mathbf{k}_i = \mathbf{x}_i W^K \quad (W^K \in \mathbb{R}^{d_{\text{model}} \times d_k})
vi=xiWV(WV∈Rdmodel×dv)\mathbf{v}_i = \mathbf{x}_i W^V \quad (W^V \in \mathbb{R}^{d_{\text{model}} \times d_v})

qi\mathbf{q}_i is the query, ki\mathbf{k}_i the key and vi\mathbf{v}_i the value of token ii. Each matrix reads dmodeld_{\text{model}} numbers and writes dkd_k or dvd_v, usually far fewer. Multiplying by such a matrix is a linear projection.

Architecture Flowchart
Diagram: Token vector x_i (length d_model); × W^Q; Query: what am I looking for?; × W^K; Key: what can I be found by?; × W^V; Value: what do I pass on?

In words. One token vector, three learned matrices: the query is what the token looks for, the key what it is matched on, and the value what it passes on.

Concrete Numerical Toy Example of Q, K, V Projections

Take dmodel=4d_{\text{model}} = 4, dk=dv=2d_k = d_v = 2, two tokens x1=[1.0, 0.0, 2.0, −1.0]\mathbf{x}_1 = [1.0, \, 0.0, \, 2.0, \, -1.0] and x2=[0.0, 1.0, 1.0, 1.0]\mathbf{x}_2 = [0.0, \, 1.0, \, 1.0, \, 1.0], and these learned matrices:

WQ=[10011−101],WK=[0110−1110]W^Q = \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ 1 & -1 \\ 0 & 1 \end{bmatrix}, \quad W^K = \begin{bmatrix} 0 & 1 \\ 1 & 0 \\ -1 & 1 \\ 1 & 0 \end{bmatrix}

Each output entry is the dot product of the input vector with one column of the matrix.

  1. Query for token 1. The first column of WQW^Q is [1,0,1,0][1, 0, 1, 0] and the second is [0,1,−1,1][0, 1, -1, 1]:
    q1=x1WQ=[1(1)+0(0)+2(1)−1(0),    1(0)+0(1)+2(−1)−1(1)]=[3.0, −3.0]\mathbf{q}_1 = \mathbf{x}_1 W^Q = [1(1) + 0(0) + 2(1) - 1(0), \;\; 1(0) + 0(1) + 2(-1) - 1(1)] = [3.0, \, -3.0]
  2. Key for token 2. The first column of WKW^K is [0,1,−1,1][0, 1, -1, 1] and the second is [1,0,1,0][1, 0, 1, 0]:
    k2=x2WK=[0(0)+1(1)+1(−1)+1(1),    0(1)+1(0)+1(1)+1(0)]=[1.0, 1.0]\mathbf{k}_2 = \mathbf{x}_2 W^K = [0(0) + 1(1) + 1(-1) + 1(1), \;\; 0(1) + 1(0) + 1(1) + 1(0)] = [1.0, \, 1.0]
  3. Raw score. Take the dot product of the query and the key:
    q1k2⊤=(3.0×1.0)+(−3.0×1.0)=3.0−3.0=0.0\mathbf{q}_1 \mathbf{k}_2^\top = (3.0 \times 1.0) + (-3.0 \times 1.0) = 3.0 - 3.0 = 0.0

The raw embeddings have dot product x1⋅x2=0+0+2−1=1\mathbf{x}_1 \cdot \mathbf{x}_2 = 0 + 0 + 2 - 1 = 1, but the query-key score is 00: the score depends on the learned matrices. Training adjusts WQW^Q and WKW^K until tokens that should attend to each other score high.

Rank and Projection Subspaces

A dmodel×dkd_{\text{model}} \times d_k matrix has rank at most dkd_k when dkd_k is smaller (section 1.3), so each projection keeps only a dkd_k-dimensional slice of the token vector, and each matrix can learn a different slice:

  • the query qi\mathbf{q}_i holds the features token ii is searching for;
  • the key kj\mathbf{k}_j holds the features token jj can be found by;
  • the score qikj⊤\mathbf{q}_i \mathbf{k}_j^\top is high when the two sets of features line up.

Module 6 turns these scores into attention.

Figure 1.6
A projection keeps one slice

Six token vectors, projected by two different matrices. Each keeps only the part of every vector that lies along its own direction; the strip under each plot is everything that survives.

Two dimensions projected to one, so it can be drawn. A real WQ maps dmodel numbers to dk numbers, keeping a dk-dimensional slice.
Predict, then try

Two tokens sit far apart in the plane. Can a projection onto a line ever put them on top of each other? Try to find a line that does it before you turn the controls.

In words. The figure projects six two-dimensional token vectors onto a query line and a key line. Each projection keeps only the part along its line, so distant tokens can land close together. Turning a line changes which tokens end up near each other, as training does when it adjusts W Q and W K.

1.7 How Numbers Are StoredRun this section

Each entry of a tensor has a . The standard is 32-bit floating point (fp32), 4 bytes per number. Large models usually train in 16-bit formats (bf16 or fp16, 2 bytes) and are often served in 8 bits or fewer (Module 24). A tensor's memory is entries times bytes per entry. GPT-2's token embedding matrix has 50,257 rows and 768 columns, which is 38,597,376 numbers: about 154 MB in fp32 and 77 MB in bf16.

Two kinds of tensor fill memory: the learned matrices, fixed while the model runs, and the , computed fresh from each input.

Every symbol and term is collected in the glossary.

Exercises

Check

What is the shape of XWXW when X∈R5×8X \in \mathbb{R}^{5 \times 8} and W∈R8×3W \in \mathbb{R}^{8 \times 3}? And is WXWX defined?

Apply

Compute entry (2,1)(2, 1) of ABAB for A=[1023−11]A = \begin{bmatrix} 1 & 0 & 2 \\ 3 & -1 & 1 \end{bmatrix} and B=[4025−11]B = \begin{bmatrix} 4 & 0 \\ 2 & 5 \\ -1 & 1 \end{bmatrix}.

Apply

Compute the cosine similarity of u=[3,4]\mathbf{u} = [3, 4] and v=[4,3]\mathbf{v} = [4, 3].

Apply

A projection matrix WQW^Q has shape 768×64768 \times 64. What is the largest rank it can have?

Apply

Use (AB)⊤=B⊤A⊤(AB)^\top = B^\top A^\top to write (xW)⊤(\mathbf{x}W)^\top for a row vector x\mathbf{x}, and say what shape it has when x\mathbf{x} is 1×41 \times 4 and WW is 4×24 \times 2.

Apply

An embedding table has 32,000 rows and 4,096 columns, stored in bf16 (2 bytes per number). How many megabytes (millions of bytes) does it take?

Extend

Explain, using the row-by-column rule, why multiplying a matrix of token vectors XX (one token per row) by a weight matrix WW never mixes information between tokens. Which operation in a transformer must therefore be responsible for moving information between tokens?

Core Academic References

  • Strang (2016): Introduction to Linear Algebra (5th ed.). Wellesley-Cambridge Press.
  • Golub & Van Loan (2013): Matrix Computations (4th ed.). Johns Hopkins University Press.
  • Mikolov et al. (2013): Efficient Estimation of Word Representations in Vector Space (word2vec). arXiv:1301.3781

Measured labs

These labs test what this module says by running real code. Each card states the idea, what the experiment found, and what it does not prove. The numbers come from experiments/results.json, the output of running experiments/run_all.sh on the tiny-transformers reference code at version 137f7ef. The project checks fail if a measured number in the module text stops matching that file.

Lab 1a — how big the reference model is

What the module says

Module 1 explains that a token embedding is a table lookup: each token id picks one row, a vector of dmodeld_{\text{model}} numbers. It also quotes parameter counts for large production models.

What the experiment found

The reference model has 112,323 parameters, which take 438.8 KiB when each is stored as a 32-bit float (fp32). That is small enough to inspect every weight yourself, which is the reason to study a model this size.

total parameters
112,323

2 blocks, dmodel=64d_{\text{model}}=64, feed-forward width dff=256d_{\text{ff}}=256, 2 attention heads

size on disk in fp32
438.8 KiB
vocabulary size
67

each token is one character, not a word piece

position table parameters
4,096

learned during training, not the fixed sine waves of section 7.1

characters of training text
1,059,620

What this does not prove

The two embedding tables (tokens and positions) hold 8,384 of the 112,323 parameters, about 7.5%. This lab counts parameters; it does not measure how the share changes in larger models, where the vocabulary and width are both far bigger.

Run it yourself

bash
cd tiny-transformers && .venv/bin/python experiments/parameter_count.py

The code being tested