BERT & Masked Language Modeling

Suppose you want a single model to answer questions, classify sentiment, and resolve pronoun references. You want to do this without training a bespoke architecture for each task. Before 2018, the dominant recipe used left-to-right language models. These predict the next word given everything before it. Alternatively, researchers trained task-specific architectures from scratch on limited labeled data. Neither approach let a model condition on both the left and right context of a word simultaneously. Neither made efficient use of the vast amount of unlabeled text available on the web. BERT (Bidirectional Encoder Representations from Transformers) solved this problem. It invented a pretraining objective — masked language modeling. This lets a Transformer Encoder Stack see the entire sentence at once. It is still forced to learn something nontrivial about language. Instead of predicting the next token, BERT hides random tokens. It asks the model to reconstruct them using context from both directions. This single change let a model absorb the syntax, semantics, and world knowledge embedded in billions of words of raw text. It produces representations that transfer to almost any downstream task with minimal additional training. The practical consequence was enormous. Fine-tuning BERT for a few epochs on a small labeled dataset (a few thousand examples) routinely outperformed the best previous task-specific systems. Those systems had been trained on much more supervision. BERT popularized the "pretrain once, fine-tune everywhere" workflow that now dominates NLP. It also made the encoder-only Transformer a first-class citizen alongside the decoder-only architectures used for generation. This article explains precisely how masked language modeling and the auxiliary next-sentence prediction task work. It explores why bidirectional conditioning is both powerful and non-trivial to train. It walks through the input representation and objective computation with pseudocode. It traces a concrete masking example. Finally, it surveys where BERT-style pretraining still matters in modern NLP pipelines.

Key takeaways
  • BERT pretrains a bidirectional Transformer encoder using masked language modeling (MLM): hide ~15% of tokens, predict them from full left+right context.
  • MLM avoids the trivial "see the answer" problem that a naive bidirectional next-word predictor would have.
  • A secondary objective, next sentence prediction (NSP), teaches sentence-pair relationships (largely superseded in later variants).
  • Input representation sums token, segment, and position embeddings, with special `[CLS]` and `[SEP]` tokens marking structure.
  • Fine-tuning reuses the pretrained encoder with a small task-specific head, requiring far less labeled data than training from scratch.
  • BERT's core limitation: it is not a generative model — it can't produce text left-to-right — since it was trained to fill in blanks, not extend sequences.
The core insight

BERT learns deep bidirectional language representations by training a Transformer encoder to reconstruct randomly masked tokens from both left and right context simultaneously.

The idea

A traditional autoregressive language model factors the probability of a sequence as a product of conditionals, P(x)=∏iP(xi∣x<i)P(x) = \prod_i P(x_i \mid x_{<i}), and can only condition each prediction on preceding tokens. This unidirectionality is a training necessity, not a design choice: if you let the model see the whole sequence while training it to predict each token in place, the model could trivially copy the answer through the self-attention mechanism, since every position attends to every other position including itself and the very token it is supposed to predict.

Masked language modeling (MLM) breaks this trivial-solution problem by replacing a subset of input tokens with a special `[MASK]` token (or another substitute) before the model ever sees them, and training the model to predict the original identity of only those masked positions. Because the true token is removed from the input, attending to that position no longer leaks the answer, and the model is forced to infer the missing word from the surrounding bidirectional context. This is sometimes called a cloze task, after the classic reading-comprehension exercise of filling in blanks. The second pretraining objective, next sentence prediction (NSP), trains the model to judge whether one sentence B plausibly follows another sentence A in the original text, versus being a random sentence sampled from elsewhere in the corpus. NSP was intended to teach sentence-pair relationships useful for tasks like question answering and natural language inference, though later research (RoBERTa and successors) showed NSP contributes little and can be dropped or replaced with cheaper objectives, provided training still exposes the model to pairs of contiguous text segments.

How it works

Input representation. Before any token reaches the Transformer, BERT builds an input embedding as the sum of three signals:

  • Token embeddings — a learned vector per WordPiece subword, from a fixed vocabulary (tying back to Tokenization at Scale).
  • Segment embeddings — one of two learned vectors indicating whether a token belongs to sentence A or sentence B.
  • Position embeddings — a learned vector per absolute position, since self-attention has no inherent notion of order.

A special `[CLS]` token is prepended to every input; its final hidden state is used as an aggregate sequence representation for classification tasks. A `[SEP]` token separates sentence A from sentence B (and terminates a single-sentence input).

