← Back to writing

BERT and the fine-tuning paradigm: what Devlin et al. actually built

Reading Devlin et al. (Google, 2018) while auditing a classification pipeline that was paying $300/month for GPT-4 calls to do sentiment labeling.

We had a queue of ~40,000 support tickets per day. Each one needed a severity label: P1 (production down), P2 (degraded), or P3 (everything else). Someone had wired it up to GPT-4 with a system prompt and three examples. It worked. It also cost $0.008 per ticket, which added up.

The fix took a weekend. Fine-tuned a BERT-base variant on 2,000 labeled examples. Inference cost dropped 97%. Accuracy went up slightly — the fine-tuned model had seen the specific vocabulary our users actually wrote in, not just a general language model reasoning about severity.

That weekend forced me to actually read the BERT paper rather than just cargo-culting the approach. BERT — Bidirectional Encoder Representations from Transformers, Devlin et al., 2018 — is one of the most cited papers in ML history. It's also consistently misunderstood. People reach for it as "the embedding model" without understanding the pre-training insight that makes it work. Here's what a close read gave me.

The problem BERT was solving

To understand BERT, you need to understand what came before and why it was limited.

In 2018, the dominant pre-training approach for NLP was either left-to-right language modeling (GPT's approach: predict the next token given all previous tokens) or shallow feature extraction using non-contextualized embeddings like Word2Vec and GloVe. Both approaches share a flaw: they encode words without seeing their full context.

In a left-to-right language model, when you're processing the word "bank" in the sentence "I sat on the river bank," you've already committed to a representation before you've seen "river." The model sees context in only one direction. This matters enormously for tasks where the meaning of a token depends on tokens that come after it — which is most tasks.

BERT's solution: train on a task that forces the model to see both left and right context simultaneously, before predicting anything.

The pre-training tasks

BERT uses two pre-training objectives, and the choice of both is deliberate.

Masked Language Modeling (MLM). Before feeding a sentence to the model, randomly select 15% of tokens and replace them. Of those selected tokens: 80% get replaced with [MASK], 10% get replaced with a random token, 10% stay unchanged. The model must then predict the original token at each masked position.

The 80/10/10 split is worth understanding. If you always use [MASK], the model learns a representation optimized for [MASK] prediction specifically — a token type that never appears at inference time. By sometimes replacing with random tokens or keeping the original, you force the model to maintain a useful contextual representation for every token position regardless of whether it's masked. The authors call this "mismatch" avoidance.

The bidirectional constraint is enforced by the task structure itself. To predict a masked token at position i, you need information from positions both before and after i. The model cannot cheat with directional masking — it must build a representation that integrates both directions simultaneously.

Next Sentence Prediction (NSP). Given two sentences A and B, predict whether B actually follows A in the original text or is a random sentence. This is a binary classification task trained on document pairs sampled from the pre-training corpus.

NSP was intended to improve performance on tasks that require cross-sentence reasoning, like Natural Language Inference and Question Answering. The paper shows it helps; subsequent work (RoBERTa, 2019) found that removing NSP and training longer often matches or beats BERT — suggesting the sentence-pair reasoning benefit was partly explained by more training rather than the task itself. But in the original paper, NSP is part of what makes BERT's fine-tuned variants so strong at cross-sentence tasks.

The architecture and the numbers

BERT is a Transformer encoder — specifically the encoder stack from Vaswani et al. (2017), with no decoder. It processes the full input sequence in parallel, attending to all positions in both directions at every layer. No autoregressive decoding. No sequential dependency.

The paper specifies two model sizes:

  • BERT-base: 12 Transformer layers, 768 hidden dimension, 12 attention heads, 110M parameters
  • BERT-large: 24 Transformer layers, 1024 hidden dimension, 16 attention heads, 340M parameters

Hard constraint: max sequence length is 512 tokens. This is baked into the positional embedding table. You can't just extend it without retraining. In 2026, most BERT variants have addressed this (Longformer, BigBird), but the original paper is a 512-token model.

The input format has three components stacked together:

  1. Token embeddings: WordPiece tokenization, 30,000-token vocabulary
  2. Segment embeddings: distinguish sentence A from sentence B (each token gets an embedding indicating which segment it belongs to)
  3. Position embeddings: learned, not sinusoidal (unlike the original Transformer)

Two special tokens matter for downstream tasks: [CLS] is prepended to every input. Its final hidden state is used as the aggregate sequence representation for classification tasks. [SEP] separates sentence pairs. If you're using BERT for classification, you're using the [CLS] representation — it's the model's attempt to compress the entire input into a single vector.

The fine-tuning paradigm

This is the actual contribution. Pre-training produces a model checkpoint. Fine-tuning adapts that checkpoint to a specific task by:

  1. Adding a task-specific output layer on top of BERT's outputs
  2. Training the entire stack end-to-end on task-specific labeled data

For classification (single sentence or sentence pair): take the [CLS] token's final hidden state, pass it through a linear layer + softmax, minimize cross-entropy against your labels. That's it.

For token-level tasks like NER: take the hidden state at each token position, pass each through a linear layer, predict a label per token.

For extractive QA (SQuAD): predict start and end positions of the answer span in the context. Two linear layers, one for start logits and one for end logits, applied to all token positions.

The paper reports results on GLUE (General Language Understanding Evaluation): BERT-large gets 80.4 on the aggregate score versus the previous state-of-the-art of 69.1 — an 11-point jump on a benchmark that combines 9 different NLU tasks. On SQuAD 1.1, BERT-large reaches an F1 of 93.2 versus the previous best of 86.0.

What's notable about these results is that the same pre-trained checkpoint — with only a task-specific head added — achieves SOTA across tasks with fundamentally different output formats. That generality is the paradigm.

What makes bidirectionality actually matter

The GPT architecture (also based on Transformers, released the same year) uses left-to-right language modeling. Each token attends only to previous tokens. This is necessary for generation — you can't let the model see future tokens during training or inference without leaking the answer — but it means each token's representation is conditioned only on what came before it.

For understanding tasks, this is a real limitation. The semantic content of many tokens depends on subsequent context. Consider:

  • "The development was unexpected" → "development" needs "unexpected" to resolve ambiguity
  • "She couldn't bear the weight" → "bear" needs "weight" to resolve the pun
  • "The quarterback threw incomplete" → "threw" needs "incomplete" to understand the outcome

BERT's MLM training forces every token's representation to integrate both left and right context. At inference time, when no tokens are masked, the model produces representations that are genuinely bidirectional — each position has attended to everything else in the sequence.

This is why BERT-style models dominate embedding quality for semantic search and similarity tasks. The embedding of a token or sentence has seen the full context. A left-to-right model's representation of a sentence is heavily weighted toward the end — it's the final state after processing everything, but earlier tokens didn't have access to later ones.

Production tradeoffs and failure modes

Fine-tuning data requirements. BERT's fine-tuning works with surprisingly little data. The paper fine-tunes on tasks with 3,668 training examples (MRPC) and still gets strong results. In my support ticket classifier, 2,000 examples was enough. The pre-trained weights carry enormous world knowledge; fine-tuning just steers the representation space toward your task. Expect to need 500–5,000 examples for most classification tasks. Less than 100 examples usually isn't enough for fine-tuning to beat a prompted GPT call.

The 512-token wall. You will hit this. Long documents must be truncated or chunked. The standard heuristics — truncate to the first 512 tokens, or use a sliding window and aggregate — both degrade performance on long-document tasks. If your inputs are consistently over 512 tokens, use a Longformer variant, or reconsider whether BERT is the right architecture.

Vocabulary mismatch. BERT's WordPiece tokenizer was trained on a general corpus. Domain-specific vocabulary (medical terms, financial ticker symbols, code identifiers, proprietary product names) often gets split into subwords in ways that lose meaning. "GLP-1" becomes ['GL', '##P', '-', '1']. If your domain is specialized, consider a domain-pretrained model (BioBERT, FinBERT, CodeBERT) or retrain the tokenizer.

Representation drift under fine-tuning. Fine-tuning all weights simultaneously can catastrophically degrade the general representations you're relying on. With small datasets, this happens quickly. Mitigations: lower learning rate for lower layers, freeze lower layers entirely, use weight decay aggressively. In practice, learning rates in the 2e-5 to 5e-5 range with warmup over the first 10% of steps are the recommendation in the paper and they're mostly correct.

The [CLS] token isn't magic. The paper shows [CLS] works well for classification. For semantic similarity and sentence embeddings, it's often outperformed by mean pooling over all token positions, because the [CLS] token's representations are optimized for the NSP task during pre-training, not general-purpose similarity. If you're building a vector search index, benchmark both.

Inference latency is not free. BERT-base runs a 12-layer Transformer over your input. For a 128-token input on a single CPU, that's 20-50ms per request depending on your hardware. With batching on a GPU, throughput scales well. But if you're hitting BERT with 10,000 individual requests per second without batching, you're going to have a bad time. Batch your inference.

When BERT-class models still win in 2026

The conventional wisdom is that decoder-only models (GPT-family, Claude, Llama) have superseded encoder-only models. This is mostly true for generation and reasoning. It's not true for:

High-volume classification. Any task where you have labeled data and need to classify at scale. BERT inference is 10-100x cheaper than decoder model inference. Fine-tuned BERT frequently matches or beats decoder models on narrow classification tasks once you have 1,000+ labeled examples.

Semantic search and retrieval. Your RAG pipeline's retrieval step almost certainly uses a BERT-variant embedding model (E5, BGE, sentence-transformers). The reason: bidirectional representations produce better semantic embeddings than unidirectional ones for text similarity. This has been consistently validated across benchmarks and hasn't changed with scale.

Named entity recognition and span extraction. Token-level prediction tasks are natively handled by BERT's architecture. You get per-token logits, which map directly to span boundaries. Coaxing a decoder model to do NER reliably requires prompt engineering, output parsing, and validation loops. A fine-tuned NER model is faster, cheaper, and more reliable.

Constrained-domain classification with strict latency requirements. Intent detection in voice assistants, content moderation at the network edge, real-time document routing. When you need sub-100ms P99 latency and the task is well-defined, fine-tuned BERT is the right tool.

When NOT to use BERT

Generation of any kind. BERT has no decoder. It cannot generate sequences. If your task involves producing text, use a decoder model. Don't try to hack generation out of an encoder.

Zero-shot or few-shot without fine-tuning data. BERT doesn't generalize the way GPT-style models do to prompts and examples in context. The pre-training task (MLM) doesn't create the in-context learning behavior that left-to-right language modeling seems to. If you have no labeled data and need to classify, a prompted decoder model will dramatically outperform a stock BERT [CLS] classifier.

Long-document tasks where truncation loses signal. Legal contracts, research papers, codebases. If the answer to your question depends on information past token 512, BERT can't see it. Chunking is a workaround, not a solution — it loses cross-chunk context.

Reasoning chains. Chain-of-thought, multi-step arithmetic, planning problems. BERT's architecture doesn't produce intermediate reasoning — it maps input to output in a single forward pass. Decoder models with explicit reasoning (sampling, chain-of-thought prompting) are fundamentally better at tasks where the correct output depends on intermediate steps.

When your task distribution shifts frequently. Fine-tuned BERT is brittle to out-of-distribution inputs in a way that large decoder models aren't. If your classification schema changes frequently, or you're operating in a domain where new categories appear regularly, you'll be retraining often.

What the paper got right about the field

Reading BERT in 2026 is interesting because many of its framing choices turned out to be correct in ways the authors probably didn't anticipate.

The two-stage pre-train/fine-tune paradigm is still the dominant approach, just at larger scale. The BERT paper describes pre-training on 800M words from BooksCorpus and 2.5B words from English Wikipedia. Current pre-training runs use 10-100x more compute and data — but the structure is the same. You pre-train on the general task (predicting tokens in context), then adapt to specific tasks.

The decision to use a deep bidirectional Transformer encoder, rather than a shallower or unidirectional model, meant that the learned representations were rich enough to transfer across tasks. The 11-point GLUE jump wasn't just better pre-training data — it was the bidirectional pre-training task creating fundamentally more useful representations.

And the fine-tuning paradigm — one shared checkpoint, thin task-specific heads, end-to-end training — democratized NLP. Before BERT, building a good NER model required either specialized architectures, large amounts of labeled data, or both. After BERT, you could get competitive results by adding a linear layer and training on hundreds of examples. That accessibility changed who could build production NLP systems.


The support ticket classifier is still running. It's now on a DistilBERT variant — half the size of BERT-base, 97% of the performance — running in a container that costs about $40/month. It handles the full ticket volume with headroom.

The weekend I spent reading the paper was worth more than any amount of prompt engineering I'd done on the GPT-4 endpoint. Knowing which architecture solves which problem is still the most useful thing you can know in production ML.