Thomas Piacentini
← Workshop

Python exercise

Speculative decoding: accept, reject and resample

Original text · English35 min

Speculative decoding makes a large model generate text faster with no change to its output. A small draft model proposes a few tokens. The large target model checks all of them in one forward pass. A rejection rule keeps the output distribution exactly equal to the distribution of the target model.

Task

Write four functions. In this problem, p is a distribution of the target model and q is a distribution of the draft model, over a vocabulary of V tokens.

  1. acceptance_rate(target, draft) returns \alpha = \sum_x \min(p(x), q(x)). This is the probability that the rule accepts one draft token.
  2. residual_distribution(target, draft) returns \mathrm{norm}(\max(0, p - q)): the elementwise maximum of 0 and p - q, divided by its sum. When that sum is 0, return a copy of target as a float array.
  3. speculative_step(target_probs, draft_probs, draft_tokens, rng) runs the verify step for \gamma draft tokens and returns the output tokens.
  4. expected_tokens(alpha, gamma) returns the expected number of tokens of one step, (1 - \alpha^{\gamma + 1}) / (1 - \alpha). For \alpha = 1 it returns \gamma + 1.

speculative_step does these steps. The order of the random draws is part of the task.

  1. For each draft token x_i, with i from 0 to \gamma - 1, let p_i be row i of target_probs and q_i be row i of draft_probs.
  2. Draw u = rng.random(). When u < \min(1, p_i(x_i) / q_i(x_i)), accept x_i, add it to the output, and go to the next draft token.
  3. Otherwise, draw one token with rng.choice(V, p=r), where r is the residual distribution of p_i and q_i. Add it to the output and return the output.
  4. When all \gamma draft tokens are accepted, draw one bonus token with rng.choice(V, p=p_gamma) from the last row of target_probs. Add it and return the output.

Input and output

Name Type Shape Meaning
target float array (V,) a target distribution p
draft float array (V,) a draft distribution q
target_probs float array (gamma + 1, V) the target distributions at each draft position and one more
draft_probs float array (gamma, V) the draft distributions at each draft position
draft_tokens list of int length gamma the tokens that the draft model sampled
rng np.random.Generator the source of all random draws
alpha float an acceptance rate from 0 to 1
gamma int the number of draft tokens
  • acceptance_rate returns a Python float.
  • residual_distribution returns a float array of shape (V,) that sums to 1.
  • speculative_step returns a list of Python ints of length from 1 to gamma + 1.
  • expected_tokens returns a Python float.

Constraints

  • 2 <= V <= 64 and 0 <= gamma <= 8. Each row of probabilities sums to 1.
  • Each draft token has q_i(x_i) > 0, because the draft model sampled it. The target probability p_i(x_i) can be 0.
  • Use only rng.random() and rng.choice(V, p=...), in the order above. Make no other draws.
  • Do not change the input arrays or the list of draft tokens.
  • Use numpy only.

Examples

python
target = np.array([0.5, 0.3, 0.2, 0.0])
draft = np.array([0.25, 0.25, 0.25, 0.25])
acceptance_rate(target, draft)
residual_distribution(target, draft)
text
0.7
[0.83333333 0.16666667 0.         0.        ]
python
target_probs = np.array([[0.5, 0.3, 0.2, 0.0], [0.1, 0.6, 0.2, 0.1], [0.25, 0.25, 0.25, 0.25]])
draft_probs = np.array([[0.25, 0.25, 0.25, 0.25], [0.4, 0.2, 0.2, 0.2]])
speculative_step(target_probs, draft_probs, [0, 1], np.random.default_rng(0))
speculative_step(target_probs, draft_probs, [3, 0], np.random.default_rng(0))
speculative_step(target_probs, draft_probs, [0, 0], np.random.default_rng(3))
text
[0, 1, 0]
[0]
[0, 0, 3]
python
expected_tokens(0.8, 4), expected_tokens(1.0, 4), expected_tokens(0.0, 4)
text
(3.3616, 5.0, 1.0)
Code and artifacts 14
What you take away

Saved in your notebook on this device.

Sources and limits

Reading checkpoints are self-reported. Test results are recorded separately and apply to the executed cases.

AI Engineering from Scratch · 3f9715c · MIT

Download this file ↓