VKVlad KulikovPublic / lectures
RL for LLM3 / 13

Module 3. Bandits, exploration, and one-step decisions

Try each exercise first. Expand worked answers or project guidance when needed; their open state is shared between RU/EN.

Download course files (.zip) 382.1 KB

The archive preserves the source folder structure, both languages, and supporting files.

Bandit or sequential problem

For each case, choose the most accurate model: ordinary bandit, contextual bandit, or Markov decision process (MDP).

  1. For every independent request, a service chooses one of three models. Request features are known, one scalar score arrives after the response, and the choice does not affect later requests.

  2. An agent opens web pages, extracts information, and decides which link to follow next.

  3. Two fixed banners are rotated for an otherwise identical audience; only the click on the displayed banner is observed.

  4. A dialogue system chooses an utterance, after which the user replies and changes the course of the conversation.

For every answer, name one assumption whose violation would change the model.

Show answer and solution
  1. Contextual bandit. Request features affect the model choice, but the response does not change the next request. The abstraction fails if serving a user affects retention or later requests.

  2. Markov decision process (MDP). Opening a page changes the available links and information, so the action creates a successor state.

  3. Ordinary bandit. Context is treated as constant and only the displayed banner's reward is observed. Audience drift or changing banner appeal would introduce non-stationarity or context.

  4. MDP, possibly partially observed. The utterance changes the future dialogue. A bandit would be adequate only for one isolated utterance with no continuation.

The decisive test is whether action value depends on a controlled future state.

What regret measures

Select three correct statements.

  1. A trajectory's pseudo-regret can be computed without knowing the true reward means.

  2. The decomposition RT=∑aΔaE[Na(T)]R_T=\sum_a\Delta_a\mathbb{E}[N_a(T)] shows that an action with a small gap may be selected more often at a small immediate cost.

  3. Sublinear regret means RT/T→0R_T/T\to0.

  4. Logarithmic regret guarantees that an algorithm outperforms every other algorithm at every finite horizon.

  5. Realized cumulative reward remains random under a fixed action sequence when rewards are noisy.

Show answer and solution

Statements 2, 3, and 5 are correct.

Pseudo-regret requires the true means, which are normally known only to a simulator. The gap decomposition assigns cost Δa\Delta_a to every suboptimal selection. Sublinear regret is exactly RT/T→0R_T/T\to0. An asymptotic order does not rank all algorithms at every finite horizon. Finally, noisy rewards make realized cumulative reward random even under a fixed action sequence.

Constant ε and optimistic initialization

Select the two most accurate statements.

  1. With fixed ε>0\varepsilon>0, ε-greedy continues to select suboptimal actions with positive frequency.

  2. Optimistic initialization guarantees logarithmic regret in every non-stationary environment.

  3. A constant step size can help under reward drift because it downweights old observations.

  4. Pure greediness has linear regret on every individual run.

  5. Any decaying εt\varepsilon_t schedule automatically gives optimal regret.

Show answer and solution

Statements 1 and 3 are correct.

A fixed ε leaves a permanent random branch. A constant step size exponentially downweights old observations and can track drift. Optimistic initialization is not a universal guarantee, pure greediness can succeed on a particular run, and a decaying ε schedule can stop exploration too early if it decreases too fast.

Scope of a classical confidence-bound guarantee

An upper confidence bound (UCB) method is used in a stationary bandit; UCB1 is its classical variant.

Select three conditions or qualifications needed to read the UCB1 guarantee correctly.

  1. Rewards are bounded; the standard theorem uses [0,1][0,1].

  2. Reward means remain unchanged over time.

  3. The logarithmic bound is independent of action gaps Δa\Delta_a.

  4. Finite-horizon regret may remain substantial when two actions are nearly equal.

  5. Any neural uncertainty score is automatically a UCB confidence bound.

  6. The action set may change arbitrarily during learning while the classical UCB1 proof remains unchanged.

Show answer and solution

An upper confidence bound (UCB) method and its classical UCB1 variant must be read together with their assumptions. Statements 1, 2, and 4 are correct.

Classical UCB1 uses bounded rewards in [0,1][0,1], stationary means, and an instance-dependent bound involving 1/Δa1/\Delta_a. Nearly tied actions can therefore be expensive to distinguish. An arbitrary neural uncertainty score is not automatically a confidence bound. An arbitrarily changing action set is a different problem, so the classical proof cannot simply be reused unchanged.

What Thompson sampling does

A Bernoulli action starts with a Beta⁡(1,1)\operatorname{Beta}(1,1) prior. After 8 successes and 2 failures, select three correct statements.

  1. The posterior is Beta⁡(9,3)\operatorname{Beta}(9,3).

  2. The algorithm always selects the largest posterior mean with no randomness.

  3. On every round, it samples one plausible mean for every action.

  4. A poorly observed action can be selected because its posterior is wide.

  5. The 1933 publication date itself proves a modern logarithmic regret guarantee.

Show answer and solution

Statements 1, 3, and 4 are correct.

The posterior is

Beta⁡(1+8,1+2)=Beta⁡(9,3).\operatorname{Beta}(1+8,1+2)=\operatorname{Beta}(9,3).

Thompson sampling draws one plausible mean per action and selects the largest draw. A broad posterior can therefore trigger exploration. The method is not greedy in the posterior mean, and the historical publication date does not establish later regret theory.

An LLM as a contextual bandit

Select three correct statements.

  1. If the prompt is context, a full response is one action, a scalar reward follows, and the episode ends, the external problem is a contextual bandit.

  2. The whole-response abstraction implies that tokens cease to be sequential actions.

  3. A multi-turn tool-using agent usually needs state that contains consequences of previous actions.

  4. Choosing among several models for independent requests can be a contextual bandit.

  5. Every Best-of-N procedure is automatically a multi-armed bandit.

Show answer and solution

Statements 1, 3, and 4 are correct.

A whole-response terminal abstraction is a contextual bandit. Token generation remains sequential internally. Tool-using and multi-turn systems need state because actions change what happens next. Model routing over independent requests is a natural contextual bandit. Fixed-policy Best-of-N is repeated sampling and selection, not automatically a multi-armed bandit.

Overlap in logged-policy evaluation

Inverse propensity scoring (IPS) evaluates a target policy π\pi from logs generated by behavior policy μ\mu. Its self-normalized form is self-normalized inverse propensity scoring (SNIPS), while a doubly robust (DR) estimator combines reward predictions with propensity weights.

Select three correct statements.

  1. Every pair (x,a)(x,a) with π(a∣x)>0\pi(a\mid x)>0 requires μ(a∣x)>0\mu(a\mid x)>0.

  2. Small behavior probabilities can produce large weights and high variance.

  3. If behavior probabilities were not logged, they can always be reconstructed exactly from selected actions.

  4. Self-normalized IPS is generally biased.

  5. A doubly robust estimator creates an observed reward for an action that was never selected or modeled.

Show answer and solution

Inverse propensity scoring (IPS), self-normalized inverse propensity scoring (SNIPS), and a doubly robust (DR) estimator all depend on how the log was collected. Statements 1, 2, and 4 are correct.

IPS needs positive behavior probability wherever the target policy places mass. Small propensities cause large importance weights and high variance. SNIPS usually reduces sensitivity to scale but introduces bias. Chosen actions alone do not identify the randomized selection probability, and DR does not manufacture observed counterfactual outcomes without support.

Temperature, Best-of-N, and entropy

Item 6 refers to group relative policy optimization (GRPO). Select four correct statements.

  1. Raising the temperature of a pure softmax with fixed logits flattens the distribution.

  2. Temperature sampling from a frozen LLM updates the policy from reward by itself.

  3. For independent candidates with the same success probability pp, 1−(1−p)N1-(1-p)^N is the probability that the pool contains at least one success.

  4. The finite-sample pass@kk estimator from nn candidates and cc successes is 1−(n−ck)/(nk)1-\binom{n-c}{k}/\binom{n}{k}.

  5. Lower entropy always means a worse policy.

  6. If all rewards in a GRPO group are equal, subtracting the group mean gives zero relative signal.

Show answer and solution

Statements 1, 3, 4, and 6 are correct.

