Skip to main content

Module 9 — The Transformers library in practice

You have used the Transformers library in fragments since module 5. This module steps back and covers the API as a whole: the three levels of abstraction it exposes, when to use each, and how to pick a model on the Hugging Face Hub without wasting a week fine-tuning the wrong one.

Three levels, from friendliest to most flexible

from transformers import pipeline, AutoTokenizer, AutoModel

Each of the three you import above is a rung on a ladder.

Level 1 — pipeline. One line, one string in, one prediction out. No batching to think about, no tokenization to configure. Perfect for demos, scripts and prototypes.

clf = pipeline("sentiment-analysis")
print(clf("The screen is amazing but the battery drains in three hours."))
# [{'label': 'NEGATIVE', 'score': 0.98}]

Notice you never picked a model. The default for the task is downloaded silently. That is fine for a demo and dangerous in production: the default is distilbert-base-uncased-finetuned-sst-2-english, a two-class model trained on movie reviews. The output above is a lucky guess as much as a real prediction.

Level 2 — AutoTokenizer and AutoModel. You name the model, you control the tokenization, you decide the batching. This is where 90 % of production code lives.

tok = AutoTokenizer.from_pretrained("distilbert-base-uncased")
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased-finetuned-sst-2-english"
)

batch = tok(["The screen is amazing.", "Battery drains too fast."],
padding=True, truncation=True, return_tensors="pt")
with torch.no_grad():
logits = model(**batch).logits
probs = logits.softmax(dim=-1)

Everything is explicit: the tokenizer pairs with the model by construction (Auto* classes match the model type from the config), padding is handled, gradients are off. This is what you deploy.

Level 3 — the classes themselves. AutoModel returns an instance of one of the concrete classes, like DistilBertModel, BertForTokenClassification, T5ForConditionalGeneration. You subclass them when you need a custom head, a modified attention or an integration with something outside the Trainer loop. Most projects never need this level.

The Auto* family, explained

Every task the library supports has an AutoModelFor... counterpart:

TaskClass
Sentence classificationAutoModelForSequenceClassification
Token classification (NER)AutoModelForTokenClassification
Question answering (extractive)AutoModelForQuestionAnswering
Masked language modellingAutoModelForMaskedLM
Causal language modellingAutoModelForCausalLM
Seq2seq (summarisation, translation)AutoModelForSeq2SeqLM

Picking the right one attaches the appropriate head to the pretrained body. AutoModel alone returns only the body — useful for feature extraction (module 5) but not for classification.

Trainer, or the loop you don't have to write

You saw Trainer in modules 6 and 7. It handles the training loop, distributed backends, mixed-precision, checkpointing, evaluation and logging. Its main configuration surface is TrainingArguments, which is 60 flags long but reduces to about eight for most projects.

from transformers import TrainingArguments, Trainer

args = TrainingArguments(
output_dir="run-01",
num_train_epochs=3,
per_device_train_batch_size=16,
learning_rate=2e-5,
weight_decay=0.01,
warmup_ratio=0.06,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
metric_for_best_model="f1",
logging_steps=50,
)

trainer = Trainer(model=model, args=args, train_dataset=train_ds,
eval_dataset=dev_ds, tokenizer=tok, compute_metrics=metrics)
trainer.train()

Three flags earn their place: load_best_model_at_end=True restores the best checkpoint at the end (otherwise you keep the last epoch, which may have overfit); warmup_ratio=0.06 ramps the learning rate up over the first 6 % of steps (avoids the collapse you saw fine-tuning without it); and metric_for_best_model decides what "best" means. Set it to f1 on imbalanced tasks; leave the default loss for balanced ones.

The Hugging Face Hub: pick the right model

The Hub lists over a million models. Filtering by task, language and licence is done from the search bar. Three properties dominate the decision.

Language coverage. A model card lists the languages it was trained on. bert-base-uncased is English. bert-base-multilingual-cased covers 104 languages but is measurably worse on each of them than a monolingual counterpart. xlm-roberta-base is multilingual and often the best trade-off if your corpus mixes languages. For English customer reviews specifically, roberta-base or distilbert-base-uncased are the standard choices.

Size. The number of parameters decides latency, memory and, indirectly, quality.

ModelParametersMemoryLatency (CPU)
distilbert-base66M260 MB~10 ms / doc
bert-base110M440 MB~25 ms / doc
bert-large340M1.3 GB~80 ms / doc
xlm-roberta-large550M2.2 GB~150 ms / doc

The rule of thumb: start with distilbert-base for English or xlm-roberta-base for multilingual, and move up only if metrics demand it. On the review corpus, distilbert-base reaches within 2 macro-F1 points of bert-large at a quarter of the cost.

Licence. The Hub shows the licence on every model card, and it matters. apache-2.0 and MIT allow commercial use with attribution. cc-by-nc-4.0 forbids commercial use. Some LLMs use custom licences (llama-*, openrail) with specific clauses about downstream training, model output and monthly active users. Read the licence before you commit; a research paper's model that lands in a product with the wrong licence is a legal problem.

Model cards: read them, and read the training data section

Every model on the Hub has a model card, and the useful sections are not the ones with the most text. Two are worth reading before every download:

  • Training data. A model trained on Wikipedia will perform differently on informal customer reviews than a model trained on Reddit. If the section is missing, distrust the model.
  • Intended uses and limitations. Bias evaluation, known failure modes, use cases the authors explicitly excluded. This is where you learn that a face-recognition model was trained on celebrities and will fail on children, or that a sentiment model was fine-tuned on movie reviews and struggles on medical text.
A model that appears in a pipeline default is not a validated model for your task

pipeline("sentiment-analysis") defaults to a movie-review model. pipeline("summarization") defaults to a news model. Both work on unrelated corpora, but neither has been evaluated on yours. In a serious project, always name the model explicitly.

Cache the model, pin the revision

from_pretrained(name, revision="a1b2c3") pins the exact commit hash from the Hub. Without it, a model author who updates their weights next month silently changes what your production system does. Pin the revision on release, and read the release notes when you decide to bump it.

In summary

  • The library exposes three levels of abstraction: pipeline for demos, AutoTokenizer + AutoModel for production, subclasses for custom architectures.
  • AutoModelForXxx attaches the right head for the task; AutoModel alone returns only the body and is meant for feature extraction.
  • Trainer hides the training loop; warmup_ratio, load_best_model_at_end and metric_for_best_model are the three flags worth enabling on almost every project.
  • On the Hub, pick by language, size and licence in that order; read the model card's training data and intended-uses sections before committing; pin the revision on release.

Next module: the full project — bringing the whole pipeline to bear on the review corpus and comparing three approaches head to head.