← All notes

Pretraining

Pretraining teaches the model what the world and language look like.

Suppose the training text is “The capital of France is Paris.” This gets preprocessed into training examples:

  1. Input: “The” → Target: “capital”
  2. Input: “The capital” → Target: “of”
  3. Input: “The capital of” → Target: “France”

The loss is

L=tlogpθ(xtx<t)L = -\sum_t \log p_\theta(x_t \mid x_{<t})

To see where this comes from, suppose the training text is “The cat sat.” The model sees:

"The"     → predict "cat"
"The cat" → predict "sat"

At each position, the model outputs a probability distribution over all possible next tokens. For example:

ContextTrue next tokenModel probability
”The”cat0.9
”The cat”sat0.8

The probability the model assigns to the entire sequence is

pθ(x1,x2,,xT)=t=1Tpθ(xtx<t)p_\theta(x_1, x_2, \dots, x_T) = \prod_{t=1}^T p_\theta(x_t \mid x_{<t})

Using the chain rule,

p("The cat sat")=p(catThe)×p(satThe cat)=0.9×0.8=0.72p(\text{"The cat sat"}) = p(\text{cat} \mid \text{The}) \times p(\text{sat} \mid \text{The cat}) = 0.9 \times 0.8 = 0.72

Pretraining tries to make the training text as probable as possible: maximize pθ(training data)p_\theta(\text{training data}).

Why we take logs

Since the probability of an entire sequence is a product,

p=p(x1)p(x2x1)p(x3x1,x2)p = p(x_1)\, p(x_2 \mid x_1)\, p(x_3 \mid x_1, x_2) \cdots

this is inconvenient: derivatives are messy, and probabilities become tiny very quickly. Instead we take the logarithm. Since log(ab)=loga+logb\log(ab) = \log a + \log b,

logp(sequence)=tlogp(xtx<t)\log p(\text{sequence}) = \sum_t \log p(x_t \mid x_{<t})

and we optimize a sum instead of a product. This helps for two reasons:

Taking the log doesn’t change the objective, because the logarithm is monotonically increasing: if a>ba > b then loga>logb\log a > \log b, so the sequence with the highest probability also has the highest log probability.

From log-likelihood to loss

Maximizing ff is mathematically identical to minimizing f-f, and frameworks like PyTorch, TensorFlow, and JAX expect you to provide a scalar loss and then compute its gradient to minimize it. So instead of “maximize log likelihood” we say “minimize negative log likelihood”; they are the same optimization problem. So instead of

maxθtlogpθ(xtx<t)\max_\theta \sum_t \log p_\theta(x_t \mid x_{<t})

we define

L=tlogpθ(xtx<t)L = -\sum_t \log p_\theta(x_t \mid x_{<t})

Suppose the true next token is “cat”: