BERT and the Encoder-Only Family
Masked language modelling, next sentence prediction, fine-tuning on downstream tasks. The model that changed NLP — still powering classification and NER.
GPT reads left to right. BERT reads the entire sentence at once — forward and backward simultaneously. That one change made it the best model for understanding tasks for three years running.
Before BERT (2018), language models were unidirectional. GPT reads token 1, then token 2, then token 3 — each token only sees what came before it. This is necessary for generation (you cannot read the future when writing) but it is a handicap for understanding. To classify whether a sentence is positive or negative, every word should inform the meaning of every other word — bidirectionally.
BERT (Bidirectional Encoder Representations from Transformers) uses a Transformer encoder — the left half of the original Transformer architecture from Module 48. Every token attends to every other token with no causal mask. To pretrain this bidirectional model without the ability to simply predict the next token (which would leak the answer), BERT uses two novel pretraining objectives: Masked Language Modelling and Next Sentence Prediction.
The result: BERT representations capture deep bidirectional context. Fine-tune BERT on 1,000 labelled examples and it outperforms models trained from scratch on 100,000. Amazon's review classifier, DoorDash's complaint tagger, Stripe's intent detector — all fine-tuned BERT variants.
Reading comprehension in school: you read the full passage, then answer questions about it. You read forwards and backwards, checking context in both directions. A student who only reads left to right and never re-reads misses nuance. BERT is the student who reads the full passage before answering. GPT is the student writing an essay — they cannot read what they have not written yet.
This is why BERT dominates understanding tasks (classification, NER, Q&A) while GPT dominates generation tasks (completion, summarisation, chat). Same Transformer architecture, different direction of attention, completely different use cases.
Masked Language Modelling and Next Sentence Prediction — the two pretraining tasks
BERT cannot use next-token prediction as its pretraining objective — that would require masking future tokens, making it unidirectional. Instead it uses two self-supervised objectives that can be computed from raw unlabelled text with no human annotation.
Note: Later research (RoBERTa, 2019) showed NSP does not help and may hurt. RoBERTa removed it entirely and achieved better results training with MLM only on more data for longer.
BERT's three embeddings — token, segment, and position
BERT's input is the sum of three embedding types. The token embedding is the standard lookup table for each WordPiece token. The segment embedding distinguishes sentence A (all zeros) from sentence B (all ones) — needed for the NSP task and any two-sentence input like Q&A. The position embedding is learned (unlike GPT's sinusoidal encoding) — one vector per position 0 to 511.
Fine-tuning BERT — add a task head, update all weights end-to-end
BERT fine-tuning is simple: add one task-specific layer on top of the pretrained encoder and train the entire model end-to-end on your labelled data for 2–4 epochs. For classification, use the [CLS] token's final hidden state (a 768-dim vector) as input to a linear classifier. For NER, use every token's final hidden state. For Q&A, predict start and end positions of the answer span.
RoBERTa, DistilBERT, ALBERT, DeBERTa — what each one improved
BERT spawned an entire family of encoder-only models. Each one identified a specific weakness in the original BERT and fixed it — more data, better training recipe, smaller model, better attention mechanism. Understanding what each model improved helps you choose the right one for your task.
Named Entity Recognition — labelling every token in a sequence
Classification uses only the [CLS] token. NER uses every token's output — one label per token. Useful at Stripe to extract merchant names, amounts, and dates from unstructured dispute text. The label format is BIO: B-entity (beginning), I-entity (inside), O (outside/no entity).
Every common BERT mistake — explained and fixed
Where encoder-only models still win in production — and where generative LLMs took over
Since large generative models became commodity, many teams reach for a prompt instead of a fine-tuned classifier for the first version of almost anything. But encoder-only models — BERT, RoBERTa, DeBERTa, and their smaller relatives like DistilBERT — remain the default in three categories of production system: high-throughput classification and moderation, search and retrieval, and structured entity extraction at scale. In all three, the reason is not that encoders are more capable in isolation. It is latency and cost, multiplied by volume.
A fine-tuned DistilBERT classification call runs in single-digit to low-double-digit milliseconds on a small GPU and costs a small fraction of a cent per call. A comparable call to a generative model through an API takes hundreds of milliseconds to multiple seconds and costs orders of magnitude more per call. At ten calls a day the difference is invisible. At fifty million messages a day — a realistic volume for content moderation at a large platform — that difference compounds into a genuinely different infrastructure bill and a genuinely different latency budget, which is why almost every large-scale moderation, spam-filtering, and search-ranking pipeline still runs an encoder model even well into the generative-LLM era.
A content moderation team routing every message through even a cheap generative API call at a fraction of a cent and a few hundred milliseconds of latency each would face tens of thousands of dollars a day in inference cost alone, plus a moderation queue with far more latency than the product can tolerate. The same volume through a fine-tuned DistilBERT model, running on a modest, fixed number of GPUs, costs a small fraction of that and responds in single-digit milliseconds. This is why many teams land on a two-stage architecture instead of picking one approach exclusively: an encoder model handles the full volume as a cheap first pass, and only the small share of genuinely ambiguous cases — where the encoder's own confidence sits near the decision boundary — get escalated to a slower, more expensive generative model for a judgment call.
Five things people get wrong about BERT and the encoder family
NSP was one of BERT's two original pretraining objectives, alongside masked language modelling, and it was presented as necessary for tasks that require understanding relationships between sentences (like question answering). RoBERTa's 2019 ablation directly tested this by removing NSP entirely and training MLM alone for longer on more data — and matched or exceeded original BERT's results across the board. The actual reason NSP looked useful in the original BERT paper wasn't the objective itself; it was that the NSP-trained runs happened to also get more training data and time. Once that confound was controlled for, NSP contributed nothing and was dropped from essentially every BERT successor since.
[CLS] is just a special token prepended to every input sequence at position 0 — there is nothing architecturally different about how attention treats it compared to any other token; it attends to and is attended to exactly like every other position. Its final hidden state only becomes a useful sentence-level summary because it is explicitly trained to be one — during pretraining, [CLS]'s output feeds the NSP classifier, and during fine-tuning it feeds whatever task-specific head you attach for classification. In a hypothetical BERT with random, untrained weights, [CLS]'s hidden state is exactly as meaningless as any other token's — the "summary" property is a learned behaviour from the training objective, not a structural guarantee from where the token sits in the sequence.
This is precisely the problem the 80/10/10 rule exists to fix. If every masked position were simply replaced with the literal [MASK] token, the model would only ever need to predict from context around [MASK] tokens — but [MASK] never appears in real fine-tuning or inference data, which creates a mismatch between what the model practiced on and what it will actually see in production. The 80/10/10 split — 80% of selected tokens become [MASK], 10% become a random token, 10% stay unchanged — forces the model to keep a robust, context-sensitive representation for every token, not just the ones that happen to be masked, because it can never be sure whether the token in front of it is genuine, corrupted, or masked without checking context regardless.
DistilBERT is roughly 40% smaller than BERT-base by parameter count and retains about 97% of its performance on standard benchmarks — for many production classification and NER tasks, that gap is invisible relative to the 60% latency improvement it buys. On small labelled datasets (a few hundred examples), even simpler non-Transformer baselines like TF-IDF plus logistic regression can outperform a fully fine-tuned BERT, because BERT has enough parameters to overfit before it ever benefits from its pretrained knowledge. Model size is one variable among several — data size, domain match, latency budget, and overfitting risk usually matter more than raw parameter count when picking which encoder-family model to actually deploy.
Bidirectional attention and causal attention are not a strictly-better-vs-strictly-worse pair — they are a direct architectural trade-off. Bidirectionality is exactly what makes BERT unable to generate text autoregressively: if every token could already see every future token during training, predicting the next token would be trivial and would leak the answer, which is why BERT cannot be used for open-ended generation without substantial modification. GPT's causal mask sacrifices access to future context specifically so that next-token prediction remains a genuine prediction problem, which is what makes autoregressive generation possible at all. Each architecture is specialised for what its masking allows it to do — understanding tasks that benefit from full context versus generation tasks that require the model to only ever see the past — neither one dominates the other in general.
BERT and the encoder family — 5 questions interviewers actually ask
Next-token prediction requires that the model, when predicting token t+1, only has access to tokens 1 through t — otherwise the "prediction" is trivial, since the answer is sitting right there in the input. That requirement forces a causal mask, which is exactly what makes GPT unidirectional: each token can only attend to what came before it. BERT's whole design goal is the opposite — every token should attend to every other token in both directions, because that full context is what makes it strong at understanding tasks. Applying a causal mask to get next-token prediction working would directly contradict BERT's bidirectional design, so it needs an objective that can be computed with full bidirectional context without leaking the answer — which is exactly what masked language modelling provides: hide 15% of tokens, let the model see everything else in both directions, and predict only the hidden ones.
If masking always meant literally inserting the [MASK] token, the model would learn a representation that is only ever exercised at [MASK] positions — but at fine-tuning and inference time, [MASK] never appears in real input, so the model's representations for ordinary, non-masked tokens would never get the same training pressure to be context-aware. The 80/10/10 split forces every token's representation to stay robust regardless of what it turns out to be: of the 15% of tokens selected for the MLM task, 80% are replaced with [MASK] (learn to predict from context), 10% are replaced with a random wrong token (learn to notice when a token doesn't fit and correct it using context, not just copy it), and 10% are left unchanged (learn to still use context even when the input token is already correct, since the model can't tell this case apart from the other two). The net effect: BERT can't develop a shortcut of "just copy whatever token is in front of me," because 20% of the time that would be wrong.
The token embedding is the standard WordPiece lookup table, one vector per vocabulary entry. The position embedding is a learned vector per sequence position (0 through 511), added so the model can distinguish token order despite attention being permutation-equivariant on its own — same reason every Transformer needs positional information, GPT included. The segment embedding is BERT-specific: it's a binary signal (sentence A vs sentence B) added to every token, needed because BERT was designed from the start to take two-sentence inputs for tasks like question answering (question + context) or the original NSP objective (sentence A + sentence B), and the model needs an explicit signal for which sentence each token belongs to since bidirectional attention alone can't infer a sentence boundary from [SEP] tokens reliably at every layer. GPT never needs this because it processes a single continuous stream of tokens for autoregressive generation — there's no fixed two-segment input structure to disambiguate.
It's a direct lesson in controlling for confounds before crediting a specific design choice. The original BERT paper presented MLM and NSP together as a package, so it looked like NSP was contributing to BERT's strong results. RoBERTa isolated the variable: same architecture, same MLM objective, NSP removed, but trained for longer on substantially more data — and it matched or beat BERT anyway. That means the original NSP-included runs' apparent success was confounded with the additional data and training time, not evidence that NSP itself was doing useful work. The broader interview-relevant point: when someone claims a specific training component is "necessary" based on a paper that changed several things at once, the right instinct is to ask what was actually ablated — a single change tested in isolation is much stronger evidence than a bundle of changes that all shipped together and happened to work.
Sequence classification uses only the final hidden state at the [CLS] position — a single 768-dimensional vector — fed into a linear layer that outputs class logits for the whole input; the rest of the sequence's hidden states are simply discarded at the head. Token classification (NER) instead uses every token's final hidden state independently, each fed through the same linear layer to produce a label per token — the model is predicting a tag for every position, not one tag for the whole sequence. The architecture-level difference is just where you attach the head (one position vs all positions) — the pretrained encoder underneath is identical. What commonly goes wrong is label alignment: WordPiece splits a single annotated word into multiple subword tokens ("Stripe" becomes "St" + "##ripe"), so you can't naively assign your word-level label to each resulting token — you have to use the tokeniser's word_ids() to give the real label only to a word's first subword and mask out continuation subwords with label -100 so they're ignored in the loss, otherwise the model is trained on silently corrupted labels.
You can fine-tune BERT for any classification or NER task. Next: fine-tune with less than 1% of the parameters.
Full fine-tuning updates all 110 million parameters of BERT. For large models (7B, 13B, 70B parameters) this requires enormous GPU memory and storage. PEFT (Parameter-Efficient Fine-Tuning) methods like LoRA and adapters fine-tune less than 1% of parameters while achieving 95% of full fine-tuning performance. Module 51 covers LoRA, adapters, and prefix tuning — how to fine-tune a 7B parameter model on a single GPU.
Tune less than 1% of a model's parameters and get 95% of the performance. LoRA, adapters, and prefix tuning — when and how to use each.
🎯 Key Takeaways
- ✓BERT uses a Transformer encoder with bidirectional attention — every token attends to every other token with no causal mask. This makes it ideal for understanding tasks (classification, NER, Q&A) where context from both directions matters.
- ✓BERT is pretrained with two objectives: Masked Language Modelling (predict 15% of randomly masked tokens using surrounding context) and Next Sentence Prediction (predict whether sentence B follows sentence A). RoBERTa later showed NSP hurts — train MLM only on more data.
- ✓BERT input is the sum of three embeddings: token (WordPiece lookup), segment (sentence A vs B), and position (learned, 0–511). Special tokens [CLS] (start) and [SEP] (sentence separator) are always added by the tokeniser automatically.
- ✓Fine-tuning pattern: for classification use the [CLS] token final hidden state → Linear(768, n_classes). For NER use every token final hidden state → Linear(768, n_labels). For Q&A predict start and end positions. All use the same pretrained backbone, different task heads.
- ✓The encoder family: RoBERTa (better training recipe, no NSP) is the default when accuracy matters most. DistilBERT (40% smaller, 60% faster, 97% quality) is the default for production serving. DeBERTa achieves state of the art on NLU benchmarks. BioBERT/SciBERT for domain-specific scientific and medical text.
- ✓For NER, use word_ids() to align labels to tokenised subwords. First subword of each word gets the real label. Continuation subwords (## prefix) get label -100 to be ignored in loss. Never align labels by position index — WordPiece splits change the count of tokens per word unpredictably.
Discussion
0Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.