<?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://qpoch.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://qpoch.com/" rel="alternate" type="text/html" /><updated>2026-08-24T10:46:03+00:00</updated><id>https://qpoch.com/feed.xml</id><title type="html">Hari Prasad - Blog</title><subtitle>Blog posts by Hari Prasad on AI research — perception, planning, sim2real and novel view synthesis.</subtitle><author><name>Hari Prasad</name></author><entry><title type="html">The 95% confidence interval that was right 0% of the time</title><link href="https://qpoch.com/blog/ope-coverage-audit/" rel="alternate" type="text/html" title="The 95% confidence interval that was right 0% of the time" /><published>2026-08-24T00:00:00+00:00</published><updated>2026-08-24T00:00:00+00:00</updated><id>https://qpoch.com/blog/ope-coverage-audit</id><content type="html" xml:base="https://qpoch.com/blog/ope-coverage-audit/"><![CDATA[<p>Last week I ran a nominal 95% confidence interval a hundred times against a ground truth I could compute exactly, to the sixth decimal place. It contained the truth in zero of the hundred runs. Not 80%, not 50%. Zero. And it came from bootstrap FQE (fitted Q-evaluation, which learns a value function from logged data, with intervals built by resampling that data), one of the estimators people treat as the sensible default when deciding whether an RL policy is safe to deploy.</p>

<blockquote>
  <p><strong>TL;DR</strong></p>
  <ul>
    <li>On a 25-state gridworld with exact ground truth, nominal 95% intervals from bootstrap FQE and doubly-robust estimators covered the true policy value in as few as 0% and 5% of replicates at N=10 episodes, and WIS intervals were still 12 to 17 points below nominal at N=200.</li>
    <li>Below roughly 200 episodes, no standard off-policy interval on this task was trustworthy, and even the on-policy baseline failed at tiny N because of a 1.3% rare event.</li>
    <li>The payoff: once calibrated (N &gt;= 200), FQE and DR intervals were 2 to 3x tighter than just running the policy, on this toy task.</li>
  </ul>
</blockquote>

<h2 id="the-gap-nobody-had-filled">The gap nobody had filled</h2>

<p>Off-policy evaluation (OPE) means estimating how well a new policy would perform using only data collected by an old one, without deploying the new policy. Every offline deploy/no-deploy decision ultimately rests on an uncertainty interval around an OPE estimate. So you would expect someone to have checked whether the intervals practitioners actually compute deliver their advertised coverage. The usual suspects: bootstrap intervals around importance sampling (reweighting old data by how likely the new policy was to take each action), fitted Q-evaluation (FQE, fitting a value function to the logged data), and doubly-robust hybrids (combining the model estimate with an importance-weighted correction). Coverage here means the plain thing: a 95% interval should contain the true value about 95% of the time.</p>

<p>Mostly, nobody had. The big empirical studies never audit intervals: <a href="https://arxiv.org/abs/1911.06854">COBS</a> compares roughly 30 estimators on point-estimate accuracy, and <a href="https://arxiv.org/abs/2103.16596">DOPE</a> benchmarks value error and ranking metrics. The methods literature keeps proposing new interval constructions instead: high-confidence bounds (<a href="https://arxiv.org/abs/1604.00923">Thomas &amp; Brunskill 2016</a>), bootstrap corrections (<a href="https://arxiv.org/abs/2007.13609">Kostrikov &amp; Nachum 2020</a>), empirical-likelihood intervals (<a href="https://arxiv.org/abs/2010.11652">CoinDICE</a>), and the conformal OPE line from 2022 onward (<a href="https://arxiv.org/abs/2206.04405">Taufiq et al. 2022</a>; see also Foffano, Russo &amp; Proutiere 2023 in that same line).</p>

<p>One honest caveat up front: this is not the first coverage number ever published. <a href="https://arxiv.org/abs/2102.03607">Hao et al. 2021</a> embedded a coverage-vs-episodes study for their own bootstrap-FQE method and noted undercoverage at 10 episodes. What I could not find in an adversarial three-search sweep of 2022+ work is any paper whose primary contribution is a cross-estimator audit of the intervals practitioners currently use, with sample-size guidance attached. That sweep had limited recall (the OpenAlex queries were noisy), so if you know a paper I missed, please send it.</p>

<h2 id="the-experiment-a-world-small-enough-to-compute-the-truth">The experiment: a world small enough to compute the truth</h2>