Temperature changes a fixed softmax distribution but does not update parameters from reward. The coverage formula assumes independence and the same success probability pp for a fixed prompt. Perfect selection is an additional condition for equating coverage with returned-answer accuracy; a successful candidate can exist without being selected. The combinatorial expression estimates pass@kk from a finite sample. Entropy can decrease for legitimate reasons; it becomes a failure mode only in context. Equal group rewards yield zero mean-centered advantages.

Incremental mean

An action has been selected 4 times and its current estimate is Q4=0.35Q_4=0.35. The fifth reward is 11.

  1. Compute Q5Q_5 incrementally.

  2. Find the sum of the first four rewards consistent with Q4Q_4.

  3. Verify the result with the direct mean of all five observations.

Show answer and solution
Q5=0.35+15(1−0.35)=0.48.Q_5 =0.35+\frac{1}{5}(1-0.35) =0.48.

The first four rewards sum to

S4=4Q4=1.4.S_4=4Q_4=1.4.

Directly,

S4+15=2.45=0.48.\frac{S_4+1}{5}=\frac{2.4}{5}=0.48.

Regret decomposition

Three actions have means

μ=(0.2, 0.5, 0.7).\mu=(0.2,\ 0.5,\ 0.7).

Over T=100T=100 rounds, expected selection counts are

E[N(T)]=(10, 30, 60).\mathbb{E}[N(T)]=(10,\ 30,\ 60).
  1. Find μ∗\mu^* and the gaps Δa\Delta_a.

  2. Compute expected regret.

  3. How does regret change if 10 selections of action 2 are replaced by 10 selections of action 3?

Show answer and solution

The optimum is μ∗=0.7\mu^*=0.7, so

Δ=(0.5, 0.2, 0).\Delta=(0.5,\ 0.2,\ 0).

Expected regret is

RT=0.5⋅10+0.2⋅30=11.R_T=0.5\cdot10+0.2\cdot30=11.

Replacing ten selections of action 2 by action 3 removes 10⋅0.2=210\cdot0.2=2 regret, leaving 99.

One UCB1 index calculation

At round t=101t=101, two actions have estimates and counts

μ^1=0.55,N1=80,\widehat\mu_1=0.55,\quad N_1=80, μ^2=0.48,N2=20.\widehat\mu_2=0.48,\quad N_2=20.

For

Ia=μ^a+2log⁡tNa,I_a=\widehat\mu_a+\sqrt{\frac{2\log t}{N_a}},

compute I1I_1 and I2I_2 to three decimals and state the selected action. Explain why the action with the lower sample mean may win.

Show answer and solution
I1=0.55+2log⁡10180≈0.890,I_1 =0.55+\sqrt{\frac{2\log101}{80}} \approx0.890, I2=0.48+2log⁡10120≈1.159.I_2 =0.48+\sqrt{\frac{2\log101}{20}} \approx1.159.

Action 2 is selected. Its sample mean is lower, but it has only one quarter as many observations, so its uncertainty bonus is much larger. The index is an optimistic selection rule, not a claim that action 2 is truly better.

Beta posterior

Two Bernoulli actions use Beta⁡(1,1)\operatorname{Beta}(1,1) priors.

  • action 1: 12 successes and 8 failures;
  • action 2: 3 successes and 1 failure.
  1. Write both posteriors.

  2. Compute their means.

  3. Which action has the larger posterior mean?

  4. Why can Thompson sampling still select the other action?

Show answer and solution

Action 1:

μ1∣D∼Beta⁡(13,9),E[μ1∣D]=1322≈0.591.\mu_1\mid\mathcal D\sim\operatorname{Beta}(13,9), \qquad \mathbb E[\mu_1\mid\mathcal D]=\frac{13}{22}\approx0.591.

Action 2:

μ2∣D∼Beta⁡(4,2),E[μ2∣D]=46≈0.667.\mu_2\mid\mathcal D\sim\operatorname{Beta}(4,2), \qquad \mathbb E[\mu_2\mid\mathcal D]=\frac{4}{6}\approx0.667.

Action 2 has the larger posterior mean, but its posterior is based on only four observations and is wider. A sample from Beta⁡(13,9)\operatorname{Beta}(13,9) can exceed a sample from Beta⁡(4,2)\operatorname{Beta}(4,2) on a given round, so Thompson sampling can choose action 1.

IPS, SNIPS, and DR on three rows

The log contains:

iirir_iμ(ai∣xi)\mu(a_i\mid x_i)π(ai∣xi)\pi(a_i\mid x_i)r^(xi,ai)\widehat r(x_i,a_i)∑aπ(a∣xi)r^(xi,a)\sum_a\pi(a\mid x_i)\widehat r(x_i,a)
110.501.000.600.70
200.250.500.300.40
310.800.400.700.65
  1. Compute wi=π/μw_i=\pi/\mu.

  2. Compute V^IPS=n−1∑iwiri\widehat V_{\mathrm{IPS}}=n^{-1}\sum_iw_ir_i.

  3. Compute V^SNIPS=∑iwiri/∑iwi\widehat V_{\mathrm{SNIPS}}=\sum_iw_ir_i/\sum_iw_i.

  4. Compute the doubly robust (DR) estimate.

  5. Which row contributes most to IPS variance, and why?

Show answer and solution

The weights are

w=(2, 2, 0.5).w=(2,\ 2,\ 0.5).

IPS:

V^IPS=2⋅1+2⋅0+0.5⋅13≈0.8333.\widehat V_{\mathrm{IPS}} =\frac{2\cdot1+2\cdot0+0.5\cdot1}{3} \approx0.8333.

SNIPS:

V^SNIPS=2.54.5≈0.5556.\widehat V_{\mathrm{SNIPS}} =\frac{2.5}{4.5} \approx0.5556.

The row-wise DR terms are

0.70+2(1−0.60)=1.50,0.70+2(1-0.60)=1.50, 0.40+2(0−0.30)=−0.20,0.40+2(0-0.30)=-0.20, 0.65+0.5(1−0.70)=0.80.0.65+0.5(1-0.70)=0.80.

Therefore

V^DR=1.50−0.20+0.803=0.70.\widehat V_{\mathrm{DR}}=\frac{1.50-0.20+0.80}{3}=0.70.

Rows 1 and 2 have the largest weights and are most capable of inflating variance. In general, the most dangerous row combines small behavior probability with non-zero target probability.

Entropy-regularized policy, Best-of-N, and pass@k

Two actions have scores q=(0,1)q=(0,1) and temperature τ=0.5\tau=0.5.

  1. Compute π∗(a)∝exp⁡(q(a)/τ)\pi^*(a)\propto\exp(q(a)/\tau).

  2. If one independent candidate succeeds with probability p=0.2p=0.2, find the chance of at least one success for N=5N=5.

  3. Find the smallest NN giving probability at least 0.90.9.

  4. For n=10n=10, c=2c=2, and k=3k=3, compute the finite-sample pass@kk estimator.

  5. Explain why parts 2 and 4 describe different statistical objects.

Show answer and solution
π∗(1)=11+e2≈0.1192,π∗(2)=e21+e2≈0.8808.\pi^*(1)=\frac{1}{1+e^2}\approx0.1192, \qquad \pi^*(2)=\frac{e^2}{1+e^2}\approx0.8808.

For five independent samples,

1−0.85=0.67232.1-0.8^5=0.67232.

For at least 90%,

N≥log⁡0.1log⁡0.8≈10.32,N\ge\frac{\log0.1}{\log0.8}\approx10.32,

so N=11N=11.

The finite-sample estimate is

1−(83)(103)=1−56120≈0.5333.1-\frac{\binom{8}{3}}{\binom{10}{3}} =1-\frac{56}{120} \approx0.5333.

The first number uses a known population success probability for future independent draws. The second is computed from a finite set of ten candidates with two observed successes.

Pseudo-regret from actions

Implement:

Python
import numpy as np

def pseudo_regret_curve(means: np.ndarray, actions: np.ndarray) -> np.ndarray:
    """Return cumulative pseudo-regret after each action."""
    ...

