Concepts / Evaluating a Loaded GPT Model

Evaluating a Loaded GPT Model

BASE_CONFIG holds the shared GPT-2 settings, and BASE_CONFIG.update copies the chosen size's emb_dim, n_layers, and n_heads into it.

  • Programming

Predicting the Length of a Generated Output

A GPT model that has been loaded with pretrained weights is not finished until you have checked that it runs and produces the output you expect. One of the simplest checks is to ask the model to continue a short piece of text and then examine what comes back. This article follows one such run from start to finish. The program is executed, its printed result is shown, and then each part of that result is traced back to the code that produced it.

Before you read on, try to predict something concrete. The generation call receives four input tokens and is asked to generate six new tokens. How long will the returned sequence of output token IDs be?

What do you think happens?

The input has 4 tokens and max_new_tokens is 6. How many token IDs does the output contain?

  • 6

  • 4

  • 10

  • 24

Reveal answer
Answer:

10

The reported output length equals the 4 input tokens plus the 6 newly generated tokens. The returned sequence therefore contains 10 token IDs, and that total is a useful checkpoint when you debug a run.

The Configuration Dictionary Before and After the Update

The model's settings begin in a dictionary named BASE_CONFIG. This dictionary holds the four settings that describe the GPT-2 model and that are shared by every GPT-2 size. The vocab_size entry is 50257. The context_length entry is 1024. The drop_rate entry is the dropout rate, and it is set to 0.0 here. The qkv_bias entry is True, which sets the query-key-value bias. Because these four values do not change from one size to another, they live in a base dictionary that every size can use.

The four base settings do not describe a particular size. The size-specific values are stored separately, in a second dictionary named model_configs. Each key in model_configs is a model name such as gpt2-medium (355M), and each value gives the emb_dim, n_layers, and n_heads for that model. The line BASE_CONFIG.update(model_configs[CHOOSE_MODEL]) copies the three size-specific entries of the chosen model into BASE_CONFIG. After that line runs, one dictionary holds both the shared settings and the settings for the chosen size.

What do you think happens?

After BASE_CONFIG.update(model_configs[CHOOSE_MODEL]) runs, which keys does BASE_CONFIG contain?

Reveal answer
Answer:

The four shared keys (vocab_size, context_length, drop_rate, qkv_bias) plus the three size-specific keys (emb_dim, n_layers, n_heads) copied from the chosen entry.

The update call adds the chosen size's emb_dim, n_layers, and n_heads to the dictionary that already holds the shared settings. Afterwards one dictionary holds both kinds of setting.

Deriving the Short Model Size Name

The download step needs a short model size string, but the CHOOSE_MODEL variable holds a longer name that includes the parameter count in parentheses. The source derives model_size from CHOOSE_MODEL with one chained expression, which splits the name on spaces and strips the parentheses. For the medium model, this produces 355M.

Worked example

Tracing model_size for the Medium Model

CHOOSE_MODEL holds the name gpt2-medium (355M). What value does model_size receive?

  1. 1
    Start with the full name

    The variable holds the string gpt2-medium (355M), which contains a space and a parenthesized parameter count.

  2. 2
    Split on spaces

    Splitting on the space separates the name into two pieces: gpt2-medium and (355M).

  3. 3
    Keep the parameter count piece

    The parameter count is the second piece, (355M), which still has its parentheses.

  4. 4
    Strip the parentheses

    Removing the parentheses leaves 355M, which is the short string the download step needs.

Result

model_size is 355M.

The value 355M is then passed to download_and_load_gpt2 as model_size, together with models_dir set to gpt2. That call returns two values, named settings and params. The weight-loading step that follows uses params, which holds the pretrained parameters.

Building the Model and Loading Its Weights

Loading pretrained GPT-2 weights is a two-part job. A GPT model is built from a set of settings, and the pretrained weights are stored values that were produced for a specific model shape. First you create a GPT model object with the right settings, and then you pass the pretrained parameters into that object. The listing does this in two lines. The first line, model = GPTModel(BASE_CONFIG), creates a GPT model instance from the merged configuration. The second line, load_weights_into_gpt(model, params), takes that instance and the pretrained parameters and loads the weights into the model.

The order of these lines matters. The model must exist before the second line runs, because load_weights_into_gpt receives the model object as its first argument. The configuration and the downloaded parameters are two separate inputs. The model is created from the configuration alone, and the loading function is the point where the two inputs meet.

Merged BASE_CONFIGshared plus size settingsGPTModel(BASE_CONFIG)model instance createdparamsfrom download_and_load_gpt2load_weights_into_gptmodel plus paramsmodel.eval()last statement in thelistingcreatesmodel argumentparams argumentthen
What is the sequence from the merged configuration to the loaded model, and which step must come before which?

The same model object passes through three states in the listing. It starts as a GPT model built from BASE_CONFIG. The loading call changes it so that it holds the pretrained weights. The final line, model.eval(), is the last statement in the listing. The source does not explain what that line does in the loading listing, so this article covers evaluation mode separately in the next section.

Generating Text and Reading the Output Tokens

The generation step is a single call to generate_text_simple. The function receives four things. It receives the model. It receives an encoded input tensor named idx, which holds the starting tokens. It receives a limit of 6 new tokens through max_new_tokens. It receives a context size, taken from the model configuration as its context length. Each argument answers a separate question: which model to use, what the starting tokens are, how far to continue, and how much preceding text the model may look at.

The function returns output token IDs, not readable words. The reported output length of 10 equals the 4 input tokens plus the 6 newly generated tokens. Each step of the run adds one token to the sequence, so the length grows from 4 to 10 over six steps.

Input tokenslength 4Step 1length 5Step 2length 6Step 3length 7Step 4length 8Step 5length 9Step 6length 10+1 token+1 token+1 token+1 token+1 token+1 token
How does the output sequence grow by one token per step, and at which step would an unexpected length first appear?

Evaluation Mode and What Dropout Does

Before generating anything, the model is placed into evaluation mode by calling model.eval(). The source describes this as the switch that disables random components such as dropout. Dropout is a training-time mechanism, so it is only used while the model is learning. When the model is only being run to produce output, that randomness is not wanted, and evaluation mode turns it off.

AspectTraining modeEvaluation mode (model.eval())
Purpose of the runThe model is learning from dataThe model is only producing output
DropoutUsed as a training-time mechanismDisabled, so the random component is turned off
Use in this articleNot run hereSet before generate_text_simple is called

Training mode and evaluation mode compared for dropout

Where to Look When Results Diverge

When a loaded model does not match what you expected, the fastest route is to ask which line of the listing first produced a value you did not expect. Each line depends on the ones above it, so the earliest wrong value usually points to the real cause. The mistakes below follow the order of the listing.

  • Common mistake

    Assuming the update call replaces the shared settings

    What it looks like
    Expecting vocab_size or context_length to change after BASE_CONFIG.update(model_configs[CHOOSE_MODEL]) runs.
    Why it fails

    The update copies the size-specific entries into BASE_CONFIG, and the four shared settings are part of the same dictionary.

    Do this instead

    Check the dictionary before and after the update call and confirm that the shared keys are still present.

  • Common mistake

    Passing the full model name where the short size is needed

    What it looks like

    Using gpt2-medium (355M) directly as model_size instead of the short string 355M.

    Why it fails

    The download step needs the short size string, which is derived from CHOOSE_MODEL by splitting on spaces and stripping parentheses.

    Do this instead

    Trace the chained expression for model_size one operation at a time and confirm it yields 355M for the medium model.

  • Common mistake

    Calling the loading function before the model exists

    Why it fails

    load_weights_into_gpt receives the model object as its first argument, so the model must be created by GPTModel(BASE_CONFIG) first.

    Do this instead

    Confirm that the line model = GPTModel(BASE_CONFIG) runs before load_weights_into_gpt(model, params).

  • Common mistake

    Reading the generated output as readable text

    What it looks like

    Expecting generate_text_simple to return words or a sentence.

    Why it fails

    The function returns output token IDs, which are numbers that represent tokens.

    Do this instead

    Compare the length of the returned sequence with the expected length, 4 input tokens plus 6 new tokens for this run.

  • Common mistake

    Skipping evaluation mode before generation, so the run is not in the state the code expects

Checking a Run With the Output Length

Suppose a run returns a sequence of 7 token IDs, and the input had 4 tokens with max_new_tokens set to 6. Use the output length as a checkpoint to decide what should be investigated first.

MEDIUM

A generation run with 4 input tokens and max_new_tokens of 6 returns 7 token IDs instead of 10. At which point in the run did the unexpected result first appear, and which earlier step would you check first?

Hints
  • The expected output length is the input length plus the newly generated tokens.
  • Each step adds one token, so the length after step 3 should be 7 if all steps behave as expected.
  • The earliest mismatch in the run is the step where the length stops growing as expected.
EASY

Write out the chain of values that model_size passes through when CHOOSE_MODEL is gpt2-medium (355M), and state which line would first show a wrong value if model_size came out as (355M).

Hints
  • Count the operations: split, select, strip.
  • The parentheses are removed by the strip step.

Key Takeaways

  • BASE_CONFIG holds four shared GPT-2 settings, and BASE_CONFIG.update(model_configs[CHOOSE_MODEL]) copies the chosen size's emb_dim, n_layers, and n_heads into it.
  • A loaded GPT-2 model is built in two parts: GPTModel(BASE_CONFIG) creates the model, and load_weights_into_gpt(model, params) loads the pretrained parameters into that model.
  • Calling model.eval() switches the model into evaluation mode, which disables dropout because the run is only producing output, not learning.
  • generate_text_simple returns output token IDs, and its output length equals the input length plus the newly generated tokens, which makes that length a useful checkpoint for debugging.

Related concepts

More concepts starting with E