SST-2

Stanford Sentiment Treebank (binary)

Tests whether a model can tell if a movie-review sentence is positive or negative.

Released Oct 2013 Metric GLUE test accuracy SOTA 97.9 · Vega v1 (2022)
01

At a glance

Task
Binary sentence classification
Size
67k train (includes sub-phrases) / 872 dev / 1.8k test
Metric
Accuracy
Source
Rotten Tomatoes movie-review sentences, parsed and labelled at every node of the parse tree
Part of
GLUE
Recursive Deep Models for Semantic Compositionality Over a Sentiment Treebank
Socher, Perelygin, Wu, Chuang, Manning, Ng, Potts · EMNLP 2013
Read the paper ↗ Hugging Face ↗
02

What it tests

SST started as a treebank: every phrase in every parse tree of 11,855 movie-review sentences has a sentiment label, so a model can be trained on how sentiment composes ('not bad' from 'bad'). SST-2 keeps only full sentences, drops the neutral ones and collapses the five-point scale to positive/negative.

It is the simplest task in GLUE — single sentences, two labels, lots of training data — and was the first to be effectively solved. It still appears in model cards as a sanity check.

GPT-1 reached 91.3%; the human baseline (97.8%) was matched by 2021.

03

Examples

Items from the dataset (or representative items where the originals are not freely redistributable).

Sentence
a stirring , funny and finally transporting re-imagining of beauty and the beast and 1930s horror films
Answerpositive (1)
Sentence
apparently reassembled from the cutting-room floor of any given daytime soap .
Answernegative (0)
Sentence
the movie is not bad , just mediocre .
Answernegative — note the negation handling
04

Reported results

Scores reported on this benchmark, with the evaluation setting each one used.

SettingReportedContext
Fine-tuned91.3 accPrior best 93.2 (SOTA then was an ensemble); GPT-1 did not win this one
05

State of the art

Best known · GLUE test accuracy
97.9
✓ saturated · at or above human level
Model
Vega v1
2022
Human baseline
97.8

Source: arxiv.org ↗ · checked October 2026.

06

Quickstart

Load the benchmark and score a Hugging Face causal LM on it in a few lines.

1Install
shell
pip install -U datasets transformers evaluate lm-eval sacrebleu rouge-score scikit-learn
2Load the data

sentence, label (0 negative · 1 positive)

python · load
from datasets import load_dataset

ds = load_dataset("nyu-mll/glue", "sst2", split="validation")
print(ds)            # columns: sentence, label (0 negative · 1 positive)
print(ds[0])
3Score a model

Two helpers cover every benchmark in this collection: loglik for anything multiple-choice (score each option, pick the highest) and generate for anything free-form. Swap MODEL for whatever you are evaluating.

python · helpers
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

MODEL = "gpt2"                                   # or "Qwen/Qwen2.5-1.5B", "meta-llama/Llama-3.2-1B", …
tok = AutoTokenizer.from_pretrained(MODEL); model = AutoModelForCausalLM.from_pretrained(MODEL, torch_dtype=torch.bfloat16).eval().to("cuda")

@torch.no_grad()
def loglik(context, continuation):
    """Sum of log-probs of `continuation` tokens given `context` — the standard multiple-choice scorer."""
    ids = tok(context + continuation, return_tensors="pt").input_ids.to(model.device)
    n_ctx = len(tok(context).input_ids)
    logp = model(ids).logits.log_softmax(-1)[0, :-1]
    return logp.gather(1, ids[0, 1:, None])[n_ctx - 1:].sum().item()

@torch.no_grad()
def generate(prompt, max_new_tokens=32, stop=None):
    ids = tok(prompt, return_tensors="pt").input_ids.to(model.device)
    out = model.generate(ids, max_new_tokens=max_new_tokens, do_sample=False, pad_token_id=tok.eos_token_id)
    text = tok.decode(out[0, ids.shape[1]:], skip_special_tokens=True)
    return text.split(stop)[0] if stop else text
python · evaluate
LABELS = {"sst2": ["negative", "positive"], "cola": ["unacceptable", "acceptable"]}["sst2"]  # pick the task
def prompt(ex): return f"{ex['sentence']}\nQuestion: Is this sentence {LABELS[0]} or {LABELS[1]}?\nAnswer:"
preds = [max(range(2), key=lambda i: loglik(prompt(ex), " " + LABELS[i])) for ex in ds]
from sklearn.metrics import accuracy_score, matthews_corrcoef
print("acc", accuracy_score(ds["label"], preds), "mcc", matthews_corrcoef(ds["label"], preds))
4Or use lm-evaluation-harness

Task name(s): sst2. The harness reproduces the GPT-3 prompt formats and reports the standard metric.

shell
lm_eval --model hf --model_args pretrained=gpt2,dtype=bfloat16 \
        --tasks sst2 --num_fewshot 0 --batch_size auto --output_path results/
07

Pitfalls

  • The train split includes sub-phrases; dev/test are full sentences only.
  • Text is lower-cased and tokenised with spaces around punctuation — keep it as is for comparability.
  • Zero-shot LLM prompts should include 'positive'/'negative' as the verbaliser; 'good'/'bad' changes results.
08

References