Requirements:

  • means is a one-dimensional vector of means;
  • actions is a one-dimensional integer vector;
  • an invalid action index raises ValueError;
  • the result has floating type and the same length as actions.

Check:

Python
means = np.array([0.2, 0.5, 0.7])
actions = np.array([0, 2, 1])
# expected: [0.5, 0.5, 0.7]

Open checks:

Python
np.testing.assert_allclose(
    pseudo_regret_curve([0.2, 0.5, 0.7], [0, 2, 1]),
    [0.5, 0.5, 0.7],
)
Show answer and solution
Python
import numpy as np

def pseudo_regret_curve(means: np.ndarray, actions: np.ndarray) -> np.ndarray:
    means = np.asarray(means, dtype=float)
    actions = np.asarray(actions, dtype=int)
    if means.ndim != 1 or means.size < 2:
        raise ValueError("means must be one-dimensional")
    if actions.ndim != 1:
        raise ValueError("actions must be one-dimensional")
    if np.any((actions < 0) | (actions >= means.size)):
        raise ValueError("invalid action index")
    return np.cumsum(means.max() - means[actions], dtype=float)

Every increment is non-negative, so cumulative pseudo-regret cannot decrease.

ε-greedy Bernoulli bandit

Implement:

Python
import numpy as np

def run_epsilon_greedy(
    probabilities: np.ndarray,
    horizon: int,
    epsilon: float,
    seed: int,
) -> tuple[np.ndarray, np.ndarray]:
    """Return action and reward arrays."""
    ...

Rules:

  • reward is rng.random() < probabilities[action];
  • break greedy ties uniformly;
  • update estimates as sample means;
  • use np.random.default_rng(seed);
  • decide whether to explore before sampling the reward.

Compare ε=0\varepsilon=0, 0.050.05, and 0.20.2 on one instance over at least 100 independent runs. Report mean pseudo-regret, not a conclusion from one seed.

Open checks:

Python
actions, rewards = run_epsilon_greedy([0.1, 0.4, 0.6], 40, 0.1, 17)
assert actions.shape == (40,)
assert rewards.shape == (40,)
assert np.all((rewards == 0.0) | (rewards == 1.0))
Show answer and solution
Python
import numpy as np

def run_epsilon_greedy(probabilities, horizon, epsilon, seed):
    p = np.asarray(probabilities, dtype=float)
    if p.ndim != 1 or p.size < 2 or np.any((p < 0) | (p > 1)):
        raise ValueError("invalid probabilities")
    if horizon <= 0 or not 0 <= epsilon <= 1:
        raise ValueError("invalid horizon or epsilon")

    rng = np.random.default_rng(seed)
    q = np.zeros(p.size)
    n = np.zeros(p.size, dtype=int)
    actions = np.empty(horizon, dtype=int)
    rewards = np.empty(horizon, dtype=float)

    for t in range(horizon):
        if rng.random() < epsilon:
            action = int(rng.integers(p.size))
        else:
            best = np.flatnonzero(np.isclose(q, q.max()))
            action = int(rng.choice(best))
        reward = float(rng.random() < p[action])
        q[action] += (reward - q[action]) / (n[action] + 1)
        n[action] += 1
        actions[t] = action
        rewards[t] = reward
    return actions, rewards

Average over many independent seeds. One greedy run may succeed or fail by chance and does not estimate expected regret.

UCB1

Implement UCB1 for rewards in [0,1][0,1]:

Python
import numpy as np

def run_ucb1(
    probabilities: np.ndarray,
    horizon: int,
    seed: int,
) -> tuple[np.ndarray, np.ndarray]:
    ...

Requirements:

  1. select actions 0, 1, ..., K-1 on the first KK rounds;

  2. then use μ^a+2log⁡t/Na\widehat\mu_a+\sqrt{2\log t/N_a};

  3. update sample means incrementally;

  4. return action and reward arrays.

Verify that every action is selected at least once and cumulative pseudo-regret never decreases.

Open checks:

Python
actions, rewards = run_ucb1([0.1, 0.4, 0.6], 3, 5)
assert np.array_equal(actions, [0, 1, 2])
assert rewards.shape == (3,)
Show answer and solution
Python
import numpy as np

