Concepts / Temperature and Token Sampling

Temperature and Token Sampling

The output dimension equals vocab_size. Each logit is a score attached to one vocabulary token, indexed by its position in that final dimension.

  • Programming
Interactive lab

Try it: Text Vectorization: Tokens to Vectors

The text-to-tensor pipeline: standardize, split into tokens, build a frequency-ranked vocabulary with padding and [UNK], map tokens to integer ids, pad or truncate, then one-hot or multi-hot encode and look the ids up in an embedding table.

How it works

  1. Standardize: lowercase and delete punctuation.
  2. Split on whitespace into tokens.
  3. Build the vocabulary: 0 = padding, 1 = [UNK], then words by frequency (ties: first appearance), capped at max tokens.
  4. Map each token to its id (1 if it did not make the vocabulary), then pad with 0 or truncate to the sequence length.
  5. Encode: one-hot rows per position or one multi-hot row per text; embed: id k selects row k of the embedding table.

Default run (18 steps): Raw text (59 characters): "The movie was great. The plot was great, the acting wasn't!". A model cannot read strings, so it is turned into numbers step by step. … Embedding lookup: id k selects row k of a fixed 8 x 3 table, giving a (8, 3) dense matrix instead of (8, 8) sparse one-hots. Row 0 (padding) is looked up too; a trained Embedding layer would learn these rows.

Simplified: Bounded ASCII text (up to 200 characters, 40 tokens), whitespace splitting only, and a small FIXED embedding table (a real Embedding layer learns its rows). The multi-hot vector keeps the padding slot (always 0) so its positions line up with the ids.

Educational simulation

Loading the simulation…

Predicting What Temperature Does

A GPT model does not simply announce the next word. It produces a score for every token in its vocabulary, and then a token is chosen from those scores by sampling. The setting that controls how that choice is made is called temperature. This article follows the path from raw token indices to the scores the model produces, and then to the counts that come out of sampling. Work through it in the order given, because each stage consumes the output of the stage before it.

What do you think happens?

The token 'pizza' is sampled many times from the same model. If you repeat the sampling with temperature set to 0 or 0.1, and then again with temperature set to 5, how many times do you expect 'pizza' to be sampled in each case?

  • About the same count in both cases

  • Zero in the low-temperature runs and many times in the temperature 5 run

  • Many times in the low-temperature runs and zero at temperature 5

Reveal answer
Answer:

Zero times at temperature 0 or 0.1, and 32 times at temperature 5.

Raising the temperature changes the distribution from which tokens are sampled, so a token that is never picked at low temperature can be picked often at high temperature. Keep this result in mind; the rest of the article explains how it arises.

Three Main Parts of a GPT Model

A GPT model is built from three main parts: an embedding stage, a sequence of transformer blocks run with nn.Sequential, and a linear output head with no bias. The embedding stage turns token indices into vectors. The transformer blocks process those vectors. The output head converts the processed vectors into logits, which are the raw scores for each vocabulary entry. The GPTModel class is a PyTorch module, and all three parts are attributes of it. The diagram below shows how they sit inside the whole model.

GPTModelEmbedding stagetoken and positionalembeddings, then dropouttok_embTransformer blocksrun with nn.Sequentialpos_embOutput headfinal normalization, thenlinear layer with no biasLogitscontainscontainscontainstoken partposition partproduces
Which components sit inside GPTModel, and how the embedding stage, the transformer block stack, and the output head relate to one another as parts of the whole.

The embedding stage has two lookups that are later added together. The token embedding represents which tokens appear. The positional embedding represents where in the sequence they appear. The transformer blocks are not a single layer but a stack of identical-shaped blocks, and the source builds that stack in one line. The output head is the last part, and it is the only part that produces the scores used for sampling.

Building the Transformer Block Stack

The source builds the sequence of transformer blocks in a single expression. It creates one TransformerBlock for each layer, using the count stored under the n_layers key of the configuration dictionary, and wraps the blocks in nn.Sequential. Wrapping them this way means they run one after another, so the output of the first block becomes the input of the second, and so on. You do not need to call each block by hand inside forward; the sequential container handles the ordering.

