Skip to content

exploring bayesian blp heterskedastic normal#2524

Open
NathanielF wants to merge 22 commits into
mainfrom
bayesian_blp
Open

exploring bayesian blp heterskedastic normal#2524
NathanielF wants to merge 22 commits into
mainfrom
bayesian_blp

Conversation

@NathanielF
Copy link
Copy Markdown
Contributor

@NathanielF NathanielF commented Apr 28, 2026

Description

Experimental Bayesian BLP - DO NOT MERGE YET. Awaiting @cluhmann 's review.

Bayesian BLP: structural demand on aggregate market-share panels

What this adds

A new BayesianBLP class in pymc_marketing.customer_choice for fitting structural random-coefficients logit demand on aggregate market-share data. Implements the joint-posterior reformulation of Berry, Levinsohn & Pakes (1995) following Jiang, Manchanda & Rossi (2009, QME) and Yang, Chen & Allenby (2003). Fit happens via NUTS over preference parameters and the latent product–market shocks $\xi_{jm}$ jointly, with the Berry (1994) heteroskedastic-Normal log-share-ratio likelihood.

Features

  • Random coefficients across arbitrary $D \geq 1$ taste dimensions (price + characteristics), diagonal only.
  • IV correction for price endogeneity via the conditional decomposition of $(\eta, \tilde\xi)$, reparameterised on $(\gamma, \omega) = (\rho\sigma_\xi, \sigma_\xi\sqrt{1-\rho^2})$ to break the multiplicative ridge that pins NUTS at the tree-depth cap when sampling $(\rho, \sigma_\xi)$ directly.
  • Hierarchical pooling across regions with centered or non-centered parameterisation.
  • Time-aware coordinates: pass time_col and counterfactual_shares / elasticities accept periods= / regions= filters.
  • Posterior elasticities and counterfactual shares with full uncertainty.
  • Memory-bounded batch_shares (2 GiB cap with automatic sample-axis chunking + warning).

New submodule: taste_profiles

Public namespace exposing four posterior-summary lenses that exploit the Bayesian structure to characterise who buys in each market — analyses the classical BLP estimator can't produce because it has no posterior over $\xi$:

Function What it returns
buyer_nu_posterior $(S, M, D)$ posterior of average buyer taste vector per market
brand_buyer_nu $(M, J)$ brand-level buyer profile along chosen taste dimension
demand_concentration_gini $(S, M)$ Gini of inside-good demand across consumer types
taste_type_demand_share bucketed sensitive / modal / insensitive shares

Plus four convenience plotters (stacked area, market × dimension heatmap, brand × market heatmap, Gini-vs-price scatter) that return matplotlib Figures with layout="constrained".

Demo notebooks

  • bayesian_blp.ipynb (synthetic, 61 cells, sections 1–10). Methodology walkthrough on a panel with known truth: aggregate-data motivation, Halton quadrature, share integral, Berry log-share-ratio likelihood, model construction, parameter recovery, IV vs no-IV bias comparison, posterior elasticities, time-targeted counterfactuals, hierarchical pooling, multi-dim taste profiles.
  • bayesian_blp_nevo.ipynb (34 cells, sections 1–8). Applies the same model to Nevo's (2000) cereal panel and validates the literature own-price elasticity range $[-2, -4]$.

Both registered in the example gallery with auto-generated thumbnails. MixedLogit now exported from pymc_marketing.customer_choice.

API design highlights

  • BayesianBLP.iterate_posterior_samples and BayesianBLP.batch_shares are public methods (not underscore-prefixed) — promoted so the taste_profiles adapter sits on a stable public boundary.
  • save / load raise NotImplementedError with a clear message rather than ship a placeholder round-trip that mis-serialises market_data. Tracked for v2.
  • Pre-condition guards (RuntimeError("Model has no posterior; call .fit(...) before <name>().")) are consistent across every public function that needs a fitted model.

Tests

109 tests across three files, all in the default pytest suite:

  • test_bayesian_blp.py — 72 tests covering build, validation, prior predictive, fit, counterfactual, elasticities, time-aware behaviour, hierarchical parameterisation, numerical stability under extreme parameters, batch_shares chunking, save/load NotImplementedError.
  • test_taste_profiles.py — 35 tests across validation, compute shapes, math correctness (Gini limits), multi-dim path, and plotter return types.
  • test_taste_profiles_integration.py — 2 papermill-based integration tests (success-path + error-propagation guard) following the project's scripts/run_notebooks/runner.py house style with mocked pm.sample. Runs in ~13s under the default suite.

Useful reference video lecture on the frequentist BLP model.

https://youtu.be/koSUtDemjMo?is=8J0TFciBo_-oDqtS

Related Issue

Checklist


📚 Documentation preview 📚: https://pymc-marketing--2524.org.readthedocs.build/en/2524/

Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@github-actions github-actions Bot added docs Improvements or additions to documentation tests customer choice Related to customer choice module labels Apr 28, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

❌ Patch coverage is 97.26368% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.14%. Comparing base (a2d8c1d) to head (d9e7b0f).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pymc_marketing/customer_choice/bayesian_blp.py 96.57% 18 Missing ⚠️
pymc_marketing/customer_choice/_choice_helpers.py 91.30% 2 Missing ⚠️
pymc_marketing/customer_choice/taste_profiles.py 98.80% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2524      +/-   ##
==========================================
+ Coverage   93.96%   94.14%   +0.17%     
==========================================
  Files          95       98       +3     
  Lines       14371    15172     +801     
==========================================
+ Hits        13504    14283     +779     
- Misses        867      889      +22     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
@NathanielF NathanielF marked this pull request as ready for review May 4, 2026 10:08
@NathanielF NathanielF requested a review from cluhmann May 4, 2026 10:10
NathanielF added 10 commits May 25, 2026 21:24
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
@NathanielF NathanielF requested review from juanitorduz, ricardoV94 and timbo112711 and removed request for ricardoV94 May 27, 2026 05:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

customer choice Related to customer choice module docs Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant