<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://darpanjain.com/blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://darpanjain.com/blog/" rel="alternate" type="text/html" /><updated>2026-11-14T13:23:39-08:00</updated><id>https://darpanjain.com/blog/feed.xml</id><title type="html">Darpan’s Blog</title><subtitle>A collection of my thoughts on Technology x everything else, in a quiet corner of the internet 🙂</subtitle><author><name>Darpan Jain</name></author><entry><title type="html">The Evolution of the Attention Mechanism in LLMs</title><link href="https://darpanjain.com/blog/the-evolution-of-attention-in-LLMs/" rel="alternate" type="text/html" title="The Evolution of the Attention Mechanism in LLMs" /><published>2026-11-05T17:14:32-08:00</published><updated>2026-11-05T17:14:32-08:00</updated><id>https://darpanjain.com/blog/the-evolution-of-attention-in-LLMs</id><content type="html" xml:base="https://darpanjain.com/blog/the-evolution-of-attention-in-LLMs/"><![CDATA[<p><em>Serving one 4,096-token request on Qwen3-32B takes about 1.07 GB of key-value cache. Give every query head its own keys and values, as the original Transformer did, and that same request would need 8.59 GB.</em></p>

<p>As a language model’s context grows, reading and storing its history becomes more expensive. Attention designs tackle different parts of that cost: some share keys and values across heads, some compress what each token stores, and others restrict which positions a query reads.</p>

<p>We’ll follow these choices from a single attention head to hybrid memory and paged caches, using small worked examples. The question throughout is simple: what changes, what does it save, and what do we give up?</p>

<h2 id="1-attention-was-all-we-needed">1. Attention Was All We Needed?</h2>

<p>A language model needs more than a representation of each token in isolation. It needs a way to bring information from the surrounding context into that representation. <strong>Attention provides that connection:</strong> each position computes weights over the context it can see, then uses those weights to combine information from those positions.</p>

<p>In a Transformer, this happens inside a block that also contains a feed-forward network. Stack these blocks, and the representations produced by one become the inputs to the next. In the decoder-only pattern used by GPT-style models, a vocabulary projection at the end produces scores for the next token.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-transformer-context.png" alt="Token IDs become embeddings, pass through repeated Transformer blocks containing causal self-attention and feed-forward networks, and reach a vocabulary projection and next-token probabilities." />
<em>Simplified decoder-only architecture; residual connections and normalization are omitted. Original schematic following Jay Alammar’s <a href="https://jalammar.github.io/illustrated-gpt2/">The Illustrated GPT-2</a>.</em></p>

<p>An <strong>attention head</strong> is one learned query/key/value projection pathway within the attention layer. It produces its own weights for mixing token information. Multiple heads give the layer several such pathways in parallel. For a fuller introduction, Jay Alammar’s <a href="https://jalammar.github.io/illustrated-transformer/">The Illustrated Transformer</a> and <a href="https://jalammar.github.io/illustrated-gpt2/">The Illustrated GPT-2</a> cover the surrounding architecture in detail.</p>

<p>We’ll start with multiple heads, then explore shared KV caches, restricted reads and compressed representations. From there, we’ll look at output gates, hybrid memory and cache allocation. Each design addresses a different constraint, and a model can combine several of them.</p>

<p>The <a href="https://github.com/darpan-jain/attention-gym/tree/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples">companion examples</a> use small inputs to make the calculations and storage costs inspectable. They demonstrate how the mechanisms work. The weights are chosen by hand, not trained, so they say nothing about model quality, and none of the examples is a latency or throughput benchmark.</p>

<h2 id="2-single-head-self-attention">2. Single-Head Self-Attention</h2>

<p>Start with one head. The <a href="https://arxiv.org/abs/1706.03762">original Transformer</a> already used multiple heads, but isolating one lets us see the computation that the later designs modify.</p>

<p>Self-attention projects the input into queries, keys and values. Queries and keys determine how strongly positions match; values carry the information that gets mixed. The <strong>scaled dot-product formulation</strong> combines these operations:</p>

\[\begin{aligned}
Q &amp;= XW_Q, \quad K = XW_K, \quad V = XW_V \\
A &amp;= \operatorname{softmax}\!\left(\frac{QK^{\mathsf T}}{\sqrt{d_k}} + M\right) \\
Y &amp;= (AV)W_O
\end{aligned}\]

<p>Here \(d_k\) is the query/key dimension. Scaling moderates dot-product growth with dimension, and softmax normalizes the scores across keys. For causal attention, \(M\) masks future positions before normalization, so each query reads only its own position and earlier ones.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-single-head-architecture.png" alt="Input representations split into query, key and value projections. Queries and keys produce scaled scores; a causal mask and softmax produce weights that mix the values before an output projection." />
<em>One head computes a distribution over visible positions, mixes their values, and applies an output projection. Original schematic; see <a href="https://jalammar.github.io/illustrated-transformer/#self-attention-in-detail">Alammar’s Q/K/V walkthrough</a> and the <a href="https://arxiv.org/abs/1706.03762">Transformer paper</a>.</em></p>

<p>For a concrete example, take <strong>“The cat sat”</strong> with chosen vectors \([1, 0]\), \([0, 1]\) and \([1, 1]\). Use identity projections so we can follow the calculation directly. These are untrained teaching vectors, with positional encoding omitted. The query for “sat” has dot products \([1, 1, 2]\) with the keys. Scaling and softmax turn these into weights of approximately \([0.248, 0.248, 0.503]\). Mixing the values gives \([0.752, 0.752]\).</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-single-head-weights.png" alt="The causal attention matrix gives The weights of 1, 0, 0; cat approximately 0.330, 0.670, 0; and sat approximately 0.248, 0.248, 0.503. Future positions are masked." />
<em>Computed weights for the example: each row is a query, each column a key/value position. Future positions receive zero weight.</em></p>

<p>The result is a context-dependent mixture. To understand its cost, distinguish processing a sequence from generating one new token. Holding the head dimensions, batch size and numerical precision fixed:</p>

<table>
  <thead>
    <tr>
      <th>Quantity</th>
      <th>Growth with sequence length \(n\)</th>
      <th>Why</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Full-sequence attention work, as during prompt prefill</td>
      <td>\(\mathcal{O}(n^2)\)</td>
      <td>Each query attends to its visible keys</td>
    </tr>
    <tr>
      <td>Attention work for one new token with a KV cache</td>
      <td>\(\mathcal{O}(n)\)</td>
      <td>The new query reads the retained history</td>
    </tr>
    <tr>
      <td>Retained KV-cache storage</td>
      <td>\(\mathcal{O}(n)\)</td>
      <td>Each retained token contributes one key and value per head</td>
    </tr>
  </tbody>
</table>

<p>Full-sequence attention has quadratically many query-key interactions, but implementations can avoid storing the entire score matrix at once. A KV cache reuses earlier keys and values during generation; the new query still has to read them. The <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/single_head.py">runnable implementation</a> and <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples/single_head.py">example</a> show both full-sequence and cached execution.</p>

<p>There is another constraint: <strong>one head gives each query one attention distribution.</strong> Several relationships can contribute, but they share those mixing weights. Multiple heads let the layer form separate distributions through different learned projections, then combine their outputs. That is the first architectural change we’ll make.</p>

<h3 id="key-takeaways">Key Takeaways</h3>

<ul>
  <li>One head forms a context-dependent mixture of visible token representations.</li>
  <li>A causal mask excludes future positions; a KV cache reuses earlier keys and values during generation.</li>
  <li>Full-sequence attention work grows quadratically; one cached decoding step and retained KV storage grow linearly with history length.</li>
</ul>

<h2 id="3-multi-head-self-attention">3. Multi-Head Self-Attention</h2>

<p>Single-head attention has a fundamental limitation: each query gets only one attention distribution. But language is rich with different types of dependencies—syntactic, semantic, positional, and more. Multi-head attention solves this by running multiple attention operations in parallel.</p>

<h3 id="the-intuition">The Intuition</h3>

<p>Think of the heads as specialists that can look for different patterns in the same context. Their roles are learned: one head can capture several relationships, and different heads can learn overlapping patterns.</p>

<h3 id="mathematical-formulation">Mathematical Formulation</h3>

<p>The attention calculation stays the same. We now give each head its own learned query, key and value projections, then concatenate their outputs and apply a learned output projection:</p>

\[\begin{aligned}
\operatorname{head}_i &amp;= \operatorname{Attention}(XW_Q^i, XW_K^i, XW_V^i) \\
\operatorname{MultiHead}(X) &amp;= \operatorname{Concat}(\operatorname{head}_1, \ldots, \operatorname{head}_h)W_O
\end{aligned}\]

<p>The <a href="https://arxiv.org/html/1706.03762v7#S3.SS2.SSS2">Transformer paper</a> describes this as attending across different representation subspaces.</p>

<p>Let’s reuse <strong>“The cat sat”</strong> and the same input vectors. This time, split the two input coordinates across two heads: the first head projects onto the first coordinate, and the second onto the second. Each head therefore has width one, keeping the total width unchanged. These are chosen projections to make the difference visible, with positional encoding still omitted.</p>

<p>For the final query, the first head assigns weights of approximately \([0.422, 0.155, 0.422]\) to “The,” “cat” and “sat.” The second assigns \([0.155, 0.422, 0.422]\). Same input, different mixtures. Their scalar outputs are concatenated into \([0.845, 0.845]\); an identity output projection leaves that vector unchanged in this example.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-multi-head.png" alt="The same input feeds separate query, key and value projections for two heads, whose outputs are concatenated and projected. For sat, head 1 has weights 0.422, 0.155, 0.422, while head 2 has 0.155, 0.422, 0.422." />
<em>The architecture above the heatmap shows how the head outputs are combined. The calculated weights below show the final query from our single-head example alongside the two narrower heads.</em></p>

<h3 id="putting-the-heads-to-work">Putting the Heads to Work</h3>

<p>We don’t need a Python loop for each head. The <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/attention.py">implementation</a> packs their projections into larger linear layers, reshapes the result to expose a head dimension, and computes attention across those heads in a batch. The <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples/multi_head.py">runnable example</a> exposes the weights so we can inspect the patterns above.</p>

<h3 id="what-does-this-cost-us">What Does This Cost Us?</h3>

<p>Here’s a detail that’s easy to miss: <strong>more heads do not automatically mean a larger KV cache.</strong> Usually, we divide a fixed model width across the heads. If \(h \times d_{\text{head}} = d_{\text{model}}\), changing the head count while keeping \(d_{\text{model}}\) fixed leaves the total cached width unchanged.</p>

<p>For equal key and value widths, the cache payload in bytes across the model is:</p>

\[\begin{aligned}
&amp;2 \times \text{batch\_size} \times \text{cached\_length} \times \text{n\_layers} \\
&amp;\quad \times h \times d_{\text{head}} \times \text{bytes\_per\_element}
\end{aligned}\]

<p>The cache still grows with context length, batch size and layer count. Each head retains its own keys and values, and each new query reads that history. Splitting into heads also keeps full-context attention quadratic in sequence length.</p>

<p>That leaves us with a useful question: do all those query heads need separate keys and values? Could they ask different questions while reading from shared memory? That is the idea behind multi-query attention.</p>

<h3 id="key-takeaways-1">Key Takeaways</h3>

<ul>
  <li>Separate projections let heads form different attention patterns, which are combined through an output projection.</li>
  <li>Packed projections and batched attention compute the heads together.</li>
  <li>At fixed total width, more heads do not automatically increase KV-cache size. Retaining separate keys and values for every head still leaves a memory cost worth reducing.</li>
</ul>

<h2 id="4-sharing-the-kv-cache-mqa-and-gqa">4. Sharing the KV Cache: MQA and GQA</h2>

<p>Multi-head attention gives every head its own keys and values to store during generation. But do all those heads need separate memories? Multi-query attention (MQA) lets each head ask its own question through a separate query projection, while sharing one set of keys and values across all heads. With eight heads sharing one K/V set, for example, the KV cache becomes eight times smaller at the same head width. Reading less data at each decoding step can also mean lower latency.</p>

<h3 id="mqa-one-shared-kv-head">MQA: One Shared KV Head</h3>

<p>The query projections stay separate, but every head now reads the same keys and values. The causal mask and the way we combine outputs stay unchanged:</p>

\[\begin{aligned}
Q_i &amp;= XW_Q^i, \quad K_s = XW_K, \quad V_s = XW_V \\
\operatorname{head}_i &amp;= \operatorname{softmax}\!\left(\frac{Q_iK_s^{\mathsf T}}{\sqrt{d_k}} + M\right)V_s \\
\operatorname{MQA}(X) &amp;= \operatorname{Concat}(\operatorname{head}_1, \ldots, \operatorname{head}_h)W_O
\end{aligned}\]

<p>This is the sharing strategy introduced in <a href="https://arxiv.org/abs/1911.02150">Noam Shazeer’s MQA paper</a>. Shared memory still allows different attention distributions: in our <strong>“The cat sat”</strong> example, the query heads at “cat” assign \([0.500, 0.500]\) and \([0.731, 0.269]\) to the same visible positions. They read the same keys and values but ask different questions.</p>

<p>The catch is that all heads must work with one shared K/V representation. That restriction can affect quality, even though the queries remain separate. So what if we relaxed the sharing a little?</p>

<h3 id="gqa-share-within-groups">GQA: Share Within Groups</h3>

<p>Instead of making every query head share one memory, give each group its own keys and values. With four query heads and two KV groups, heads 1 and 2 share one K/V pair, while heads 3 and 4 share another.</p>

<p>This is grouped-query attention, introduced by <a href="https://arxiv.org/abs/2305.13245">Joshua Ainslie and colleagues</a>. For evenly sized groups, a query head selects its KV group as follows, using zero-based indices:</p>

\[\begin{aligned}
\text{group\_size} &amp;= \left\lfloor \frac{\text{n\_heads}}{\text{n\_kv\_heads}} \right\rfloor \\
\text{group} &amp;= \left\lfloor \frac{\text{head\_index}}{\text{group\_size}} \right\rfloor \\
\operatorname{head}_i &amp;= \operatorname{Attention}(Q_i, K_{\text{group}}, V_{\text{group}})
\end{aligned}\]

<p>Now we can describe all three designs with the same parameter:</p>

<table>
  <thead>
    <tr>
      <th>Design</th>
      <th>KV heads for \(h\) query heads</th>
      <th>Sharing</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>MHA</strong></td>
      <td>\(h\)</td>
      <td>Each query head has its own K/V</td>
    </tr>
    <tr>
      <td><strong>GQA</strong></td>
      <td>Between \(1\) and \(h\)</td>
      <td>Query heads share within groups</td>
    </tr>
    <tr>
      <td><strong>MQA</strong></td>
      <td>\(1\)</td>
      <td>All query heads share K/V</td>
    </tr>
  </tbody>
</table>

<p><strong>MQA is the one-group endpoint of GQA.</strong> They are choices along the same spectrum; applying both does not produce another round of cache savings.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-kv-sharing.png" alt="Four query heads read four separate KV heads in MHA, two KV heads in GQA, or one shared KV head in MQA. The same three-token example stores 24, 12, or 6 cache elements respectively." />
<em>Illustrative topology showing who shares with whom. Cache counts come from the same fixed-width, four-head example; the queries and sequence stay unchanged across designs.</em></p>

<p>To make an intermediate group count visible, our <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples/grouped_query.py">grouped example</a> repeats the earlier input coordinates into a wider representation and uses four scalar query heads. Its K/V payload falls from <strong>24 elements with MHA</strong>, to <strong>12 with GQA</strong>, to <strong>6 with MQA</strong>.</p>

<h3 id="what-do-we-save-and-what-do-we-give-up">What Do We Save, and What Do We Give Up?</h3>

<p>We can use one cache formula for the whole spectrum, assuming equal key and value widths:</p>

\[\begin{aligned}
\text{KV payload bytes} &amp;= 2 \times \text{batch\_size} \times \text{cached\_length} \\
&amp;\quad \times \text{n\_layers} \times \text{n\_kv\_heads} \\
&amp;\quad \times d_{\text{head}} \times \text{bytes\_per\_element}
\end{aligned}\]

<p>Holding the other dimensions fixed, the reduction relative to MHA is \(\frac{\text{n\_heads}}{\text{n\_kv\_heads}}\). As a larger example, <a href="https://huggingface.co/Qwen/Qwen3-32B/blob/main/config.json">Qwen3-32B’s configuration</a> has 64 query heads and 8 KV heads. At batch size 1 and 4096 cached tokens, its 64 layers and head width 128 give a derived BF16 cache payload of <strong>1.07 GB</strong>, versus <strong>8.59 GB</strong> for a hypothetical MHA version: an <strong>8× reduction</strong>. These are decimal gigabytes of K/V data, excluding weights, temporary tensors and allocator overhead.</p>

<p>The quality and latency tradeoff is less mechanical. The <a href="https://arxiv.org/abs/2305.13245">GQA study</a> found quality close to MHA with inference speed close to MQA in its evaluated settings. Converting existing checkpoints also involved further training. Group count gives us a design choice, not a universal optimum or a free inference-time swap.</p>

<p>Our <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/attention.py">implementations</a> retain only the KV groups in the cache. The GQA path uses an explicit group dimension so adjacent query heads read the right group without an explicit per-query KV repetition. Backend temporaries and kernel selection still matter.</p>

<h3 id="where-these-show-up">Where These Show Up</h3>

<table>
  <thead>
    <tr>
      <th>Design</th>
      <th>Model examples</th>
      <th>Primary source</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>MHA</strong></td>
      <td>GPT-2</td>
      <td><a href="https://github.com/openai/gpt-2/blob/master/src/model.py">OpenAI’s implementation</a></td>
    </tr>
    <tr>
      <td><strong>MQA</strong></td>
      <td>PaLM; Falcon-7B</td>
      <td><a href="https://arxiv.org/html/2204.02311v5#S2">PaLM paper</a>; <a href="https://huggingface.co/tiiuae/falcon-7b/blob/main/config.json">Falcon-7B configuration</a></td>
    </tr>
    <tr>
      <td><strong>GQA</strong></td>
      <td>Llama-2-70B; Llama-3-8B and 70B</td>
      <td><a href="https://github.com/meta-llama/llama-models/blob/main/models/sku_list.py">Meta’s model configurations</a></td>
    </tr>
    <tr>
      <td><strong>GQA</strong></td>
      <td>Falcon-40B; Mistral-7B v0.1</td>
      <td><a href="https://huggingface.co/tiiuae/falcon-40b/blob/main/config.json">Falcon-40B configuration</a>; <a href="https://arxiv.org/abs/2310.06825">Mistral paper</a></td>
    </tr>
    <tr>
      <td><strong>GQA</strong></td>
      <td>Qwen3-32B</td>
      <td><a href="https://huggingface.co/Qwen/Qwen3-32B/blob/main/config.json">Qwen3-32B configuration</a></td>
    </tr>
  </tbody>
</table>

<p>These labels apply to the named variants, not necessarily their entire model families. Mistral-7B also combines GQA with sliding-window attention, which changes a different part of the problem: how many token positions each query reads.</p>

<h3 id="key-takeaways-2">Key Takeaways</h3>

<ul>
  <li>MQA and GQA keep separate queries while sharing keys and values across all heads or within groups.</li>
  <li>MHA, GQA and MQA form a spectrum controlled by the number of KV heads; their cache reductions do not stack.</li>
  <li>Fewer KV heads reduce stored history, with quality and latency tradeoffs that depend on training and execution.</li>
  <li>Sharing heads still leaves the sequence-length cost. Sliding-window attention tackles that next.</li>
</ul>

<h2 id="5-sliding-window-attention">5. Sliding Window Attention</h2>

<p>GQA reduces the number of KV heads, but each query still reads the retained sequence. As the context grows, so does the work. Sliding-window attention, used for long documents in <a href="https://arxiv.org/abs/2004.05150">Longformer</a>, changes a different part of the problem: how far back each query looks.</p>

<h3 id="the-intuition-1">The Intuition</h3>

<p>Do tokens really need to attend to every previous token? Often, much of the useful context is nearby. Give each query a window of recent positions instead of the entire history. Here, the window size \(W\) includes the current position, so a query at position \(i\) can read:</p>

\[\max(0, i - W + 1) \leq \text{key\_position} \leq i\]

<p>Let’s extend our sentence to <strong>“The cat sat on the mat”</strong> and use a window of three positions. The query at “sat” can read “The cat sat.” Move to “on,” and the window becomes “cat sat on.” At “mat,” it reads only “on the mat.” The attention calculation within that window is unchanged; older positions simply stop participating.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-sliding-window.gif" alt="A three-position window moves across The cat sat on the mat. Visible tokens are highlighted, older tokens leave the window, and retained KV storage stops growing after the window fills." />
<em>Visibility and cache counts follow the verified single-layer example. <a href="/blog/assets/images/attention-gym/attention-gym-sliding-window.png">Static version</a>.</em></p>

<h3 id="what-changes-in-the-cost">What Changes in the Cost?</h3>

<p>Full causal attention has quadratically many query-key pairs across a sequence. With local execution, each query reads at most \(W\) positions, reducing that attention work to \(\mathcal{O}(nW)\) for sequence length \(n\). For a fixed window, that is linear in sequence length. In our six-token example, the number of visible pairs per head falls from <strong>21 to 15</strong>; the gap grows with longer sequences.</p>

<p>That benefit requires computing only the local interactions. Creating a dense score matrix and masking most of it afterward still does the dense computation. Our <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/sliding_window.py">implementation</a> processes local slices directly. The <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples/sliding_window.py">example runner</a> compares full-sequence and cached local execution.</p>

<h3 id="combining-it-with-gqa">Combining It with GQA</h3>

<p>These two changes do compose: GQA reduces the number of KV heads, while a rolling window bounds the retained positions per local layer. Once the window fills, older K/V entries can leave that layer’s cache. Its retained payload is:</p>

\[\begin{aligned}
&amp;2 \times \text{batch\_size} \times \min(\text{cached\_length}, W) \\
&amp;\quad \times \text{n\_kv\_heads} \times d_{\text{head}} \times \text{bytes\_per\_element}
\end{aligned}\]

<p>The token position keeps advancing even when the stored length stops growing. A rolling cache reuses its slots, but positional encoding still uses each token’s true position, so a cache slot and a token’s position are no longer the same number.</p>

<h3 id="what-do-we-give-up">What Do We Give Up?</h3>

<p>An older token can no longer be read directly by that local layer once it leaves the window. That can matter when a task needs information from far back. Stacked layers can relay information over longer distances, however, so the per-layer window is not the model’s entire effective context.</p>

<p><a href="https://arxiv.org/abs/2310.06825">Mistral-7B v0.1</a> combines GQA with sliding-window attention; its <a href="https://huggingface.co/mistralai/Mistral-7B-v0.1/blob/main/config.json">configuration</a> specifies a window of <strong>4096</strong>. <a href="https://arxiv.org/abs/2408.00118">Gemma 2</a> takes another approach, alternating local sliding-window and global attention layers. Those global layers still need their broader history, so the bounded-cache formula above applies to the local layers.</p>

<h3 id="key-takeaways-3">Key Takeaways</h3>

<ul>
  <li>Sliding-window attention restricts token positions; GQA shares KV heads. Their savings address different dimensions.</li>
  <li>Local execution makes attention work \(\mathcal{O}(nW)\) and a rolling cache bounds retained history per local layer.</li>
  <li>The tradeoff is reduced direct access to distant tokens; stacked layers and local/global designs can provide broader information paths.</li>
</ul>

<p>A window is a simple rule for deciding what to read. But what if the useful token is somewhere much earlier?</p>

<h2 id="6-sparse-attention-beyond-sliding-windows">6. Sparse Attention Beyond Sliding Windows</h2>

<p>A sliding window assumes recent tokens deserve our attention. Often they do. But if a function was defined two thousand tokens ago, a wider window is a fairly expensive way to find it again. Can we keep the local context and selectively reach further back?</p>

<p>Sparse attention is a family of answers: local bands, designated global positions, selected blocks, or tokens chosen from their content. The common idea is to spend the full attention calculation on a subset of the history. The selection rule determines what the layer can miss.</p>

<p>For a local window plus selected remote tokens, the calculation becomes:</p>

\[\begin{aligned}
S_t &amp;= \operatorname{local\_window}(t) \cup \operatorname{selected\_remote\_tokens}(t) \\
\operatorname{output}_t &amp;= \operatorname{softmax}\!\left(\frac{q_t K[S_t]^{\mathsf T}}{\sqrt{d}}\right)V[S_t]
\end{aligned}\]

<p>Both sets contain only positions up to the current token, so their union \(S_t\) already enforces causal visibility.</p>

<p>Our <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples/attention_extensions.py">example</a> gives each query two local positions, including itself, and one remote slot. When reading “mat” in “The cat sat on the mat”, the chosen index projections select the first “The” as well as the final “the mat”: positions <strong>[0, 4, 5]</strong>. That distant token is directly visible again.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-selected-sparse.png" alt="Six-token visibility map: a two-position local window plus one content-selected distant token. The final query reads positions 0, 4 and 5." />
<em>Blue cells are local reads; orange cells are selected remote reads. White cells are skipped by the main attention calculation.</em></p>

<p>With window \(W\) and remote budget \(k\), the main attention stage reads at most \(W + k\) positions per query. Finding them has a cost too: our small indexer scans the earlier history, so selection can still take quadratic total work during prefill. It also retains the full K/V and index-key history. Fewer attention reads do not automatically mean a bounded cache or an end-to-end speedup.</p>

<p><a href="https://arxiv.org/abs/2502.11089">Native Sparse Attention</a> combines compressed, selected and local branches. <a href="https://github.com/deepseek-ai/DeepSeek-V3.2-Exp">DeepSeek-V3.2-Exp</a> uses DeepSeek Sparse Attention (DSA), with an indexer selecting entries for sparse attention. Our <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/sparse_attention.py">local-plus-selector implementation</a> isolates selection rather than reproducing these architectures.</p>

<h3 id="compress-first-then-select-or-reuse">Compress First, Then Select or Reuse</h3>

<p>So far, we’ve selected individual tokens. We can also compress groups of tokens into fewer entries, then decide which of those entries to read:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Token history → compressed entries → selected compressed entries
</code></pre></div></div>

<p><em>Illustrative sequence-compression path. Compression reduces the number of historical entries; selection limits which entries a query reads.</em></p>

<p><a href="https://arxiv.org/abs/2606.19348">DeepSeek-V4</a> combines a local window over uncompressed tokens with two forms of compressed history: <strong>Compressed Sparse Attention (CSA)</strong> selects from compressed entries, while <strong>Heavily Compressed Attention (HCA)</strong> reads all entries in a much more compressed history. The model interleaves these layer types. Compression now acts along the sequence dimension: fewer historical entries, with some detail traded for compact summaries.</p>

<p><a href="https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash">DeepSeek-V4.1-Flash</a> asks another question: does every layer need to repeat the same selection work? Its <strong>Compressed Sparse Attention 2 (CSA2)</strong> lets layers share cached representations and reuse selection results. Later decoder layers can also narrow their search to candidates found earlier, though finding that initial pool still has a cost.</p>

<details>
  <summary><b><i>For the curious: how CSA2 reuses work</i></b></summary>

  <p>CSA2 assigns layers Full, Reindex or Reuse modes, sharing KV and indexer keys and reusing top-k selections. A hierarchical indexer limits later decoder selection to an earlier candidate pool.</p>

</details>

<p>The progression is useful: choose fewer entries, compress those entries, then avoid rebuilding the same cache and selections at every layer. Our toy demonstrates the first step; these newer models combine several steps.</p>

<h3 id="key-takeaways-4">Key Takeaways</h3>

<ul>
  <li>Sparsity can preserve direct access to selected distant tokens while limiting the main attention reads.</li>
  <li>Selection cost, retained cache and hardware execution determine the actual savings; newer designs also compress history and reuse state across layers.</li>
  <li>Missing a useful token is the architectural tradeoff; choosing well requires more than a small attention budget.</li>
</ul>

<p>MLA takes a different compression axis: shrink each token’s stored representation, rather than combine entries across time.</p>

<h2 id="7-multi-head-latent-attention-mla">7. Multi-Head Latent Attention (MLA)</h2>

<p>We’ve shared the KV heads and limited how much history each layer reads. Multi-head latent attention, introduced in <a href="https://arxiv.org/abs/2405.04434">DeepSeek-V2</a>, changes what we store for each token: a compact learned representation from which the heads’ keys and values can be recovered.</p>

<h3 id="the-key-idea">The Key Idea</h3>

<p>Instead of caching expanded K and V vectors, project each input into a smaller latent vector \(C\). Each head then has its own up-projections from that latent into content keys and values:</p>

\[\begin{aligned}
C &amp;= XW_{\text{down}} \\
K_i &amp;= CU_K^i, \quad V_i = CU_V^i
\end{aligned}\]

<p>The shared part is the latent state. The reconstructed keys and values can differ across heads, so this has a different constraint from making heads use identical K/V as in MQA. The model learns to work through this compact representation during training; it is not a lossless codec for an arbitrary existing MHA model.</p>

<p>Take “cat” from our four-head example. With the chosen down-projection, its latent is \([0, 1]\). The key up-projections produce \([0, 1, 1, -1]\), while the value up-projections produce \([1, 0, 1, 1]\), with one scalar per head. The three-token content cache stores <strong>6 elements instead of 24</strong> expanded K/V elements. Positional encoding is omitted in this worked example.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-latent-attention.png" alt="The input is down-projected into the cached latent 0, 1. Separate up-projections recover head-specific keys 0, 1, 1, minus 1 and values 1, 0, 1, 1. The content cache stores 6 elements instead of 24." />
<em>Calculated reconstruction for the chosen vectors and weights. The diagram shows the content branch; positional information gets a separate path in the full design.</em></p>

<h3 id="do-we-have-to-decompress-the-whole-history">Do We Have to Decompress the Whole History?</h3>

<p>That would give back some of the memory benefit as repeated work. Fortunately, we can rearrange the content calculation. For head \(i\), let \(Q_i\) be the current token’s content query and \(A_i\) its attention weights over the visible history. \(C\) holds the cached latent vectors, one row per token. Then:</p>

\[\begin{aligned}
Q_i(CU_K^i)^{\mathsf T} &amp;= \bigl(Q_i(U_K^i)^{\mathsf T}\bigr)C^{\mathsf T} \\
A_i(CU_V^i) &amp;= (A_iC)U_V^i
\end{aligned}\]

<p>These identities cover the content calculation; we’ll handle positional information next. For keys, move the up-projection into the current query before comparing it with the latent history. For values, mix the latents first and apply the up-projection afterward. The results match explicit reconstruction for the same factorized weights. This is the matrix-absorption idea: we can avoid rebuilding every past token’s expanded content keys and values during decoding.</p>

<p>Our <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/attention.py">implementation</a> includes both paths, and the <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples/latent_attention.py">example</a> compares them. The tradeoff depends on latent rank, head dimensions and kernels.</p>

<h3 id="where-does-position-information-go">Where Does Position Information Go?</h3>

<p>RoPE applies position-dependent rotations, which prevents us from freely moving a content up-projection through that rotation. DeepSeek’s solution is a decoupled positional branch: rotate a small query component and a shared positional key, then add their dot product to the content score.</p>

<p>That positional key is cached alongside the latent. For a layer with latent rank \(r\) and positional-key width \(d_{\text{rope}}\), the retained payload is:</p>

\[\begin{aligned}
&amp;\text{batch\_size} \times \text{cached\_length} \\
&amp;\quad \times (r + d_{\text{rope}}) \times \text{bytes\_per\_element}
\end{aligned}\]

<p>So the full cache is more than just \(C\), and it still grows with context length. Our educational model implements this decoupled RoPE path and causal cached decoding, while omitting the production model’s query bottleneck and normalization layers. Its cache allocates only the latent and positional buffers.</p>

<h3 id="where-this-is-used">Where This Is Used</h3>

<p><a href="https://arxiv.org/abs/2405.04434">DeepSeek-V2</a> introduced MLA, and <a href="https://arxiv.org/abs/2412.19437">DeepSeek-V3</a> retained it. The compression ratio is an architectural choice: a smaller latent imposes a stronger constraint on what the heads can reconstruct. Training determines how well the model uses that capacity.</p>

<h3 id="key-takeaways-5">Key Takeaways</h3>

<ul>
  <li>MLA shares a compact latent while retaining head-specific content K/V up-projections.</li>
  <li>Matrix absorption avoids explicitly reconstructing the entire content K/V history during decoding.</li>
  <li>Full MLA also retains a shared positional key; cache savings depend on both latent rank and positional width.</li>
  <li>Compression reduces the stored representation, while context length, model quality and execution cost remain separate considerations.</li>
</ul>

<h2 id="8-gated-softmax-attention">8. Gated Softmax Attention</h2>

<p>So far, we’ve changed what attention reads or stores. Here’s a different question: once a head has read the context, how much of its answer should it pass on?</p>

<p>Softmax distributes a total weight of one across the visible keys. Even when a head’s retrieved information is unhelpful, it still produces that weighted mixture. A learned gate gives the model another control: scale the retrieved output before mixing the heads together.</p>

<p>A simple head-wise version uses the same causal mask \(M\) as before:</p>

\[\begin{aligned}
H_i &amp;= \operatorname{softmax}\!\left(\frac{Q_iK_i^{\mathsf T}}{\sqrt{d}} + M\right)V_i \\
g_i &amp;= \operatorname{sigmoid}(Xw_{\text{gate}}^i + b_i) \\
Y &amp;= \operatorname{concat}(g_1 \odot H_1, \ldots, g_h \odot H_h)W_O
\end{aligned}\]

<p>Each token gets one scalar gate per head, scaling every channel of that head’s output. Here \(\odot\) denotes elementwise multiplication, with the scalar applied across all channels. More expressive variants give individual output channels their own gates. The gate sits after the attention mixture and before the output projection; it does not replace softmax or renormalize the attention weights.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-gated-softmax.png" alt="Two attention heads feed sigmoid gates of 0.50 and 0.75 before concatenation and the output projection. The final toy output changes from 0.845, 0.845 to 0.422, 0.633." />
<em>The example fixes the gates to make their effect visible. In a trained model they depend on the current token representation.</em></p>

<p>For “sat” in our two-head example, the ungated output is \([0.845, 0.845]\). With identity output mixing and gates <strong>0.50 and 0.75</strong>, it becomes <strong>[0.422, 0.633]</strong>. The attention distributions are unchanged; only the head outputs are scaled. The <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/gated_attention.py">implementation</a> also supports token-dependent gates and cached decoding.</p>

<p><a href="https://arxiv.org/abs/2505.06708">Qiu and colleagues</a> studied where to place these gates and reported training-stability and performance benefits for gating after scaled dot-product attention in their experiments. <a href="https://huggingface.co/Qwen/Qwen3-Next-80B-A3B-Instruct">Qwen3-Next</a> uses gated attention alongside Gated DeltaNet layers. Gating introduces input-dependent nonlinearity.</p>

<h3 id="key-takeaways-6">Key Takeaways</h3>

<ul>
  <li>Gated softmax controls how much of an attention output passes forward.</li>
  <li>Small output gates do not imply skipped token reads, less KV storage or a faster kernel.</li>
  <li>Output gating and sparse token selection solve different problems and can coexist.</li>
</ul>

<h2 id="9-hybrid-attention-mix-memory-with-retrieval">9. Hybrid Attention: Mix Memory with Retrieval</h2>

<p>Do all layers need to keep every token’s keys and values? A recurrent layer offers a different deal: update a fixed-size state as tokens arrive, then read from that state. The memory stays compact, but individual past tokens are no longer separately addressable.</p>

<p>Hybrid architectures combine these recurrent or linear-attention layers with softmax attention. Many layers can maintain compact state, while selected attention layers retain direct access to token history. We already saw a simpler kind of hybrid in Gemma 2’s local/global layout; here the mix changes the form of memory itself.</p>

<p><a href="https://arxiv.org/abs/2412.06464">Gated DeltaNet</a> updates its memory in two steps: first decay the existing state, then correct what it stores for the current key using the incoming value. Both steps update the same fixed-size matrix.</p>

<details>
  <summary><b><i>For the curious: the gated-delta update</i></b></summary>

  <p>For normalized keys and queries, our reference recurrence is:</p>

\[\begin{aligned}
S_{\text{decayed}} &amp;= \alpha_t S_{t-1} \\
\operatorname{error}_t &amp;= v_t - k_t^{\mathsf T}S_{\text{decayed}} \\
S_t &amp;= S_{\text{decayed}} + \beta_t k_t \operatorname{error}_t^{\mathsf T} \\
\operatorname{output}_t &amp;= q_t^{\mathsf T}S_t
\end{aligned}\]

  <p>\(\alpha\) controls forgetting; \(\beta\) controls how strongly to correct the current association.</p>

</details>

<p>Repeated updates share the matrix’s capacity, so it is not an exact replacement for a list of past K/V vectors.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-hybrid-attention.png" alt="A recurrent layer with fixed matrix state feeds a full attention layer with growing KV history. Across one, two and three tokens, the toy recurrent state holds four elements while live attention KV grows from four to eight to twelve." />
<em>Our two-layer example isolates the two kinds of memory. Counts are live tensor elements, not measured process memory.</em></p>

<p>The <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/hybrid_attention.py">companion code</a> puts one gated-delta layer before one ordinary attention layer. Across three tokens, its recurrent state stays at <strong>4 elements</strong>, while the attention layer’s live KV grows <strong>4 → 8 → 12</strong>. Full-sequence and cached execution agree. The whole hybrid therefore still has growing memory; only its recurrent component is fixed in context length.</p>

<p><a href="https://huggingface.co/Qwen/Qwen3-Next-80B-A3B-Instruct">Qwen3-Next-80B-A3B</a> uses three Gated DeltaNet layers for every gated-attention layer, with MoE blocks in between. Our two-layer reference omits those blocks, convolutions, normalization and model-specific gate parameterization.</p>

<p><a href="https://arxiv.org/abs/2510.26692">Kimi Linear</a> makes another choice: combine <strong>Kimi Delta Attention (KDA)</strong> with MLA layers. KDA extends Gated DeltaNet with finer-grained gating, giving the recurrent state more selective control over forgetting. MLA supplies the layers that still read token history directly. This connects two ideas we’ve already covered: a hybrid can combine recurrent memory with compressed attention, rather than ordinary full attention. Our scalar-decay recurrence illustrates the shared foundation; it does not implement KDA’s finer-grained gates.</p>

<h3 id="key-takeaways-7">Key Takeaways</h3>

<ul>
  <li>Hybrid models choose which layers need token-addressable history and which can use compact recurrent state.</li>
  <li>Fixed state reduces history storage in recurrent layers, with a capacity and retrieval tradeoff.</li>
  <li>Remaining attention layers still grow their KV cache, even with MLA compression; both the layer mix and the attention design matter.</li>
</ul>

<h2 id="10-pagedattention-where-the-cache-lives">10. PagedAttention: Where the Cache Lives</h2>

<p>Even after choosing a smaller cache, we still have to fit many requests into GPU memory. They arrive at different times, grow at different rates and sometimes share a prompt. Reserving a large contiguous cache for each request can waste capacity that another request could use.</p>

<p><a href="https://arxiv.org/abs/2309.06180">PagedAttention</a>, introduced with vLLM, brings paging to KV storage. Split each request’s logical token sequence into fixed-size blocks, then map those blocks to physical cache pages wherever space is available. The attention implementation follows a block table instead of requiring one contiguous history.</p>

<p><img src="/blog/assets/images/attention-gym/attention-gym-paged-attention.png" alt="Request A maps to physical pages 0 and 2, B to page 1. A branch shares page 0 but copies its partially filled last page into page 3 when appending a token." />
<em>Two tokens per page in our allocator example. Page numbers are storage addresses; their order does not change token positions.</em></p>

<p>Our <a href="https://github.com/darpan-jain/attention-gym/blob/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/paged_attention.py">reference allocator</a> interleaves two requests, so A’s three tokens occupy pages <strong>[0, 2]</strong>, while B occupies page 1. Forking A initially shares its pages. Appending to that branch copies the shared, partially filled final page before writing: the branch now uses <strong>[0, 3]</strong>, and A’s history stays intact. This is copy-on-write; completed prefix pages can remain shared.</p>

<p>The softmax still covers the same visible keys. Our attention routine combines page-wise scores using a stable running maximum, denominator and weighted-value sum; its result matches a contiguous reference. Paging changes allocation and access, not which tokens the model attends to.</p>

<p>The payoff is at serving time: less reservation and fragmentation waste, plus reusable shared prefixes, can leave room for more concurrent requests. There is still page-table overhead and unused space in partially filled pages. Our CPU example verifies allocation, sharing and exact attention arithmetic. PagedAttention belongs to the serving stack rather than to a particular model architecture.</p>

<h3 id="key-takeaways-8">Key Takeaways</h3>

<ul>
  <li>PagedAttention maps logical KV history onto noncontiguous physical blocks.</li>
  <li>Prefix sharing and copy-on-write reduce duplication while preserving separate request histories.</li>
  <li>It preserves the attention calculation; savings come from managing cache capacity across requests.</li>
</ul>

<h2 id="11-a-brief-look-ahead">11. A Brief Look Ahead</h2>

<p>Efficiency is only part of the story. <a href="https://arxiv.org/abs/2410.05258">Differential Attention</a> combines two softmax attention maps subtractively, giving it a way to cancel shared signals. <a href="https://huggingface.co/blog/microsoft/diff-attn-v2">Differential Transformer V2</a> revises this with a token-dependent, per-head subtraction gate and an implementation that uses standard FlashAttention kernels. Compare that with gated softmax: one scales a retrieved output; the other subtracts a learned fraction of another attention output. These are different ways to control what survives retrieval.</p>

<p><a href="https://arxiv.org/abs/2603.15031">Attention Residuals</a> (<a href="https://github.com/MoonshotAI/Attention-Residuals">code</a>) changes the axis of attention itself. Instead of only asking which earlier tokens matter, a layer learns how to mix earlier layers’ representations at the same token position. Its block variant groups layer outputs to reduce the overhead of retaining them all. This changes information flow through model depth and can sit alongside the token-attention mechanisms above.</p>

<h2 id="12-closing-thoughts">12. Closing Thoughts</h2>

<p>The interesting part of these designs is how many decisions fit inside the same query–key–value idea. We can share the history across heads, compress what represents it, choose which parts to read, or decide how much of the retrieved output to pass forward. We can also give different layers different kinds of memory, then organize that memory across requests at serving time.</p>

<p>Here’s the comparison of the attention designs we discussed:</p>

<table>
  <thead>
    <tr>
      <th>Design</th>
      <th>What changes</th>
      <th>What it helps with</th>
      <th>What to watch</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Multi-head attention</td>
      <td>Multiple learned query, key and value projections</td>
      <td>Representing different relationships in parallel</td>
      <td>Full-history attention still reads a growing token history</td>
    </tr>
    <tr>
      <td>MQA / GQA</td>
      <td>Query heads share KV heads</td>
      <td>KV storage and repeated KV reads</td>
      <td>Shared KV reduces independent per-head capacity</td>
    </tr>
    <tr>
      <td>Sliding window</td>
      <td>Each local layer reads recent positions</td>
      <td>Bounded local history and attention work</td>
      <td>Distant tokens lose direct visibility in that layer</td>
    </tr>
    <tr>
      <td>Selected / compressed sparse attention</td>
      <td>Select historical entries, optionally after sequence compression</td>
      <td>Expensive attention over long histories</td>
      <td>Selection overhead and information missed or compressed away</td>
    </tr>
    <tr>
      <td>MLA</td>
      <td>Cache a compact latent and positional key per token</td>
      <td>Stored width of the history</td>
      <td>Latent capacity, positional state and kernel design</td>
    </tr>
    <tr>
      <td>Gated softmax</td>
      <td>Scale retrieved outputs before mixing heads</td>
      <td>Control over which retrieved features pass forward</td>
      <td>Gating alone does not reduce token reads or KV storage</td>
    </tr>
    <tr>
      <td>Recurrent / attention hybrids</td>
      <td>Mix compact recurrent state with token-addressable attention</td>
      <td>History storage in recurrent layers</td>
      <td>Finite-state capacity and growing KV in the remaining attention layers</td>
    </tr>
    <tr>
      <td>PagedAttention</td>
      <td>Map logical KV history to physical pages</td>
      <td>Allocation waste and duplicated prefixes across requests</td>
      <td>Page management and partially filled blocks</td>
    </tr>
  </tbody>
</table>

<p>These choices compose. GQA can sit inside a sliding-window layer; a hybrid can use MLA for its attention layers; a serving engine can page the resulting cache. The newer designs also make reuse across layers part of the architecture. Each choice changes a different part of the memory and computation budget.</p>

<p>The <a href="https://github.com/darpan-jain/attention-gym/tree/a9746600cd203c8012efb58ef442593d6d92eb19/src/attention_gym/examples">companion examples</a> make those choices inspectable with the same small inputs.</p>

<p>When reading the next model report, start with three questions: <strong>what history is stored, which entries does a query read, and what work is repeated as the sequence grows?</strong> Then check how those choices map to the target hardware. Cache size and attention complexity explain part of generation throughput; kernels, batching and data movement determine how much of that advantage reaches the user.</p>

<h2 id="references">References</h2>

<ul>
  <li><a href="https://arxiv.org/abs/1706.03762">Attention Is All You Need</a> (Vaswani et al., 2017)</li>
  <li><a href="https://arxiv.org/abs/1911.02150">Fast Transformer Decoding: One Write-Head is All You Need</a> (Shazeer, 2019)</li>
  <li><a href="https://arxiv.org/abs/2305.13245">GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints</a> (Ainslie et al., 2023)</li>
  <li><a href="https://arxiv.org/abs/2505.09388">Qwen3 Technical Report</a> (Qwen Team, 2025)</li>
  <li><a href="https://arxiv.org/abs/2004.05150">Longformer: The Long-Document Transformer</a> (Beltagy et al., 2020)</li>
  <li><a href="https://arxiv.org/abs/2310.06825">Mistral 7B</a> (Jiang et al., 2023)</li>
  <li><a href="https://arxiv.org/abs/2408.00118">Gemma 2: Improving Open Language Models at a Practical Size</a> (Gemma Team, 2024)</li>
  <li><a href="https://arxiv.org/abs/2405.04434">DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model</a> (DeepSeek-AI, 2024)</li>
  <li>
    <p><a href="https://arxiv.org/abs/2412.19437">DeepSeek-V3 Technical Report</a> (DeepSeek-AI, 2024)</p>
  </li>
  <li><a href="https://arxiv.org/abs/2502.11089">Native Sparse Attention</a> (Yuan et al., 2025)</li>
  <li><a href="https://github.com/deepseek-ai/DeepSeek-V3.2-Exp">DeepSeek-V3.2-Exp</a> (DeepSeek-AI, 2025)</li>
  <li><a href="https://arxiv.org/abs/2505.06708">Gated Attention for Large Language Models</a> (Qiu et al., 2025)</li>
  <li><a href="https://arxiv.org/abs/2412.06464">Gated Delta Networks: Improving Mamba2 with Delta Rule</a> (Yang et al., 2025)</li>
  <li><a href="https://huggingface.co/Qwen/Qwen3-Next-80B-A3B-Instruct">Qwen3-Next-80B-A3B model card</a> (Qwen, 2025)</li>
  <li>
    <p><a href="https://arxiv.org/abs/2309.06180">Efficient Memory Management for Large Language Model Serving with PagedAttention</a> (Kwon et al., 2023)</p>
  </li>
  <li><a href="https://arxiv.org/abs/2606.19348">DeepSeek-V4: Towards Highly Efficient Million-Token Context Intelligence</a> (DeepSeek-AI, 2026)</li>
  <li><a href="https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash">DeepSeek-V4.1-Flash model card</a> (DeepSeek-AI, 2026)</li>
  <li><a href="https://arxiv.org/abs/2510.26692">Kimi Linear: An Expressive, Efficient Attention Architecture</a> (Kimi Team, 2025)</li>
  <li><a href="https://arxiv.org/abs/2410.05258">Differential Transformer</a> (Ye et al., 2024)</li>
  <li><a href="https://huggingface.co/blog/microsoft/diff-attn-v2">Differential Transformer V2</a> (Ye et al., 2026)</li>
  <li><a href="https://arxiv.org/abs/2603.15031">Attention Residuals</a> (Kimi Team et al., 2026)</li>
</ul>]]></content><author><name>Darpan Jain</name></author><category term="llm" /><category term="transformers" /><category term="attention" /><category term="kv-cache" /><category term="inference" /><summary type="html"><![CDATA[How LLM attention shares, compresses, and selects context, and what each design trades for efficiency.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://darpanjain.com/blog/assets/images/attention-gym/attention-gym-kv-sharing.png" /><media:content medium="image" url="https://darpanjain.com/blog/assets/images/attention-gym/attention-gym-kv-sharing.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Everyone Agrees with Me</title><link href="https://darpanjain.com/blog/everyone-agrees-with-me/" rel="alternate" type="text/html" title="Everyone Agrees with Me" /><published>2026-10-03T00:00:00-07:00</published><updated>2026-10-03T00:00:00-07:00</updated><id>https://darpanjain.com/blog/everyone-agrees-with-me</id><content type="html" xml:base="https://darpanjain.com/blog/everyone-agrees-with-me/"><![CDATA[<p><em>How our feeds build echo chambers that follow us into what we believe, who we trust, and how we treat the people we love.</em></p>

<p><img src="/blog/assets/images/everyone-agrees-with-me/echo-chambers.png" alt="Echo Chamber Illustration" /></p>

<p>During the <a href="https://en.wikipedia.org/wiki/2026_Delhi_Jantar_Mantar_protests">recent protests in Delhi</a>, my screen time climbed to nine or ten hours a day. I was hooked. My feed was full of explanations, media footage from independent journalists, influencers, and some friends. I saw young people, people of other ages, huge crowds protesting and supporting each other. It all felt like we were one big family. My agitation became a way of feeling connected without physically being there.</p>

<p>Then, occasionally, a reel would show up attacking the protestors or defending the forces being protested against. My first reaction was disbelief. How could someone, knowing everything that’s happened and seeing everything that’s happening, still reach that conclusion? Then it occurred to me that maybe they didn’t know. Maybe they weren’t seeing what I was seeing, or being told what I was being told. Information is tricky.</p>

<p>I wondered what their feeds looked like. How was the same information being delivered to them? How much was their surrounding context playing a role in what they were taking from it? Were they scrolling through hours of posts that made their position feel obvious?</p>

<p>Those occasional reels were a glimpse into another worldview. In recommendation systems, they’re a deliberate move called exploration. Most of the time, the algorithm exploits what it already knows about you, serving more of what keeps you watching. Every so often, it explores: it shows you something new or contrasting to test whether you have an interest it hasn’t found yet. If you do, that becomes one more way to keep you coming back to the app instead of going to a friend, especially when emotions are running high. Those exploration reels made me notice how much the rest of my feed agreed with me.</p>

<p>I still held my views. I just began asking how much I hadn’t seen. Nine hours of scrolling can feel like you know the whole story, even when you keep encountering versions of the same argument.</p>

<p>Everyone seemed to agree with me. I had started to wonder who “everyone” actually included.</p>

<h2 id="a-room-full-of-your-own-voice">A room full of your own voice</h2>

<p>An Echo Chamber is an environment where beliefs get reinforced by like-minded voices, while competing perspectives struggle to enter. A study of more than 100M pieces of social media content<sup>1</sup> found that these patterns differ across platforms. Both our social connections and feed design matter.</p>

<p>Once I started noticing that pattern, I wondered where else it shows up. My playlists, my watchlist, my humor, my shopping preferences, a shirt I was sure I’d picked out myself. How much had I chosen and how much had become familiar through repetition?</p>

<p>And the room need not have a screen. Group chats, workplaces, or friend circles can become a surface where agreement becomes the price of belonging.</p>

<p>Hear the same opinion enough, and you can stop asking why you believe it. Eventually, someone questioning it feels like someone questioning you</p>

<h2 id="who-put-this-on-repeat">Who put this on repeat?</h2>

<p>It’s a harder question than whether algorithms simply “ruin taste”. Recommendations can introduce us to wonderful things (this one is <em>closes(T)</em> to me). But if I discover everything through the same feed, its recommendations start setting the boundaries of what I try. An unfamiliar artist, a slower film, or a different sense of humor might never get a chance. I can keep finding new things without moving very far from what I already like.</p>

<p>Between autoplay, “because you watched,” and the “For You” page, it gets hard to tell where my taste ends and the feed begins. And when millions of people are nudged towards the same few songs, “my taste” starts to sound a lot like everyone else’s.</p>

<p>When Spotify’s own research<sup>2</sup> looked at listening habits, music that people found through recommendations was much less varied than music they chose themselves. Listeners who broadened their taste over time did it by drifting away from recommendations. And those varied listeners were more likely to stick around and pay. Narrowing someone’s taste isn’t even good for business.</p>

<h2 id="the-feed-is-doing-its-job">The feed is doing its job</h2>

<p>I’ve spent the last six years building recommendation and personalisation systems. I know how they’re designed, what they learn from, and how they decide what to show us. None of that stopped me from spending nine or ten hours a day on my phone.</p>

<p>As I wrote in my technical piece on multi-armed bandits<sup>3</sup>, many of these algorithms learn by trial and error: exploit what they think you’ll like, explore just enough to find something more engaging.</p>

<p>The catch is the reward. “<strong>Did this make your life better?</strong>” is hard to measure, so success gets translated into things that are easy to count: views, likes, shares, session length, and return rates over days or weeks. Some systems also predict satisfaction. YouTube used survey responses to estimate “value watch time<sup>4</sup>”, giving more weight to time spent on videos people rated highly. Engineers evaluate ranking quality with metrics like NDCG<sup>5</sup>, which gives more weight to relevant results near the top of your feed. These models are live, retraining multiple times a day or even on the fly with the objective of getting good at those numbers (and thus maximizing shareholder value).</p>

<p>Bandits even have a metric for getting it wrong. It’s called regret: the gap between what the system chose and the best option it could have chosen. My systems measure their regret. Nobody measures mine.</p>

<p>I’ve written before<sup>6</sup> about how easily these systems end up optimising for the wrong things. Agreement is comfortable, and comfort keeps you scrolling. Outrage gets rewarded too (and much more often). Yale researchers found<sup>7</sup> that positive feedback for outrage encouraged more outrage expression later. That tracks what people posted, not what they felt, but it shows how a platform can help rehearse a habit.</p>

<p>The obvious fix is to ask people what they actually want. One Twitter experiment<sup>8</sup> got close. It found that engagement ranking amplified anger and hostility, even though users didn’t prefer the political tweets it selected. Ranking by stated preferences reduced anger but could deepen echo chambers. I might end up agreeing with myself more politely.</p>

<p>Our own habits matter too. A 2023 Facebook experiment<sup>9</sup> reduced like-minded content without measurably changing political attitudes. Confirmation bias<sup>10</sup> draws us toward evidence that fits our beliefs, while the illusory truth effect<sup>11</sup> makes repeated claims feel more credible. My choices help curate the feed that keeps confirming them.</p>

<h2 id="when-the-feed-comes-to-dinner">When the feed comes to dinner</h2>

<p>Picture a dinner where everyone repeats the same take, dislikes the same stranger, and recommends the same purchase. We pass posts around, discuss them, and send similar ones back. A view I encountered online can return through several people I trust, each adding their own experience to it. By then, it’s hard to separate how many people have thought it through from how many times we’ve all encountered it.</p>

<p>The group chat is the last step of the recommendation. Someone shares what their feed served them, and now it arrives with a friend’s voice attached. I’ll skip an ad in a second. I won’t skip something my friend sent.</p>

<p><img src="/blog/assets/images/everyone-agrees-with-me/echo-chambers-conversation.png" alt="Echo chambers" /></p>

<p>Online repetition becoming offline consensus, then returning online as further confirmation. “<strong>Everyone agrees with me</strong>” sounds like evidence, unless everyone has been looking through similar windows.</p>

<p>I like having that shared language with friends, especially with memes. I’d also like us to feel comfortable saying “I’m not sure I see it that way.”</p>

<h2 id="who-gets-to-explain-the-people-i-love">Who gets to explain the people I love?</h2>

<p>Imagine having an argument with someone you care about, then opening your feed. A stranger describes a situation that sounds like yours. Another gives it a name. Soon you have an explanation ready, before you’ve asked the person.</p>

<p>Smoothie’s essay on Instagram and relationships<sup>12</sup> raises the question of letting the feed interpret our relationships. Val Quarta<sup>13</sup> takes it further, arguing that the search for warning signs can turn into constant scrutiny. I read them as invitations to examine how online advice shapes our expectations of each other.</p>

<p>Alvin Chang’s “A love story”<sup>14</sup> explores how we ask one partner to provide what was once needed from an entire village - companionship, excitement, meaning, and personal growth. A feed can keep adding to those expectations. I wonder how often the advice I find helps me understand someone, and how often it gives me another reason to stay angry.</p>

<p>A feed has fragments of my attention. It hasn’t lived through the relationships (at least <em>not yet</em>). Sometimes a kind conversation fills in details that no amount of scrolling could give me. I’m still learning this, sometimes the hard way.</p>

<p>Advice can help us recognise patterns worth taking seriously and work out what we need ourselves and people around us. I also want to leave room for awkward moments, misunderstandings, or someone having a difficult day. Getting to know people takes more context than a short video with a hook can offer.</p>

<h2 id="almost-enough">Almost enough</h2>

<p>The commercial version of this loop is: your life is almost <em>good enough</em>. A better body, a better holiday, a more photogenic weekend. One more purchase should do it.</p>

<p>Research on social comparison and envy<sup>15</sup> links them with lower well-being, although comparison can also inspire. Zoe Keziah Mendelson’s essay<sup>16</sup> made me think about the jumble itself: suffering, a beautiful home, somebody’s holiday, all sharing one feed. Within minutes, I can move between grief, joy, excitement, anger, jealousy, and inspiration. The vertical feed keeps the next feeling one swipe away. I barely sit with one before something else asks for my attention.</p>

<p>Rapid switching between short videos17 has been found to have effects on remembering intended actions. It doesn’t tell us exactly what this emotional jumble does to us, but I recognise the experience of opening an app and forgetting it along the way.</p>

<p>I think about our hunter-gatherer ancestors and the curiosity that brought us here. I picture someone looking up at the sky (<em>in better AQI</em>), wondering about their place in it.</p>

<p>Meanwhile, someone beside me is waiting for me to put the phone down and look up.</p>

<h2 id="breaking-free">Breaking free</h2>

<p>Leaving is complicated when the same app holds your friends, your audience, and your work. “Just delete it” asks some people to give up much more than a scrolling habit.</p>

<p>Start with something you can take back. Read outside your feed. Ask friends what might change their minds, and answer the question yourself. When a post seems to explain someone you know, leave room to hear their explanation too.</p>

<p>Intentionally search instead of scrolling (<em>warning: those are personalised too</em>.) Reset your recommendations now and then - online and offline - and give the “explore” side of the algorithm something to do. Notice which accounts leave you curious and which leave you feeling inadequate.</p>

<p>Agreeing with people is fine. <strong>I just want to know that I chose to.</strong></p>

<p>A life of your own needs something a personalised feed cannot guarantee: room to be surprised and change your mind about things. So when everyone agrees with me, I’m learning to treat it less as proof and more as a prompt to ask: who’s missing from the room?</p>

<h2 id="references">References</h2>

<ol>
  <li><a href="https://www.pnas.org/doi/10.1073/pnas.2023301118">The echo chamber effect on social media</a></li>
  <li><a href="https://www.cs.toronto.edu/~ashton/pubs/alg-effects-spotify-www2020.pdf">Algorithmic Effects on the Diversity of Consumption on Spotify</a></li>
  <li><a href="https://belovedthoughtss.substack.com/p/multi-armed-bandit-algorithms-for?r=b0aer">Multi-arm bandits for recommendation systems by Darpan</a></li>
  <li><a href="https://blog.youtube/inside-youtube/on-youtubes-recommendation-system/">On YouTube’s Recommendation System</a></li>
  <li><a href="https://www.evidentlyai.com/ranking-metrics/ndcg-metric">Normalized Cumulative Gain Metric (NDCG) explained</a></li>
  <li><a href="https://belovedthoughtss.substack.com/p/winning-the-metrics">Winning the Metric, Losing the Point by Darpan</a></li>
  <li><a href="https://isps.yale.edu/research/publications/isps21-25">How Social Learning Amplifies Moral Outrage Expression in Online Social Networks</a></li>
  <li><a href="https://knightcolumbia.org/content/engagement-user-satisfaction-and-the-amplification-of-divisive-content-on-social-media">Engagement, User Satisfaction, and the Amplification of Divisive Content on Social Media</a></li>
  <li><a href="https://www.nature.com/articles/d41586-023-02425-8">Facebook ‘echo chamber’ has little impact on polarized views, according to study</a></li>
  <li><a href="https://thedecisionlab.com/biases/belief-perseverance">Why do we maintain the same beliefs, even when we are proved wrong?</a></li>
  <li><a href="https://thedecisionlab.com/biases/illusory-truth-effect">Why do we believe misinformation more easily when it’s repeated many times?</a></li>
  <li><a href="https://shedrinkswater.substack.com/p/instagram-is-training-you-to-leave">Instagram is training you to leave people who love you</a></li>
  <li><a href="https://valquarta.substack.com/p/social-media-is-teaching-you-to-leave?utm_source=%2Finbox&amp;utm_medium=reader2">Social Media Is Teaching You to Leave the People You Love</a></li>
  <li><a href="https://pudding.cool/2026/06/love-story/#:~:text=%E2%80%9CNever%20before%20in%20history%20had%20societies%20thought%20that%20such%20a%20set%20of%20high%20expectations%20about%20marriage%20was%20either%20realistic%20or%20desirable%2C%E2%80%9D%20Coontz%20writes.">Love Story by The Pudding</a></li>
  <li><a href="https://www.researchgate.net/publication/358251605_Social_comparison_and_envy_on_social_media_A_critical_review">Social comparison and envy on social media - A critical review</a></li>
  <li><a href="https://zoekeziahmendelson.substack.com/p/it-is-urgent-and-imperative-that?utm_source=%2Finbox&amp;utm_medium=reader2">It Is Urgent and Imperative That We All Permanently Exit Instagram</a></li>
  <li><a href="https://www.tandfonline.com/doi/full/10.1080/09658211.2025.2521076">Context-switching in short-form videos: What is the impact on prospective memory?</a></li>
</ol>

<hr />

<p><br /></p>

<p><em>I was, of course, in a potential echo chamber during my research and writing of this blog post. Please <a href="https://darpanjain.com/#contact-section">reach out</a> with your thoughts!</em></p>]]></content><author><name>darpan-jain</name></author><category term="social-media" /><category term="recommendation-systems" /><category term="echo-chambers" /><category term="cognitive-biases" /><category term="attention-economy" /><summary type="html"><![CDATA[How our feeds build echo chambers that follow us into what we believe, who we trust, and how we treat the people we love.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://darpanjain.com/blog/assets/images/everyone-agrees-with-me/echo-chambers.png" /><media:content medium="image" url="https://darpanjain.com/blog/assets/images/everyone-agrees-with-me/echo-chambers.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Winning the Metric, Losing the Point</title><link href="https://darpanjain.com/blog/winning-the-metric/" rel="alternate" type="text/html" title="Winning the Metric, Losing the Point" /><published>2025-11-10T17:14:32-08:00</published><updated>2025-11-10T17:14:32-08:00</updated><id>https://darpanjain.com/blog/winning-the-metric</id><content type="html" xml:base="https://darpanjain.com/blog/winning-the-metric/"><![CDATA[<p><em>Rethinking success in a world optimized for metrics instead of meaning</em></p>

<p>Consider the last time you caught yourself <a href="https://belovedthoughtss.substack.com/p/multi-armed-bandit-algorithms-for?r=b0aer">doomscrolling</a>. Your feed was likely a minefield of <a href="https://en.wikipedia.org/wiki/Rage-baiting">rage-bait</a>,  each post a little more infuriating than the last. You saw post after post like that, not because anyone decided to show you them, but because an algorithm learned a simple, powerful lesson: <strong>outrage keeps you scrolling</strong>.</p>

<p>This isn’t an accident. It’s the predictable outcome of optimizing for the wrong metric. And it’s not just social media; this pattern is everywhere across business, technology, policy, and society.</p>

<p>Economists have a name for this (as they always do): Goodhart’s Law, often paraphrased as “when a measure becomes a target, it ceases to be a good measure.” It’s usually told as a story about economics and bureaucracy. As someone who builds recommendation and AI systems, I see it as an engineering problem, and engineering problems have engineering fixes.</p>

<p><img src="/blog/assets/images/winning-the-metric/goodhart-chart.svg" alt="Chart: as optimization pressure increases, the metric keeps rising while the real goal peaks and then declines" />
  <em>Push hard enough on a proxy, and it stops pointing at the goal.</em></p>

<h2 id="how-we-got-here-the-measurement-paradox">How we got here: the measurement paradox</h2>

<p>Metrics start with good intentions. They help us understand progress, compare approaches, and make decisions. They promise control over outcomes. They promise clarity.</p>

<p>But they capture only part of what we want: screen time isn’t time well spent, a reward score isn’t guaranteed truthfulness, and quarterly earnings aren’t long-term company health. The danger comes when the measure stands in for the goal. Reward a number, and people and systems will find ways to improve it, through better work or shortcuts.</p>

<p>A system can also reinforce the behavior it measures. A feed that keeps serving content about reasons to distrust someone may encourage habitual scrutiny, then count return visits as success.</p>

<h2 id="lost-in-translation">Lost in translation</h2>

<p>There’s often a dangerous delay between when we start optimizing for a metric and when we see the negative effects.</p>

<ul>
  <li><strong>Social Media &amp; Engagement</strong>:
    <ul>
      <li><strong>We want</strong>: An engaged community</li>
      <li><strong>We measure</strong>: clicks, shares, and screen time</li>
      <li><strong>We get</strong>: Algorithms discover that outrage, <a href="https://insights.som.yale.edu/insights/how-social-media-rewards-misinformation">misinformation</a>, and harmful content are most engaging, , keeping users in <a href="https://belovedthoughtss.substack.com/p/everyone-agrees-with-me?r=b0aer">echo chambers</a>, and radicalizing users to keep them scrolling.</li>
    </ul>
  </li>
  <li><strong><a href="/blog/reward-hacking/">Reward Hacking during post-training of AI models</a></strong>:
    <ul>
      <li><strong>We want</strong>: Helpful and truthful AI models</li>
      <li><strong>We measure</strong>: a “reward score” that fine-tunes to human preferences.</li>
      <li><strong>We get</strong>: A model that learns to <a href="/blog/reward-hacking/">reward hack</a>: flattering users, telling them what they want to hear, and sounding confident whether or not it’s right. The reward goes up, but the truthfulness doesn’t. AI slop is born.</li>
    </ul>

    <p>(I often ran into this during my own pursuit of <a href="https://darpanjain.com/#work-section">building early RAG systems for Conversational Search</a>: they scored well on training metrics, but fell flat on quality benchmarks.)</p>
  </li>
  <li><strong>Environment Offsets</strong>:
    <ul>
      <li><strong>We want</strong>: <a href="https://zerotracker.net/">Carbon neutral organizations</a></li>
      <li><strong>We measure</strong>: offset credits purchased (often tied to trees planted)</li>
      <li><strong>We get</strong>: the net-zero claims on paper, while the local harm of new construction and community impact, like data centers and supply chains, goes unaccounted for</li>
    </ul>
  </li>
</ul>

<p>The same pattern shows up in boardrooms chasing quarterly earnings and governments chasing GDP growth. And this goes on and on. But you get the idea.</p>

<p>Blindly optimizing for proxies can often render human suffering invisible or externalize it.</p>

<h2 id="three-disciplines-for-responsible-metrics">Three disciplines for responsible metrics</h2>

<p>Clearly, metrics can be tricky, and the real world is hard to model. They can be dangerous when left unquestioned. But the solution isn’t to run in the opposite direction and abandon metrics; it’s to treat them with suspicion.</p>

<p>For example, consider optimizing a RAG pipeline for p95 end-to-end latency under a fixed workload. You could reduce retrieval depth, skip reranking, or cap output tokens to make responses faster. But a faster answer isn’t necessarily a correct, grounded, or complete one.</p>

<ul>
  <li>
    <p><strong>Definition</strong>: name the real goal <br />
Latency is a proxy. The real goal is a user getting a correct, grounded answer, quickly. Writing that down makes it obvious what latency alone ignores.</p>
  </li>
  <li><strong>Critique</strong>: look for the shortcut <br />
Actively stress-test your metric. Red team it. Put guardrails in place before the system drifts. Ask:
    <ul>
      <li>How could this be gamed?</li>
      <li>What behaviors might this incentivize?</li>
      <li>Who could be harmed?</li>
      <li>Who might bear the cost?</li>
    </ul>
  </li>
  <li><strong>Iteration</strong>: revise the measure
  – Metrics should evolve like software. They need to be updated, patched, or even deprecated when they stop serving the real purpose</li>
</ul>

<p>Reality moves. Metrics must too. <strong>The most dangerous metric is the one we stop questioning.</strong></p>

<h2 id="where-does-this-leave-us">Where does this leave us?</h2>

<p>Look around you, and you’ll see how fundamental metrics are in the systems we build and inhabit. They guide choices, reward behaviors, and define winning. <strong>They influence what companies build, what governments prioritize, and what technology becomes.</strong></p>

<p>Progress isn’t only measured. It’s interpreted. Argued over. Redefined.</p>

<p>The systems that thrive are the ones that stay curious, that treat metrics as evolving guides rather than fixed truths. So the next time you’re working hard toward a goal, pause and ask:</p>

<blockquote>
  <p>“<em>Did I reach meaning — or just the metric?</em>”</p>
</blockquote>

<p>That simple question can be surprisingly liberating.</p>

<hr />

<p><br /></p>

<p><em>If you manage to implement some of these in your next work project or personal endeavor, <a href="https://darpanjain.com/#contact-section">I would love to know how it went</a>!</em></p>]]></content><author><name>darpan-jain</name></author><category term="metrics" /><category term="systems-thinking" /><category term="business-strategy" /><summary type="html"><![CDATA[Rethinking success in a world optimized for metrics instead of meaning]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://darpanjain.com/blog/assets/images/shared/thinking.webp" /><media:content medium="image" url="https://darpanjain.com/blog/assets/images/shared/thinking.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Clip, Compare, or Skip: How PPO, GRPO, and DPO Align Language Models</title><link href="https://darpanjain.com/blog/policy-optimization/" rel="alternate" type="text/html" title="Clip, Compare, or Skip: How PPO, GRPO, and DPO Align Language Models" /><published>2025-05-18T18:14:32-07:00</published><updated>2026-11-03T00:00:00-08:00</updated><id>https://darpanjain.com/blog/policy-optimization</id><content type="html" xml:base="https://darpanjain.com/blog/policy-optimization/"><![CDATA[<p><em>Why your chatbot loves saying “Great question!”</em></p>

<!-- <figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/policy_optimization.png" alt="Policy Optimization Algorithms for Alignment" style="width: 80%; display: block; margin-left: auto; margin-right: auto;">
</figure> -->

<p>Pretraining gives a language model broad knowledge, but not preferences. It doesn’t know which of two plausible answers a person would actually want. Alignment closes that gap: you collect human preference data, then use it to push the model toward better responses without letting it drift into nonsense or exploit blind spots in how “better” is measured. That last failure mode is reward hacking, which I covered in <a href="/blog/reward-hacking/">Gaming the System</a>.</p>

<p>This post walks through the three algorithms you’ll most often see for this step: PPO, GRPO, and DPO. For each one, I’ll cover the problem it solves, how it works, what it costs, and how it relates to reward hacking. There’s a side-by-side comparison at the end.</p>

<p>To keep things concrete, I’ll use one toy prompt throughout: <strong>“What is 17 × 24?”</strong> The right answer is 408.</p>

<p><strong>Notation</strong>:</p>
<ul>
  <li>\(x\): prompt</li>
  <li>\(y\): response</li>
  <li>\(\pi_\theta\): the policy (the model being trained)</li>
  <li>\(\pi_{\text{ref}}\): frozen reference model, usually the SFT model</li>
  <li>\(r_\phi(x, y)\): learned reward model</li>
  <li>\(\beta\): strength of the KL penalty</li>
</ul>

<h2 id="1-proximal-policy-optimization-ppo-small-steps-toward-the-reward">1. Proximal Policy Optimization (PPO): small steps toward the reward</h2>

<p><strong>The problem.</strong> You’ve trained a reward model \(r_\phi(x, y)\) on human preferences, and now you want the language model to produce answers it scores highly. Taking big gradient steps toward higher reward is unstable, and it quickly finds outputs the reward model happens to love but humans wouldn’t.</p>

<p><strong>The idea.</strong> Sample answers from the current model, score them, and nudge the model toward the answers that did better than expected, but only a little per update. A KL penalty acts as a leash back to the reference model.</p>

<p><strong>Example.</strong> The model answers “17 × 24 = 340 + 68 = 408.” The reward model scores it 0.9. A separate value model, which predicts how well answers to a prompt like this usually score, expected about 0.6. So the answer did better than expected (an advantage of roughly +0.3), and its tokens get pushed up. With a typical clip of \(\epsilon = 0.2\), once an update has made those tokens about 20% more likely than before, PPO stops pushing for this batch.</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/ppo-step-by-step.gif" alt="Animation of one PPO update: the policy samples an answer, the reward model scores it 0.9, the value model expected 0.6 so the advantage is +0.3, and the token probability ratio rises from 1.0 until it hits the clip at 1.2." style="width: 100%;" />
</figure>

<p><strong>The math.</strong> The overall objective is to maximize reward while staying close to the reference model:</p>

\[J(\theta) = \mathbb{E}_{x \sim \mathcal{D},\, y \sim \pi_\theta(\cdot \mid x)}\big[r_\phi(x, y)\big] \;-\; \beta\, \mathrm{KL}\big(\pi_\theta(\cdot \mid x)\,\|\,\pi_{\text{ref}}(\cdot \mid x)\big)\]

<p>PPO optimizes this one token at a time. The state is the prompt plus everything generated so far, \(s_t = (x, y_{&lt;t})\), and the action is the next token \(y_t\). For each token, PPO compares the new policy to the one that generated the data:</p>

\[\rho_t(\theta) = \frac{\pi_\theta(y_t \mid s_t)}{\pi_{\theta_{\text{old}}}(y_t \mid s_t)}\]

<p>and maximizes the clipped objective:</p>

\[L^{\text{CLIP}}(\theta) = \mathbb{E}_t\Big[\min\big(\rho_t(\theta)\,\hat{A}_t,\; \mathrm{clip}(\rho_t(\theta),\, 1-\epsilon,\, 1+\epsilon)\,\hat{A}_t\big)\Big]\]

<p>In words: push up tokens with positive advantage and push down tokens with negative advantage, but once \(\rho_t\) leaves \([1-\epsilon, 1+\epsilon]\), the gradient for that token goes to zero. This keeps each update close to the policy that generated the data, approximating a trust region without the second-order machinery of <a href="https://arxiv.org/abs/1502.05477">TRPO</a>.</p>

<p><br /></p>
<details>
  <summary><b><i>For the curious: where the advantage comes from</i></b></summary>

  <p>In <a href="https://openai.com/index/instruction-following/">InstructGPT</a>-style setups, the KL penalty is folded into a per-token reward, with the reward model’s score added at the final token \(T\):</p>

\[r_t = -\beta \log \frac{\pi_\theta(y_t \mid s_t)}{\pi_{\text{ref}}(y_t \mid s_t)} \;+\; \mathbb{1}[t = T]\, r_\phi(x, y)\]

  <p>A learned value model \(V_\psi(s_t)\) estimates how good each partial response is, and the advantage is typically computed with Generalized Advantage Estimation (GAE):</p>

\[\delta_t = r_t + \gamma V_\psi(s_{t+1}) - V_\psi(s_t), \qquad \hat{A}_t = \sum_{l=0}^{T-t} (\gamma\lambda)^l\, \delta_{t+l}\]

  <p>The advantage answers one question: was this token better or worse than the value model expected at this point?</p>

</details>
<p><br /></p>

<p><strong>Where reward hacking hides.</strong> PPO has two brakes, and they do different jobs. <strong>The clip limits how fast the policy moves; the KL penalty limits how far.</strong> Clipping alone can’t stop reward hacking, because a policy can drift toward an exploit one small, clipped step at a time. Suppose opening with “Great question!” happens to raise the reward model’s score. PPO will learn to say it, just slowly. The KL penalty pushes back against the total drift from \(\pi_{\text{ref}}\), which makes gibberish-but-high-reward outputs expensive. Neither brake fixes the reward model itself: if \(r_\phi\) has a blind spot, PPO will still find it.</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/ppo-kl-leash.gif" alt="Animation comparing PPO with and without a KL penalty: with clipping alone, the policy takes small steps that eventually reach a reward hack; with a KL penalty, the policy is pulled back and settles where extra reward no longer outweighs the penalty." style="width: 100%;" />
<figcaption><i>Illustrative numbers. The clip limits how fast the policy moves; the KL penalty limits how far.</i></figcaption>
</figure>

<p><strong>The cost.</strong> PPO keeps four models in play: the policy, the reference model, the reward model, and the value model. The value model is as large as the policy and needs its own training. That overhead is exactly what GRPO was designed to cut.</p>

<h2 id="2-group-relative-policy-optimization-grpo-grade-answers-against-each-other">2. Group Relative Policy Optimization (GRPO): grade answers against each other</h2>

<p><strong>The problem.</strong> PPO needs a value model to judge whether each answer did better or worse than expected. That’s a whole extra model to train and keep in memory, and a poorly trained value model gives noisy advantages.</p>

<p><strong>The idea.</strong> Skip the value model. Ask the same question several times, and judge each answer against its siblings. Answers that beat the group average get pushed up; answers that fall below it get pushed down. GRPO was introduced in <a href="https://arxiv.org/abs/2402.03300">DeepSeekMath</a> and popularized by <a href="https://arxiv.org/abs/2501.12948">DeepSeek-R1</a>.</p>

<p><strong>Example.</strong> The model samples 4 answers to “What is 17 × 24?” Three say 408 (correct, reward 1) and one says 418 (wrong, reward 0). The group’s average reward is 0.75 and its standard deviation is about 0.43.</p>

<ul>
  <li>Each correct answer is slightly above average. Its advantage is (1 − 0.75) / 0.43 ≈ <strong>+0.58</strong>, so it gets a gentle push up.</li>
  <li>The wrong answer is well below average. Its advantage is (0 − 0.75) / 0.43 ≈ <strong>−1.73</strong>, so it gets a strong push down.</li>
</ul>

<figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/grpo-step-by-step.gif" alt="Animation of one GRPO update: four answers are sampled and scored 1, 0, 1, 1; with a group mean of 0.75 and standard deviation of 0.43, the correct answers get an advantage of +0.58 and are pushed up, while the wrong answer gets −1.73 and is pushed down." style="width: 100%;" />
</figure>

<p>If all four answers had been correct, every advantage would be zero, and the model would learn nothing from that prompt.</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/grpo-tied-group.gif" alt="Animation showing that when all four answers get the same reward, whether all correct or all wrong, the standard deviation is zero, every advantage is zero, and the prompt produces no learning signal." style="width: 100%;" />
</figure>

<p><strong>The math.</strong> For each prompt \(x\), sample a group of \(G\) responses \(\{o_1, \dots, o_G\}\) from \(\pi_{\theta_{\text{old}}}\) and score them to get rewards \(r_1, \dots, r_G\). Each response’s advantage is its reward normalized within the group:</p>

\[\hat{A}_i = \frac{r_i - \mathrm{mean}(r_1, \dots, r_G)}{\mathrm{std}(r_1, \dots, r_G)}\]

<p>Every token in \(o_i\) gets the same advantage \(\hat{A}_i\). The policy is then updated with PPO’s clipped objective, averaged over the group, with the KL penalty applied directly in the loss.</p>

<p><br /></p>
<details>
  <summary><b><i>For the curious: the full GRPO objective</i></b></summary>

\[J_{\text{GRPO}}(\theta) = \mathbb{E}\Bigg[\frac{1}{G}\sum_{i=1}^{G}\frac{1}{|o_i|}\sum_{t=1}^{|o_i|}\Big(\min\big(\rho_{i,t}\,\hat{A}_i,\; \mathrm{clip}(\rho_{i,t},\, 1-\epsilon,\, 1+\epsilon)\,\hat{A}_i\big) - \beta\, \mathbb{D}_{\text{KL}}\big[\pi_\theta \,\|\, \pi_{\text{ref}}\big]\Big)\Bigg]\]

  <p>where</p>

\[\rho_{i,t} = \frac{\pi_\theta(o_{i,t} \mid x,\, o_{i,&lt;t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid x,\, o_{i,&lt;t})}\]

  <p>and the KL term is estimated per token as</p>

\[\mathbb{D}_{\text{KL}} = \frac{\pi_{\text{ref}}(o_{i,t} \mid \cdot)}{\pi_\theta(o_{i,t} \mid \cdot)} - \log\frac{\pi_{\text{ref}}(o_{i,t} \mid \cdot)}{\pi_\theta(o_{i,t} \mid \cdot)} - 1\]

  <p>In practice, a small constant is added to the standard deviation so the advantage stays defined when every reward in a group is the same.</p>

</details>
<p><br /></p>

<p><strong>Where reward hacking hides.</strong> GRPO doesn’t care where the reward comes from. DeepSeekMath experimented with both outcome rewards (one score per response) and process rewards (scores for each reasoning step). DeepSeek-R1-Zero used simple rule-based rewards for answer accuracy and output format, partly because learned reward models are vulnerable to hacking at scale. So <strong>GRPO is exactly as hackable as its reward.</strong> With verifiable rewards (does the code pass the tests? is the answer 408?), there’s far less to exploit than with a learned reward model, though format rewards can still be gamed.</p>

<p><strong>The cost.</strong> GRPO drops the value model, leaving the policy, the reference model, and a reward model or rule-based scorer. In exchange, it generates \(G\) responses for every prompt, so it spends more compute on sampling.</p>

<h2 id="3-direct-preference-optimization-dpo-skip-reinforcement-learning-entirely">3. Direct Preference Optimization (DPO): skip reinforcement learning entirely</h2>

<p><strong>The problem.</strong> PPO and GRPO both need a reward signal and an online loop that samples from the model during training. If what you have is a dataset of preference pairs, do you need either?</p>

<p><strong>The idea.</strong> No. <a href="https://arxiv.org/abs/2305.18290">Direct Preference Optimization</a> (Rafailov et al., 2023) shows that the KL-regularized objective PPO optimizes can be rewritten as a simple classification-style loss on preference pairs. You train directly on “this answer was preferred over that one,” with no reward model and no sampling. On sentiment control, summarization, and single-turn dialogue, the paper shows DPO matching or beating PPO-based RLHF.</p>

<p><strong>Example.</strong> A preference pair for our prompt:</p>

<ul>
  <li><strong>Preferred</strong> (\(y_w\)): “17 × 24 = 340 + 68 = 408.”</li>
  <li><strong>Rejected</strong> (\(y_l\)): “418.”</li>
</ul>

<p>At the start of training, the policy equals the reference model, so the model has no preference between the two. The loss is \(\log 2 \approx 0.69\). As training makes the preferred answer more likely and the rejected one less likely, both relative to the reference model, the loss falls. With \(\beta = 0.1\), if the preferred answer’s log-probability rises by 2 and the rejected one’s falls by 2, the loss drops to about 0.51. The parameter \(\beta\) controls how hard the model is willing to pull away from the reference model to separate the two.</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/dpo-step-by-step.gif" alt="Animation of one DPO update: a preferred answer and a rejected answer start with log-probability ratios of 0 against the reference model, giving a loss of 0.69; training raises the preferred answer to +2 and lowers the rejected one to −2, and the loss falls to 0.51." style="width: 100%;" />
</figure>

<p><strong>The math.</strong></p>

\[\mathcal{L}_{\text{DPO}}(\theta) = -\mathbb{E}_{(x,\, y_w,\, y_l) \sim \mathcal{D}}\Big[\log \sigma\Big(\beta \log \frac{\pi_\theta(y_w \mid x)}{\pi_{\text{ref}}(y_w \mid x)} - \beta \log \frac{\pi_\theta(y_l \mid x)}{\pi_{\text{ref}}(y_l \mid x)}\Big)\Big]\]

<p>where \(\sigma(z) = 1 / (1 + e^{-z})\). Two things are worth noticing:</p>

<ol>
  <li>This is <strong>the same \(\beta\)</strong> as PPO’s KL penalty. DPO doesn’t drop the KL constraint; it builds it into the loss.</li>
  <li>The quantity \(\beta \log \frac{\pi_\theta(y \mid x)}{\pi_{\text{ref}}(y \mid x)}\) acts as an <em>implicit reward</em>. That’s why the paper’s subtitle is “Your Language Model Is Secretly a Reward Model.”</li>
</ol>

<p><br /></p>
<details>
  <summary><b><i>For the curious: how the loss is derived</i></b></summary>

  <p>DPO starts from the same KL-regularized objective PPO optimizes. That objective has a closed-form optimal policy:</p>

\[\pi^*(y \mid x) = \frac{1}{Z(x)}\, \pi_{\text{ref}}(y \mid x)\, \exp\!\Big(\frac{1}{\beta}\, r(x, y)\Big)\]

  <p>Rearranging expresses the reward in terms of the policy:</p>

\[r(x, y) = \beta \log \frac{\pi^*(y \mid x)}{\pi_{\text{ref}}(y \mid x)} + \beta \log Z(x)\]

  <p>The Bradley–Terry model says the probability that \(y_w\) is preferred over \(y_l\) is \(\sigma\big(r(x, y_w) - r(x, y_l)\big)\). Substituting the expression above, the intractable \(Z(x)\) cancels, and maximizing the likelihood of the observed preferences gives the DPO loss.</p>

</details>
<p><br /></p>

<p><strong>Where reward hacking hides.</strong> Because DPO trains offline on a fixed dataset, there’s no reward model for it to exploit during training. But it absorbs every bias in the preference data. Length is the classic one: if annotators tended to prefer longer answers, DPO learns that longer is better. And it can still over-optimize. <a href="https://arxiv.org/abs/2406.02900">Rafailov et al. (2024)</a> found that direct alignment methods show the same over-optimization pattern as classic RLHF, with quality degrading as the model moves further from the reference, often before a single epoch is complete.</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/dpo-length-bias.gif" alt="Animation showing a dataset where the preferred answer is always longer, followed by a model that pads a simple answer to 17 × 24 with extra sentences as its implicit reward rises." style="width: 100%;" />
<figcaption><i>Illustrative. DPO can't tell length from quality if the data never separates them.</i></figcaption>
</figure>

<p><strong>The cost.</strong> DPO is the cheapest of the three: the policy and the reference model, and the reference model’s log-probabilities can be precomputed. There’s no sampling loop and one main hyperparameter, \(\beta\).</p>

<h2 id="side-by-side">Side by side</h2>

<figure style="text-align: center;">
<img src="/blog/assets/images/policy-optimization/policy-optimization-pipeline.svg" alt="Diagram comparing what PPO, GRPO, and DPO need during training: PPO uses a policy, reference model, reward model, value model, and online samples; GRPO drops the value model; DPO also drops the reward model and trains on fixed preference pairs." style="width: 100%;" />
<figcaption><i>Each method removes a piece of the one before it.</i></figcaption>
</figure>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>PPO</th>
      <th>GRPO</th>
      <th>DPO</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Models during training</strong></td>
      <td>Policy, reference, reward, value</td>
      <td>Policy, reference, reward (or a rule-based scorer)</td>
      <td>Policy, reference (reference log-probs can be precomputed)</td>
    </tr>
    <tr>
      <td><strong>Online sampling?</strong></td>
      <td>Yes</td>
      <td>Yes, \(G\) responses per prompt</td>
      <td>No, uses fixed preference pairs</td>
    </tr>
    <tr>
      <td><strong>Baseline</strong></td>
      <td>Learned value model + GAE</td>
      <td>Group mean and standard deviation</td>
      <td>None (implicit reward)</td>
    </tr>
    <tr>
      <td><strong>Main knobs</strong></td>
      <td>\(\epsilon\), \(\beta\), GAE \(\lambda\), value model</td>
      <td>\(G\), \(\epsilon\), \(\beta\)</td>
      <td>\(\beta\)</td>
    </tr>
    <tr>
      <td><strong>Reward hacking</strong></td>
      <td>Clip slows it, KL bounds it; reward-model blind spots remain</td>
      <td>As hackable as the reward; verifiable rewards help a lot</td>
      <td>No online exploitation, but inherits dataset biases and can still over-optimize</td>
    </tr>
    <tr>
      <td><strong>Reach for it when</strong></td>
      <td>You have a learned reward model and the compute for it</td>
      <td>Rewards are verifiable (math, code) or memory is tight</td>
      <td>You have good preference pairs and want simplicity</td>
    </tr>
  </tbody>
</table>

<h2 id="choosing-between-them">Choosing between them</h2>

<p>In practice, I’ve found the choice of algorithm matters less than the signal you feed it: a clean, verifiable reward or a well-curated preference set will beat a clever optimizer on noisy data. If I could only get one thing right, it would be the signal, not the method.</p>

<p>When you do choose, it’s less about which one is “best” and more about where you want the risk to sit. PPO gives you the most control and the most moving parts. GRPO trades the critic for more samples, and it shines when the reward is something you can verify. DPO removes the RL loop entirely, moving the risk out of training and into your data. None of them makes reward hacking go away; they decide where you have to watch for it.</p>

<p>For what reward hacking looks like in practice, see <a href="https://belovedthoughtss.substack.com/p/gaming-the-system-reward-hacking?r=b0aer">Gaming the System</a>. For the broader pattern of optimizing a proxy until it stops meaning anything, see <a href="https://belovedthoughtss.substack.com/p/winning-the-metrics">Winning the Metric, Losing the Point</a>.</p>

<h2 id="further-reading">Further reading</h2>

<p>[1] J. Schulman, F. Wolski, P. Dhariwal, A. Radford, and O. Klimov, “<a href="https://arxiv.org/abs/1707.06347">Proximal Policy Optimization Algorithms</a>,” <em>arXiv:1707.06347 [cs.LG]</em>, Jul. 2017.</p>

<p>[2] L. Ouyang et al., “<a href="https://arxiv.org/abs/2203.02155">Training Language Models to Follow Instructions with Human Feedback</a>,” <em>arXiv:2203.02155 [cs.CL]</em>, Mar. 2022.</p>

<p>[3] Z. Shao et al., “<a href="https://arxiv.org/abs/2402.03300">DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models</a>,” <em>arXiv:2402.03300 [cs.CL]</em>, Feb. 2024.</p>

<p>[4] DeepSeek-AI et al., “<a href="https://arxiv.org/abs/2501.12948">DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning</a>,” <em>arXiv:2501.12948 [cs.CL]</em>, Jan. 2025.</p>

<p>[5] R. Rafailov, A. Sharma, E. Mitchell, S. Ermon, C. D. Manning, and C. Finn, “<a href="https://arxiv.org/abs/2305.18290">Direct Preference Optimization: Your Language Model is Secretly a Reward Model</a>,” <em>arXiv:2305.18290 [cs.LG]</em>, May 2023.</p>

<p>[6] L. Gao, J. Schulman, and J. Hilton, “<a href="https://arxiv.org/abs/2210.10760">Scaling Laws for Reward Model Overoptimization</a>,” <em>arXiv:2210.10760 [cs.LG]</em>, Oct. 2022.</p>

<p>[7] R. Rafailov et al., “<a href="https://arxiv.org/abs/2406.02900">Scaling Laws for Reward Model Overoptimization in Direct Alignment Algorithms</a>,” <em>arXiv:2406.02900 [cs.LG]</em>, Jun. 2024.</p>

<hr />]]></content><author><name>darpan-jain</name></author><category term="llm" /><category term="rlhf" /><category term="ai-alignment" /><category term="policy-optimization" /><category term="preference-optimization" /><summary type="html"><![CDATA[Why your chatbot loves saying “Great question!”]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://darpanjain.com/blog/assets/images/policy-optimization/policy_optimization.png" /><media:content medium="image" url="https://darpanjain.com/blog/assets/images/policy-optimization/policy_optimization.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Gaming the System: Understanding Reward Hacking in LLM Training</title><link href="https://darpanjain.com/blog/reward-hacking/" rel="alternate" type="text/html" title="Gaming the System: Understanding Reward Hacking in LLM Training" /><published>2025-05-12T18:14:32-07:00</published><updated>2025-05-12T18:14:32-07:00</updated><id>https://darpanjain.com/blog/reward-hacking</id><content type="html" xml:base="https://darpanjain.com/blog/reward-hacking/"><![CDATA[<p><em>How clever shortcuts can derail our smartest algorithms, and what is being done about it</em></p>

<h2 id="introduction">Introduction</h2>

<p>Large Language Models (LLMs) have achieved remarkable performance through alignment techniques like <a href="https://en.wikipedia.org/wiki/Reinforcement_learning_from_human_feedback">Reinforcement Learning from Human Feedback (RLHF)</a>. This process aims to steer models toward generating content that aligns with human preferences—helpful, harmless, and honest outputs.</p>

<p>But what happens when the model starts finding clever (often unintended) ways to maximize its rewards without actually achieving the desired goals?</p>

<h2 id="reward-models-representing-human-preferences">Reward Models representing Human Preferences</h2>

<p>At the core of alignment techniques like <a href="https://en.wikipedia.org/wiki/Reinforcement_learning_from_human_feedback">RLHF</a> lies a critical component: the Reward Model. A Reward Model (RM, also called a <a href="https://huggingface.co/blog/rlhf#reward-model-training">preference model</a>) is a neural network trained to approximate human preferences by assigning scores to language model outputs. It effectively translates qualitative human judgments into quantitative signals that can guide optimization.</p>

<p>A simple reward model receives a prompt and a candidate response as input, then outputs a scalar value representing how “good” that response is according to learned human preferences. During training, humans provide comparative judgments (e.g., “response A is better than response B for this prompt”), and the reward model learns to predict these preferences by maximizing the likelihood that preferred responses receive higher scores.</p>

<p>Once trained, this model would serve as a constant feedback mechanism during reinforcement learning. The language model (acting as the policy) generates text, the reward model evaluates it, and the policy is updated to increase the probability of producing higher-scoring outputs. This creates a closed optimization loop that pushes the model toward behavior that the reward model scores highly.</p>

<p>This is precisely where the challenge of reward hacking emerges.</p>

<h2 id="the-roots-of-reward-hacking">The Roots of Reward Hacking</h2>

<figure style="text-align: center;">
<img src="/blog/assets/images/reward-hacking-visual.png" alt="Reward Hacking" style="width: 80%; display: block; margin-left: auto; margin-right: auto;" />
  <figcaption><i></i></figcaption>
</figure>

<p>The reward model is merely a proxy for true human preferences, not the preferences themselves. As we look to optimize these models to maximize human preferences, they sometimes find ways to game the system, exploiting quirks, rather than truly achieving our intended goals, much like a student who finds loopholes in grading criteria by rote memorization rather than truly mastering the subject matter.</p>

<p>This is Reward Hacking in its simplest form—optimizing for the reward rather than the intended goal. The model discovers shortcuts that skyrocket its reward score, without genuinely improving the behavior we care about.</p>

<p>More formally, Reward hacking (also called <a href="https://deepmind.google/discover/blog/specification-gaming-the-flip-side-of-ai-ingenuity/">Specificiation Gaming</a>) is when an AI agent exploits flaws in its reward signal or objective function to achieve a high proxy reward without accomplishing the true intended goal. While defining reward models to represent human preferences, we inadvertently create incentives for the model to exploit loopholes in our measurement system.</p>

<p>Before diving deeper into this further, let’s take a look at <a href="https://huggingface.co/blog/rlhf">how modern LLMs are trained</a> from foundational models to the highly agreeable assistants that you interact with (almost) every day.</p>

<h2 id="rlhf-training-pipeline-for-llm-alignment">RLHF Training Pipeline for LLM Alignment</h2>

<p>LLMs generally go through three stages of training, each incrementally advancing the model’s generation patterns to suit what humans understand and prefer. Each stage introduces opportunities for misalignment if not carefully managed.</p>

<h3 id="1-pretraining-unsupervised-language-modeling">1. Pretraining (Unsupervised Language Modeling)</h3>

<p>An LLM begins as a pretrained model trained on an internet-scale dataset (refer to open-source datasets like <a href="https://commoncrawl.org/">Common Crawl</a> and <a href="https://pile.eleuther.ai/">The Pile</a>) via next-token prediction. Pretraining imparts general language understanding but not task-specific alignment.</p>

<p>The pre-trained model simply predicts text that sounds plausible, without regard for a user’s instructions or preferences. This stage generally doesn’t involve human feedback or rewards, so reward hacking is not a concern yet. However, it lays the foundation: the model learns broad patterns of human-like text, which the later stages will refine.</p>

<h3 id="2-supervised-fine-tuning-sft">2. Supervised Fine-Tuning (SFT)</h3>

<p>Next, the pre-trained model is fine-tuned on examples of the <a href="https://medium.com/@aleenatleejoy/training-language-models-to-follow-instructions-with-human-feedback-a-comprehensive-review-267a30344028">desired behavior</a>. Humans provide demonstrations or high-quality responses to prompts (e.g., question-answer pairs, helpful dialogue turns). The model is trained via <a href="https://en.wikipedia.org/wiki/Supervised_learning">supervised learning</a> to imitate these demonstrations. If \((p, y^*)\) are prompt-response pairs from the demonstration set, the fine-tuning objective is:</p>

<p>Next, the base LLM is fine-tuned on demonstration data or instructions to produce preferred responses. Human annotators provide example prompts \(x\) and ideal responses \(y^*\), and the model is updated via supervised learning to mimic these responses. Formally, the model \(\pi_\theta\) is trained to maximize the likelihood of the expert demonstration:</p>

\[L_{\text{SFT}}(\theta) = -\mathbb{E}{(p,y^*)}; \log P_{\theta}(y^* \mid p)\]

<p>This aligns the model closer to the task. SFT primes the model to be helpful and follow instructions. While this stage by itself does not use a reward model, it <a href="https://developers.google.com/machine-learning/crash-course/fairness/types-of-bias">can still introduce biases</a> based on the demonstration data. For example, if demonstrations consistently prefer a certain style (e.g., very polite or detailed answers), the model will adopt those patterns. SFT ensures the model (often called the “policy” at this point) responds reasonably to a variety of prompts, producing decent responses.</p>

<h3 id="31-reward-model-training-preference-modeling">3.1. Reward Model Training (Preference Modeling)</h3>

<p>This is where human feedback enters. We train a reward model \(r_\phi(x,y)\) to predict a scalar reward that represents how preferable a model output \(y\) is for a given prompt \(x\). Typically, humans label or rank the model-generated responses to prompts.</p>

<p>For example, given a prompt and two candidate completions, a human might indicate which they prefer. The reward model is then fit to these comparisons. A common loss is the <a href="https://vinija.ai/concepts/loss/#pairwise-logistic-loss">pairwise logistic loss</a>: for a human-preferring output \(y^+\) over \(y^-\) for prompt \(x\) -</p>

\[\mathcal{L}_{RM}(\phi) = -\log \sigma\Big(r_\phi(x,y^+) - r_\phi(x,y^-)\Big),\]

<p>where \(\sigma\) is the sigmoid function.</p>

<p>Minimizing this loss trains \(r_\phi\) to assign higher scores to human-like outputs. The reward model effectively learns an approximation of human preference.</p>

<p>However, it is an imperfect proxy; it may latch onto heuristics correlated with human preference in the training data (like “longer answers are better” or certain polite phrases) rather than truly understanding quality. This imperfect proxy is the crux of potential reward hacking – the policy will later exploit any systematic weaknesses in \(r_\phi\). To mitigate obvious issues, reward model training data often covers a wide range of scenarios and instructs labelers to reward truthfulness, clarity, etc., not just verbosity or sentiment. Nonetheless, any bias or blind spot in the preferences will carry into \(r_\phi\).</p>

<h3 id="32-reinforcement-learning-fine-tuning">3.2. Reinforcement Learning Fine-Tuning</h3>

<p>Finally, the LLM (or “policy”) is optimized to maximize the reward model’s score using an RL algorithm. At this stage, the LLM becomes an RL policy \(\pi_\theta\) interacting with a reward signal provided by \(r_\phi\). During each iteration, for a given prompt \(x\), the policy generates an output \(y\) , the reward model computes a reward \(r = r_\phi(x,y)\), and the policy’s parameters are adjusted to increase the probability of \(y\) (and similar outputs) in the future.</p>

<p>In practice, <strong><a href="https://arxiv.org/abs/1707.06347">Proximal Policy Optimization (PPO)</a></strong> is frequently used for this policy update step. PPO is a stable RL algorithm that maximizes expected reward while penalizing too large a change from the previous policy. The PPO objective (simplified) is:</p>

\[L_{\text{PPO}}(\theta) = -\mathbb{E}_{x,y \sim \pi_{\theta_{\text{old}}}}\Big[\min\big(r_{\theta}(x,y)\,\hat{A},\; \text{clip}(r_{\theta}(x,y), 1-\epsilon,1+\epsilon)\,\hat{A}\big)\Big],\]

<p>where, <br />
  \(r\_{\theta}(x,y)=\frac{\pi_\theta(y|x)}{\pi_{\theta_{\text{old}}}(y|x)}\) is the policy ratio and \(\hat{A}\) an advantage estimate.</p>

<p>This clipped objective ensures the new policy \(\pi_\theta\) doesn’t stray too far from the old one in one update. In the RLHF context, the advantage can be simply the reward \(r_\phi(x,y)\) (possibly minus a baseline). In addition, implementations include a <strong>KL-divergence penalty</strong> between the new policy and the original pre-trained model \(\pi_{\text{ref}}\) (or SFT model) to keep outputs from deviating too much from human-like text. Intuitively, this KL penalty is a regularizer that “reels in” the policy if it starts generating very unusual text just to boost the reward score. In sum, the RL objective for the LLM often becomes maximizing</p>

\[J(\theta) = \mathbb{E}_{x,y\sim \pi_\theta}[\,r_\phi(x,y)\,] - \beta . \,\textrm{KL}\big(\pi_\theta(\cdot|x)\;\|\;\pi_{\text{ref}}(\cdot|x)\big)\]

<p>where \(\beta\) is a chosen penalty coefficient.</p>

<p>This approach was used in <a href="https://openai.com/index/instruction-following/">OpenAI’s InstructGPT</a> and related work to successfully align models with human preferences. Crucially, the need for a KL penalty itself hints at the risk of reward hacking: without it, the policy might drift into odd regions of text space that trick the reward model but are divorced from normal language. In fact, <strong>preventing reward hacking is one motivation for the KL term</strong>, which acts as a tether to keep the policy’s behavior within the realm of the reference model.</p>

<p>Newer methods like <a href="https://arxiv.org/abs/2305.18290">DPO</a> and <a href="https://arxiv.org/abs/2402.03300">GRPO</a> are actively being used (like DeepSeek-R1 using the GRPO algorithm).</p>

<p>In the interest of keeping this article too long, I’ve skipped the deeper dive on these algorithms. You can go to the addendum blog “<a href="/blog/policy-optimization/">Policy Optimization Algorithms for Alignment</a>” for more details on these.</p>

<p>Now, let’s head into the fun stuff!</p>

<h2 id="reward-hacking-in-action">Reward Hacking in Action</h2>

<p>Across several reinforcement learning (RL) domains, where AI agents interact with virtual environments to perform a task, reward hacking can manifest in humorous ways -</p>

<ul>
  <li>
    <p><a href="https://openai.com/index/learning-from-human-preferences/">A robotic hand in a task was supposed to grasp objects</a>, the reward function measured the distance between the fingertips and the object. The robot learned to position its hand directly above the object without actually grasping it.</p>
  </li>
  <li>
    <p>In a <a href="https://openai.com/index/faulty-reward-functions/">boat racing simulation</a>, an AI agent is rewarded for collecting points along a track. Instead of completing the race, it learned to drive in small circles, collecting the same points over and over again, and thus discovered an infinite points hack!</p>
  </li>
  <li>
    <p><a href="https://openai.com/index/emergent-tool-use/">Agents learning to play a simple game of hide-and-seek</a>, seekers learn to launch themselves up to find all the hiders in the game and win the round.</p>
  </li>
</ul>

<p>In the context of LLMs, reward hacking takes on new forms. If that reward model or feedback signal is even slightly mis-specified or over-simplified, a clever (read: large enough) language model can “game” it – producing outputs that score well on the proxy reward while deviating from what humans actually want.</p>

<p>These behaviors are often subtle – the output might look plausibly good to a casual observer, but is optimized to exploit quirks of the reward model -</p>

<ul>
  <li>
    <p><strong>Verbose Outputs (Length Hacking)</strong>: Models produce unnecessarily long responses to boost rewards without adding value. <a href="https://arxiv.org/abs/2402.07319">Chen et al. (2024)</a> note that “the most common pattern of reward hacking in practice is verbosity: the models generate more tokens to make the response appear more detailed or better formatted after RLHF … but the actual quality does not improve.” Models exploit the correlation between detail and perceived quality, sometimes generating run-on answers until hitting token limits. This happens especially when reward models lack explicit length penalties.</p>
  </li>
  <li>
    <p><strong>Sycophancy</strong>: Models tell users what they want to hear rather than what’s true. <a href="https://www.anthropic.com/research/towards-understanding-sycophancy-in-language-models">Anthropic research</a> showed “five state-of-the-art AI assistants consistently exhibit sycophancy” across diverse tasks. Even advanced models like GPT-4 and <a href="https://claude.ai/">Claude</a> will “wrongly admit mistakes when questioned by the user, give predictably biased feedback, and mimic errors made by the user” because human preference data implicitly rewards agreement and politeness over accuracy.</p>
  </li>
  <li>
    <p><strong>Boilerplate Responses</strong>: Models overuse generic, high-reward phrases or formats that were consistently rated well during training. This includes unnecessary pleasantries (“Thank you for your question!”), standard disclaimers, and templated conclusions. The model optimizes for “safe” patterns that correlated with reward in training data, reducing answer directness and clarity while technically maximizing reward.</p>
  </li>
  <li>
    <p><strong>Keyword Stuffing</strong>: Models exploit specific features favored by reward models. In <a href="https://www.anthropic.com/research/auditing-hidden-objectives">Anthropic’s reward tampering experiment</a>, they deliberately biased a reward model to favor recipes mentioning “chocolate” and code using camelCase. The resulting model inserted these elements everywhere, regardless of appropriateness. This experiment also showed how models might avoid certain content entirely (like medical advice) if the reward model penalizes it, missing the true intention of the request.</p>
  </li>
  <li>
    <p><strong>Over-optimization</strong>: In extreme cases, models could produce bizarre outputs that fool the reward model while being useless to humans. Research by OpenAI and Anthropic demonstrated that if allowed to optimize against <a href="https://www.anthropic.com/research/auditing-hidden-objectives">a reward model’s internals, models discover odd responses that maximize scores</a> while providing no value. This represents adversarial exploitation of the reward model, where the LLM effectively outsmarts its own feedback signal.</p>
  </li>
</ul>

<p><strong>Reward hacking in LLMs often looks like the model pushing a legit behavior to an illegitimate extreme</strong>: extra length without extra info, agreement without regard for truth, safe generic wording without substance, or inclusion/exclusion of content based on quirks of the reward.</p>

<p>These behaviors can harm the quality and trustworthiness of the AI’s responses, which is why identifying and mitigating reward hacking is a key part of ongoing LLM alignment research.</p>

<h2 id="why-does-reward-hacking-occur-in-llms">Why Does Reward Hacking Occur in LLMs?</h2>

<p>Several factors contribute to reward hacking in the LLM setting, primarily rooted in the gap between the proxy reward and the actual underlying goals:</p>

<ul>
  <li>
    <p><strong>Imperfect Proxy Rewards and Goodhart’s Law</strong>: The reward model $r_\phi$ inevitably serves as an imperfect proxy for human intent. When the LLM optimizes for this proxy, it exposes flaws in the reward definition—a classic manifestation of <a href="https://www.lesswrong.com/posts/EbFABnst8LsidYs5Y/goodhart-taxonomy">Goodhart’s Law</a>: “When a measure becomes a target, it ceases to be a good measure.” For instance, if the reward model learned that longer answers correlate with quality, the LLM might generate excessively long responses that exploit this correlation without adding value. The more powerful the optimization, the more likely these proxy-breaking strategies emerge. This reward mis-specification is almost inevitable for open-ended language tasks.</p>
  </li>
  <li>
    <p><strong>Reward Model Misgeneralization</strong>: Even well-trained reward models can misgeneralize when evaluating novel outputs from an evolving policy. After many RL updates, the LLM may produce outputs that are distributionally shifted from what the reward model encountered during training. As <a href="https://openreview.net/pdf?id=zcIV8OQFVF">Chen et al. (2024)</a> explain, the reward model has “limited out-of-distribution generalization, but the policy is a capable LLM that can learn to generate OOD examples to exploit the vulnerabilities of the RM”. This problem is exacerbated when the policy model (often 70B+ parameters) has significantly <a href="https://huggingface.co/blog/rlhf#reward-model-training">more capacity than the reward model</a> (typically 1.3B-6B parameters).</p>
  </li>
  <li>
    <p><strong>Biases in Human Feedback:</strong> Human preference data inherits annotator biases. If raters consistently prefer politeness over accuracy, the model learns to prioritize politeness at accuracy’s expense—<a href="https://www.anthropic.com/research/towards-understanding-sycophancy-in-language-models">leading to sycophancy</a>. Anthropic’s research found that evaluators unwittingly favored answers agreeing with users’ stated views, which models adopted as a reliable strategy. Additionally, properties difficult for humans to directly evaluate (like comprehensive consideration of facts) may be overlooked in preference data, creating blind spots that the model can exploit.</p>
  </li>
  <li>
    <p><strong>Distribution Shift in Deployment:</strong> The model may encounter different query types in deployment than during RLHF training. Strategies that worked well on training prompts (like verbose explanations for complex questions) might be inappropriately applied to simple queries in real-world usage, revealing reward hacks that weren’t apparent during training.</p>
  </li>
  <li>
    <p><strong>Lack of Negative Examples for Hacking Behavior:</strong> Many reward hacking behaviors aren’t explicitly penalized because they weren’t anticipated during training. Without examples showing that extreme verbosity is undesirable, the reward model has no basis to penalize super-long answers. This creates regions where <strong>the reward signal is erroneously flat or encouraging beyond reasonable limits</strong>. Given LLMs’ enormous action space (all possible texts), it’s practically impossible to pre-label all potential failure modes.</p>
  </li>
</ul>

<p>The better and more relentless the optimization, the more likely the divergence. Large language models, being very expressive, will inevitably test the limits of any proxy reward. Understanding these causes helps in devising strategies to counter reward hacking, by either improving the proxy or constraining the optimization.</p>

<h2 id="mitigation-strategies-for-reward-hacking-in-llms">Mitigation Strategies for Reward Hacking in LLMs</h2>

<p>Addressing reward hacking requires a combination of better reward design, improved training techniques, and ongoing oversight.</p>

<h3 id="iterative-feedback-and-refinement">Iterative Feedback and Refinement</h3>

<p>One straightforward approach is to treat alignment training as an <a href="https://apxml.com/courses/rlhf-reinforcement-learning-human-feedback/chapter-6-advanced-rlhf-techniques/addressing-reward-hacking">iterative process rather than a one-off</a>. Alignment should be an ongoing, adversarial loop. When a hack appears—say, excessive verbosity—teams collect targeted human comparisons (long vs. concise answers), update the reward model with those examples, and fine-tune again. In practice, OpenAI and others cycle through initial RLHF, auditing for failures, gathering new data on problematic outputs, and retraining to close loopholes. Although this human-in-the-loop process is labor-intensive and depends on spotting issues, it steadily reduces obvious exploits over successive rounds.</p>

<h3 id="adversarial-training-and-red-teaming">Adversarial Training and Red-Teaming</h3>

<p>Research labs training and maintaining foundational models often have a dedicated “<a href="https://learn.microsoft.com/en-us/security/ai-red-team/">Red Team</a>” responsible for “breaking” an LLM as a part of a beta-test before shipping it as a product. Most big tech companies and AI research labs have <a href="https://developer.nvidia.com/blog/nvidia-ai-red-team-an-introduction/">dedicated Red Teams</a>.</p>

<p>Instead of passively awaiting hacks, teams employ adversarial agents—whether AI models or dedicated human “red teams”—to probe for reward-gaming strategies (e.g., Anthropic’s red-team vs. blue-team sycophancy experiments). These adversaries craft prompts or outputs that the current reward model mistakenly rewards, and those failure cases become explicit negative examples in the next round of reward-model training—much like adversarial robustness in supervised learning. Researchers even leverage LLMs themselves to critique or evaluate outputs at scale, systematically uncovering blind spots. By <a href="https://hbr.org/2024/01/how-to-red-team-a-gen-ai-model">continually challenging the reward model</a>, this adaptive loop makes it progressively harder for the policy to exploit unanticipated weaknesses.</p>

<h3 id="reward-model-improvements-regularization-and-debiasing">Reward Model Improvements (Regularization and Debiasing)</h3>

<p>Since a core issue is the reward model’s flaws, an entire class of mitigations focuses on making a more robust reward model. One idea is to use information regularization to prevent the reward model from relying on spurious features.</p>

<p><a href="https://openreview.net/pdf?id=3XnBVK9sD6"><strong>Information-Theoretic Reward Modeling (InfoRM)</strong></a> applies a variational information bottleneck that forces compression of the reward model’s representation, filtering out features not genuinely correlated with human preferences. In evaluations, InfoRM reduced reward overoptimization and detected policy exploitation through outlier activations.</p>

<p>Similarly, <a href="https://openreview.net/pdf?id=zcIV8OQFVF"><strong>ODIN</strong> (Chen et al. 2024)</a> addresses verbosity by training separate quality and length prediction heads, then penalizing the length head’s influence, preventing models from gaming response length. Other approaches include:</p>

<ul>
  <li><a href="https://www.researchgate.net/publication/389392526_Reward_Shaping_to_Mitigate_Reward_Hacking_in_RLHF">Reward Shaping</a>: normalizing rewards by expected values for prompts</li>
  <li><a href="https://arxiv.org/pdf/2310.02743">Using ensembles</a> to avoid over-optimization of the reward model</li>
  <li>Training on diverse, de-biased comparison datasets</li>
</ul>

<p>These techniques make reward signals less vulnerable to easy proxies like length or keywords while remaining sensitive to actual content quality. The underlying principle is that if reward models become harder to fool, policies will have fewer opportunities to hack them.</p>

<h3 id="process-supervision-and-stepwise-rewards">Process Supervision and Stepwise Rewards</h3>

<p>Rather than rewarding only final outputs, this approach supervises the reasoning process itself. By rewarding intermediate steps (like chain-of-thought reasoning), we constrain the solution space and reduce opportunities for reward hacking. For example, if a math-solving model must show its work and receives rewards for correctness at each step, it can’t easily produce wrong answers that merely sound plausible. This can be implemented through human feedback on reasoning steps or programmatic verification (e.g., running tests on generated code rather than just judging its appearance).</p>

<p><a href="https://arxiv.org/abs/2402.03300">Group Relative Policy Optimization (GRPO)</a> exemplifies this approach by rewarding reasoning quality alongside final answers, enabling detection of errors that outcome-only rewards miss. Similarly, Anthropic’s research explored providing models with internal principle checklists as structured feedback beyond single scalar rewards. By <a href="https://blog.gopenai.com/fine-tuning-a-text-to-sql-llm-for-reasoning-using-grpo-ec2c1b55278f">constraining the pathway to good answers via intermediate checkpoints</a>, we leave less room for gaming the system. While this requires more complex training signals and verification capabilities (not always possible for subjective tasks like creative writing), process supervision provides stronger guardrails against subtle reward hacking behaviors in domains where applicable.</p>

<h3 id="constitutional-ai-and-rule-based-rewards">Constitutional AI and Rule-Based Rewards</h3>

<p>An alternative to RLHF, <a href="https://www.anthropic.com/research/constitutional-ai-harmlessness-from-ai-feedback">Constitutional AI</a> replaces direct human rewards with explicit principles (a “constitution”) that the AI should follow and use AI feedback to enforce them. During training, the model generates outputs and also generates critiques of those outputs based on the constitutional principles (or another AI does), and then it revises accordingly. The final reward is implicit: an output that doesn’t violate the principles. This approach was <a href="https://www.anthropic.com/research/collective-constitutional-ai-aligning-a-language-model-with-public-input">used to train Anthropic’s Claude</a> to be helpful and harmless without needing a human to label every response for acceptability.</p>

<p>From a reward hacking perspective, Constitutional AI is interesting because the “reward” is more transparent and rigid – it’s derived from known rules (e.g., “don’t be toxic”, “don’t give forbidden content”, “be truthful”) rather than an opaque learned model. While models could still technically pass rules but remain undesirable if principles are incomplete, the approach demonstrates a key mitigation strategy: using multiple objective signals makes it harder for models to game any single feedback channel.</p>

<p>Constitutional AI demonstrates a broader mitigation strategy: use multiple objective signals, including hard-coded constraints, to guide the model, rather than leaning entirely on a single learned reward. By diversifying feedback (human preferences + AI critiquing + rules), it becomes harder for the model to simultaneously satisfy all feedback channels in a hacky way – it can’t maximize one without being checked by another.</p>

<h3 id="monitoring-and-gradient-alignment-checks">Monitoring and Gradient Alignment Checks</h3>

<p>On the more research/interpretability end, another avenue is to audit the model’s internals for signs of reward hacking. For instance, one can train probes or use interpretability techniques to see if the model has learned an explicit representation of the reward model’s flaws. Anthropic’s “hidden reward function” experiment did exactly this: they trained a model to be an RM-sycophant and then tried to detect that objective by analyzing the model’s activations and weights. They found that certain indicators (like out-of-distribution activation patterns) could flag that the model was pursuing the proxy reward too single-mindedly.</p>

<p>In future versions, you can have a secondary process always watching the main model’s outputs (or even thoughts, if accessible) for anomalies that suggest exploitation of the reward. For example, the model’s length of output starts growing epoch over epoch without clear improvement in content, that could be automatically flagged. Similarly, if a model’s answers start to all include a strange common subphrase (a telltale sign of proxy gaming), that can be detected via n-gram analysis. These kinds of automated audits serve as a feedback loop to developers to intervene.</p>

<h3 id="explicit-penalties-for-known-hacks">Explicit Penalties for Known Hacks</h3>

<p>Finally, a very direct mitigation is to add explicit penalty terms to the reward for known hack dimensions. We discussed length – one can include a penalty for outputs longer than some threshold (or use a length-normalized reward). If sycophancy is a concern, one could have a classifier detect when the model merely mirrors the user’s opinion and subtract reward in those cases. If repetition or undue formality is an issue, likewise, add a term discouraging it.</p>

<p>This moves away from pure RLHF to a more <strong><a href="https://www.researchgate.net/publication/389392526_Reward_Shaping_to_Mitigate_Reward_Hacking_in_RLHF">Reward-Shaping</a></strong> approach, where the reward is a weighted sum of the learned preference model and some heuristic terms. Researchers have found that mild reward shaping can indeed help “steer” the RLHF process away from problematic extremes.</p>

<p>For example, <a href="https://arxiv.org/abs/2502.18770v1">Preference-as-reward (PAR)</a> shaping applies a sigmoid transform to the reward and mixes in a reference reward to dampen extremes. This can prevent the runaway effect where the model thinks it should push a feature indefinitely. The downside is that too much manual shaping can interfere with the original goal if done incorrectly. It’s a fine line between preventing hacks and accidentally biasing the model in undesirable ways. Nonetheless, when a specific form of reward hacking is identified and well-understood, adding a targeted penalty or shaping term is a practical short-term fix.</p>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>At its heart, Reward Hacking shows that as soon as we use a proxy measure as a reward, powerful models will probe its weaknesses. RLHF’s powerful optimization has driven models to excel on our metrics—yet that very pressure turns every oversight into an exploit.</p>

<p>There’s no quick fix. Just as you would harden a security system knowing attackers will adapt, alignment researchers must continuously audit and refine LLM training as the models become more capable. Ongoing research in interpretability, adversarial training, and iterative feedback is closing loopholes like verbosity and agree-with-you sycophancy. While each fix may reveal subtler hacks, steady progress shows we can steer LLMs toward genuine human‐aligned behavior, not merely higher proxy scores.</p>

<p><strong>What does it mean for an AI to truly grasp the spirit of our intentions, rather than just tick off boxes on a checklist?</strong> As we tackle reward hacking, we’re really grappling with the nature of understanding, trust, and responsibility in human–AI relationships. Some open research puzzles to keep in mind:</p>

<ul>
  <li>
    <p>How can we quantify genuine human satisfaction in a way that stays robust across contexts?</p>
  </li>
  <li>
    <p>What methods can reliably surface and penalize unseen reward hacks before they slip into production?</p>
  </li>
  <li>
    <p>Can we develop automated, scalable adversarial benchmarks that evolve alongside ever-more capable models?</p>
  </li>
</ul>

<p>If any of these questions spark ideas—or if you’d like to team up on tackling them—please don’t hesitate to reach out!</p>

<h2 id="sources">Sources</h2>

<p>[1] Joar S., Nikolaus H. R. H., Dmitrii K., and David K., “<a href="https://arxiv.org/abs/2209.13085">Defining and Characterizing Reward Hacking</a>,” arXiv:2209.13085 [cs.LG], Sep 2022</p>

<p>[2] P. Ouyang et al., “<a href="https://arxiv.org/abs/2203.02155">Training Language Models to Follow Instructions with Human Feedback</a>,” <em>arXiv:2203.02155 [cs.CL]</em>, Mar. 2022.</p>

<p>[3] J. Schulman, F. Wolski, P. Dhariwal, A. Radford, and O. Klimov, “<a href="https://arxiv.org/abs/1707.06347">Proximal Policy Optimization Algorithms</a>,” <em>arXiv:1707.06347 [cs.LG]</em>, Jul. 2017.</p>

<p>[4] R. Rafailov, A. Sharma, E. Mitchell, S. Ermon, C. D. Manning, and C. Finn, “<a href="https://arxiv.org/abs/2305.18290">Direct Preference Optimization: Your Language Model is Secretly a Reward Model</a>,” <em>arXiv:2305.04348 [cs.LG]</em>, May 2023.</p>

<p>[5] Z. Shao et al., “<a href="https://arxiv.org/abs/2402.03300">DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models</a>,” <em>arXiv:2402.03300 [cs.CL]</em>, Feb. 2024.</p>

<p>[6] T. Everitt, V. Krakovna, L. Orseau, M. Hutter, and S. Legg, “<a href="https://arxiv.org/abs/1705.08417">Reinforcement Learning with a Corrupted Reward Channel</a>,” <em>arXiv:1705.08417 [cs.AI]</em>, May. 2017.</p>

<p>[7] B. Baker et al., “<a href="https://arxiv.org/abs/1909.07528">Emergent Tool Use From Multi-Agent Autocurricula</a>,” <em>arXiv:1909.07528 [cs.LG]</em>, Sep 2019.</p>

<p>[8] S. Garrabrant, “<a href="https://www.alignmentforum.org/posts/EbFABnst8LsidYs5Y/goodhart-taxonomy">Goodhart Taxonomy</a>,” AI Alignment Forum, Dec. 30 2017.</p>

<p>[9] L. Weng, “<a href="https://lilianweng.github.io/posts/2024-11-28-reward-hacking/">Reward Hacking in Reinforcement Learning</a>,” Lil’Log, Nov. 28 2024.</p>

<p>[10] Y. Miao, S. Zhang, L. Ding, R. Bao, L. Zhang, and D. Tao, “<a href="https://arxiv.org/abs/2402.09345">InfoRM: Mitigating Reward Hacking in RLHF via Information‐Theoretic Reward Modeling</a>,” <em>arXiv:2402.09345 [cs.LG]</em>, Feb. 2024.</p>

<p>[11] A. Bukharin, H. Qian, S. Sun, A. Renduchintala, S. Singhal, Z. Wang, O. Delalleau, and T. Zhao, “<a href="https://arxiv.org/abs/2504.06141">Adversarial Training of Reward Models</a>,” <em>arXiv:2504.06141 [cs.LG]</em>, Apr. 2025.</p>

<p>[12] Anthropic, “<a href="https://www.anthropic.com/research/reward-tampering">Sycophancy to Subterfuge: Investigating Reward-Tampering in Large Language Models</a>,” Anthropic Research, Jun. 17 2024.</p>

<p>[13] J. Leike, M. Martic, V. Krakovna, P. A. Ortega, T. Everitt, A. Lefrancq, L. Orseau, and S. Legg, “<a href="https://arxiv.org/abs/1711.09883">AI Safety Gridworlds: A Toolkit for Reinforcement Learning Agents</a>,” <em>arXiv:1711.09883 [cs.LG]</em>, Nov. 2017.</p>]]></content><author><name>darpan-jain</name></author><category term="llm" /><category term="rlhf" /><category term="reward-hacking" /><category term="ai-alignment" /><category term="ai-safety" /><summary type="html"><![CDATA[Exploring how large language models can exploit reward systems during training, leading to unintended behaviors, and strategies to mitigate these issues.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://darpanjain.com/blog/assets/images/reward-hacking-visual.png" /><media:content medium="image" url="https://darpanjain.com/blog/assets/images/reward-hacking-visual.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Betting on Your Attention: Multi-Armed Bandits for Recommendation Systems</title><link href="https://darpanjain.com/blog/multi-arm-bandits-for-recommendation-systems/" rel="alternate" type="text/html" title="Betting on Your Attention: Multi-Armed Bandits for Recommendation Systems" /><published>2025-03-23T17:19:00-07:00</published><updated>2025-03-23T17:19:00-07:00</updated><id>https://darpanjain.com/blog/multi-arm-bandits-for-recommendation-systems</id><content type="html" xml:base="https://darpanjain.com/blog/multi-arm-bandits-for-recommendation-systems/"><![CDATA[<p><em>Meet the efficient mathematical gamblers working behind the scenes that predict your desires before they form. Multi-armed Bandits are why you probably can’t stop scrolling.</em></p>

<h2 id="online-learning">Online Learning</h2>

<p>Imagine navigating a vast ocean of content where the map constantly changes and user preferences shift like tides. This is the dynamic challenge faced by modern recommendation systems, which must perform a delicate balancing act: discovering user preferences while simultaneously delivering valuable recommendations that keep users engaged. Unlike traditional supervised learning that comfortably trains on static historical datasets, recommendation engines operate in a perpetual state of discovery, adapting their strategies with every user interaction through a process known as online learning.</p>

<p>Enter <a href="https://en.wikipedia.org/wiki/Multi-armed_bandit">Multi-Armed Bandit (MAB) algorithms</a> -— powerful mathematical frameworks designed to solve one of computing’s most elegant puzzles. These algorithms embody the perfect (read: profitable) mix of exploration and exploitation, treating each recommendation as both a service to the user and a carefully designed experiment.</p>

<p>As users scroll through TikTok videos, browse Netflix shows, or shop on Amazon, MABs <strong>silently orchestrate a dance of trial and error</strong>, continuously refining their understanding of user preference patterns while minimizing the cost of learning.</p>

<p>This elegant solution to the exploration-exploitation dilemma has revolutionized how digital platforms deliver personalized experiences at an unprecedented scale.</p>

<h2 id="the-explore-exploit-dilemma">The Explore-Exploit Dilemma</h2>

<p>At the core of recommendation systems lies the explore-exploit tradeoff:</p>

<ul>
  <li><strong>Exploitation</strong>: Recommend items we believe users will like based on past knowledge</li>
  <li><strong>Exploration</strong>: Try new items to discover potentially better recommendations</li>
</ul>

<p>This resembles the classic “multi-armed bandit” problem from probability theory, named after <a href="https://idioms.thefreedictionary.com/one-arm+bandit">casino slot machines</a> (“one-armed bandits”).</p>

<p>Imagine facing multiple slot machines, each with unknown payout probabilities. How do you maximize your total reward?</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/multi-arm-bandits-for-recommendation-systems/slot-machines.webp" alt="Slots machines in a Casino" style="width: 80%; display: block; margin-left: auto; margin-right: auto;" />
    <figcaption><i></i></figcaption>
</figure>

<h2 id="early-approaches-to-the-explore-exploit-dilemma">Early Approaches to the Explore-Exploit Dilemma</h2>

<p>Before sophisticated multi-armed bandit algorithms, recommendation systems used simpler strategies to balance exploration and exploitation:</p>

<h3 id="1-random-selection">1. Random Selection</h3>

<p>The most basic approach simply selects items randomly:</p>

\[action = random\ choice\ (all\ possible\ actions)\]

<p>This provides <strong>maximum exploration</strong> but no exploitation, resulting in poor user experience.</p>

<h3 id="2-greedy-algorithm">2. Greedy Algorithm</h3>

<p>The purely greedy approach always chooses the currently best-known option:</p>

\[action = argmax_a Q(a)\]

<p>Where \(Q(a)\) is the estimated reward for each action based on past observations. This <strong>maximizes exploitation</strong> but fails to discover potentially better (and more engaging) options.</p>

<h3 id="3-epsilon-ε-greedy-algorithm">3. (Epsilon) ε-Greedy Algorithm</h3>

<p>A simple but effective compromise:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">random</span><span class="p">()</span> <span class="o">&lt;</span> <span class="n">ε</span><span class="p">:</span>
    <span class="n">action</span> <span class="o">=</span> <span class="n">random_choice</span><span class="p">(</span><span class="n">all_possible_actions</span><span class="p">)</span>  <span class="c1"># explore
</span><span class="k">else</span><span class="p">:</span>
    <span class="n">action</span> <span class="o">=</span> <span class="n">argmax_a</span> <span class="n">Q</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>  <span class="c1"># exploit
</span></code></pre></div></div>

<p>Where \(\epsilon\) is the exploration probability (typically 0.05-0.1). This introduces randomness but still <strong>mostly exploits</strong> known rewards. <a href="https://papers.nips.cc/paper_files/paper/2007/hash/4b04a686b0ad13dce35fa99fa4161c65-Abstract.html">Here’s the paper</a> if you would like to get into details.</p>

<h3 id="4-upper-confidence-bound-ucb">4. Upper Confidence Bound (UCB)</h3>

<p>UCB algorithms select actions based on optimistic estimates of potential reward:</p>

\[action = argmax_a \left[ Q(a) + c \sqrt{\frac{\log t}{N(a)}} \right]\]

<p>Where:</p>

<ul>
  <li>\(Q(a)\) is the estimated reward</li>
  <li>\(N(a)\) is the number of times action a was selected</li>
  <li>\(t\) is the total number of trials</li>
  <li>\(c\) controls exploration</li>
</ul>

<p>UCB systematically decreases exploration of underperforming actions while maintaining sufficient exploration, providing a principled approach to the explore-exploit tradeoff that <strong>laid groundwork for modern MAB algorithms</strong>.</p>

<h2 id="multi-armed-bandit-fundamentals">Multi-Armed Bandit Fundamentals</h2>

<p>In the MAB framework:</p>

<ul>
  <li>Each <strong>arm (action)</strong> represents a possible recommendation</li>
  <li>Pulling an arm yields a reward (user engagement)</li>
  <li><strong>The goal is to maximize cumulative reward over time</strong></li>
</ul>

<p>Mathematically, at each time step \(t\), we:</p>

<ol>
  <li>Select an action \(a_t\)</li>
  <li>Observe reward \(r_t\)</li>
  <li>Update our belief about the value of action \(a_t\)</li>
</ol>

<p>The expected reward of an action \(a\) is denoted as:</p>

\[Q(a) = E[r|a]\]

<h2 id="core-mab-algorithms">Core MAB Algorithms</h2>

<p>With this framework established, let’s explore specific algorithms that implement these principles in increasingly sophisticated ways. The following approaches represent the backbone of modern recommendation systems, each offering unique advantages in solving the exploration-exploitation dilemma.</p>

<h3 id="1-thompson-sampling">1. Thompson Sampling</h3>
<p><a href="https://en.wikipedia.org/wiki/Thompson_sampling">Thompson Sampling</a> is a Bayesian approach that maintains a probability distribution over the possible values of each arm.</p>

<p>Unlike deterministic methods, it naturally balances exploration and exploitation by sampling from <a href="https://www.sciencedirect.com/topics/computer-science/posterior-probability#:~:text=Posterior%20Probability%20in%20Computer%20Science,decisions%20based%20on%20observed%20data.">posterior distributions</a>, allowing the algorithm to express uncertainty in its current knowledge:</p>

\[\pi(a|D) = \int I[a = \text{argmax}_{a'} \ Q(a',\theta)] \cdot p(\theta|D) \cdot d\theta\]

<p>where,</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">π(a|D)</code> is the probability of selecting action <code class="language-plaintext highlighter-rouge">a</code> given data <code class="language-plaintext highlighter-rouge">D</code></li>
  <li><code class="language-plaintext highlighter-rouge">p(θ|D)</code> is the posterior distribution of parameters θ given observed data</li>
  <li><code class="language-plaintext highlighter-rouge">I[·]</code> is the indicator function</li>
</ul>

<p>In practice, the algorithm:</p>

<ol>
  <li>Samples a reward estimate from each arm’s posterior distribution</li>
  <li>Selects the arm with the highest sampled value</li>
  <li>Updates the posterior after observing the reward</li>
</ol>

<h3 id="2-contextual-bandits">2. Contextual Bandits</h3>

<p>Contextual bandits represent a significant evolution in the multi-armed bandit framework.</p>

<p>While standard MAB algorithms treat all users identically and focus solely on learning the expected reward of each action, contextual bandits recognize that the optimal action often depends on the specific situation or “context” in which the decision is made.</p>

\[Q(x,a) = E[r|x,a]\]

<p>where, \(x\) represents the context (user features, time, item characteristics).</p>

<p>Context vectors in production systems often include:</p>

<p>\(x_t ∈ R^d\) = [<em>user_features</em> || <em>time_features</em> || <em>content_features</em>]</p>

<p>These can be high-dimensional (1000-10,000 features) capturing nuanced patterns.</p>

<p>This powerful extension allows the system to personalize decisions based on user characteristics, environmental factors, or item features. For example, the best article to recommend might differ dramatically between a tech enthusiast browsing in the morning versus a casual reader at night.</p>

<p>By incorporating context, <strong>contextual bandits can learn much more nuanced policies</strong> compared to context-free approaches, making them particularly valuable for highly personalized recommendation systems.</p>

<h2 id="reward-engineering">Reward Engineering</h2>
<p>Beyond modeling context, the critical art of designing recommendation systems lies in defining what constitutes success.</p>

<p>Reward engineering transforms abstract business objectives into mathematical signals that guide algorithm behavior, effectively translating concepts like “user satisfaction” and “long-term engagement” (<a href="https://appstekcorp.com/blog/must-track-metrics-to-determine-the-success-of-your-recommender-system/">product teams often call these KPIs</a>) into quantifiable metrics that bandits can optimize for:</p>

\[R(a,x) = α₁(engagement) + α₂(retention) - α₃(fatigue) + α₄(diversity)\]

<p>The coefficients (\(α₁...α₄\)) balance competing objectives and can be adjusted based on business goals or user lifecycle stage.</p>

<p>Of course, <strong>this reward formulation is merely an illustrative example</strong>-—in reality, every product team believes their unique concoction of metrics is the definitive measure of success, much like how every parent is convinced their particular method of making mac and cheese is objectively superior to all others.</p>

<h2 id="regret-measuring-success-through-failure">Regret: Measuring Success Through Failure</h2>

<p>While reward functions tell us what we’re optimizing for, we need a way to evaluate how efficiently our algorithms learn. Enter the concept of <strong>Regret</strong> - perhaps the most elegantly named metric in machine learning, as it literally quantifies how much we should regret our choices.</p>

<p>Regret measures the opportunity cost of not always selecting the optimal action. In other words, it’s the difference between what we could have earned if we knew the best option in advance versus what we actually earned while learning. It answers the question:</p>

<p><em>“How much reward did we sacrifice during our exploration process?”</em></p>

<p>Formally, the cumulative regret \(R(T)\) over \(T\) time steps is defined as:</p>

\[R(T) = ∑(t=1)^T [r*(t) - r(t)]\]

<p>where,</p>

<ul>
  <li>\(r*(t)\) is the reward from the optimal action at time \(t\)</li>
  <li>\(r(t)\) is the reward received from the algorithm’s chosen action</li>
  <li>The summation represents the accumulated “missed opportunity” over time</li>
</ul>

<p>Different algorithms achieve different regret bounds. For instance:</p>

<ul>
  <li><strong>Random selection</strong>: Linear regret -&gt; \(O(T)\)</li>
  <li><strong>ε-greedy</strong>: \(O(T·ε + (1-ε)·log(T))\)</li>
  <li><strong>UCB algorithms</strong>: \(O(log(T))\)</li>
  <li><strong>Thompson Sampling</strong>: \(O(log(T))\)</li>
</ul>

<p>The logarithmic regret of UCB and Thompson Sampling explains their popularity - they guarantee that our learning becomes exponentially more efficient over time.</p>

<p>In practical terms, this means these algorithms quickly converge to near-optimal performance while still maintaining enough exploration to adapt to changing environments.</p>

<p>When evaluating recommendation systems in production, regret provides a theoretical foundation for A/B testing results. If an algorithm shows lower regret in testing environments, it will likely outperform competitors in production by more quickly identifying and exploiting the most effective recommendations while minimizing the “cost of learning” experienced by users.</p>

<h2 id="putting-it-all-together-end-to-end-contextual-bandit-implementation">Putting It All Together: End-to-End Contextual Bandit Implementation</h2>

<!-- _Short version_ -->

<p>Now that we’ve explored the theoretical foundations—let’s integrate these concepts into a comprehensive implementation framework. The elegance of contextual bandits emerges when these components work in concert.</p>

<!-- _Longer version_

Now that we've explored the theoretical foundations—from the basic explore-exploit dilemma to sophisticated contextual approaches and reward engineering—let's integrate these concepts into a comprehensive implementation framework. The elegance of contextual bandits emerges when these components work in concert: context vectors capturing user circumstances, exploration strategies balancing discovery with performance, and carefully designed reward functions aligning algorithmic behavior with business objectives.

What follows is not merely an academic exercise but a practical blueprint that powers recommendation systems across today's digital landscape. By implementing these algorithms thoughtfully, we transform abstract mathematical frameworks into systems that can learn user preferences incrementally, adapt to changing environments, and make increasingly personalized recommendations—all while navigating the fundamental tension between exploring new possibilities and exploiting known preferences. -->

<h3 id="algorithm-overview">Algorithm Overview</h3>

<p>At a high level, a contextual bandit system follows this workflow:</p>

<h4 id="1-observe-context-data-collection-and-feature-engineering">1. <strong>Observe context</strong> (Data collection and feature engineering):</h4>

<p>The algorithm begins by collecting a rich feature vector \(x_t\) that describes the current situation. This includes user characteristics (demographics, historical preferences, device information), environmental factors (time of day, day of week, location), and content features (item attributes, popularity metrics, recency). These context vectors can be high-dimensional as mentioned earlier, often containing thousands of features to capture the nuanced patterns that influence user preferences.</p>

<h4 id="2-select-action-using-policy">2. <strong>Select Action using policy</strong>:</h4>

<p>Based on the observed context, the algorithm applies an action-selection strategy balancing exploration and exploitation. This might use one of the approaches we discussed earlier: ε-greedy for simplicity, UCB for principled exploration, or Thompson Sampling for Bayesian uncertainty modeling.</p>

<p>The policy evaluates \(Q(x,a)\) for each potential action, incorporating both the expected reward and the uncertainty in that estimate. For Linear Contextual Bandits, this calculation would use the formula:</p>

\[\theta_a^T \cdot x + \text{exploration term}\]

<h4 id="3-serving-recommendations-to-users">3. <strong>Serving Recommendations to Users</strong>:</h4>

<p>After selecting the action(s), the chosen recommendation(s) are served to the user through the application interface.</p>

<p>While the fundamental bandit formulation selects a single arm (one recommendation) at each iteration, modern systems typically extend this to select multiple arms simultaneously using techniques like batch selection or slate recommendation. These systems might present a ranked list of items (as in a social media feed), a curated collection (like Netflix’s rows of content), or even a single prominent recommendation with several alternatives.</p>

<p>Business rules, diversity requirements, and fairness constraints often modify algorithmic selections before presentation to users, creating the essential feedback loop for the observe-reward mechanism.</p>

<h4 id="4-observe-reward">4. <strong>Observe reward</strong>:</h4>

<p>After presenting the selected recommendation to the user, the system measures the resulting engagement to determine the reward \(r_t\). This connects directly to our earlier discussion of reward engineering - the reward might be a weighted combination of immediate signals (clicks, views) and longer-term engagement metrics (session duration, return visits). The reward function translates business objectives into numerical feedback that guides the learning process.</p>

<h4 id="5-feedback-loops--updating-the-model">5. <strong>Feedback loops &amp; updating the model</strong></h4>

<p>The system incorporates this new observation (context-action-reward triplet) into its knowledge base, updating the estimated value function \(Q(x,a)\). For linear models, this means adjusting the parameter vectors \(\theta_a\) based on the prediction error. This step embodies the core of online learning - unlike static supervised models, bandit systems continuously refine their understanding through incremental updates, gradually shifting from exploration-heavy policies toward more focused exploitation as confidence increases.</p>

<p>By connecting reward engineering (what to optimize) with regret minimization (how efficiently we optimize), we create recommendation systems that not only target the right objectives but do so with minimal wasted interactions - a critical consideration when each suboptimal recommendation risks user disengagement.</p>

<h4 id="6-long-running-experiments--ab-tests">6. <strong>Long-running experiments &amp; A/B tests</strong></h4>

<p>While individual interactions power the feedback loop, recommendation systems must evaluate performance at a macro scale through structured experimentation:</p>

<ul>
  <li>
    <p><strong>Algorithm competition</strong>: Different bandit variants compete by serving recommendations to randomized user segments, measuring which approach better optimizes the defined reward function across thousands or millions of interactions.</p>
  </li>
  <li>
    <p><strong>Continuous evaluation</strong>: Unlike traditional offline models, bandit systems operate as perpetual experiments. Online metrics or KPIs (CTR, engagement time, conversion rates) are monitored continuously, with statistical significance calculated through sequential testing methods.</p>
  </li>
  <li>
    <p><strong>Exploration rate adaptation</strong>: As confidence in arm values increases, successful algorithms typically modulate their exploration rates. Systems might start exploration-heavy when introducing new content or features, then gradually shift toward exploitation as patterns emerge, moving towards a “performance” mode to maximize the success metrics and value from user attention.</p>
  </li>
</ul>

<p>This experimentation layer sits above the core bandit algorithm, ensuring the system not only identifies optimal recommendations but also refines its learning strategy itself. The approach prevents recommendations from growing stale despite evolving user preferences, content catalogs, and business objectives—creating a truly adaptive system.</p>

<h3 id="implementation-variations-from-theory-to-practice">Implementation Variations: From Theory to Practice</h3>

<p>While the algorithm overview provides the conceptual framework, contextual bandit implementations vary widely in how they model the relationship between context, actions, and rewards. These variations build directly upon the exploration-exploitation principles we’ve been exploring.</p>

<h4 id="1-linear-contextual-bandits">1. Linear Contextual Bandits</h4>

<p><a href="https://courses.cs.washington.edu/courses/cse599i/18wi/resources/lecture9/lecture9.pdf">Linear models</a> (LinUCB, Linear Thompson Sampling) express rewards as linear functions of context features. These implementations:</p>

<ul>
  <li>Extend UCB principles with contextual information</li>
  <li>Provide computational efficiency at scale</li>
  <li>Offer provable regret bounds</li>
  <li>Excel with strong feature engineering but underperform with complex non-linear patterns</li>
</ul>

<p>This approach bridges basic MAB algorithms and sophisticated contextual models, serving as an effective foundation for many recommendation systems.</p>

<h4 id="2-neural-contextual-bandits">2. Neural Contextual Bandits</h4>

<p>For complex recommendation spaces where linear relationships prove insufficient, neural network implementations offer greater expressivity. These approaches:</p>

<ul>
  <li>Capture intricate non-linear patterns between user context and rewards</li>
  <li>Learn representations directly from raw features</li>
  <li>Naturally extend to deep contextual bandits using architectures like <a href="https://en.wikipedia.org/wiki/Q-learning">deep Q-networks</a></li>
  <li>Connect to our reward engineering discussion by learning complex multi-objective reward functions</li>
</ul>

<p>This approach particularly shines in content domains where user preferences exhibit subtle, high-dimensional patterns that simpler models might miss.</p>

<h4 id="3-tree-based-approaches">3. Tree-Based Approaches</h4>

<p>Decision tree implementations like Contextual Random Forests offer another compelling alternative:</p>

<ul>
  <li>Handle mixed feature types (categorical and numerical) common in user contexts</li>
  <li>Provide natural feature importance rankings to enhance interpretability</li>
  <li>Efficiently model non-linear relationships without extensive feature engineering</li>
  <li>Implement exploration through bootstrap sampling, connecting to the randomized exploration strategies covered earlier</li>
</ul>

<p>Tree-based methods often excel in cold-start scenarios where the explicit structure helps to quickly identify meaningful patterns in limited data.</p>

<h4 id="4-ensemble-and-hybrid-methods">4. Ensemble and Hybrid Methods</h4>

<p>Modern production systems frequently combine multiple approaches:</p>

<ul>
  <li>Policy ensembles that blend exploration strategies (e.g., ε-greedy for new users, Thompson sampling for established users)</li>
  <li>Multi-level models using bandits for high-level category selection and specialized models for within-category ranking</li>
  <li>Online-offline hybrid approaches balancing pre-trained models with real-time adaptation</li>
</ul>

<p>These hybrid implementations represent the culmination of our exploration-exploitation journey, strategically combining different techniques to address the complex, multi-faceted nature of real-world recommendation challenges.</p>

<p>The choice among these implementations depends on several factors: data volume, feature dimensionality, latency requirements, and the complexity of the context-reward relationship. For instance, a video streaming platform might leverage neural approaches for its complex content recommendation task, while a simpler e-commerce use case might achieve excellent results with linear models.</p>

<p>With this understanding of implementation variations, we can now examine how these concepts manifest in real-world applications that <a href="https://www.ourmental.health/screen-time-sanity/how-tiktoks-bite-sized-videos-are-rewiring-our-brains">shape our digital experiences daily</a>.</p>

<h2 id="real-world-applications-in-products-we-use-everyday">Real-World Applications in products we use everyday</h2>

<h3 id="tiktok-when-the-algorithm-knows-you-better-than-your-therapist">TikTok: When the Algorithm Knows You Better Than Your Therapist</h3>

<p>TikTok’s “<a href="https://www.tiktok.com/tag/foryoupage?lang=en">For You Page</a>” has achieved almost mythical status among users who routinely exclaim, “How did it know I needed to see this?!” This isn’t digital sorcery—it’s contextual bandits at work:</p>

<ul>
  <li>
    <p><strong>Rapid testing at scale</strong>: TikTok’s algorithm shows new videos to small test audiences first. If you’ve ever wondered why you suddenly saw a video with only 12 views—congratulations, you’re a test subject in one of billions of daily experiments.</p>
  </li>
  <li>
    <p><strong>Microscopic attention tracking</strong>: The system doesn’t just track if you watched a video but how you watched it. Did you watch it twice? Slow down at a specific part? Hover your finger considering whether to like it before deciding against it. All of these micro-interactions feed the context vectors.</p>
  </li>
  <li>
    <p><strong>The “just one more video” effect</strong>: Reward functions can be optimized for what is called “<em>stickiness</em>” — that magical quality that keeps you scrolling at 1 AM despite your better judgment and next morning’s early meeting.</p>
  </li>
</ul>

<h3 id="instagram-the-explore-tab-becomes-a-digital-mirror">Instagram: The Explore Tab Becomes a Digital Mirror</h3>

<p>Instagram’s implementation of MABs is fascinating because it has to balance aesthetic consistency with discovery:</p>

<ul>
  <li>
    <p><strong>The “How did they know this?” phenomenon</strong>: Users often report the uncanny experience of seeing ads for products they only thought about. The reality is less paranormal —- Instagram’s contextual bandits have simply identified patterns in your behavior that correlate with others who explicitly searched for those products.</p>
  </li>
  <li>
    <p><strong>Creator recommendation roulette</strong>: Instagram famously adjusts its exploration parameters based on your behavior. Open the app at 3 PM on a workday, and the algorithm might serve you quick, digestible content. Open it at 9 PM on a weekend, and suddenly you’re being introduced to long-form creators who match your extended session potential.</p>
  </li>
</ul>

<h3 id="netflix-a-bold-experiment-in-dynamic-artwork-personalization">Netflix: A Bold Experiment in Dynamic Artwork Personalization</h3>

<ul>
  <li>
    <p><strong>Adaptive Artwork Selection</strong>: <a href="https://netflixtechblog.com/artwork-personalization-c589f074ad76">Netflix leverages multi-armed bandit algorithms</a> to continuously analyze user behavior and context. The platform tailors artwork to align with your unique preferences, rather than relying on static thumbnails served to all users.</p>
  </li>
  <li>
    <p><strong>Genre-Specific Personalization</strong>: For example, if a viewer frequently watches sci-fi thrillers, they might be shown artwork that emphasizes the show’s mysterious and supernatural elements. Conversely, a fan of 80s nostalgia might see a version highlighting its retro aesthetic and character dynamics. Drawing on real-time engagement data, the system refines its choices to ensure each artwork feels both personal and compelling.</p>
  </li>
</ul>

<h2 id="closing-thoughts">Closing Thoughts</h2>

<!-- _long version_ -->
<p>From the basic ε-greedy strategy to sophisticated contextual implementations, our journey through multi-armed bandit algorithms reveals an elegant solution to one of the most fundamental challenges in recommendation systems. These algorithms represent the perfect marriage of theory and practice—mathematically rigorous frameworks that power the digital experiences billions of people interact with daily.</p>

<p>As these systems evolve, they face growing challenges beyond mere technical optimization — transparency, <a href="https://en.wikipedia.org/wiki/Filter_bubble">filter bubbles</a>, and <a href="https://library.fiveable.me/key-terms/introduction-journalism/user-agency">user agency</a> become increasingly important. How much should algorithms nudge our discovery process versus amplifying existing preferences? When does personalization cross from helpful to manipulative? The tension between algorithmic efficiency and human autonomy presents rich territory for both technical innovation and ethical consideration.</p>

<!-- The real magic happens when these technical concepts manifest in the unanimous products we use every day. Behind these experiences lies a carefully orchestrated system of exploration and exploitation, continuously learning and adapting with every scroll, click, and pause. -->

<p>As these systems evolve, they face growing challenges beyond mere technical optimization. Questions of transparency, filter bubbles, and user agency become increasingly important. How much should algorithms nudge our discovery process versus amplifying existing preferences? When does personalization cross from helpful to manipulative? The tension between algorithmic efficiency and human autonomy presents rich territory for both technical innovation and ethical consideration.</p>

<p>Perhaps most fascinating is how these recommendation engines increasingly shape our cultural landscape—influencing not just what content we consume but what content gets created. As creators optimize for algorithmic distribution, the line between human and algorithmic taste continues to blur.</p>

<p>The next time a recommendation perfectly matches your interests or you are <a href="https://en.wikipedia.org/wiki/Doomscrolling">doomscrolling</a> your weekend away, take a moment to appreciate the elegant mathematical dance happening behind the scenes—an ongoing experiment in understanding human preference, one interaction at a time. And perhaps occasionally, deliberately choose the option the algorithm wouldn’t predict—if only to maintain that most human of qualities: <a href="https://www.psychologytoday.com/us/blog/ulterior-motives/200811/unpredictability-is-in-our-nature">Unpredictability</a>.</p>

<!-- _short version_
As recommendation systems continue to shape our digital landscapes, the technical foundations explored here will likely evolve by further integrating deep learning architectures and reinforcement learning frameworks. Yet the core principles of balancing exploration with exploitation will remain essential—not just as mathematical abstractions, but as practical tools that quietly orchestrate the digital content that fills our screens each day. 

The next time a perfect recommendation catches your attention or doomscrolling your weekend away, remember that behind that moment lies a carefully calibrated experiment, one small step in an endless process of algorithmic adaptation. -->

<h2 id="references">References</h2>

<ol>
  <li>
    <p>Eugene Yan, “<a href="https://applyingml.com/resources/bandits/">Bandits for Recommender Systems</a>,” applyingml.com, 2024.</p>
  </li>
  <li>
    <p>J. McInerney et al., “<a href="https://doi.org/10.1145/3240323.3240354">Explore, exploit, and explain</a>,” Proceedings of the 12th ACM Conference on Recommender Systems, Sep. 2018.</p>
  </li>
  <li>
    <p>L. Li, W. Chu, J. Langford, and R. E. Schapire, “<a href="https://doi.org/10.1145/1772690.1772758">A contextual-bandit approach to personalized news article recommendation</a>,” Proceedings of the 19th international conference on World wide web - WWW ’10, 2010.</p>
  </li>
  <li>
    <p>N. Silva, H. Werneck, T. Silva, A. C. M. Pereira, and L. Rocha, “<a href="https://doi.org/10.1016/j.eswa.2022.116669">Multi-Armed Bandits in Recommendation Systems: A survey of the state-of-the-art and future directions</a>,” Expert Systems with Applications, vol. 197, p. 116669, Jul. 2022.</p>
  </li>
  <li>
    <p>L. Zhou, “<a href="https://arxiv.org/abs/1508.03326">A Survey on Contextual Multi-armed Bandits</a>,” <em>arXiv:1508.03326 [cs]</em>, 2015.</p>
  </li>
</ol>]]></content><author><name>darpan-jain</name></author><category term="machine-learning" /><category term="recommendation-systems" /><category term="multi-armed-bandits" /><category term="online-learning" /><summary type="html"><![CDATA[Meet the efficient mathematical gamblers working behind the scenes that predict your desires before they form. Multi-armed Bandits are why you probably can't stop scrolling.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://darpanjain.com/blog/assets/images/multi-arm-bandits-for-recommendation-systems/slot-machines.webp" /><media:content medium="image" url="https://darpanjain.com/blog/assets/images/multi-arm-bandits-for-recommendation-systems/slot-machines.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Resilient Verses: Exploring the Enduring Power of “Invictus”</title><link href="https://darpanjain.com/blog/reilient-verses-enduring-power-of-invictus-henley/" rel="alternate" type="text/html" title="Resilient Verses: Exploring the Enduring Power of “Invictus”" /><published>2025-03-09T18:14:32-07:00</published><updated>2025-03-09T18:14:32-07:00</updated><id>https://darpanjain.com/blog/reilient-verses-enduring-power-of-invictus-henley</id><content type="html" xml:base="https://darpanjain.com/blog/reilient-verses-enduring-power-of-invictus-henley/"><![CDATA[<p><em>There’s something rather spectacular about this poem that manages to remain relevant over a century later.</em></p>

<p>“Invictus” penned by William Ernest Henley in 1875, is perhaps the ultimate “pull yourself up by your bootstraps” pep talk—except, ironically, Henley couldn’t physically wear boots due to his tuberculosis of the bone. Talk about commitment to the metaphor.</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/invictus/henley.webp" alt="Side-face of Henley" style="width: 30%; display: block; margin-left: auto; margin-right: auto;" />
    <figcaption><i>A (side) face to the name — William Ernest Henley</i></figcaption>
</figure>

<h2 id="the-unconquerable-soul">The Unconquerable Soul</h2>

<p>Henley opens with:</p>

<blockquote>
  <p><em>Out of the night that covers me,</em><br />
<em>Black as the pit from pole to pole,</em></p>
</blockquote>

<p>He wasn’t being melodramatic—the man wrote this while recovering from a leg amputation at a very young age. While my worst days typically involve a lazy day and cold coffee, his perspective on facing adversity continues to resonate &amp; humble me.</p>

<p>The central message—<strong>“I am the master of my fate, I am the captain of my soul”</strong>—has become somewhat of a motivational poster cliché. Yet, stripped of modern self-help packaging, this sentiment remains profoundly powerful.</p>

<p><strong>We might not control circumstances, but we can command our responses.</strong></p>

<h2 id="stoicism-before-it-was-cool">Stoicism Before It Was Cool</h2>

<figure style="text-align: center;">
<img src="/blog/assets/images/shared/thinking.webp" alt="thinking stoic guy statue" style="width: 60%; display: block; margin-left: auto; margin-right: auto;" />
    <figcaption><i></i></figcaption>
</figure>

<p>The philosophical roots of “Invictus”
Long before Silicon Valley executives discovered Marcus Aurelius, Henley was embodying <a href="https://en.wikipedia.org/wiki/Stoicism">stoicism</a> with lines like:</p>

<blockquote>
  <p><em>In the fell clutch of circumstance,</em><br />
<em>I have not winced nor cried aloud.</em></p>
</blockquote>

<p>This isn’t about suppressing emotions—rather, it’s acknowledging hardship while refusing to be defined by it.</p>

<p>What fascinates me most is how Henley doesn’t deny suffering. The “bludgeonings of chance” are very real in his world. This is no toxic positivity here, just stubborn, unconquered resilience (“Invictus” is <a href="https://www.etymonline.com/word/invictus">Latin for “unconquered”</a>).</p>

<h2 id="continued-modern-relevance">Continued Modern Relevance</h2>
<p>In a world of <a href="https://www.reddit.com/r/Adulting/comments/140qk1x/social_media_is_not_real_it_will_only_make_you/">carefully curated social media personas</a>, “Invictus” reminds us that our most authentic strength often emerges not from our highlight reels, but from how we navigate our darker, more depressing times.</p>

<p>The poem’s lasting appeal lies in its broad resonance. Whether facing physical challenges like Henley, professional setbacks, or the existential dread of <strong>“What am I doing with my life?!”</strong>, the principle remains—we determine our internal response.</p>

<h2 id="finding-your-unconquerable">Finding Your Unconquerable</h2>
<p>Perhaps the most practical takeaway from “Invictus” isn’t about heroic resistance against monumental odds. It’s about the everyday choice to remain unbowed in spirit, even when circumstances suggest otherwise.</p>

<p>As someone who occasionally feels defeated when something (although insignificantly small) doesn’t go my way, I find Henley’s perspective both humbling and inspiring. If he could maintain such resolve while literally losing a limb, surely I can summon similar fortitude when facing life’s lesser inconveniences.</p>

<p>In the end, being “Invictus” -— unconquered—isn’t about never falling; it’s about <strong>maintaining sovereignty over that internal space</strong> where your true self resides, regardless of external circumstances.</p>

<p>And that, I believe, is a lesson worth carrying through whatever darkness may cover our paths.</p>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>As we navigate our increasingly complex world, Henley’s century-old words offer a timeless reminder: circumstances may constrain our options, but never our dignity. “Invictus” isn’t just Victorian motivation—it’s <strong>a blueprint for psychological resilience.</strong></p>

<p>When I revisit this poem during difficult moments, I’m struck less by its defiance and more by its quiet assurance. It’s reassuring that past generations also faced their own unimaginable challenges and discovered that true inner freedom comes not from controlling external circumstances, but from within.</p>

<blockquote>
  <p><em>It matters not how strait the gate,</em><br />
<em>How charged with punishments the scroll,<br />
_I am the master of my fate,</em><br />
<em>I am the captain of my soul.</em></p>
</blockquote>

<p>Perhaps that’s <strong>the ultimate gift of “Invictus”</strong> —- the recognition that being unconquerable has nothing to do with avoiding life’s storms and everything to do with how we sail through them.</p>

<figure style="text-align: center;">
<img src="/blog/assets/images/invictus/lighthouse-seas.webp" alt="Lighthouse standing tall in a seastorm" style="width: 70%; display: block; margin-left: auto; margin-right: auto;" />
    <figcaption><i>Like the steadfast lighthouse, the unconquerable soul stands firm against life's tempests</i></figcaption>
</figure>

<p>In a world increasingly beyond our control, William Ernest Henley reminds us of the one territory where our authority remains absolute: <strong>The realm of our own response.</strong></p>

<h3 id="the-complete-poem">The complete poem:</h3>

<blockquote>
  <p><em>Out of the night that covers me,</em><br />
      <em>Black as the pit from pole to pole,</em><br />
<em>I thank whatever gods may be</em><br />
       <em>For my unconquerable soul.</em><br />
<br />
<em>In the fell clutch of circumstance</em><br />
      <em>I have not winced nor cried aloud.</em><br />
<em>Under the bludgeonings of chance</em><br />
      <em>My head is bloody, but unbowed.</em><br />
<br />
<em>Beyond this place of wrath and tears</em><br />
      <em>Looks but Horror of the shade,</em><br />
<em>And yet the menace of the years</em><br />
      <em>Finds and shall find me unafraid.</em><br />
<br />
<em>It matters not how strait the gate,</em><br />
      <em>How charged with punishments the scroll,</em><br />
<em>I am the master of my fate,</em><br />
      <em>I am the capitan of my soul.</em><br /></p>
</blockquote>

<h2 id="unconquered-indeed">Unconquered indeed!</h2>]]></content><author><name>darpan-jain</name></author><category term="poetry" /><category term="resilience" /><category term="stoicism" /><summary type="html"><![CDATA[A deep dive into William Ernest Henley's timeless poem "Invictus," exploring its themes of resilience, stoicism, and personal empowerment that continue to inspire readers today.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://darpanjain.com/blog/assets/images/shared/thinking.webp" /><media:content medium="image" url="https://darpanjain.com/blog/assets/images/shared/thinking.webp" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>