Masking procedure. During pretraining, 15% of WordPiece tokens are selected uniformly at random (excluding `[CLS]`/`[SEP]`) to participate in the masked-prediction loss. Of those selected positions:

  • 80% are replaced with the literal `[MASK]` token,
  • 10% are replaced with a random token from the vocabulary,
  • 10% are left unchanged.

This 80/10/10 split exists to close a train/fine-tune mismatch: `[MASK]` never appears during fine-tuning or inference, so if the model only ever saw `[MASK]` during pretraining it would learn representations conditioned on an artificial token that never recurs later. Occasionally leaving the original token, or substituting a random wrong one, forces the encoder to maintain a good contextual representation for every input token (not just masked ones), because it can never be sure whether a given token is "trustworthy" or secretly a corrupted target it must correct.

The Transformer encoder. The embedded, positionally-augmented sequence is passed through LL stacked Transformer encoder layers, each composed of multi-head self-attention followed by a position-wise feed-forward network, with residual connections and layer normalization around each sublayer (assume this stack as given from Transformer Encoder Stack). Because encoder self-attention is fully bidirectional — every position attends to every other position in the sequence with no causal mask — each output vector is a function of the entire input, subject to the masking-out described above.

Output heads. At the masked positions, the final hidden vectors are fed through a linear layer plus softmax over the vocabulary to predict the original token, and the cross-entropy loss is computed only over the masked positions. Separately, the final hidden vector of `[CLS]` is fed through a small feed-forward classifier and softmax to predict `IsNext` versus `NotNext` for the NSP loss. The two losses are summed and backpropagated jointly. ``` function BUILD_PRETRAINING_EXAMPLE(sentence_A, sentence_B, is_actual_next): tokens = ["[CLS]"] + tokenize(sentence_A) + ["[SEP]"] + tokenize(sentence_B) + ["[SEP]"] segment_ids = [0](len(sentence_A_tokens)+2) + [1](len(sentence_B_tokens)+1) candidate_positions = all indices i where tokens[i] not in {"[CLS]", "[SEP]"} shuffle(candidate_positions) num_to_mask = round(0.15 * len(candidate_positions)) mask_positions = candidate_positions[0 : num_to_mask] labels = array of size len(tokens), default = IGNORE for i in mask_positions: labels[i] = tokens[i] # ground truth to predict r = random_uniform(0, 1) if r < 0.8: tokens[i] = "[MASK]" else if r < 0.9: tokens[i] = random_vocab_token()

# else: leave tokens[i] unchanged (10% of the time) return tokens, segment_ids, labels, is_actual_next

function PRETRAIN_STEP(model, batch): total_loss = 0 for (tokens, segment_ids, mlm_labels, nsp_label) in batch: input_embeds = TokenEmbed(tokens) + SegmentEmbed(segment_ids) + PositionEmbed(0..len(tokens)-1) hidden = TransformerEncoderStack(input_embeds) # bidirectional, L layers

# --- Masked LM loss (only over masked positions) --- mlm_loss = 0 for i where mlm_labels[i] != IGNORE: logits_i = OutputProjection(hidden[i]) # vocab-sized logits mlm_loss += CrossEntropy(softmax(logits_i), mlm_labels[i])

# --- Next sentence prediction loss --- cls_vector = hidden[0] nsp_logits = NSPHead(cls_vector) # 2-way logits nsp_loss = CrossEntropy(softmax(nsp_logits), nsp_label) total_loss += mlm_loss + nsp_loss gradients = backprop(total_loss) update_parameters(model, gradients) return total_loss / len(batch) ```

Fine-tuning. After pretraining, the same encoder is reused for a downstream task by attaching a small task-specific head — a linear classifier on `[CLS]` for sentence classification, two linear layers predicting span start/end logits for extractive question answering, a token-wise classifier for sequence labeling — and all parameters (encoder plus head) are updated together for a small number of epochs on the labeled task data. Because the encoder already encodes rich contextual and syntactic structure, this stage typically needs orders of magnitude less labeled data than training from scratch.

Figure
BERT input representation and dual pretraining objectives
BERT pretraining: input stack, encoder, and two loss heads Tokens [CLS] the [MASK] sat [SEP] it purred [SEP] Segment AAA AA BBB Position 012 34 567 Bidirectional Transformer Encoder (L layers) full self-attention: every position attends to every position multi-head attention → add & norm → feed-forward → add & norm no causal mask — [MASK] position sees both "the" and "sat" MLM head hidden[2] → linear → softmax predict "cat" at masked slot loss over masked tokens only NSP head hidden[CLS] → linear → softmax predict IsNext / NotNext binary sentence-pair loss