python
Notes on the code
  • The count comes from the n_layers entry of the configuration dictionary.
  • One TransformerBlock is created for each layer.
  • nn.Sequential runs the blocks in order, each consuming the previous block's output.

Tracing the Forward Method

The forward method is where an input of token indices becomes a set of output scores called logits. Read it as a pipeline. For each stage, ask three questions: what does this line receive, what does it produce, and which part of the GPT model does it belong to. The diagram below traces the input named in_idx from the embedding stage to the logits.

in_idxtoken indices, shape readas batch size and sequencelengthtok_emb applied toin_idxtoken embeddingsAdd the twoembeddingsEmbedding dropoutTransformer blocksrun with nn.SequentialFinal normalizationOutput headlinear layer with no biasLogitsreturned by forwardpos_emb overarange(seq_len)positional embeddingsindices inlength onlytoken partposition partsumembeddingsprocessed vectorsnormalized vectorsscores
What happens to the token-index tensor at each step as it moves from the embedding stage through the transformer blocks to the output head, and what kind of data it holds at each point.
Worked example

Following the shape of in_idx

Suppose in_idx holds a batch of 2 sequences, each with 4 token indices. Trace what each stage receives and produces.

  1. 1
    Read the input

    The shape of in_idx gives batch size 2 and sequence length 4. The input is a grid of token indices, one row per sequence.

  2. 2
    Token embeddings

    self.tok_emb is applied to in_idx. Each index is replaced by its embedding vector, so the result has an extra embedding dimension while keeping the batch and sequence structure.

  3. 3
    Positional embeddings

    torch.arange produces the integers from 0 up to the sequence length, which is 4 here. self.pos_emb turns those positions into vectors. This part depends only on the length of the input, not on which tokens appear.

  4. 4
    Add and drop out

    The token and positional results are added together. The sum passes through the embedding dropout layer and then into the transformer blocks.

  5. 5
    Normalize and project

    After the blocks, the final normalization layer runs, and then the output head projects each embedding to a vector with one entry per vocabulary token. forward returns this as logits.

Result

The logits keep the batch and sequence structure of the input, and the final dimension holds one score per vocabulary entry. Note that this is a generated example illustrating the stated order of stages; the sizes 2 and 4 are chosen for illustration.

Why the Output Head Has No Bias

The phrase with no bias is part of the definition of the output head. The layer is created with bias set to False, so it only applies a weight matrix to its input. It has no added offset term. A learner reading the constructor should note this explicitly, because a bias term would change the arithmetic of every output score. Without a bias, each score is produced purely by the weight matrix acting on the embedding, with nothing added on top.

Best practice

When you read a layer constructor, check its arguments explicitly. A flag such as bias set to False changes the computation, so treat it as part of the definition of the component rather than a minor setting.

Output Dimension as Vocabulary Scores

The output head maps each embedding to a vector whose size is vocab_size. That means each position in the sequence receives one score per vocabulary entry. The final dimension of the logits is therefore a lookup: position number k in that dimension corresponds to one specific token in the vocabulary, and the value stored there is the score for that token. Reading the logits this way lets you treat each entry as a score for one token, which is exactly what sampling needs.

Key point

The output dimension equals vocab_size. Each logit is a score attached to one vocabulary token, indexed by its position in that final dimension.

Estimating Probability from Sample Counts

Once the model has produced scores, a token is chosen by sampling. Each time a token is drawn it adds one to that token's count. If you draw N samples in total and a particular token was drawn c times, then c divided by N is an estimate of that token's probability: $\frac{c}{N}$. The estimate improves as N grows, but it is still an estimate. A count from 1000 draws is a sample-based estimate, and it is not the same thing as reading the probability directly from the distribution. Keeping both numbers in view helps you see the difference between what was sampled and what the distribution holds.

Worked example

Turning a count into a probability estimate

