wikillm

Paper · 2019-08-27 · cs.CL

Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks

Sentence-BERT fine-tunes BERT or RoBERTa in a siamese setup: both sentences pass through the same network, are mean-pooled into one vector, and are compared by cosine similarity. Trained on NLI, STS or triplets. Author-reported: SBERT-NLI-large averages 76.55 Spearman over seven STS tasks; the closest pair among 10,000 sentences takes about 5 s instead of about 65 h with cross-encoder BERT.

Text embeddingMetric learningSiamese networksentence-embeddingssiamese-networkcosine-similaritysemantic-searchbert

arXivPDFCodeMarkdown12 min read

AI-compiled by claude-haiku-5-5 on 2026-10-19, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.

In plain words

BERT is very good at judging how alike two sentences are, but it has to read both sentences together every time, so comparing a new sentence against a big collection means running the model once per pair. That is far too slow for search or clustering.

Sentence-BERT changes the setup so that each sentence is turned into a single list of numbers once. The same network reads each sentence separately, and the outputs are averaged into one vector. Two sentences are then compared with a quick calculation on their vectors, and the vectors can be stored and searched. The network is trained on labelled sentence pairs or triplets so that similar sentences end up with similar vectors. The authors report that its accuracy on similarity benchmarks is competitive with BERT's, with some gaps, while large comparisons drop from many hours to seconds.

TL;DR

  • Sentence-BERT (SBERT) adds a pooling step to a pretrained BERT or RoBERTa and fine-tunes it with a siamese structure, so each sentence gets one fixed-size embedding §3.
  • Similarity is cosine similarity between two embeddings, which allows nearest-neighbour search and clustering over a collection §1 §3.
  • Training uses an NLI softmax head, a cosine regression loss, or a triplet loss. The softmax head is only used during training §3 §6.
  • Author-reported: SBERT-NLI-large reaches an average Spearman of 76.55 over seven STS tasks, close to RoBERTa-based SRoBERTa-NLI-large at 76.68, and above InferSent and Universal Sentence Encoder tab. 1. Cross-topic AFS results are weaker than BERT tab. 3.

Problem

A cross-encoder (BERT reads a sentence pair together and outputs a score) must run once for every pair. Finding the most similar pair among 10,000 sentences takes n(n−1)/2 = 49,995,000 inference passes, about 65 hours on a V100 GPU in the authors' setup §1 §2.

BERT outputs, used directly as sentence vectors, are poor for similarity. Averaging BERT's output layer or using the [CLS] token gives average STS correlations of 54.81 and 29.19, below averaged GloVe vectors at 61.32 tab. 1 §4.1. The authors treat this as the motivation: a model that gives independent sentence embeddings is needed for semantic search and clustering §1.

Method

Architecture §3 fig. 1. Two copies of the same pretrained encoder (BERT or RoBERTa, 12 or 24 layers §2) share weights. A pooling layer turns the token outputs of each sentence into one vector §3. The paper compares three pooling strategies: the [CLS] output, the mean of all token outputs (MEAN), and the max over time (MAX) §3. MEAN is the default §3 §3.1.

Objective for labelled pairs (NLI classification) §3. For embeddings u and v with dimension n and k labels, the model computes softmax(W_t (u, v, |u − v|)), where W_t maps the concatenation of size 3n to k logits, and trains with cross-entropy §3. The equation is unnumbered in the paper.

Objective for scored pairs (regression) §3 fig. 2. The cosine similarity of u and v is compared to the gold score with mean squared error §3.

Objective for triplets §3. For an anchor a, a positive p and a negative n, the loss is max(‖s_a − s_p‖ − ‖s_a − s_n‖ + ε, 0) with Euclidean distance and margin ε = 1 §3.

Training on NLI §3.1. SBERT is trained on SNLI (570,000 pairs) and MultiNLI (430,000 pairs) with the three-way softmax objective for one epoch, batch size 16, Adam with learning rate 2e-5, and a linear warm-up over 10% of the training data §3.1.

Training on STS benchmark and on triplets §4.2 §4.4. The regression objective is trained on the STS benchmark training split (5,749 pairs). Two setups are compared: STSb only, and NLI first then STSb §4.2. The triplet objective is trained for one epoch on about 1.8 million Wikipedia-section triplets §4.4.

Inference §3 §6. The softmax head is discarded. Similarity is the cosine of the pooled embeddings of the two sentences §6. The authors also tried negative Manhattan and Euclidean distances and report roughly the same results, without reporting numbers §4.

The pseudocode below follows the official code at code_commit. The mean pooling is pooling.py. The NLI head is softmax.py. The triplet hinge is triplet.py.

Pseudocode
# Sentence embedding with mean pooling  [§3]
# Input:  token ids (B, T), attention mask (B, T)
# Output: sentence embeddings (B, n)

def embed(token_ids, mask):
    # Run the pretrained encoder (BERT or RoBERTa)  [§3]
    token_vectors = encoder(token_ids, mask)            # (B, T, n)
    # Average over the real tokens only, ignoring padding  [§3]
    total = (token_vectors * mask[..., None]).sum(dim=1)  # (B, n)
    count = mask.sum(dim=1, keepdims=True)              # (B, 1)
    return total / count                                # (B, n)
Pseudocode
# NLI training step with the softmax head  [§3] [§3.1]
# Input:  ids_a, ids_b (B, T); labels (B,) in {0, 1, 2}
# Output: scalar cross-entropy loss

def nli_loss(ids_a, ids_b, labels):
    # Embed both sentences with the same (tied) encoder  [§3] [fig. 1]
    u = embed(ids_a)                                    # (B, n)
    v = embed(ids_b)                                    # (B, n)
    # Concatenate u, v and |u - v|; no product u * v  [§3] [§6]
    features = concat([u, v, abs(u - v)], axis=1)       # (B, 3n)
    # Linear layer W_t of shape (3n, k) gives logits  [§3]
    logits = features @ W_t                             # (B, k)
    # Cross-entropy over the k labels  [§3]
    return cross_entropy(logits, labels)
Pseudocode
# Triplet training step  [§3] [§4.4]
# Input:  anchor, positive, negative token ids; margin epsilon (paper: 1)
# Output: scalar hinge loss

def triplet_loss(anchor, positive, negative, margin):
    # Embed the three sentences with the shared encoder  [§3]
    s_a = embed(anchor)                                 # (B, n)
    s_p = embed(positive)                               # (B, n)
    s_n = embed(negative)                               # (B, n)
    # Euclidean distances from the anchor  [§3]
    dist_pos = norm(s_a - s_p)                          # (B,)
    dist_neg = norm(s_a - s_n)                          # (B,)
    # Hinge: the positive must be at least margin closer  [§3]
    return mean(max(dist_pos - dist_neg + margin, 0))
Pseudocode
# Similarity at inference, softmax head not used  [§3] [§6]
# Input:  two sentences
# Output: cosine similarity in [-1, 1]

def similarity(sentence_a, sentence_b):
    # Embed each sentence separately  [§3]
    u = embed(sentence_a)                               # (n,)
    v = embed(sentence_b)                               # (n,)
    # Cosine similarity of the two vectors  [§3]
    return dot(u, v) / (norm(u) * norm(v))              # scalar

Hyperparameters

