BERT Pre-training › Next Sentence Prediction

Michael BrenndoerferUpdated July 19, 20257 min read
Language AI HandbookAll chapters
Part 24 of 67BERT and Variants
Chapter 170BERT Pre-training › Next Sentence Prediction
Reading section 4 of 12 · Next Sentence Prediction · 7 minSection 4 of 12 · 7 min

Book contents

Section 4 of 12 · 7 min read

BERT Pre-training › Next Sentence PredictionOne section · Sections in this chapter4 / 12 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Masked language modeling teaches BERT about word-level and sentence-level patterns. But understanding full documents requires reasoning about how sentences relate to each other. Does this sentence follow logically from the previous one? Are these two sentences from the same document?

Next Sentence Prediction (NSP) provides this document-level signal. Given two sentences A and B, the model must predict whether B immediately follows A in the original corpus.

Next Sentence Prediction (NSP)

A binary classification task where the model predicts whether sentence B is the actual next sentence after sentence A in the source document (IsNext) or a random sentence from elsewhere in the corpus (NotNext).

How NSP Works

The [CLS] token's representation at the final layer is used for the NSP prediction. A small classification head (typically a single linear layer) maps this representation to two logits, one for IsNext and one for NotNext.

Out[17]:
Visualization
Diagram showing sentence pair input flowing through BERT to produce CLS embedding which feeds into binary classifier.
Next Sentence Prediction uses the [CLS] token representation. After processing both sentences through the transformer, the [CLS] embedding is passed to a binary classifier that predicts whether the sentences are consecutive.

The training procedure constructs balanced batches with 50% positive (actual next sentence) and 50% negative (random sentence) pairs. The NSP loss is cross-entropy between the predicted probabilities and the binary label.

In[18]:
Code
class NSPHead(nn.Module):
    """Classification head for Next Sentence Prediction."""

    def __init__(self, hidden_size):
        super().__init__()
        self.classifier = nn.Linear(hidden_size, 2)

    def forward(self, cls_embedding):
        # cls_embedding: (batch_size, hidden_size)
        logits = self.classifier(cls_embedding)
        return logits  # (batch_size, 2)


# Example usage
hidden_size = 768
nsp_head = NSPHead(hidden_size)

# Simulate batch of CLS embeddings
batch_size = 4
cls_embeddings = torch.randn(batch_size, hidden_size)
nsp_logits = nsp_head(cls_embeddings)
Out[19]:
Console
Input CLS embeddings shape: torch.Size([4, 768])
NSP logits shape: torch.Size([4, 2])

Predicted probabilities:
  Example 1: IsNext=0.714, NotNext=0.286
  Example 2: IsNext=0.733, NotNext=0.267
  Example 3: IsNext=0.732, NotNext=0.268
  Example 4: IsNext=0.701, NotNext=0.299

The NSP Controversy

NSP was designed to help BERT understand document structure, particularly for tasks like question answering where reasoning across sentences matters. However, subsequent research questioned its value.

RoBERTa (2019) found that removing NSP entirely and training on longer contiguous sequences improved performance. The researchers hypothesized that NSP's negative examples (random sentences from different documents) were too easy to distinguish. This provides weak signal. Topic differences between sentences gave obvious cues without requiring deeper understanding.

ALBERT took a different approach, replacing NSP with Sentence Order Prediction (SOP). Instead of distinguishing consecutive sentences from random ones, SOP asks whether two consecutive sentences are in the correct order or swapped. This harder task forced the model to learn finer-grained discourse relationships.

Out[20]:
Visualization
Diagram showing IsNext versus NotNext with different topics.
NSP distinguishes consecutive sentences from random pairs. The topic difference makes this easy.
Diagram showing correct order versus swapped order with same topic.
SOP distinguishes correct order from swapped order. Same topic forces focus on coherence.

Despite the controversy, understanding NSP matters for working with pre-trained BERT models. Many available checkpoints were trained with NSP, and the [CLS] token was optimized for this task. When fine-tuning for classification, you're building on representations shaped by both MLM and NSP.

Implementing NSP

Let's implement a complete NSP training step to see how the pieces fit together:

In[21]:
Code
def prepare_nsp_batch(sentence_pairs, tokenizer, max_length=128):
    """
    Prepare a batch of sentence pairs for NSP training.

    Args:
        sentence_pairs: List of (sent_a, sent_b, is_next) tuples
        tokenizer: BERT tokenizer
        max_length: Maximum sequence length

    Returns:
        Dictionary with input_ids, attention_mask, token_type_ids, labels
    """
    sentences_a = [pair[0] for pair in sentence_pairs]
    sentences_b = [pair[1] for pair in sentence_pairs]
    labels = torch.tensor([1 if pair[2] else 0 for pair in sentence_pairs])

    # Tokenize with sentence pairs
    encoding = tokenizer(
        sentences_a,
        sentences_b,
        padding=True,
        truncation=True,
        max_length=max_length,
        return_tensors="pt",
    )

    encoding["labels"] = labels
    return encoding
In[22]:
Code
# Create sample pairs
nsp_pairs = [
    ("The weather is nice today.", "Let's go for a walk.", True),
    (
        "Python is a programming language.",
        "It supports multiple paradigms.",
        True,
    ),
    ("The cat is sleeping.", "Stock prices rose sharply.", False),
    ("She studied hard for the exam.", "The movie was entertaining.", False),
]

batch = prepare_nsp_batch(nsp_pairs, tokenizer)
Out[23]:
Console
Batch contents:
  input_ids shape: torch.Size([4, 17])
  attention_mask shape: torch.Size([4, 17])
  token_type_ids shape: torch.Size([4, 17])
  labels: [1, 1, 0, 0]

Decoded first example:
  [CLS] the weather is nice today. [SEP] let ' s go for a walk. [SEP]
  Label: IsNext

The token_type_ids distinguish sentence A (0) from sentence B (1). This helps the model understand which tokens belong to which segment, enabling it to reason about sentence relationships.