Concepts / Initializing and Preparing the GPT Model for Fine-Tuning

Initializing and Preparing the GPT Model for Fine-Tuning

The output layer of a pre-trained GPT model is replaced with a new torch.nn.Linear layer so the model can produce one output per class.

  • Programming

A Model That Knows Language but Not Your Task

A pre-trained GPT model has already learned general patterns from a large amount of text. That learning is valuable, but the model was not built to answer one specific question, such as whether a message is spam or not spam. Before it can be fine-tuned for a classification task, its final layer has to be adapted so that it produces one output for each class the task requires.

This article follows the setup step that does exactly that, and then prepares the model to run on an available device. The setup is short, but every line changes something specific. As you read, ask two questions about each line: what object is being changed, and what value does it end up holding? Keeping those two questions in mind will make the rest of the article much easier to follow.

Tracing the Model Before Any Change

Think of the pre-trained model as a stack of components. Most of the stack is the GPT architecture itself, which turns input text into internal representations. The last component is the output layer, which turns those internal representations into the outputs that the model was originally built to produce. For a language model, those outputs are scores for possible next tokens, which is why the original output layer is sized to the model's vocabulary.

A classifier needs something different. It must produce one output per class, and the number of outputs should match the number of categories in the task. The setup therefore leaves the body of the model alone and swaps only the final layer. The diagram below shows the change: the input width stays the same, while the output side is redrawn for the classes.

Internalrepresentation768 featuresOriginal output layervocabulary-sizedVocabulary outputsone per tokenInternalrepresentation768 featuresNew output layernum_classesClass outputsone per class768 invocabulary out768 innum_classes out
What changes when the final linear layer is replaced: the input side stays at 768 features, but the output side now has one position per class instead of one per vocabulary token.

Replacing the Output Layer in One Assignment

The replacement is a single assignment to the model's out_head attribute. The right side of the assignment creates a new torch.nn.Linear object. The left side stores that object in place of the old layer. Nothing else in the setup code redefines the model, so the rest of the GPT architecture stays exactly as it was loaded. Only the final layer that turns internal representations into outputs is changed.

python
Notes on the code
  • num_classes = 2 sets the number of classes before the layer is created
  • model.out_head is the spot in the model that gets overwritten
  • torch.nn.Linear(...) builds the new layer whose shape is defined by the arguments
  • in_features=768 is fixed in this setup and does not depend on the class count
  • out_features=num_classes takes its value from the class count

Read the anatomy from left to right. The attribute on the left is the location being overwritten. The call on the right defines the new layer's shape. The in_features value is 768 in this setup, and the out_features value comes from num_classes. Changing the number of classes therefore changes only the output side of the layer, while the input side stays fixed at 768.

Following the Setup Line by Line

The setup can be read as a sequence of state changes. Each line leaves the model in a new state, and the next line builds on it. The diagram traces the model from the pre-trained version through the output layer replacement and the device placement. The states are listed in the order the code runs.

Pre-trained modeloriginal output layernum_classes set2out_head replacedout_features = 2device chosencuda or cpuModel on deviceready for fine-tuningassigncreate layerselect devicemodel.to(device)
After each line of setup code runs, the model object moves to a new state, and the output layer and placement are the parts that differ from the pre-trained version.

Notice what does not appear in this trace. The body of the GPT architecture is never reassigned, so its learned parameters are carried forward unchanged from the pre-trained model. The only new object is the output layer, and the only new placement is the device the model is moved to. Both the output replacement and the device selection happen before any fine-tuning begins.

Choosing the Device and Moving the Model

After the output layer is replaced, the setup prepares the device the model will run on. The setup code first creates a device object. It selects CUDA when torch.cuda.is_available() reports that CUDA is available, and selects the CPU otherwise. The device is therefore chosen based on what the machine offers, rather than being hard-coded into the program.

python
Notes on the code
  • torch.cuda.is_available() reports whether CUDA is available on this machine
  • the conditional expression selects cuda when available and cpu otherwise
  • torch.device(...) creates the device object that stores that choice
  • model.to(device) applies the choice to the model

The order of the two steps matters for reading the code. The model is first adapted to the classification task by replacing its output layer, and then it is placed on the device where it will run. Reversing the order would not change which layer is replaced, but the setup as written adapts the model first and places it second.

Mistakes Beginners Make with the Setup

  • Common mistake

    Changing in_features when the number of classes changes

    What it looks like

    Setting in_features=2 because the task has two classes.

    Why it fails

    in_features describes the width of what the layer receives from the model body, which stays at 768. The class count controls only the output side.

    Do this instead

    Keep in_features=768 and change only num_classes, which feeds out_features.

  • Common mistake

    Assuming the whole model is rebuilt

    What it looks like

    Believing that creating a new layer resets the GPT architecture.

    Why it fails

    The setup is a single assignment to out_head. Nothing else in the setup code redefines the model.

    Do this instead

    Recognize that only the final layer is new, and the rest of the loaded architecture is unchanged.

  • Common mistake

    Hard-coding the device

    What it looks like

    Writing device = "cuda" on a machine without CUDA.

    Why it fails

    The setup chooses the device from what the machine offers, using torch.cuda.is_available().

    Do this instead

    Use the conditional expression that selects cuda when available and cpu otherwise.

  • Common mistake

    Forgetting that model.to(device) is the step that applies the choice, so creating a device object alone leaves the model where it was.

Predicting the Shape of the New Head

EASY

A fine-tuning task has four classes. Before reading the answer, predict the out_features value of the new layer and whether the in_features value changes. Then explain which dimension of the layer's weight matrix corresponds to outputs and which to inputs.

Hints
  • Follow the setup pattern: out_features is taken from num_classes.
  • in_features describes the representations received from the model body, not the classes.
  • In a linear layer, the weight matrix maps inputs to outputs, so one of its two dimensions tracks the output count and the other tracks the input count.
MEDIUM

Explain, in one sentence, why changing the number of classes from 2 to 5 should not change the 768 input features. Then state which single line of the setup would need to change.

Hints
  • Think about what 768 describes: the width of what the layer receives.
  • Look for the line that assigns num_classes.

Key Takeaways

  • A pre-trained GPT model's output layer is replaced with a new torch.nn.Linear layer so the model can produce one output per class.
  • The replacement is a single assignment to model.out_head, with in_features fixed at 768 and out_features taken from num_classes.
  • Changing the number of classes changes only out_features, leaving the rest of the GPT architecture as it was loaded.
  • The device is chosen with torch.cuda.is_available(), selecting CUDA when available and the CPU otherwise, and model.to(device) applies that choice before fine-tuning begins.

Related concepts

More concepts starting with I