Complexity & correctness

Time complexity. Each Transformer encoder layer computes self-attention over a sequence of length nn with hidden dimension dd. Computing the pairwise attention scores costs O(n2d)O(n^2 d) (the n×nn \times n attention matrix, each entry requiring an O(d)O(d) dot product), and the position-wise feed-forward sublayer costs O(nd2)O(n d^2). Stacking LL layers gives a total forward-pass cost of

O(L⋅(n2d+nd2))O\big(L \cdot (n^2 d + n d^2)\big)

per sequence. This is identical to the cost of a plain Transformer encoder — MLM changes what is predicted, not the architecture's asymptotic cost. The MLM output projection adds O(m⋅d⋅∣V∣)O(m \cdot d \cdot |V|) for mm masked positions and vocabulary size ∣V∣|V|, which is typically small relative to the encoder cost since m≈0.15n≪nm \approx 0.15n \ll n in absolute count but the projection is applied only at those mm positions rather than all nn (a deliberate efficiency choice: computing softmax over ∣V∣|V| at every position would cost O(n∣V∣d)O(n|V|d) instead).

Space complexity. Storing the attention matrices for backpropagation costs O(Ln2)O(L n^2), and activations across layers cost O(Lnd)O(L n d); parameters cost O(Ld2)O(L d^2) independent of sequence length. For BERT-base (L=12L=12, d=768d=768) and BERT-large (L=24L=24, d=1024d=1024), parameter counts are roughly 110M and 340M respectively, dominated by the O(Ld2)O(Ld^2) feed-forward and attention projection weights.

Why masking (rather than naive bidirectionality) is necessary — a correctness argument. Consider training a bidirectional encoder to predict every token xix_i directly from a hidden state hih_i that was computed by letting position ii attend to all positions including itself. Since self-attention, absent any masking, includes the identity mapping among its accessible information (the query at position ii can trivially attend most strongly to the key at position ii, and the residual connection passes the input embedding of xix_i straight through), the model can achieve zero loss by learning the identity function, never learning any genuine contextual dependency. This degenerate optimum is a global minimizer of the naive objective, so gradient descent has no pressure to avoid it. MLM breaks this degenerate optimum by removing the target token from the input entirely at masked positions (replacing it with `[MASK]`, a random token, or leaving it — but computing loss only at the subset that was selected for masking). The identity shortcut is unavailable at a masked position because the true xix_i is not present anywhere in the input for the model to copy; the residual stream at that position carries information derived only from the corrupted/absent token plus attention to other positions. The only way to reduce loss at masked positions is to build a representation that infers the missing token from bidirectional context — which is exactly the representation-learning signal MLM is designed to elicit. The 10%-unchanged rule reintroduces a small amount of genuine self-information at a controlled rate specifically to prevent the encoder from underusing the current token's own identity at non-masked positions during fine-tuning, where no masking occurs at all.

Tradeoffs. MLM's central cost is statistical efficiency at training time: because loss is computed at only ~15% of positions per example, each training example yields less gradient signal per token than an autoregressive model's per-token loss over the entire sequence, requiring more total pretraining steps or data to match. BERT also cannot generate text autoregressively — there is no well-defined way to sample a full sequence left-to-right from a model trained only to fill in blanks — which is why the encoder-only, MLM-pretrained family (BERT, RoBERTa, ALBERT) is used for representation learning and classification/extraction tasks, while decoder-only, next-token-pretrained models (GPT family) dominate open-ended generation.

Worked example

Consider the sentence pair used for pretraining: > Sentence A: "the cat sat on the mat" > Sentence B: "it purred softly" (the true next sentence, so `IsNext`) After WordPiece tokenization and adding special tokens: ``` [CLS] the cat sat on the mat [SEP] it purred softly [SEP] 0 1 2 3 4 5 6 7 8 9 10 11 ``` Suppose the random 15% selection picks positions 2 (`cat`) and 9 (`purred`) to mask. Applying the 80/10/10 rule with independent draws:

PositionOriginal tokenRandom drawMasking outcomeModel input at position
2cat0.34 (< 0.8)replace with `[MASK]``[MASK]`
9purred0.91 (≥ 0.9)leave unchanged`purred`

The final model input becomes: ``` [CLS] the [MASK] sat on the mat [SEP] it purred softly [SEP] ``` with `mlm_labels[2] = "cat"` and `mlm_labels[9] = "purred"` (the label at position 9 is still recorded and scored even though the visible token was left unchanged — the model must learn that even an apparently-normal token might be a scored target). Passing this through the encoder, the hidden vector at position 2 is computed with full bidirectional self-attention: it can attend to `the` (position 1), `sat`, `on`, `the`, `mat` (positions 3–6), and even the second sentence, `it purred softly` (positions 8–10) through the shared attention mechanism across the `[SEP]` boundary. Given "the ___ sat on the mat" plus "it purred softly," the model should assign high probability to `cat` at the MLM head applied to hidden[2]. Simultaneously, the hidden vector at position 9 is scored against the label `purred`, forcing the model to maintain an accurate representation of tokens even when they were not corrupted. Separately, the `[CLS]` hidden state feeds the NSP head. Because sentence B genuinely follows sentence A in the source text, the target label is `IsNext`; had sentence B been swapped for an unrelated sentence sampled elsewhere in the corpus (e.g., "stock prices fell sharply today"), the target would be `NotNext`, and the model would need to use the `[CLS]` representation to detect the topical and discourse discontinuity. Total loss for this example is `CrossEntropy(predicted[2], "cat") + CrossEntropy(predicted[9], "purred") + CrossEntropy(NSP_prediction, IsNext)`, backpropagated through the shared encoder so that every parameter is updated to improve both objectives jointly.

Common pitfalls & traps

PitfallWhy it happensFix
Assuming BERT can generate textMLM trains fill-in-the-blank prediction, not left-to-right sequence generationUse decoder-only or encoder-decoder models for generation; use BERT for representation/classification
Forgetting the 80/10/10 rule and always using `[MASK]`Simplifies implementation but creates a pretrain/fine-tune mismatch since `[MASK]` never appears at fine-tuning timeImplement all three cases; the 10% "unchanged" case is what keeps non-masked representations sharp
Treating NSP as essentialOriginal paper included it, but later ablations (RoBERTa) showed removing NSP, while keeping contiguous-segment training, does not hurt or even helpsTreat NSP as optional; focus on MLM quality and training scale
Mismatched segment/position embeddings during fine-tuning for single-sentence tasksFine-tuning code sometimes forgets to set all segment ids to the same value for single-sequence inputsAlways explicitly set segment ids matching the pretraining convention
Ignoring subword masking granularityMasking individual WordPieces can let the model guess a partially-masked multi-piece word from its visible sub-pieces, weakening the taskWhole-word masking (mask all subword pieces of a word together) strengthens the training signal
Truncation silently dropping the `[SEP]`/second sentenceFixed max sequence length (e.g., 512) can truncate long sentence-pair inputs asymmetricallyApply a defined truncation strategy (e.g., alternately truncate the longer sequence) and verify both segments and special tokens survive

Pioneers & history

Origins · 1 minJacob Devlin and how this was discovered
JD
Jacob Devlin
active 2010s–present · Google AI Language, lead author of the BERT paper

Jacob Devlin led the team at Google that designed the masked language modeling objective and demonstrated that a deep bidirectional Transformer, pretrained at scale and lightly fine-tuned, could set new state-of-the-art results across eleven distinct NLP benchmarks with a single unified architecture, catalyzing the pretrain-then-finetune paradigm across the field.

History
2017
— the Transformer architecture is introduced, providing the encoder stack BERT would repurpose.
2018
— BERT is released, introducing masked language modeling and next sentence prediction for bidirectional pretraining.
2019
— RoBERTa shows NSP is largely unnecessary and that longer training with more data substantially improves MLM pretraining.
2019
— ALBERT introduces parameter-sharing and factorized embeddings to shrink BERT-style models while preserving performance.
2020
— ELECTRA replaces token masking with a replaced-token-detection objective, improving pretraining sample efficiency.

Where this matters

BERT-style pretraining reshaped how production NLP systems are built. Search engines use bidirectional encoder representations to better match query intent to document content, since understanding a query word often requires seeing words on both sides of it. Question-answering systems fine-tune a pretrained encoder with a span-extraction head to locate answers within a passage, reusing the same encoder weights across many domains. Content moderation, sentiment analysis, and named-entity recognition pipelines commonly fine-tune a compact BERT variant (DistilBERT, ALBERT, or a domain-specific checkpoint like BioBERT or SciBERT) rather than training from scratch, since the pretrained encoder already encodes syntax and much of the world knowledge needed for the downstream task. The masked-token idea also generalizes beyond text: masked modeling objectives inspired vision transformers trained with masked patch prediction and masked audio modeling for speech representation learning, showing that the cloze-style self-supervision principle is architecture- and modality-agnostic. Understanding BERT is a natural bridge to the broader Pretraining-Finetuning Paradigm and to Transfer Learning in NLP, both of which generalize the idea that a single large model pretrained on unlabeled data can be efficiently specialized for many downstream tasks with modest labeled data and compute.

Ask the tutor: How would you modify the masking procedure or objective to make pretraining more sample-efficient, the way ELECTRA does?

Why does BERT use WordPiece subword tokens rather than whole words?

Subword tokenization keeps the vocabulary size manageable while still covering rare and out-of-vocabulary words, since any word can be decomposed into known subword pieces (down to individual characters if necessary). This avoids the unbounded vocabulary growth of whole-word tokenization on open-domain text, at the cost of longer token sequences and the need for whole-word masking strategies to avoid trivially easy sub-token completion. This connects directly to the general concerns discussed under Tokenization at Scale, where vocabulary size, sequence length, and out-of-vocabulary handling trade off against each other.

How is BERT fine-tuned for a task like sentiment classification?

A linear classification layer is attached on top of the final hidden state of the `[CLS]` token, which after pretraining has learned to aggregate whole-sequence information via self-attention. During fine-tuning, both this new layer and all of the pretrained encoder's weights are updated using gradient descent on the labeled sentiment dataset, typically for only a few epochs with a small learning rate. Because the encoder already encodes syntax and semantics from pretraining, fine-tuning converges quickly and generalizes well even with a few thousand labeled examples, far less than would be required to train a comparable model from random initialization.

Is next sentence prediction (NSP) still used in modern BERT-style models?

Largely not in its original form. RoBERTa's ablation studies showed that removing NSP while still training on long, contiguous multi-sentence segments performed as well as or better than the original NSP setup. Subsequent models like ALBERT replaced NSP with a sentence-order prediction task (distinguishing correctly ordered versus swapped sentence pairs), which turned out to be a harder and more useful auxiliary signal. The core lesson is that MLM, not NSP, provides the dominant pretraining signal, and sentence-pair objectives need careful design to add real value.

What is whole-word masking and why was it introduced?

Whole-word masking modifies the masking procedure so that if any subword piece of a multi-piece word is selected for masking, all subword pieces of that word are masked together, rather than masking individual WordPieces independently. Without this rule, a model could exploit visible neighboring subword pieces of the same word to trivially reconstruct a masked piece — for instance, seeing "hyper" unmasked next to a masked "##active" strongly hints at the missing piece regardless of sentence context. Masking the whole word forces genuine reliance on surrounding sentence context, producing a harder and more informative training signal.

How does BERT differ architecturally from GPT-style models?

BERT uses an encoder-only Transformer with fully bidirectional self-attention: every token attends to every other token in the sequence, with no causal restriction, which suits it for representation learning and understanding tasks. GPT-style models use a decoder-only Transformer with causal (masked) self-attention, where each token only attends to earlier tokens, which is exactly the constraint needed to support autoregressive, left-to-right text generation. The training objectives follow from these architectural choices — masked language modeling for BERT's bidirectional encoder, and next-token prediction for GPT's causal decoder.

Does masked language modeling scale as well as autoregressive pretraining?

Both objectives scale favorably with more data and compute, but they are not identical in statistical efficiency: MLM computes loss over only the masked subset of tokens (about 15%) per training example, while autoregressive training computes loss over every token position in the sequence. This means MLM extracts less gradient signal per token seen, generally requiring more total tokens or training steps to reach comparable representation quality, a tradeoff later explored explicitly by ELECTRA's replaced-token-detection objective, which scores every position and trains more sample-efficiently.

Why does BERT need both token, segment, and position embeddings added together rather than concatenated?

Adding the three embedding types keeps the input dimensionality fixed at dd regardless of how many auxiliary signals are injected, so the rest of the Transformer architecture (attention projections, feed-forward layers) does not need to change size. Because these embeddings are learned jointly during pretraining, the model can allocate different subspaces of the shared dd-dimensional vector to represent token identity, segment membership, and position, effectively learning an implicit disentanglement rather than requiring an explicit concatenation-and-projection step, which would add parameters without a clear benefit.

Before this

Where this leads