NameValueWhereNotes
EncoderBERT or RoBERTa, base (12 layers) or large (24 layers)§2 tab. 1 tab. 2Table labels "base" and "large" are the model sizes.
PoolingMEAN (default); MAX and CLS also tried§3 §3.1 tab. 6
Weight sharingSiamese, tied weights for both branches§3 fig. 1
Classifier head (NLI)Linear W_t ∈ ℝ^{3n×k}, input (u, v, |u−v|)§3 tab. 6Initialisation not stated.
Regression lossMSE between cosine similarity and the label§3Label scaling is not stated; see Pitfalls.
Triplet margin ε1§3Euclidean distance.
Optimizer (NLI)Adam§3.1Weight decay and β values not stated.
Learning rate (NLI)2e-5§3.1Learning rate for STSb and triplet training not stated.
Batch size (NLI)16§3.1Batch sizes for STSb and triplet training not stated.
Warm-up (NLI)linear, 10% of training data§3.1
Epochs (NLI)1§3.1
Epochs (triplet)1§4.4
Epochs (STSb)4 for BERT systems; SBERT not statedtab. 2Caption says "BERT systems were trained with 10 random seeds and 4 epochs".
Random seeds10 for STSb and for the ablation§4.2 §6 tab. 2
Max sequence lengthnot stated
Training hardwarenot stated
Inference hardwareIntel i7-5820K CPU @ 3.30GHz; NVIDIA Tesla V100 GPU; CUDA 9.2, cuDNN§7Used for the speed table.
Smart batchingSentences of similar length grouped; padded to longest in batch§7Inference speed-up.
NLI dataSNLI (570,000 pairs) + MultiNLI (430,000 pairs)§3.1Three labels.
STS benchmark8,628 pairs: train 5,749, dev 1,500, test 1,379§4.2Labels 0–5 §4.1.
AFS corpus6,000 argument pairs, 3 topics, labels 0–5§4.3Two evaluation setups.
Wikipedia sectionsabout 1.8M training triplets; 222,957 test triplets§4.4
SentEval7 transfer tasks, logistic regression, 10-fold CV§5 tab. 5

Results

Author-reported. Setups: STS evaluation with cosine similarity and Spearman ρ × 100, no STS training data for unsupervised rows §4.1 tab. 1; STSb test set §4.2 tab. 2; AFS with 10-fold CV and cross-topic evaluation §4.3 tab. 3; Wikipedia section triplets §4.4 tab. 4; SentEval 10-fold logistic regression §5 tab. 5; ablation on STSb dev §6 tab. 6; speed on STSb sentences §7 tab. 7.

Table 1 tab. 1: STS tasks, Spearman ρ × 100, no STS training data for these rows §4.1.

ModelSTS12STS13STS14STS15STS16STSbSICK-RAvg.
Avg. GloVe embeddings55.1470.6659.7368.2563.6658.0253.7661.32
Avg. BERT embeddings38.7857.9857.9863.1561.0646.3558.4054.81
BERT CLS-vector20.1630.0120.0936.8838.0816.5042.6329.19
InferSent - GloVe52.8666.7562.1572.7766.8768.0365.6565.01
Universal Sentence Encoder64.4967.8064.6176.8373.1874.9276.6971.22
SBERT-NLI-base70.9776.5373.1979.0974.3077.0372.9174.89
SBERT-NLI-large72.2778.4674.9080.9976.2579.2373.7576.55
SRoBERTa-NLI-base71.5472.4970.8078.7473.6977.7774.4674.21
SRoBERTa-NLI-large74.5377.0073.1881.8576.8279.1074.2976.68

Table 2 tab. 2: STS benchmark test set, Spearman ρ × 100, mean ± std over 10 seeds where given §4.2.

ModelSpearman
Not trained for STS
Avg. GloVe embeddings58.02
Avg. BERT embeddings46.35
InferSent - GloVe68.03
Universal Sentence Encoder74.92
SBERT-NLI-base77.03
SBERT-NLI-large79.23
Trained on STS benchmark
BERT-STSb-base84.30 ± 0.76
SBERT-STSb-base84.67 ± 0.19
SRoBERTa-STSb-base84.92 ± 0.34
BERT-STSb-large85.64 ± 0.81
SBERT-STSb-large84.45 ± 0.43
SRoBERTa-STSb-large85.02 ± 0.76
Trained on NLI data + STS benchmark
BERT-NLI-STSb-base88.33 ± 0.19
SBERT-NLI-STSb-base85.35 ± 0.17
SRoBERTa-NLI-STSb-base84.79 ± 0.38
BERT-NLI-STSb-large88.77 ± 0.46
SBERT-NLI-STSb-large86.10 ± 0.13
SRoBERTa-NLI-STSb-large86.15 ± 0.35

Table 3 tab. 3: Argument Facet Similarity, average Pearson r and Spearman ρ §4.3.