<p>The whole design hinges on one choice: an environment where the true policy value is exact, so any interval failure is unambiguously the interval’s fault. I used a 5x5 slippery gridworld (slip probability 0.2, goal +1, pit -1, gamma 0.99, horizon 50). The target policy is a noisy greedy policy; the behavior policy that generates the data mixes in 30% uniform noise, with action probabilities known exactly, so importance weights are exact too. Ground truth comes from finite-horizon dynamic programming: V = 0.874020, cross-checked against 50,000 Monte Carlo rollouts (0.873701 +/- 0.000959, z = -0.33).</p>

<figure>
  <img src="/assets/blog/ope-coverage-audit/gridworld-env.png" alt="A 5 by 5 grid with the start cell in the top-left corner, a pit worth minus one in the exact center, and the goal worth plus one in the bottom-right corner, alongside a slip-dynamics panel showing the intended move succeeding with probability 0.8 and slipping to each perpendicular direction with probability 0.1." />
  <figcaption>Figure 1 — The environment: a 5×5 slippery gridworld with the start at state 0, a −1 pit dead center, and the +1 goal in the far corner. Every move goes as intended with probability 0.8 and slips sideways 0.1 each way.</figcaption>
</figure>

<p>I made the return distribution deliberately safety-flavored: the target policy hits the pit 1.3% of the time, giving a skew of -8.3. Then: datasets of N in {10, 50, 200, 1000} behavior episodes, 100 independent replicates per N, four estimators (IS, WIS, DR, tabular FQE), percentile bootstrap (B=200) and normal-approximation intervals, plus an on-policy Monte Carlo baseline at matched budget. Monte Carlo error on each coverage number is about 2 to 3 points.</p>

<p>The whole pipeline in one picture: the behavior policy generates the offline datasets along the top path, dynamic programming computes the exact truth along the bottom path, and the audit checks how often each estimator’s interval contains that truth.</p>

<figure>
  <img src="/assets/blog/ope-coverage-audit/experiment-pipeline.png" alt="Pipeline diagram: a slippery gridworld feeds a behavior policy that generates offline datasets for four estimators with bootstrap confidence intervals, and a target policy whose exact value comes from dynamic programming; both paths converge on the coverage audit, which checks whether each 95% interval contains the true value over 100 replicates." />
  <figcaption>Figure 2 — The audit pipeline: offline estimates flow along the top path, the exact truth along the bottom, and coverage is checked where they meet.</figcaption>
</figure>

<p>Empirical coverage of nominal <strong>95%</strong> intervals:</p>

<table>
  <thead>
    <tr>
      <th>Estimator / CI</th>
      <th>N=10</th>
      <th>N=50</th>
      <th>N=200</th>
      <th>N=1000</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>IS / bootstrap</td>
      <td>0.67</td>
      <td>0.88</td>
      <td>0.90</td>
      <td>0.93</td>
    </tr>
    <tr>
      <td>IS / normal</td>
      <td>0.70</td>
      <td>0.87</td>
      <td>0.87</td>
      <td>0.92</td>
    </tr>
    <tr>
      <td>WIS / bootstrap</td>
      <td>0.78</td>
      <td>0.82</td>
      <td>0.83</td>
      <td>0.92</td>
    </tr>
    <tr>
      <td>WIS / normal</td>
      <td>0.62</td>
      <td>0.78</td>
      <td>0.78</td>
      <td>0.91</td>
    </tr>
    <tr>
      <td>DR / bootstrap</td>
      <td><strong>0.05</strong></td>
      <td><strong>0.33</strong></td>
      <td>0.93</td>
      <td>0.91</td>
    </tr>
    <tr>
      <td>FQE / bootstrap</td>
      <td><strong>0.00</strong></td>
      <td><strong>0.05</strong></td>
      <td>0.96</td>
      <td>0.93</td>
    </tr>
    <tr>
      <td>On-policy MC / normal</td>
      <td>0.29</td>
      <td>0.38</td>
      <td>0.90</td>
      <td>0.92</td>
    </tr>
  </tbody>
</table>

<figure>
  <img src="/assets/blog/ope-coverage-audit/coverage_vs_N.png" alt="Empirical coverage of nominal 95% confidence intervals versus dataset size for seven estimator and interval combinations, all falling well below the nominal line at small N." />
  <figcaption>Figure 3 — Empirical coverage of nominal 90% and 95% intervals vs dataset size. FQE and DR bootstrap intervals collapse to near-zero coverage at small N; WIS is the last to recover.</figcaption>
</figure>

<p>Not a single estimator-interval combination stayed within 5 points of nominal at all N &lt;= 200. Under my pre-stated rule (miscalibration if any N &lt;= 200 cell misses nominal by more than 10 points), miscalibration was demonstrated many times over.</p>

<p>The FQE and DR collapse has a clean mechanism, and it is not heavy tails. With 10 episodes, most (state, action) pairs are never visited, and the fitted Q-function defaults them to zero. That produces a strong pessimistic bias in the point estimate (about -0.24 to -0.25) while the bootstrap, resampling the same blinkered data, produces narrow intervals around the wrong value. Confidently wrong is the worst failure mode an interval can have, and the “safe default” DR estimator was among the worst calibrated at small N. That was one of the surprises I had pre-registered as “would surprise me” in the plan, and it happened.</p>

<p>Two more surprises. First, WIS (weighted importance sampling, which normalizes the weights to cut variance) was the only estimator still failing at N=200, sitting 12 to 17 points below nominal, after everything else had recovered. Low variance, persistent bias. Second, the honest complication: the on-policy baseline also failed at tiny N (0.29 and 0.38 coverage at N &lt;= 10 and 50). With a 1.3% catastrophic event, small samples usually contain zero catastrophes, so every variance-based interval collapses around an optimistic value. The tiny-N failure is partly universal rare-event skew, not an OPE problem. The OPE-specific findings are the far more extreme, bias-driven FQE/DR collapse (0.00 to 0.05 versus 0.29 to 0.38) and WIS still failing at N=200 after on-policy has recovered.</p>

<h2 id="how-many-episodes-before-you-can-trust-the-interval">How many episodes before you can trust the interval</h2>

<p>The audit only earns its keep if it translates into guidance. N* is the smallest tested N where 95% coverage lands in [90%, 100%]: 200 episodes for bootstrap IS, DR, FQE, and on-policy MC; 1000 for WIS (both interval types) and normal-approximation IS. Note the grid: N* is resolved only on {10, 50, 200, 1000}, so the true thresholds sit somewhere between grid points.</p>

<p>Width is where OPE redeems itself. Median 95% interval width relative to on-policy Monte Carlo at matched budget:</p>

<table>
  <thead>
    <tr>
      <th>Estimator / CI</th>
      <th>N*</th>
      <th>Width vs on-policy (N=200)</th>
      <th>Width vs on-policy (N=1000)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>FQE / bootstrap</td>
      <td>200</td>
      <td>0.35x</td>
      <td>0.31x</td>
    </tr>
    <tr>
      <td>DR / bootstrap</td>
      <td>200</td>
      <td>0.51x</td>
      <td>0.59x</td>
    </tr>
    <tr>
      <td>WIS / bootstrap</td>
      <td>1000</td>
      <td>0.82x</td>
      <td>0.88x</td>
    </tr>
    <tr>
      <td>IS / bootstrap</td>
      <td>200</td>
      <td>9.5x</td>
      <td>10.6x</td>
    </tr>
  </tbody>
</table>

<figure>
  <img src="/assets/blog/ope-coverage-audit/width_vs_N.png" alt="Median 95% confidence interval width versus dataset size on a log axis, showing importance sampling intervals roughly ten times wider than the rest." />
  <figcaption>Figure 4 — Median 95% interval width vs dataset size (log scales). IS intervals are honest but roughly 10x wider than the rest; calibrated FQE and DR are the tightest.</figcaption>
</figure>

<p>So the practitioner takeaway, scoped strictly to this toy task: below ~200 episodes, trust nothing. At 200+, prefer bootstrap FQE or DR; once calibrated, their intervals are 2 to 3x tighter than actually running the policy on-policy at the same episode budget. IS is calibrated at 200 but roughly 10x wider than just running the policy (honest but useless). Distrust WIS intervals until around 1000 episodes.</p>

<h2 id="what-this-does-and-does-not-show">What this does and does not show</h2>

<p>This is a 25-state tabular world with exact importance weights, exact ground truth, and a hand-picked rare-event structure. Real offline RL has function approximation, estimated behavior policies, and estimated weights, none of which will make calibration easier. That is exactly why the framing is “even in the easiest possible setting, standard intervals fail at small N”: the failure here is a floor, not a ceiling. Add the N* grid coarseness and the limited-recall novelty sweep, and the right reading is “a confirmed, consequential problem on the easiest instance,” not a field-wide measurement.</p>

<h2 id="whats-next">What’s next</h2>

<p>The obvious follow-up is the same audit at D4RL scale: continuous control, function-approximation FQE, learned behavior policies, with the deliverable being per-estimator N* tables a practitioner can actually use. Two backlog directions from this run also survived: anytime-valid stopping rules for policy certification (confidence sequences that answer “how many eval rollouts before I can certify this policy” without fixing N in advance), and testing whether formal robustness certificates on policy networks actually predict return degradation under distribution shift, which nobody appears to have checked empirically.</p>

<p>Everything above is reproducible from <a href="https://github.com/qpochlabs/ope-coverage-audit">the code on GitHub</a>: two Python files (numpy and matplotlib only), fully seeded with MASTER_SEED=20260824, about 20 seconds on a laptop CPU. If a 95% interval can be wrong 100 times out of 100 in a world this small, it is worth 20 seconds to check yours.</p>

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

<ol>
  <li>Voloshin, Le, Jiang, Yue (2021). <em>Empirical Study of Off-Policy Policy Evaluation for Reinforcement Learning</em> (COBS). NeurIPS Datasets &amp; Benchmarks. <a href="https://arxiv.org/abs/1911.06854">arXiv:1911.06854</a></li>
  <li>Fu et al. (2021). <em>Benchmarks for Deep Off-Policy Evaluation</em> (DOPE). ICLR. <a href="https://arxiv.org/abs/2103.16596">arXiv:2103.16596</a></li>
  <li>Thomas &amp; Brunskill (2016). <em>Data-Efficient Off-Policy Policy Evaluation for Reinforcement Learning</em>. ICML. <a href="https://arxiv.org/abs/1604.00923">arXiv:1604.00923</a></li>
  <li>Kostrikov &amp; Nachum (2020). <em>Statistical Bootstrapping for Uncertainty Estimation in Off-Policy Evaluation</em>. <a href="https://arxiv.org/abs/2007.13609">arXiv:2007.13609</a></li>
  <li>Dai, Chow, Nachum, Li, Szepesvari, Schuurmans (2020). <em>CoinDICE: Off-Policy Confidence Interval Estimation</em>. NeurIPS. <a href="https://arxiv.org/abs/2010.11652">arXiv:2010.11652</a></li>
  <li>Taufiq, Ton, Cornish, Teh, Doucet (2022). <em>Conformal Off-Policy Prediction in Contextual Bandits</em>. NeurIPS. <a href="https://arxiv.org/abs/2206.04405">arXiv:2206.04405</a></li>
  <li>Hao, Ji, Duan, Lu, Szepesvari, Wang (2021). <em>Bootstrapping Fitted Q-Evaluation for Off-Policy Inference</em>. ICML. <a href="https://arxiv.org/abs/2102.03607">arXiv:2102.03607</a></li>
  <li>Foffano, Russo, Proutiere (2023). <em>Conformal Off-Policy Evaluation in Markov Decision Processes</em>. (No link — I could not verify the arXiv ID during the literature sweep.)</li>
</ol>]]></content><author><name>Hari Prasad</name></author><summary type="html"><![CDATA[I audited the confidence intervals RL practitioners actually use for off-policy evaluation on a tiny gridworld with exact ground truth. Nominal 95% intervals from bootstrap FQE covered the truth 0% of the time at N=10 episodes, and no standard interval was trustworthy below ~200 episodes on this task.]]></summary></entry><entry><title type="html">Welcome to the blog</title><link href="https://qpoch.com/blog/welcome-to-the-blog/" rel="alternate" type="text/html" title="Welcome to the blog" /><published>2026-08-24T00:00:00+00:00</published><updated>2026-08-24T00:00:00+00:00</updated><id>https://qpoch.com/blog/welcome-to-the-blog</id><content type="html" xml:base="https://qpoch.com/blog/welcome-to-the-blog/"><![CDATA[<p>This is the new home for my blog posts at <a href="https://qpoch.com">qpoch.com</a>, covering my work and notes on AI research — perception, planning, sim2real, novel view synthesis, and the occasional thought experiment in fundamental AI.</p>

<h2 id="how-this-blog-works">How this blog works</h2>

<p>Posts are written in plain Markdown and live in the <code class="language-plaintext highlighter-rouge">_posts</code> folder of the repository. Each file is named <code class="language-plaintext highlighter-rouge">YYYY-MM-DD-title.md</code> and starts with a small front matter block containing the post title. Everything else — the list on the home page, the post pages, dates and the RSS feed — is generated automatically.</p>

<h2 id="what-to-expect">What to expect</h2>

<p>Write-ups of ongoing projects, paper notes, and short explainers. For my publications and research profile, head over to <a href="https://hari.qpoch.com">hari.qpoch.com</a>.</p>]]></content><author><name>Hari Prasad</name></author><summary type="html"><![CDATA[This is the new home for my blog posts at qpoch.com, covering my work and notes on AI research — perception, planning, sim2real, novel view synthesis, and the occasional thought experiment in fundamental AI.]]></summary></entry></feed>