Suppose 100 draws are taken from the same distribution, and the token 'pizza' appears 32 times. Estimate its probability.

  1. 1
    Identify the count

    The token was drawn c = 32 times out of N = 100 draws.

  2. 2
    Divide by the total

    Compute $\frac{32}{100}$, which equals 0.32.

  3. 3
    Interpret the estimate

    The sampled frequency suggests a probability near 0.32 for this draw. Repeating with more draws would refine the estimate, and a different set of 100 draws could give a somewhat different count.

Result

The estimate is 0.32. This is a generated illustration using hypothetical numbers, not a value taken from the source.

How Temperature Reshapes the Counts

Temperature changes the probability distribution from which tokens are sampled. A higher temperature increases how often certain tokens are sampled. The source makes this concrete with the token 'pizza'. At temperature 0 or 0.1, 'pizza' is sampled zero times. When the temperature is scaled up to 5, it is sampled 32 times. The counts come from the print_sampled_tokens function that the source defines in an earlier section, which is the function to use if you want to reproduce these numbers yourself.

pizzatemperature 0 or 0.1pizzatemperature 50 samples32 samplesraise temperature
How the number of times 'pizza' is sampled changes when the temperature moves from a low setting to 5.

The before and after counts show that a token with no samples under a low temperature can accumulate many samples under a higher one. The source does not give the full distribution at each temperature, so the important lesson is the direction of the change: raising temperature shifts sampling toward tokens that were rarely picked before.

Mistakes Learners Make with Sampling Counts

  • Common mistake

    Treating a sampled count as the exact probability

    What it looks like

    Seeing 32 samples out of 100 and concluding the probability is exactly 32 percent.

    Why it fails

    A count from a finite number of draws is a sample-based estimate. Another run of the same number of draws can give a different count.

    Do this instead

    Describe the result as an estimate, and draw more samples if you need a more stable number.

  • Common mistake

    Assuming the positional part depends on the token values

    What it looks like

    Expecting the positional embeddings to change when the same positions hold different tokens.

    Why it fails

    The source builds the positional embeddings from torch.arange over seq_len, which is read from the input shape. They depend only on sequence length.

    Do this instead

    Attribute changes in the token part to token identity and changes in the positional part to sequence length.

  • Common mistake

    Ignoring the bias argument in the output head

    Why it fails

    With bias set to False, the layer applies only a weight matrix. Adding a bias would change the arithmetic of every output score.

    Do this instead

    Read the constructor arguments as part of the definition of the layer.

  • Common mistake

    Reading the logits as a list of token names

    Why it fails

    The logits are numbers. Each position in the final dimension corresponds to one vocabulary token, and the stored value is the score for that token.

Checking Your Reading of forward

EASY

Without looking back, write the order of the stages that in_idx passes through inside forward, from the first step to the returned value. Then say which stage is responsible for the positional part and which is responsible for the scores that sampling uses.

Hints
  • Start from the token and positional embeddings and their addition.
  • The final stage before the return is the output head.
  • The output head is the only stage that produces the logits.
MEDIUM

Suppose a temperature 5 run shows a token sampled 32 times and a temperature 0.1 run shows the same token sampled 0 times. In one or two sentences, explain why the count changes, referring to the distribution from which tokens are sampled rather than to the token itself.

Hints
  • Temperature affects the distribution, not the stored token name.
  • Think about which tokens a higher temperature makes more likely to be picked.

Key Takeaways

  • A GPT model has three main parts: an embedding stage, a sequence of transformer blocks run with nn.Sequential, and an output head that is a linear layer with no bias.
  • The forward method takes in_idx, adds token and positional embeddings, applies dropout, runs the transformer blocks, normalizes, and projects to logits using the output head.
  • The output head maps each embedding to a vector of size vocab_size, so each logit is a score for one vocabulary entry.
  • A token's probability can be estimated as its sample count divided by the total number of draws, and this is an estimate rather than an exact value.
  • Raising temperature changes the sampling distribution; in the source example, 'pizza' goes from 0 samples at temperature 0 or 0.1 to 32 samples at temperature 5.

Related concepts

More concepts starting with T