Modelrρ
Unsupervised methods
tf-idf46.7742.95
Avg. GloVe embeddings32.4034.00
InferSent - GloVe27.0826.63
10-fold cross-validation
SVR [Misra et al.]63.33-
BERT-AFS-base77.2074.84
SBERT-AFS-base76.5774.13
BERT-AFS-large78.6876.38
SBERT-AFS-large77.8575.93
Cross-topic evaluation
BERT-AFS-base58.4957.23
SBERT-AFS-base52.3450.65
BERT-AFS-large62.0260.34
SBERT-AFS-large53.8253.10

Table 4 tab. 4: Wikipedia section triplets, accuracy §4.4.

ModelAccuracy
mean-vectors0.65
skip-thoughts-CS0.62
Dor et al.0.74
SBERT-WikiSec-base0.8042
SBERT-WikiSec-large0.8078
SRoBERTa-WikiSec-base0.7945
SRoBERTa-WikiSec-large0.7973

Table 5 tab. 5: SentEval, accuracy, 10-fold cross-validation §5.

ModelMRCRSUBJMPQASSTTRECMRPCAvg.
Avg. GloVe embeddings77.2578.3091.1787.8580.1883.072.8781.52
Avg. fast-text embeddings77.9679.2391.6887.8182.1583.674.4982.42
Avg. BERT embeddings78.6686.2594.3788.6684.4092.869.4584.94
BERT CLS-vector78.6884.8594.2188.2384.1391.471.1384.66
InferSent - GloVe81.5786.5492.5090.3884.1888.275.7785.59
Universal Sentence Encoder80.0985.1993.9886.7086.3893.270.1485.10
SBERT-NLI-base83.6489.4394.3989.8688.9689.676.0087.41
SBERT-NLI-large84.8890.0794.5290.3390.6687.475.9487.69

Table 6 tab. 6: Ablation on STSb dev (cosine, Spearman) and NLI classification (accuracy) §6.

SettingNLISTSb
Pooling
MEAN80.7887.44
MAX79.0769.92
CLS79.8086.62
Concatenation (classification head, MEAN pooling)
(u, v)66.04-
(|u−v|)69.78-
(u * v)70.54-
(|u−v|, u * v)78.37-
(u, v, u * v)77.44-
(u, v, |u−v|)80.78-
(u, v, |u−v|, u * v)80.44-

Table 7 tab. 7: Sentences per second on STS benchmark sentences, higher is better §7.

ModelCPUGPU
Avg. GloVe embeddings6469-
InferSent1371876
Universal Sentence Encoder671318
SBERT-base441378
SBERT-base - smart batching832042

Headline claims in the text: the closest pair among 10,000 sentences drops from about 65 hours with BERT to about 5 seconds with SBERT (about 10,000 embeddings plus about 0.01 s of cosine computation) §1 §8. On GPU throughput, the smart-batched SBERT-base comes out roughly 9% ahead of InferSent and roughly 55% ahead of the Universal Sentence Encoder §7 tab. 7.

Paper vs code

Checked against the official repository UKPLab/sentence-transformers at code_commit (shallow clone of the default branch at HEAD, a later version of the library than the 2019 release). Training example scripts for the paper's tasks are present under examples/ at this commit.

  • Triplet margin: discrepancy. Paper uses ε = 1 §3. The TripletLoss default is triplet_margin = 5 triplet.py. The Wikipedia-sections example creates TripletLoss(model) without a margin argument, so it runs with 5 training_wikipedia_sections.py. Pass triplet_margin=1 to match the paper.
  • Optimizer: discrepancy. Paper says Adam §3.1. The fit default is torch.optim.AdamW with weight decay 0.01 fit_mixin.py. The NLI example sets neither the optimizer nor the learning rate training_nli.py, so the 2e-5 of the paper is not in the example. Whether the Trainer default matches was not verified.
  • Warm-up: matches the examples, not the fit default. Paper uses 10% of training §3.1. The examples pass warmup_steps=0.1 training_nli.py training_wikipedia_sections.py. The old fit default is a fixed 10000 steps fit_mixin.py.
  • NLI head: matches. Default concatenation is (u, v, |u − v|) with the product off softmax.py §3 §6. Cross-entropy is the default loss softmax.py. The classifier is a linear layer over 3n inputs softmax.py. Batch size 16, one epoch and num_labels=3 match training_nli.py training_nli.py training_nli.py.
  • Regression: matches with a caveat. MSE is the default loss on cosine similarity cosine_similarity.py. The default score transform is the identity, so labels are compared to a cosine in [−1, 1] without rescaling cosine_similarity.py. Paper gold labels are 0–5 §4.1; how they were rescaled is not stated.
  • Pooling: matches. MEAN is the default pooling.py. MAX is a masked max over tokens pooling.py.
  • STSb and triplet examples. STSb example: batch 16, 4 epochs training_stsbenchmark.py. Wikipedia example: batch 16, one epoch training_wikipedia_sections.py.
  • Mixed precision: not in the paper. The NLI example sets fp16=True training_nli.py. The paper does not mention precision.

Pitfalls

  • Triplet margin differs. Paper ε = 1 §3; library default 5 triplet.py. Using the default changes the loss scale and the margin's effect on training.
  • Optimizer differs. Paper "Adam" §3.1; library default AdamW with weight decay 0.01 fit_mixin.py. Weight decay is not in the paper.
  • Regression label scale is not stated. STS labels are 0–5 §4.1, cosine is in [−1, 1], and the default transform is the identity cosine_similarity.py. Rescale labels to the cosine range before training, and say so in your own code.
  • STSb epochs for SBERT are not stated. Table 2's caption gives four epochs for the BERT systems only tab. 2. The paper says nothing about SBERT's STSb epochs or batch size; the example uses 4 epochs and 16.
  • Seeds and variance. STSb rows use 10 seeds with ± std tab. 2 §4.2. Other tables report single values, and the variance across seeds is not stated for them.
  • Pooling matters. MAX pooling is much worse on STSb (69.92 vs 87.44 for MEAN) tab. 6. CLS is slightly worse than MEAN tab. 6. Keep MEAN unless you have a reason.
  • The classification head is for training only. At inference only the pooled vectors and cosine are used §6. Do not keep the NLI head in the serving path.
  • Concatenation choice matters for NLI. Adding u * v to (u, v, |u − v|) lowers NLI accuracy from 80.78 to 80.44 tab. 6, and the product-only variants are much worse tab. 6. The paper says the |u − v| term is the most important one §6.
  • Cross-topic AFS is weak. SBERT-AFS-base drops to ρ = 50.65 in cross-topic evaluation, below BERT-AFS-base at 57.23 tab. 3. The authors suggest that more than two training topics may be needed §4.3. The 10-fold result is close to BERT tab. 3.
  • Cosine vs other distances. Manhattan and Euclidean results were "roughly the same" §4; no numbers are reported in the paper.
  • Timings are hardware- and library-specific. The 65 h and 5 s figures are estimates on the authors' setup §1 §7. Table 7 mixes frameworks: SBERT and InferSent are PyTorch and USE is TensorFlow Hub §7, so the ratios mix framework and model differences. Smart batching is an inference-time optimisation §7.
  • Max sequence length and training hardware are not stated. A model with a shorter or longer token limit will produce different embeddings and different costs.
  • Equations are unnumbered in the source. Cite by section (for example §3). Do not assume an equation number.
  • Code version drift. The commit is the current library, not the 2019 release, and no release tag was checked. The example scripts may have changed since the paper.

Lineage

  • Builds on: BERT (arXiv:1810.04805) §2 and RoBERTa (arXiv:1907.11692) §2, which are fine-tuned rather than trained from scratch §2. Triplet networks are cited to FaceNet (arXiv:1503.03832) §3.
  • Compared against: average GloVe embeddings tab. 1; InferSent (Conneau et al., 2017) tab. 1; Universal Sentence Encoder (arXiv:1803.11175) tab. 1; SentEval (arXiv:1803.05449) for transfer tasks §5.
  • Superseded by: not stated in this wiki.

Source and license

Adapted from “Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks” by Nils Reimers, Iryna Gurevych (arXiv:1908.10084), used under CC BY-SA 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors. This page is licensed under CC BY-SA 4.0. Code citations refer to https://github.com/UKPLab/sentence-transformers at commit 1fa45b4212a5 (Apache-2.0). Any quoted code is shown under that license.