Skip to content

Add off-policy evaluation for contextual bandits (decisionrl.ope) - #24

Merged
DenisDrobyshev merged 6 commits into
mainfrom
feature/bandit-ope
Sep 20, 2026
Merged

DenisDrobyshev merged 6 commits into
mainfrom
feature/bandit-ope

Conversation

@DenisDrobyshev

Copy link
Copy Markdown
Member

Adds decisionrl.ope, off-policy evaluation for contextual bandits: estimate what a target
policy would earn from a log of past decisions, without deploying it. This is the question
you actually face before shipping a new pricing or recommendation rule, and it fits the
library's honest-evaluation theme.

Four estimators over a (context, action, propensity, reward) log plus the target policy's
action probabilities:

  • inverse_propensity_score (IPS): unbiased, high variance.
  • self_normalized_ips (SNIPS): consistent and much steadier.
  • direct_method (DM): a fitted per-arm reward model averaged under the target.
  • doubly_robust (DR): DM plus an IPS correction; unbiased if either the propensities or
    the reward model is right.

Plus collect_bandit_log and behaviour-policy helpers (uniform_behavior,
epsilon_greedy_behavior, greedy_target_probs). Everything is pure NumPy with no torch
dependency, so it works in the minimal install.

On a synthetic bandit with a known value (0.443), all four recover it from a
uniform-behaviour log: IPS 0.447, SNIPS 0.447, DM 0.444, DR 0.447. A test also pins the
doubly-robust property: with a deliberately broken reward model the direct method collapses
toward zero, but doubly robust still returns the right value.

Docs page (docs/ope.md), nav entry, README bullet, a cross-link from the bandits page, and
a CHANGELOG entry are included. ruff, mypy, the OPE tests, and the strict docs build pass.

DenisDrobyshev and others added 3 commits August 27, 2026 14:24
New decisionrl.ope module estimates what a target policy would earn from a log of past
decisions, without deploying it, which is how you decide whether a new pricing or
recommendation rule is worth shipping. Four estimators over a (context, action, propensity,
reward) log and the target's action probabilities: inverse propensity scoring (unbiased,
high variance), self-normalized IPS (steadier), the direct method (a fitted reward model),
and doubly robust (unbiased if either the propensities or the model is right). Includes
collect_bandit_log and behaviour-policy helpers. Pure NumPy, no torch.

On a synthetic bandit with a known value, all four recover it from a uniform-behaviour log;
a test also covers the doubly-robust property, that DR stays accurate when the reward model
is deliberately broken. Docs page and cross-links added.
DenisDrobyshev and others added 3 commits September 20, 2026 17:38
Only CHANGELOG.md conflicted, and only because both sides appended to the
same `### Unreleased` heading: main gained the `set_training(bool)` entry
and a `### Fixed` section about the rollout buffer's global NumPy RNG,
this branch gained the `decisionrl.ope` entry. Nothing overlapped in
meaning, so all three survive unchanged — ope first under `### Added`
because it is the larger addition, then `set_training`, then `### Fixed`.

No source file conflicted: `decisionrl.ope` is a new module and touches
nothing main changed.
@DenisDrobyshev
DenisDrobyshev merged commit c3f4408 into main Sep 20, 2026
18 of 20 checks passed
@DenisDrobyshev
DenisDrobyshev deleted the feature/bandit-ope branch September 20, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant