Skip to main content

onlinerake

PyPI version PyPI Downloads Documentation CI

Real-time survey weighting for streaming data.

The Problem

You're collecting survey responses or observational data one record at a time. Your sample doesn't match population demographics—too many young respondents, too few from certain regions. Traditional weighting methods (raking/IPF) require reprocessing the entire dataset whenever a new response arrives.

onlinerake updates weights as observations arrive, reducing squared error between weighted margins and population targets. Each update revisits all retained observations: memory is O(n × d), work per arrival is O(n × d × n_sgd_steps), and total work grows quadratically with stream length for fixed feature count. Check the remaining margin errors; a finite number of updates need not balance all targets.

When to Use This

  • Online surveys where responses arrive continuously
  • A/B tests that need demographic balance during collection
  • Passive data collection (app usage, sensor data) requiring real-time calibration
  • Moderate streams where updating retained weights after every arrival is affordable

Quick Start

pip install onlinerake
from onlinerake import OnlineRakingSGD, Targets

# Define population targets (proportion with indicator = 1)
targets = Targets(
    female=0.51,  # 51% female in population
    college=0.32,  # 32% college educated
    age_65_plus=0.17,  # 17% age 65+
)

# Create raker
raker = OnlineRakingSGD(targets, learning_rate=5.0)

survey_stream = [
    {"female": 1, "college": 0, "age_65_plus": 0},
    {"female": 0, "college": 1, "age_65_plus": 1},
    {"female": 1, "college": 1, "age_65_plus": 0},
    {"female": 0, "college": 0, "age_65_plus": 0},
]

# Replace this list with your incoming responses.
for response in survey_stream:
    raker.partial_fit(response)

    # Check current state anytime
    print(f"Weighted margins: {raker.margins}")
    print(f"Effective sample size: {raker.effective_sample_size:.0f}")

# Get final weights
weights = raker.weights

Which Algorithm?

Update Algorithm Default learning rate
Additive weight adjustments OnlineRakingSGD 5.0
Multiplicative weight adjustments OnlineRakingMWU 1.0

Both methods accept records one at a time and initialize each new weight at one. Unequal starting weights are not supported. Each method takes a fixed number of steps toward the target means, so always inspect the remaining error. The multiplicative method need not choose the same weights as a method that fits the whole dataset at once. BatchIPF provides that comparison for binary targets.

Learning rates need evaluation on the intended data, particularly when continuous features use different units. Better target balance can require more unequal weights, reducing effective sample size.

Performance

Run python examples/streaming_mwu.py for a reproducible evaluation with 10 seeds and 500 arrivals per stream. With the default MWU settings, mean squared margin error over arrivals 100–500 falls by 83% in the stationary binary case, 75% after a sampling shift, and 83% with binary and scaled continuous features. Mean final effective sample sizes are 292, 383, and 155 out of 500, respectively. These simulations measure calibration on the accumulated sample; they do not establish improved outcome estimates or a general performance guarantee.

Features

Continuous Covariates

Target means instead of proportions:

continuous_targets = Targets(
    age=(42.0, "mean"),  # Target mean age = 42
    income=(55000, "mean"),  # Target mean income = $55,000
    female=0.51,  # Binary: 51% female
)

Learning Rate Schedules

To inspect learning-rate summability (not a guarantee of calibration):

from onlinerake import OnlineRakingSGD, Targets, PolynomialDecayLR
from onlinerake.convergence import verify_robbins_monro

schedule = PolynomialDecayLR(initial_lr=10.0, power=0.6)
scheduled_raker = OnlineRakingSGD(targets, learning_rate=schedule)

# Verify Robbins-Monro conditions (analytical for known schedules)
result = verify_robbins_monro(schedule)
print(result.condition_1_satisfied)  # True: Σ η_t = ∞
print(result.condition_2_satisfied)  # True: Σ η_t² < ∞

verify_robbins_monro() checks the two learning-rate series for known schedule types. A positive min_lr floor fails square summability. These checks do not establish convergence for a changing, clipped calibration problem.

.converged reports whether current squared moment loss is at most 1e-6 after convergence_window observations; later data can reset it. For a different loss threshold, call .check_convergence(tolerance=...). Batch IPF instead checks the maximum absolute margin error against its tolerance. A stalled or infeasible fit does not count as converged.

Unsupported numerical regret/loss-bound helpers have been removed. The learning rate helper is now suggest_mwu_learning_rate, explicitly an empirical tuning heuristic.

Diagnostics