def run_ucb1(probabilities, horizon, seed):
    p = np.asarray(probabilities, dtype=float)
    if p.ndim != 1 or p.size < 2 or np.any((p < 0) | (p > 1)):
        raise ValueError("invalid probabilities")
    if horizon <= 0:
        raise ValueError("horizon must be positive")

    rng = np.random.default_rng(seed)
    k = p.size
    q = np.zeros(k)
    n = np.zeros(k, dtype=int)
    actions = np.empty(horizon, dtype=int)
    rewards = np.empty(horizon, dtype=float)

    for t in range(horizon):
        if t < k:
            action = t
        else:
            index = q + np.sqrt(2 * np.log(t + 1) / n)
            best = np.flatnonzero(np.isclose(index, index.max()))
            action = int(rng.choice(best))
        reward = float(rng.random() < p[action])
        q[action] += (reward - q[action]) / (n[action] + 1)
        n[action] += 1
        actions[t] = action
        rewards[t] = reward
    return actions, rewards

The forced first pass prevents division by zero and ensures every action has at least one observation.

Thompson sampling

Implement Beta–Bernoulli Thompson sampling:

Python
import numpy as np

def run_thompson(
    probabilities: np.ndarray,
    horizon: int,
    seed: int,
    prior_alpha: float = 1.0,
    prior_beta: float = 1.0,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
    """Return actions, rewards, and final alpha/beta arrays."""
    ...

Increment alpha[action] after success and beta[action] after failure. Compare with UCB1 on several instances, including one with close means. Distinguish your empirical observation from a general guarantee.

Open checks:

Python
actions, rewards, alpha, beta = run_thompson(
    [0.1, 0.4, 0.6], 10, 23
)
assert actions.shape == rewards.shape == (10,)
assert alpha.shape == beta.shape == (3,)
assert np.isclose((alpha + beta).sum(), 16.0)
Show answer and solution
Python
import numpy as np

def run_thompson(
    probabilities,
    horizon,
    seed,
    prior_alpha=1.0,
    prior_beta=1.0,
):
    p = np.asarray(probabilities, dtype=float)
    if p.ndim != 1 or p.size < 2 or np.any((p < 0) | (p > 1)):
        raise ValueError("invalid probabilities")
    if horizon <= 0 or prior_alpha <= 0 or prior_beta <= 0:
        raise ValueError("invalid parameters")

    rng = np.random.default_rng(seed)
    alpha = np.full(p.size, float(prior_alpha))
    beta = np.full(p.size, float(prior_beta))
    actions = np.empty(horizon, dtype=int)
    rewards = np.empty(horizon, dtype=float)

    for t in range(horizon):
        samples = rng.beta(alpha, beta)
        action = int(np.argmax(samples))
        reward = float(rng.random() < p[action])
        alpha[action] += reward
        beta[action] += 1.0 - reward
        actions[t] = action
        rewards[t] = reward
    return actions, rewards, alpha, beta

A defensible report states the number of independent runs, horizon, reward instance, and summary statistic. It does not promote an instance-specific result into a universal ranking.

IPS, SNIPS, and doubly robust evaluation

Implement:

Python
def ips_value(rewards, behavior_probs, target_probs) -> float:
    ...

def snips_value(rewards, behavior_probs, target_probs) -> float:
    ...

def doubly_robust_value(
    rewards,
    behavior_probs,
    target_probs,
    predictions_logged,
    predictions_target,
) -> float:
    ...

predictions_target[i] already contains ∑aπ(a∣xi)r^(xi,a)\sum_a\pi(a\mid x_i)\widehat r(x_i,a). Raise ValueError for non-positive behavior probabilities. Add an experiment where one propensity decreases from 0.50.5 to 0.010.01 and show how its IPS weight changes.

Open checks:

Python
actual = ips_value(
    [1.0, 0.0, 1.0],
    [0.5, 0.25, 0.5],
    [1.0, 0.0, 0.5],
)
assert np.isclose(actual, 1.0)
Show answer and solution
Python
import numpy as np

def _arrays(rewards, behavior_probs, target_probs):
    r = np.asarray(rewards, dtype=float)
    p = np.asarray(behavior_probs, dtype=float)
    q = np.asarray(target_probs, dtype=float)
    if r.ndim != 1 or p.shape != r.shape or q.shape != r.shape or r.size == 0:
        raise ValueError("equal non-empty vectors required")
    if np.any(p <= 0) or np.any(p > 1) or np.any((q < 0) | (q > 1)):
        raise ValueError("invalid probabilities")
    return r, p, q

def ips_value(rewards, behavior_probs, target_probs):
    r, p, q = _arrays(rewards, behavior_probs, target_probs)
    return float(np.mean(q * r / p))

def snips_value(rewards, behavior_probs, target_probs):
    r, p, q = _arrays(rewards, behavior_probs, target_probs)
    w = q / p
    if w.sum() <= 0:
        raise ValueError("zero total target weight")
    return float(np.dot(w, r) / w.sum())

def doubly_robust_value(
    rewards,
    behavior_probs,
    target_probs,
    predictions_logged,
    predictions_target,
):
    r, p, q = _arrays(rewards, behavior_probs, target_probs)
    logged = np.asarray(predictions_logged, dtype=float)
    target = np.asarray(predictions_target, dtype=float)
    if logged.shape != r.shape or target.shape != r.shape:
        raise ValueError("prediction shapes must match")
    return float(np.mean(target + q / p * (r - logged)))

With target probability 0.5, lowering behavior probability from 0.5 to 0.01 increases the weight from 1 to 50. One such row can dominate the estimate, which is the practical cost of weak overlap.

Entropy, Best-of-N, and pass@k

Implement:

Python
import numpy as np

def stable_softmax(logits, temperature=1.0) -> np.ndarray:
    ...

def categorical_entropy(probabilities) -> float:
    ...

def best_of_n_success(p: float, n: int) -> float:
    ...

def pass_at_k(n: int, c: int, k: int) -> float:
    ...

Requirements:

  • softmax remains stable for large logits;
  • entropy is in nats and uses 0log⁡0=00\log0=0;
  • Best-of-N uses stable log1p/expm1 for small pp and large NN;
  • pass@kk uses 1−(n−ck)/(nk)1-\binom{n-c}{k}/\binom{n}{k} or an equivalent stable product;
  • invalid n,c,k,pn,c,k,p raise ValueError.

Verify that entropy rises for temperatures 0.50.5, 11, and 22 with fixed logits, but do not infer anything about correctness or answer quality from that fact.

Open checks:

Python
p = stable_softmax([1000.0, 1001.0])
assert np.isclose(p.sum(), 1.0)
assert np.all(p > 0.0)
Show answer and solution
Python
from math import comb
import numpy as np

def stable_softmax(logits, temperature=1.0):
    z = np.asarray(logits, dtype=float)
    if z.ndim != 1 or z.size == 0 or not np.all(np.isfinite(z)):
        raise ValueError("invalid logits")
    if temperature <= 0 or not np.isfinite(temperature):
        raise ValueError("temperature must be positive")
    scaled = z / temperature
    weights = np.exp(scaled - scaled.max())
    return weights / weights.sum()

def categorical_entropy(probabilities):
    p = np.asarray(probabilities, dtype=float)
    if p.ndim != 1 or np.any(p < 0) or not np.isclose(p.sum(), 1):
        raise ValueError("invalid probability vector")
    positive = p[p > 0]
    return float(-np.dot(positive, np.log(positive)))

def best_of_n_success(p, n):
    if not 0 <= p <= 1 or n < 1:
        raise ValueError("invalid p or n")
    if p == 1:
        return 1.0
    return float(-np.expm1(n * np.log1p(-p)))

def pass_at_k(n, c, k):
    if n <= 0 or c < 0 or c > n or k <= 0 or k > n:
        raise ValueError("invalid n, c, k")
    if n - c < k:
        return 1.0
    return float(1 - comb(n - c, k) / comb(n, k))

For fixed logits, pure-softmax entropy increases from temperature 0.5 to 1 to 2. That fact alone says nothing about factual correctness, calibration, or task reward.