Chapter 18 · Section 18.2 · 60 min

Sampling more, choosing better

Ask a model a competition math problem and it gets it right 30% of the time. You have budget for 64 samples. What should you do with them?

There are three very different things "64 samples" can buy. You could check whether any of them is right, which you can only do if you have a way to check. You could return the answer that appears most often. Or you could have a second model score each sample and return the favorite. These are called coverage, voting, and selection, and the gaps between them explain a surprising amount about modern reasoning systems. A model that solves a problem once in a hundred tries has the knowledge somewhere, and a training method that finds that one success and reinforces it is what §18.4 builds. A deployment that cannot tell which try was the right one keeps only what voting or a verifier can recover.

This section works through all three, derives the unbiased estimator that every paper uses to report pass@k (and that many people get wrong), and ends with the simplest way to turn samples into training data, rejection sampling fine-tuning.

Setup and notation

Fix a problem xx with a correct final answer a⋆a^\star. The model is a policy πθ\pi_\theta (§15.7), and we sample nn responses y1,…,yn∼πθ(⋅∣x)y_1, \dots, y_n \sim \pi_\theta(\cdot\mid x) independently, at a temperature τ>0\tau > 0 so they differ (§6.4). Each response is a chain of thought ending in an answer, and an extractor ans⁡(y)\operatorname{ans}(y) reads the answer off (§18.1 and §18.3 discuss how). Write ai=ans⁡(yi)a_i = \operatorname{ans}(y_i). The per-problem success rate is

p(x)=Py∼πθ(⋅∣x)[ans⁡(y)=a⋆],p(x) = \mathbb{P}_{y\sim\pi_\theta(\cdot\mid x)}\big[\operatorname{ans}(y) = a^\star\big],

and the answers are draws from a distribution q(a∣x)q(a\mid x) over possible final answers, with q(a⋆∣x)=p(x)q(a^\star\mid x) = p(x). A benchmark is a set of problems, so every metric below is an average over problems of a per-problem quantity.

metricper-problem definitionneeds
pass@1p(x)p(x)nothing
pass@kk (coverage)P[some ai=a⋆]\mathbb{P}[\text{some } a_i = a^\star] over kk samples, 1−(1−p)k1 - (1-p)^ka perfect checker at use time
maj@kk (self-consistency)P[the most frequent of a1..ak is a⋆]\mathbb{P}[\text{the most frequent of } a_1..a_k \text{ is } a^\star]a way to tell when two answers are the same
BoN@kk (best of kk)P[the highest-scored of k samples is right]\mathbb{P}[\text{the highest-scored of } k \text{ samples is right}]a scoring model (a verifier or reward model)

DeepSeek and others write cons@k (consensus) for maj@kk. All four agree at k=1k = 1, and they separate as kk grows.

Self-consistency, or majority voting

Wang et al. (2023) proposed the simplest possible use of many chains of thought. Sample several, ignore the reasoning, and return the most common final answer,

a^=arg⁡max⁡a∑i=1n1[ai=a].\hat a = \arg\max_a \sum_{i=1}^{n}\mathbb{1}[a_i = a].

In plain words, many different lines of reasoning that arrive at the same answer are evidence for it, and wrong lines of reasoning tend to arrive at different wrong answers. They called it self-consistency, and with 40 sampled chains the gains were large. On code-davinci-002, GSM8K accuracy went from 60.1% with one greedy chain to 78.0% (+17.9 points), SVAMP from 75.8% to 86.8%, AQuA from 39.8% to 52.0%, StrategyQA from 73.4% to 79.8%, and ARC-challenge from 83.6% to 87.5%. PaLM 540B gained the same 17.9 points on GSM8K, from 56.5% to 74.4%. They also tried weighting each vote by the chain's probability. Summing votes weighted by each chain's length-normalized probability gave 74.1% on PaLM 540B, no better than the plain vote's 74.4%, and schemes that averaged probabilities instead of summing votes did much worse, down to 22.1%. Raw sequence probabilities are dominated by length and by phrasing, so they carry little extra information about correctness.

When voting works, and its limit

Voting is a mode estimator. As nn grows, the vote count of each answer, divided by nn, converges to q(a∣x)q(a\mid x) by the law of large numbers, so the winner converges to the mode of qq. Therefore

lim⁡n→∞maj@n(x)={1if a⋆ is the unique most likely answer,0if some wrong answer is more likely than a⋆.\lim_{n\to\infty}\text{maj@}n(x) = \begin{cases} 1 & \text{if } a^\star \text{ is the unique most likely answer,} \\ 0 & \text{if some wrong answer is more likely than } a^\star. \end{cases}

Two consequences follow, and both surprise people. First, the correct answer does not need a majority, only a plurality. A model that is right 30% of the time, with its wrong answers spread over many values, gets that problem right with near certainty at large nn. Second, voting can make things worse. If the model has a favorite wrong answer that it gives 40% of the time while being right 30% of the time, then pass@1 is 0.3 but maj@∞\infty is 0. Benchmark accuracy under voting converges to the fraction of problems on which the correct answer is the mode, which can be above or below the average pass@1.

When does voting over more samples help, and when does it make things worse?
One problem. Each sample's final answer is correct with probability p, equals one favored wrong answer with probability q, and otherwise is one of several other wrong answers, all equally likely. The vote picks the most frequent answer, breaking ties at random.
Loading interactive figure…

The vote needs to know when two answers are "the same", and that is harder than it looks. 1/2, 0.5, \frac{1}{2}, and 0.50 are one answer. 1,000 and 1000 are one answer. If the normalizer misses that, it splits the correct votes across spellings and hands the win to a wrong answer that happens to be written consistently.

Python · cell 1

Majority voting moves slowly toward the fraction of problems on which the correct answer is the mode (0.44 here, against a mean pass@1 of 0.36), and it is not even monotone, dipping at k=4k = 4, because problems whose mode is a wrong answer lose ground quickly while problems whose correct answer is only a narrow mode gain slowly. Pass@kk climbs toward 1 much faster. The distance between the two lines is the subject of the rest of this section.

Interview

Majority voting with answer normalization

Implement normalize_answer(s) and majority_vote(answers).

normalize_answer takes a string or None. Return None for None or a string that is empty after stripping. Otherwise strip whitespace and a trailing period, remove dollar signs, and remove commas that sit between digits ("1,000" becomes "1000"). If what remains parses as a number with fractions.Fraction (integers, decimals such as "0.50", fractions such as "1/2", with an optional sign), return str(Fraction(...)), so "0.5", "1/2", and "2/4" all become "1/2" and "3.0" becomes "3". Otherwise return the string lowercased with runs of whitespace collapsed to one space.

majority_vote takes a list of raw answers and returns (winner, count), the normalized answer with the most votes and its count. Answers that normalize to None do not vote. Break ties in favor of the answer whose first appearance in the list comes earliest. If no answer votes, return (None, 0).

Hidden tests, hints, and AI help, from $1.99 a month.

Coverage, and the pass@k estimator

In code generation, there usually is a checker. Given a function signature and a docstring, generate kk programs, run each against unit tests, and count the problem solved if any passes. That metric, pass@kk, was introduced for code by Kulal et al. (2019) and made standard by the Codex paper (Chen et al. 2021), which also introduced HumanEval, 164 hand-written Python problems with an average of 7.7 tests each. The Codex-12B model solved 28.8% of them with one sample and, per the abstract, 70.2% with 100 samples. Selection mattered just as much. A fine-tuned variant, Codex-S, solved 37.7% with one sample. Given 100 samples, choosing the one with the highest mean log-probability solved 44.5%, and choosing one that passed the unit tests solved 77.5%.

For a single problem, pass@kk is 1−(1−p)k1 - (1 - p)^k, and in §9.6 Exercise 9.6d computed it from known pp. In practice pp is unknown and must be estimated from samples. Here is the trap.

The obvious estimator is biased

Draw n≥kn \ge k samples and count cc correct ones. The plug-in estimate replaces pp by p^=c/n\hat p = c/n,

pass@k^plug-in=1−(1−cn)k.\widehat{\text{pass@}k}_{\text{plug-in}} = 1 - \Big(1 - \frac{c}{n}\Big)^k .

This is biased low. The function f(u)=(1−u)kf(u) = (1 - u)^k is convex on [0,1][0, 1] for k≥1k \ge 1, so by Jensen's inequality E[f(p^)]≥f(E[p^])=f(p)=(1−p)k\mathbb{E}[f(\hat p)] \ge f(\mathbb{E}[\hat p]) = f(p) = (1 - p)^k. Subtracting from 1 flips the inequality, so the plug-in estimate's expectation is at most the true pass@kk, with equality only when k=1k = 1 or p∈{0,1}p \in \{0, 1\}. The bias is worst when kk is close to nn and pp is small, which is exactly the regime of interest. With n=20n = 20, k=20k = 20, and p=0.05p = 0.05, the truth is 1−0.9520=0.641 - 0.95^{20} = 0.64, but the plug-in estimate is 1−(1−c/20)201 - (1 - c/20)^{20}, which for the most likely outcome c=1c = 1 is also 0.64 and for c=0c = 0 (probability 0.360.36) is 0, and averaging over all cc gives 0.48, an underestimate of a quarter.

The unbiased estimator, derived

The fix is to stop pretending the nn samples are a sample from a distribution with success rate c/nc/n and use them directly. Imagine choosing kk of the nn samples uniformly at random without replacement. The probability that all kk chosen are wrong is the number of ways to choose kk from the n−cn - c wrong ones over the number of ways to choose kk from all nn. So define

pass@k^=1−(n−ck)(nk).\widehat{\text{pass@}k} = 1 - \frac{\binom{n-c}{k}}{\binom{n}{k}} .

In plain words, among all the size-kk subsets of your nn samples, what fraction contain at least one correct answer?

∂ Why this estimator is unbiased

Fix the problem, so pp is fixed, and treat the nn samples as random. Let SS be a uniformly random size-kk subset of {1,…,n}\{1, \dots, n\}, chosen independently of the samples. Given the samples (and so cc), the probability that every sample in SS is wrong is exactly (n−ck)/(nk)\binom{n-c}{k}/\binom{n}{k}, by counting. So

E[(n−ck)(nk)]=E[P(all samples in S wrong∣samples)]=P(all samples in S wrong),\mathbb{E}\Big[\tfrac{\binom{n-c}{k}}{\binom{n}{k}}\Big] = \mathbb{E}\big[\mathbb{P}(\text{all samples in } S \text{ wrong} \mid \text{samples})\big] = \mathbb{P}(\text{all samples in } S \text{ wrong}),

by the law of total probability. Now look at the right side the other way around. Because SS is chosen independently of the samples, and the samples are i.i.d., the kk samples indexed by SS are themselves kk i.i.d. draws from the model. The probability that kk i.i.d. draws are all wrong is (1−p)k(1-p)^k. Therefore

E[pass@k^]=1−(1−p)k=pass@k.□\mathbb{E}\big[\widehat{\text{pass@}k}\big] = 1 - (1 - p)^k = \text{pass@}k. \qquad \square

The plug-in estimator, by contrast, corresponds to choosing kk samples with replacement from the nn. Repeated picks of the same sample are not independent draws from the model, which is where its bias comes from. The unbiased estimator also uses every one of the nn samples. It is the average, over all ways of choosing the subset, of the crude estimator "is some sample in this one subset correct", so its variance is no larger than that of the alternative of splitting the samples into n/kn/k disjoint groups of kk and counting the groups that contain a success.

Computing it without overflow

Binomial coefficients get astronomically large. With n=10,000n = 10{,}000 samples (Brown et al. drew that many), (100005000)\binom{10000}{5000} has more than 3,000 digits, far beyond the largest float64, about 1.8×103081.8\times10^{308}. Dividing two floats overflows, and dividing two exact integers that size is slow when you do it for thousands of problems and many values of kk. Expand the ratio instead,

(n−ck)(nk)=(n−c)! (n−k)!n! (n−c−k)!=∏j=n−c+1nj−kj=∏j=n−c+1n(1−kj),\frac{\binom{n-c}{k}}{\binom{n}{k}} = \frac{(n-c)!\,(n-k)!}{n!\,(n-c-k)!} = \prod_{j=n-c+1}^{n}\frac{j - k}{j} = \prod_{j=n-c+1}^{n}\Big(1 - \frac{k}{j}\Big),

where the middle step pairs the cc factors j=n−c+1,…,nj = n - c + 1, \dots, n of n!/(n−c)!n!/(n-c)! with the cc factors j−kj - k of (n−k)!/(n−c−k)!(n-k)!/(n-c-k)!. The product has cc terms, each in [0,1)[0, 1), and never overflows. If n−c<kn - c < k, every size-kk subset contains a correct sample and the estimate is exactly 1. This is the form in the Codex paper's reference code. For very large cc, summing logarithms (np.log1p(-k / j).sum()) is safer than a long product, which can underflow to zero harmlessly but loses the relative precision you might want for reporting 1−pass@k^1 - \widehat{\text{pass@}k}.

How does pass@k grow with k, and what does a single number hide?
pass@k is the chance that at least one of k independent samples is correct. The x-axis is logarithmic, from 1 to 10,000 samples.
Loading interactive figure…
Interview

The unbiased pass@k estimator, numerically stable

Implement pass_at_k(n, c, k). n and c may be Python ints or NumPy arrays of the same shape (one entry per problem), and k is a positive int. Return the unbiased estimate 1−(n−ck)/(nk)1 - \binom{n-c}{k}/\binom{n}{k} for each problem, as a float or a float array of the same shape. It must be exact where n - c < k (return 1.0), give 0.0 when c == 0, raise ValueError if k > n for any problem, and stay accurate for n in the hundreds of thousands. Then the benchmark score is pass_at_k(n, c, k).mean().

Hidden tests, hints, and AI help, from $1.99 a month.

Best-of-n with a verifier

When there is no checker at deployment, we can train one. Cobbe et al. (2021) introduced GSM8K (8.5K problems, split into 7.5K for training and 1K for testing) together with this idea. Fine-tune a generator, sample 100 solutions to each training problem, label each one correct or not by its final answer, and train a verifier to predict that label from the problem and the solution. At test time, sample 100 solutions and return the one the verifier scores highest. A 6B generator with a 6B verifier slightly outperformed a fine-tuned 175B model, which the authors described as a boost roughly equivalent to a 30 times larger model. Two details are worth keeping. A verifier trained to predict correctness at every token (a value function, in the language of §15.4) eventually beat one that predicted only at the end of the solution. And accuracy rose with the number of candidates up to about 400 and then fell, because with more candidates the verifier is more likely to meet an adversarial solution that fools it.

That last finding is general. Best-of-nn is an optimizer, and it optimizes the verifier's score, not correctness. The more candidates you search over, the further you push into the verifier's errors, which is the same overoptimization that §16.5 studies for reward models. That section also derives how far best-of-nn moves from the base policy, DKL(πbon∥πθ)=log⁡n−n−1nD_{\mathrm{KL}}(\pi_{\text{bon}}\Vert\pi_\theta) = \log n - \frac{n-1}{n}, where πbon\pi_{\text{bon}} is the distribution of the selected response and πθ\pi_\theta the base policy, when scores have no ties (an upper bound when they do, as Beirami et al. 2024 showed). The KL grows only like log⁡n\log n, so best-of-1000 is less than 6 nats from the base policy, which makes best-of-nn a gentle optimizer by RL standards and a convenient yardstick for how hard a verifier is being pushed.

Best-of-nn and voting can be combined. Weighted voting sums verifier scores per distinct answer and returns the answer with the largest total, so an answer reached by many reasonably scored chains can beat one reached by a single high-scoring chain. It is often the strongest simple selector when the verifier is decent but not perfect. Lightman et al. (2023) used plain best-of-nn with outcome and process verifiers on the MATH dataset, which is where §18.6 picks up.

Evaluating a verifier raises the same estimation problem as pass@kk. You want BoN@kk for several kk, but drawing fresh sets of kk samples for each kk is wasteful. As with pass@kk, there is an unbiased estimator that uses one set of nn samples for every k≤nk \le n.

Interview

An unbiased estimate of best-of-k accuracy

For one problem you have nn samples with verifier scores scores (shape (n,), all distinct) and correctness labels correct (shape (n,), 0 or 1). Implement bon_at_k(scores, correct, k), the expected correctness of the highest-scored sample in a uniformly random subset of kk of the nn samples, computed exactly without enumerating subsets. Also implement best_of_n(answers, scores) returning the answer with the highest score (the first one if scores tie).

Hidden tests, hints, and AI help, from $1.99 a month.

Coverage versus selection

Brown et al. (2024) pushed repeated sampling far further than anyone had, up to 10,000 samples per problem, and gave the phenomenon a name, Large Language Monkeys. Coverage kept rising across four orders of magnitude of samples, and its growth was well described by an exponentiated power law, c(k)≈exp⁡(a kb)c(k) \approx \exp(a\,k^{b}) with fitted a<0a < 0 and b<0b < 0, so log⁡c(k)\log c(k) rises toward zero like a power of kk. On SWE-bench Lite, where unit tests make a checker available, DeepSeek-Coder-V2-Instruct went from 15.9% of issues solved with one sample to 56% with 250 samples, past the single-sample state of the art at the time, 43%. Five samples from the cheaper model solved more issues than one sample from GPT-4o or Claude 3.5 Sonnet, at over three times lower cost.

Without a checker, the picture was very different. On MATH, Llama-3-8B-Instruct's coverage went from 82.9% at 100 samples to 98.44% at 10,000, while the best of the selection methods they tried, majority voting or reward models, improved only from 40.50% to 41.41% over the same range. Selection methods plateaued beyond a few hundred samples. The model could solve almost every problem, sometimes, and nobody could tell which sample was the solution.

That gap is where reasoning RL comes in. When a checker exists at training time, a problem the model solves once in a hundred tries is a problem with a training signal. RL with verifiable rewards (§18.3) samples a group of answers, rewards the ones the checker accepts, and moves the policy toward them, which raises pass@1, which is what a deployed model without a checker needs. Whether RL can also raise coverage itself, or only concentrates the mass the base model already had, is an open question with real evidence on both sides (§18.5). DeepSeekMath already observed that its RL stage improved maj@kk but not pass@kk (Shao et al. 2024).

methodwhat it returnsneedshow it scales with kk
greedy or one sampleone answernothingflat
majority votethe mode of the answerscanonical answersconverges to "is the correct answer the mode"
best-of-kkthe verifier's favoritea trained verifierrises, then can fall as the verifier is exploited
weighted votethe answer with the largest total scorea verifier and canonical answersoften the most robust of the selectors
pass@kk"some sample is right"a perfect checker at use timesmooth growth toward the solvable fraction

Rejection sampling fine-tuning

The simplest way to use a checker at training time needs no RL at all. Sample many solutions per training problem, keep the ones the checker accepts, and fine-tune on them. This is rejection sampling fine-tuning (RFT), and in §15.3 we saw it is REINFORCE in disguise. With a reward of 1 for a correct answer and 0 otherwise, the REINFORCE surrogate loss is the supervised loss on the correct samples, so one round of RFT is one large policy gradient step, taken with many optimizer updates on fixed samples, which makes it increasingly off-policy as those updates move the model. Iterating the loop (sample from the new model, filter, fine-tune again) is called expert iteration.

The best-known version for reasoning is STaR, the Self-Taught Reasoner (Zelikman et al. 2022). Start from a handful of exemplar rationales, have the model write a rationale and answer for every training question, and keep the rationales that reach the right answer. For the questions it got wrong, STaR adds rationalization. Give the model the correct answer as a hint, ask it to write a rationale that arrives there, and, if it does, keep that rationale as though it had been written without the hint. Fine-tune on everything kept, starting each outer round from the original pretrained model rather than the last checkpoint to limit overfitting, and repeat. On CommonsenseQA, GPT-J (6B) with STaR reached 72.5%, against 60.0% when fine-tuned to answer directly and 68.8% for STaR without rationalization, close to the 73.0% of a fine-tuned GPT-3 that is 30 times larger. Rationalization is what lets the loop learn from problems the model never solves on its own, at the price of training on text from a different, hint-conditioned distribution, which a pure policy gradient never does. Loops of this kind are the foundation that self-improvement methods build on, and RL with verifiable rewards (§18.4) is the version that also learns from the failures instead of discarding them.

Yuan et al. (2023) studied RFT carefully on GSM8K and found that what matters is the number of distinct reasoning paths, not the number of samples. They deduplicated correct samples by their list of equations, so two solutions that do the same arithmetic in different words count once. On LLaMA-7B, supervised fine-tuning on the training set reached 35.9%. RFT with 100 samples per problem reached 41.7%. Pooling distinct correct paths sampled from several different models reached 49.3%. RFT also helped weaker models more than stronger ones, which makes sense, since a weak model's own correct samples contain more paths it was not already producing. Many labs use a version of this as a stage of post-training, often with a reward model doing the filtering when there is no checker (§14.1).

Core

Building a rejection-sampling dataset with distinct reasoning paths

samples maps each problem id to a list of generated solutions (strings), and answers maps each problem id to its correct answer as a string. Each solution ends with a line The answer is X. Implement build_rft_dataset(samples, answers, max_per_problem) returning a list of (problem_id, solution) pairs.

  • Keep a solution only if its final answer (the text after the last The answer is, stripped, without a trailing period) equals the correct answer after normalize_answer from Exercise 18.2a (it is provided).
  • Treat two solutions as the same reasoning path if they contain the same sequence of equations. An equation is a match of the regex r"[\d\.\s\+\-\*/\(\)]+=\s*[\d\.]+", with all whitespace removed. Keep only the first solution of each path.
  • Keep at most max_per_problem solutions per problem, in the order they appear. Problems with no kept solutions contribute nothing.
Hidden tests, hints, and AI help, from $1.99 a month.

In PyTorch

At evaluation scale you score thousands of problems with hundreds of samples each, so the voting and the estimator should be batched. Here is the whole evaluation of a toy model, sampling, majority vote, and unbiased pass@kk, with no Python loop over problems.

🔥 In PyTorchfor a machine with PyTorch

Note the clamp inside lgamma. Where n−c<kn - c < k the argument would be negative and lgamma would return garbage, which torch.where then discards, but a NaN in the discarded branch can still poison gradients if you ever differentiate through it. Clamping first is the habit that avoids that class of bug.

Read more

Watch next

🎬 Adv. LLM Agents MOOC | UC Berkeley Sp25 | Inference-Time Techniques for LLM Reasoning by Xinyun Chen · Berkeley RDI · starts at 46:59Self-consistency, clustering of samples in AlphaCode, universal self-consistency, and trained verifiers in one connected stretch of lecture.
🎬 Inference Scaling: A New Frontier for AI Capability · Simons Institute for the Theory of Computing · starts at 3:01Azalia Mirhoseini presents Large Language Monkeys, with coverage rising smoothly in the number of samples while majority voting and reward models plateau.
🎬 RLHF Foundations, IFT, Reward Modeling, Rejection Sampling | Post-Training Course Lecture 2 · Nathan Lambert · starts at 43:57A focused segment on rejection sampling, generating many completions, ranking them, and fine-tuning on the best.