from onlinerake import check_target_feasibility, compute_design_effect

# Screen for missing support; this does not prove joint feasibility
feasibility = check_target_feasibility(raker)
print(f"Passes support screen: {feasibility.is_feasible}")

# Measure weighting efficiency
deff = compute_design_effect(raker)
print(f"Design effect: {deff:.2f}")

Batch Comparison

Compare streaming results against traditional IPF:

from onlinerake import BatchIPF

batch_raker = BatchIPF(targets)
batch_raker.fit(survey_stream)

print(f"Online loss: {raker.loss:.6f}")
print(f"Batch loss: {batch_raker.loss:.6f}")

API Reference

Core Classes

Targets(**features) - Define population margins

  • Binary features: female=0.51 (proportion = 1)
  • Continuous features: age=(42.0, "mean") (target mean)

OnlineRakingSGD(targets, learning_rate=5.0) - SGD-based streaming raker

  • .partial_fit(obs) - Process one observation
  • .margins - Current weighted margins (dict)
  • .loss - Current squared-error loss
  • .weights - Copy of the active weight array
  • .effective_sample_size - ESS accounting for weight variation
  • .converged - Whether loss is below tolerance

OnlineRakingMWU(targets, learning_rate=1.0) - Multiplicative weights raker

  • Same API as OnlineRakingSGD

Key Parameters

Parameter Default Description
learning_rate 5.0 (SGD), 1.0 (MWU) Step size for updates
min_weight 0.001 Minimum allowed weight
max_weight 100.0 Maximum allowed weight
n_sgd_steps 3 Gradient steps per observation
convergence_window 20 Minimum observations before reporting convergence

Upgrading from 2.0.0

See the 3.0.0 upgrade notes for removed bound helpers, the renamed learning-rate heuristic, changed decay floors, and corrected convergence reporting.

Installation

pip install onlinerake

Development install:

git clone https://github.com/finite-sample/onlinerake.git
cd onlinerake
uv sync --all-groups

Testing

pytest tests/ -v

Examples

See examples/ for complete worked examples:

  • streaming_mwu.py - Online multiplicative weighting, drift, and the ESS tradeoff
  • real_survey_example.py - Basic survey weighting
  • ab_test_calibration.py - Balancing treatment/control groups
  • ad_targeting_calibration.py - Real-time ad delivery calibration
  • recommendation_balancing.py - Content recommendation fairness

Interactive notebooks in docs/notebooks/:

  • 01_getting_started.ipynb - Visual introduction
  • 02_performance_comparison.ipynb - Algorithm benchmarking
  • 03_advanced_diagnostics.ipynb - Convergence and diagnostics

Citation

If you use this package in research, please cite:

@software{onlinerake,
  author = {Sood, Gaurav},
  title = {onlinerake: Streaming Survey Raking},
  url = {https://github.com/finite-sample/onlinerake},
  year = {2026}
}

License

MIT

Implementation audit

See the software audit for reproduced defects, regression checks, and the relationship to the retired adaptive-eb prototype. The historical manuscript in ms/ describes an update that changes only the newest row and reports O(Kp) cost; it is not documentation of this implementation and its performance and convergence claims should not be used for this package.

Metadata

Release files for onlinerake 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for onlinerake 3.0.0
File Size Uploaded
onlinerake-3.0.0.tar.gz 70.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for onlinerake 3.0.0
File Interpreter ABI Platform
onlinerake-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 147.5 kB

Release files / onlinerake-3.0.0.tar.gz

Download URL onlinerake-3.0.0.tar.gz
Size 70.2 kB
Tags Source
SHA-256 checksum
How to use checksums
5a717ba4add91f91237676994e7c1f7230fb5998cae7bcd216eaf081fb7a5d92
BLAKE2b-256 checksum
How to use checksums
15392f6f0d098ccb7e8c3f4a9abe24deb155fa1ab7355cd37d216ac6f7a48ce7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release files / onlinerake-3.0.0-py3-none-any.whl

Download URL onlinerake-3.0.0-py3-none-any.whl
Size 77.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0555aebc589971508c54f4b942266a01148800918d62ab9023cfba267c7025c6
BLAKE2b-256 checksum
How to use checksums
39b40073e97879d847a7729da56e0c79f250d5ab958364b9df1bf613509d3ba6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release history Release notifications | RSS feed

3.2.0

2 release files

3.1.0

2 release files

This release

3.0.0 This release

2 release files

2.0.0

2 release files

1.0.0

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page