Hugging Face Fine-Tuning with Trainer

Fine-tuning with Hugging Face means taking a pretrained model and training it a little more on your own labeled data. Because the model already understands language, a few thousand examples and a few minutes on a GPU are often enough to get a strong classifier.

The Trainer class handles the training loop, evaluation, mixed precision, checkpoints and logging so you can focus on the data.

Step 1: Prepare the Data

from datasets import load_dataset
from transformers import AutoTokenizer

name = "distilbert/distilbert-base-uncased"
tok = AutoTokenizer.from_pretrained(name)

ds = load_dataset("stanfordnlp/imdb")
ds["train"] = ds["train"].shuffle(seed=42).select(range(4000))
ds["test"] = ds["test"].shuffle(seed=42).select(range(1000))

ds = ds.map(lambda b: tok(b["text"], truncation=True, max_length=256), batched=True)
Map: 100%|██████████| 4000/4000
Map: 100%|██████████| 1000/1000

Step 2: Load a Model with a Classification Head

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained(
    name, num_labels=2, id2label={0: "neg", 1: "pos"}, label2id={"neg": 0, "pos": 1},
)
Some weights of DistilBertForSequenceClassification were not initialized ... ['classifier.bias', 'classifier.weight', ...]
You should probably TRAIN this model on a down-stream task ...

This warning is expected: the classification head is brand new and random. Training will fill it in.

Step 3: Metrics and TrainingArguments

import numpy as np
from transformers import TrainingArguments, DataCollatorWithPadding

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    preds = np.argmax(logits, axis=-1)
    return {"accuracy": float((preds == labels).mean())}

args = TrainingArguments(
    output_dir="imdb-distilbert",
    num_train_epochs=2,
    per_device_train_batch_size=16,
    learning_rate=2e-5,
    eval_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
    bf16=True,            # use mixed precision on supported GPUs; remove on CPU
    report_to="none",
)
collator = DataCollatorWithPadding(tok)
(no output — objects created)

DataCollatorWithPadding pads each batch only to its longest example, which is faster than padding everything to max_length. Note the argument name eval_strategy; older tutorials use evaluation_strategy, which has been removed.

Step 4: Train and Evaluate

from transformers import Trainer

trainer = Trainer(
    model=model, args=args,
    train_dataset=ds["train"], eval_dataset=ds["test"],
    processing_class=tok, data_collator=collator,
    compute_metrics=compute_metrics,
)
trainer.train()
print(trainer.evaluate())
{'eval_loss': 0.29, 'eval_accuracy': 0.887, 'epoch': 2.0, ...}
(sample output — exact numbers vary per run)

processing_class replaces the older tokenizer= argument. It is saved alongside the model so the checkpoint is self-contained.

Step 5: Save and Use the Model

trainer.save_model("imdb-distilbert/final")

from transformers import pipeline
clf = pipeline("text-classification", model="imdb-distilbert/final")
print(clf("A beautiful, moving film."))
[{'label': 'pos', 'score': 0.98}]   (sample output)

Fine-Tuning Tips

  • Start with a small subset to check everything runs, then scale up.
  • Learning rates between 1e-5 and 5e-5 are typical for full fine-tuning.
  • Watch eval loss: if it rises while training loss falls, you are overfitting.
  • For LLMs, full fine-tuning is expensive; use LoRA (next lesson) instead.

Frequently asked questions

What is the Hugging Face Trainer?

A high-level class in transformers that runs the PyTorch training and evaluation loop for you, with support for mixed precision, multiple GPUs, checkpointing and logging.

How much data do I need to fine-tune a model?

For text classification, a few hundred to a few thousand labeled examples often give good results because the model is already pretrained.

Why do I get "Some weights were not initialized" when loading a model?

You added a new task head that was not in the checkpoint. It starts random and is learned during fine-tuning, so the warning is normal.

What replaced evaluation_strategy in TrainingArguments?

It is now called eval_strategy. Similarly, pass the tokenizer as processing_class instead of tokenizer.