chore: group all actions/* updates with 7-day cooldown - #2755
Merged
Conversation
juanitorduz
approved these changes
Jul 27, 2026
ColtAllen
pushed a commit
to ColtAllen/pymc-marketing
that referenced
this pull request
Jul 28, 2026
* Add v1.0.0 branch to CI triggers (pymc-labs#2610) * Add v1.0.0 branch to CI triggers (pymc-labs#2618) * Add v1.0.0 to codecov branch tracking * chore: Update UML Diagrams (pymc-labs#2608) Co-authored-by: williambdean <57733339+williambdean@users.noreply.github.com> * chore(triage): add no releasenotes label to triage agent (pymc-labs#2618) The triage agent now recognizes the 'no releasenotes' label for issues about internal/process-only changes (CI/CD, test infrastructure, automation, version bumps, agent config) that should be excluded from release notes. Key guardrails: - Never applied alongside package-affecting labels (bug, enhancement, docs, API, MMM, CLV) - Includes a gh pr list reference command for uncertain cases * Use tmp_path for CLV save-load tests (pymc-labs#2617) * [pre-commit.ci] pre-commit autoupdate (pymc-labs#2620) updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.15 → v0.15.16](astral-sh/ruff-pre-commit@v0.15.15...v0.15.16) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * chore: update test durations (pymc-labs#2619) Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> Co-authored-by: Juan Orduz <juanitorduz@gmail.com> * Chore(deps): Bump codecov/codecov-action from 6 to 7 (pymc-labs#2622) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 6 to 7. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](codecov/codecov-action@v6...v7) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * dependencies pin (pymc-labs#2623) * exploring bayesian blp heterskedastic normal (pymc-labs#2524) * exploring bayesian blp heterskedastic normal Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * updating bayesian blp with nevo example Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update nevo notebook Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update blp nevo notebook Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * tidying plots Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * tidying BLP notebook. Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * tidying the nevo example Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update nevo notebook Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update to add the nevo data csv Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * adding defensive coding Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * removing the diagnostic code Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update improving test coverage and adding gallery images Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update blp code Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * adding random effects on other features Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * tidying taste profiles code Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update adding an integration test Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * add more tests Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * add model graphs and likelihood explanation Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * uncomment slow tests Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * add variable table for BLP Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * update table formating in docstrings Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * Guard taste-profile functions against missing taste dimensions taste_type_demand_share and plot_taste_profile_stacked hardcoded halton[:, 0] as the price taste shock, silently mislabeling results for models built without 'price' in random_coef_on; they now look up the price dimension and raise a ValueError pointing at the fix. Models with random_coef_on=[] crashed downstream with an opaque einsum shape error; all taste-profile entry points now raise a clear RuntimeError explaining there is no heterogeneity dimension to profile. * Reject market_size_col=None instead of building a degenerate likelihood The None fallback set n to zeros, which makes the log-share-ratio likelihood's variance (1/(n*s)) infinite — the model built but could never be sampled. The 'normal_logshare' likelihood has no meaning without a per-market sample size, so refuse None at construction with a message explaining why. * Use the delta-method variance of the log share ratio in the likelihood The likelihood previously used (1 - s_j)/(n s_j) — the delta-method variance of log(s_j) alone. The observed quantity is the difference log(s_j) - log(s_0), whose multinomial-sampling variance is 1/(n s_j) + 1/(n s_0): the outside good's sampling noise enters too, and it is the same order as the inside term whenever s_0 is not large, so dropping it understated the measurement noise. The within-market covariance across products (shared outside share) remains ignored; this is now documented at the likelihood definition. A regression test pins the per-cell logp against a hand-computed Normal with the correct variance. * Re-execute the synthetic BLP notebook under the corrected likelihood Source fixes folded into this run: the likelihood derivation now states the delta-method variance of the log share *ratio* (including the outside-good term), the time-targeted counterfactual applies the same 10% hike as the full-panel comparison (the previous 20% contradicted the "matches the full-panel counterfactual" claim and its own printed output), and the summary no longer hardcodes a stale bias figure. All outputs regenerated against the new variance: zero divergences in both fits, parameter recovery intact, and the window invariants now print exactly 0.0. * Re-execute the Nevo notebook under the corrected likelihood Outputs regenerated with the delta-method log-share-ratio variance: zero divergences, all R-hats at 1.00, own-price elasticities in [-2.98, -2.44] (textbook cereal band), IV-vs-no-IV bias direction preserved, and the time-targeted counterfactual exactly zero outside the shocked quarter. Also fix two stale markdown passages: the diagnostics guidance now matches the actual 4-chain x 2000-draw fit and explains the wide beta_pop[mushy] interval via collinearity between time-invariant characteristics and the brand fixed effects (rather than a low-ESS claim the table no longer supports), and the caveats section now states the fit uses random coefficients on price, sugar, and mushy rather than price only. --------- Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> * fix(deps): upper bound matplotlib <3.11 (pymc-labs#2626) * chore: update test durations (pymc-labs#2631) Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> * [pre-commit.ci] pre-commit autoupdate (pymc-labs#2634) updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.16 → v0.15.17](astral-sh/ruff-pre-commit@v0.15.16...v0.15.17) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * chore: update test durations (pymc-labs#2636) Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> * docs: lead landing page with credibility signals and a production-focused CTA (pymc-labs#2635) * docs: lead landing page with credibility and a production-focused CTA Restructures the docs landing page so the highest-intent visitors hit trust signals and a clear next step before the feature inventory: - Adds a 'Trusted in production' section directly after the intro with named adopters (Bolt, HelloFresh) and a concrete, publicly-documented proof point (HelloFresh: 20min -> 2min inference, 60% variance reduction), plus download/stars/license signals. - Surfaces a single outcome-framed primary CTA near the top instead of only at the very bottom of the page. - Adds GitHub stars and license badges alongside the download badges. Rationale: a synthetic-audience test of MMM/CLV practitioners on the landing page showed strong problem recognition followed by 'is this mature / who is behind it?' skepticism, with the call-to-action too diffuse and buried. This leads with the maturity and credibility signals that resolve that doubt. * docs: address review — soften credibility copy, de-dup proof points Reword the 'research prototype' line to drop the defensive framing, and remove the Bolt/HelloFresh proof points and Calendly CTA from the top section since they already appear at the bottom (Resources/Case Studies and the Need help CTA). Keeps a light credibility signal up top without repeating the promotional material twice on the page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: root <root@e2b.local> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Juan Orduz <juanitorduz@gmail.com> * [pre-commit.ci] pre-commit autoupdate (pymc-labs#2641) updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.17 → v0.15.18](astral-sh/ruff-pre-commit@v0.15.17...v0.15.18) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * Fix flaky test_log_model_graph_no_graphviz by scoping log capture (pymc-labs#2644) The test asserted strict equality on caplog.messages while capturing INFO records from the root logger. caplog's handler is attached to the root logger, so it also captures unrelated third-party logs. When this test was the first in a shard to touch the MLflow SQLite backend store, MLflow emitted an INFO record ("Creating initial MLflow database tables...") that landed in the capture, making the assertion order-dependent and failing CI non-deterministically (consistently in test shard 1). Two changes: - pymc_marketing/mlflow.py: log via a module-level logger (logging.getLogger(__name__)) instead of the root logger. Libraries should not log to the root logger; this gives callers a named, configurable logger. - tests/test_mlflow.py: scope the capture to the pymc_marketing.mlflow logger and filter caplog.records by logger name, so the assertion only inspects messages our own code emits and is robust to third-party log noise regardless of test order. Co-authored-by: daimon-pymclabs <noreply@anthropic.com> * Chore(deps): Bump actions/checkout from 6 to 7 (pymc-labs#2643) Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Juan Orduz <juanitorduz@gmail.com> * chore: Update UML Diagrams (pymc-labs#2633) Co-authored-by: williambdean <57733339+williambdean@users.noreply.github.com> Co-authored-by: Juan Orduz <juanitorduz@gmail.com> * fix(mmm): keep RootSaturation gradient finite at zero spend (pymc-labs#2640) * fix(mmm): keep RootSaturation gradient finite at zero spend `root_saturation(x, alpha) = x**alpha` has derivative `d/dx (x**alpha) = alpha * x**(alpha - 1)`, which is infinite at `x == 0` for `alpha < 1`. In an MMM the saturation input is a function of random variables (e.g. adstocked spend) and channels routinely have exact zero-spend periods, so this singularity produces NaN gradients and NUTS fails to initialize (e.g. nutpie "All initialization points failed"). Note this is the gradient w.r.t. the *base*, not the `x**alpha * log(x)` term w.r.t. the exponent — PyTensor already guards the latter with `switch(eq(x, 0), 0, ...)`. Shift the input by a tiny `eps` (default 1e-6) so the gradient stays finite. Inputs are typically scaled to [0, 1], against which eps is negligible. Add a regression test asserting `compile_dlogp` is finite when the saturation input depends on a free RV and has exact zeros. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mmm): use pt.where guard for root_saturation gradient at zero Replace the additive eps shift with a pt.where guard pattern that keeps f(0)=0 exactly and the gradient finite everywhere for x=0. * fix(mmm): use .values to avoid XTensorVariable conversion error in root_saturation --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * [pre-commit.ci] pre-commit autoupdate (pymc-labs#2663) updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.18 → v0.15.20](astral-sh/ruff-pre-commit@v0.15.18...v0.15.20) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * Fix mypy errors on main (pymc-labs#2667) Resolve the 6 mypy failures blocking pre-commit.ci on main: - customer_choice/synthetic_data.py: cast the np.where index array to int so the loop variable and dict keys have a consistent int type (the variable was previously bound to int via an earlier range loop). - mmm/hsgp.py: coerce the scalar operands to float before max()/int() so the function returns the annotated tuple[int, float]. - mmm/lift_test.py: widen the Index alias to also accept np.ndarray, matching np.argmax's return type assigned into indices[col]. Co-authored-by: Daimon <noreply@anthropic.com> * Add merge_group trigger to CI workflows for merge queue support (pymc-labs#2676) (pymc-labs#2678) * refactor(mmm): rename optimize_budget **minimize_kwargs to **allocate_budget_kwargs (pymc-labs#2563) The variadic on BudgetOptimizerWrapper.optimize_budget relays every keyword to BudgetOptimizer.allocate_budget, not only the scipy minimize options, so the previous name was misleading (callers could end up passing minimize_kwargs={...} inside **minimize_kwargs). Closes pymc-labs#1660 Co-authored-by: Juan Orduz <juanitorduz@gmail.com> * ci: add git-ai workflow for authorship attribution (pymc-labs#2746) * Chore(deps): Bump actions/setup-node from 6 to 7 (pymc-labs#2736) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@v6...v7) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Chore(deps): Bump actions/labeler from 6 to 7 (pymc-labs#2753) Bumps [actions/labeler](https://github.com/actions/labeler) from 6 to 7. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](actions/labeler@v6...v7) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: group all actions/* updates with 7-day cooldown (pymc-labs#2755) * Chore(deps): Bump astral-sh/setup-uv from 7 to 8.3.2 (pymc-labs#2756) Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 7 to 8.3.2. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](astral-sh/setup-uv@v7...v8.3.2) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-version: 8.3.2 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Nightt <87569709+nightt5879@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> Co-authored-by: Juan Orduz <juanitorduz@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nathaniel <NathanielF@users.noreply.github.com> Co-authored-by: Pablo Vena <37351096+anevolbap@users.noreply.github.com> Co-authored-by: daimon-pymclabs <daimon@pymc-labs.com> Co-authored-by: root <root@e2b.local> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Alvaro Duran Tovar <hermesdt@gmail.com> Co-authored-by: Pablo de Roque <pablo.deroque@glovoapp.com>
ColtAllen
added a commit
to ColtAllen/pymc-marketing
that referenced
this pull request
Jul 28, 2026
* Add v1.0.0 branch to CI triggers (#2618)
* Bump version to 1.0.0.dev0
* Migrate from conda to uv for development environment (#2611)
* Remove deprecated serialization shims kept for Legacy MMM (#2599)
* rm
* rm test
* Remove TestDeprecatedShimsRemoved and importlib from test_saturation
* Fix broken saturation_from_dict import in test_link.py
---------
Co-authored-by: Will Dean <wd60622@gmail.com>
* fix: pin pymc-extras<0.11.0 and matplotlib<3.11 on v1.0.0 branch (#2629)
* fix: pin pymc-extras<0.11.0 on v1.0.0 branch
Backports the pin from #2623 (main). pymc-extras 0.11.0+ requires
arviz>=1.1, which conflicts with our arviz<1.0.0 pin and breaks the
sdist build job on every PR targeting v1.0.0.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: pin matplotlib<3.11 on v1.0.0 branch
Mirrors #2626 (main). matplotlib 3.11.0 removed the deprecated
matplotlib.style.core shim that arviz-plots 1.1.0 accesses at import
time, so the sdist import check fails with AttributeError.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(budget-optimizer): collapse default_constraints into constraints (#2570)
* refactor(budget-optimizer): collapse default_constraints into constraints
Drop default_constraints and rename custom_constraints to constraints on
BudgetOptimizer. Empty constraints auto-adds the default sum constraint;
non-empty means the caller is in charge. Pass build_default_sum_constraint()
explicitly to keep the default alongside customs.
Old kwargs stay as deprecated aliases that warn and preserve current
behavior for one release. On MMM.optimize_budget, default_constraints is
now bool | None and only triggers the legacy path when explicitly set.
Closes #1416.
* test(budget-optimizer): cover legacy constraint kwargs and MMM legacy path
Add tests for the two uncovered branches of the legacy translation in
BudgetOptimizer._migrate_legacy_constraint_kwargs and for the legacy
forwarding path in MMM.optimize_budget. Also pin the deprecation/removal
versions in the warning message and docstrings to match the project
convention (deprecated in 0.20.0, removed in 0.21.0).
* test(budget-optimizer): cover non-dict pass-through in legacy migrator
* refactor(budget-optimizer): drop noisy default-constraint UserWarning, deprecate set_constraints default kwarg
The "Using default equality constraint" UserWarning fired on the
documented happy path (empty constraints auto-add the default sum),
turning it into noise. Drop it and clean up the 11 test assertion
sites. The new contract is in the docstring instead.
Also: deprecate the `default` kwarg of `set_constraints`, since it is
now redundant under the new contract. Preserve the legacy strict
behaviour for `default_constraints=False` with empty custom_constraints
by raising a ValueError in the migration shim instead of silently
auto-adding the default.
Add tests for: the deprecated `set_constraints(default=...)` kwarg,
the strict-no-constraint edge case, and Constraint round-trip through
the legacy migrator.
* docs(budget-optimizer): note TypeError vs ValueError wrapping, fix type in docstring
Add an inline comment in the migration validator explaining why the
conflict path raises TypeError (re-raised as-is by Pydantic) while the
edge case raises ValueError (wrapped into ValidationError, which is
itself a ValueError so callers are unaffected).
Also fix the docstring type for `default_constraints` on
MMM.optimize_budget from `bool, optional` to `bool or None, optional`
to match the actual annotation.
* Add v1.0.0 branch to CI triggers (#2610)
* Add v1.0.0 branch to CI triggers (#2618)
* Add v1.0.0 to codecov branch tracking
* chore: Update UML Diagrams (#2608)
Co-authored-by: williambdean <57733339+williambdean@users.noreply.github.com>
* refactor(budget-optimizer)!: drop deprecation shim, hard removal of legacy constraint kwargs
Per review on #2570: v1.0 is the next release and carries breaking
changes anyway, so skip the one-release deprecation cycle and remove
the legacy kwargs outright.
- Drop the `_migrate_legacy_constraint_kwargs` model_validator.
- Remove `default_constraints` from `MMM.optimize_budget`.
- Simplify `set_constraints` to `set_constraints(constraints)`, auto-add
the default sum constraint when empty.
- Remove the legacy/deprecation tests; keep the new-API tests and add one
for constraint forwarding through `MMM.optimize_budget`.
BREAKING CHANGE: `custom_constraints` and `default_constraints` are
removed from `BudgetOptimizer` and `MMM.optimize_budget`. Use
`constraints` instead. The public `set_constraints(constraints, default)`
also loses its `default` parameter, becoming `set_constraints(constraints)`.
Empty `constraints` auto-adds the default sum constraint; non-empty means
the caller is in charge, so there is no longer a way to run with zero
constraints (the old `default_constraints=False` + empty case raised
anyway). Append `build_default_sum_constraint()` to keep the default
alongside custom ones.
* chore(triage): add no releasenotes label to triage agent (#2618)
The triage agent now recognizes the 'no releasenotes' label for issues
about internal/process-only changes (CI/CD, test infrastructure,
automation, version bumps, agent config) that should be excluded from
release notes.
Key guardrails:
- Never applied alongside package-affecting labels (bug, enhancement, docs, API, MMM, CLV)
- Includes a gh pr list reference command for uncertain cases
* Use tmp_path for CLV save-load tests (#2617)
* refactor(budget-optimizer): address review on set_constraints
Per cetagostini's review on #2570:
- Annotate `set_constraints(constraints: Sequence[Constraint])`.
- Document the `()` default for `constraints` in `MMM.optimize_budget`.
- Add tests for explicit `constraints=[]`, re-entrant `set_constraints`,
and duplicate-key rejection.
Out of scope for the rename but applied per review: store Constraint
objects directly (drop the redundant per-item copy) and raise on
duplicate constraint keys instead of silently overwriting.
* refactor(budget-optimizer): drop in-code out-of-scope note from set_constraints
* [pre-commit.ci] pre-commit autoupdate (#2620)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.15 → v0.15.16](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.15...v0.15.16)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* chore: update test durations (#2619)
Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* Chore(deps): Bump codecov/codecov-action from 6 to 7 (#2622)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 6 to 7.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v6...v7)
---
updated-dependencies:
- dependency-name: codecov/codecov-action
dependency-version: '7'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Will Dean <57733339+williambdean@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Nightt <87569709+nightt5879@users.noreply.github.com>
Co-authored-by: Carlos Trujillo <59846724+cetagostini@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: migrate to pymc>=6.0.0, arviz>=1.1.0, pytensor>=3.0.0 (#2616)
Migrate from az.InferenceData to xr.DataTree across the entire codebase.
Key changes:
- All az.InferenceData → xr.DataTree type annotations (~44 source files)
- idata.extend() → idata.update(), add_groups() → bracket assignment
- az.plot_* → azp.plot_* (arviz_plots), pm.plot_trace → azp.plot_trace
- DataTree child variable access: .posterior.VAR → .posterior["VAR"] (25 fixes)
- az.hdi(): hdi_prob= → prob=, ci_bounds → ci_bound, "higher" → "upper"
- shifted_beta_geo: restore pm.sample_posterior_predictive() with sample_vars
- Upper pins on all dependencies per review feedback
- 54 notebooks updated for arviz_plots 2.x and DataTree API
- pyproject.toml: pymc-extras git pin (temp until >=0.12.2 on PyPI)
Reviewers: @OriolAbril, @ricardoV94, @juanitorduz, @cetagostini, @daimon-pymclabs
* feat(plot): add n_samples=0 support and list hdi_prob in plot_hdi (#2650)
Original commits by pkaf in PR #2257, adapted to v1.0.0:
- 41714d07 nsamples 0 and hdi loop added
- 45f1d851 nsamples 0 and hdi loop comments addressed
- b7970ae5 nsamples 0 and hdi loop comments addressed
- e016ae66 nsamples 0 and hdi loop added
- 8ce9052b nsamples 0 and hdi loop comments addressed
- d210c4e4 nsamples comments addressed
- 27bfec22 nsamples comments addressed
- f58c9ddb plot_hdi arg corrected to hdi_prob
- 0dcb48f2 hdi_prob parameter fix
- 2b97fe38 subplot_kwargs fixed
- 9bc530a6 type hints error fixed
- d9b9ca3b bug fix
Allow n_samples=0 in plot_curve() to skip individual sample lines
and only plot HDI bands. Allow hdi_prob to accept a list of values
in plot_hdi() for multiple HDI intervals.
Tests added for both new features.
Closes #2225
Co-authored-by: pkaf <kafleprraj@gamil.com>
* chore: add pre-commit hook for notebook watermark validation (#2653)
Add watermark validation pre-commit hook and fix 33 notebooks
* feat(mmm): consolidate data input into unified xr.Dataset representation (#2596)
* Consolidate MMM data input into unified xr.Dataset representation
* Harden data conversion pipeline — DataFrame y support, date coercion, dead param cleanup
* Restore self.X in _generate_and_preprocess_model_data
* Fix mmm_gam_options notebook: replace removed _create_xarray_from_pandas
* Inline melt logic in notebook — no private import needed
* Rename _data_conversion to data_conversion and add coverage tests
* test: add coverage tests for to_mmm_dataset validation errors, MultiIndex, and unsupported types
8 new tests covering previously untested branches in data_conversion.py:
- MultiIndex Series as y (panel data path)
- Validation errors: missing _channel, date, channel, _control, date_column
- Unsupported type errors: list[int] for y, set for X
Coverage in data_conversion.py improves from 83% to 90%.
* chore: remove dead code, fix validate_target guard, add coverage test
- Inline _add_target_to_dataset (one-liner wrapper)
- Remove _validate_dims_in_multiindex, _process_multiindex_series,
pd.Series branches in _pandas_to_xarray_dataarray and _validate_metrics
- Guard validate_target via xarray_dataset to prevent TypeError on y=None
- Add test_fit_with_dataset_embedded_target covering the guard path
* test: add assertions to dataset embedded target test for codecov coverage
* test: add many more assertions to dataset embedded target test for codecov coverage
* Add patch coverage threshold to codecov.yml
* [Notebook Re-Run] MMM Fundamentals 1 (#2657)
* migration init
* rerun
* traceplot
* add titles and legends
* rm plot
* budget allocaton plot
* fine tune plots
* fix labelewr
* Runs and QAs the adstock guide notebook (#2664)
* [Notebook Re-Run] Bass + General Notebooks (#2658)
* [Notebook Re-Run] Bass + General Notebooks
- Bump arviz>=1.2.0, arviz-plots>=1.2.0 for arviz-darkgrid support
- Re-execute bass_example.ipynb with azp.plot_trace_dist
- Re-execute model_configuration.ipynb
- Re-execute other_nuts_samplers.ipynb
- Re-execute prior_predictive.ipynb
- Apply style migration: arviz-vibrant -> arviz-darkgrid
Related to #2614
* Re-execute bass_example with ipywidgets installed (fix warnings)
* Fix plt.subplots + plot_dist pattern for arviz_plots 1.2.0
azp.plot_dist no longer draws on plt.gca() in arviz_plots 1.2.0.
- other_nuts_samplers: replaced plot_dist with seaborn kdeplot on axes
- prior_predictive: use PlotCollection to access figure/axes from plot_dist
* Fix plot_forest axis access: fig.axes[0] -> fig.axes[1]
arviz_plots >=1.2.0 splits plot_forest into two axes:
- axes[0]: labels (variable name text)
- axes[1]: forest plot (credible intervals)
axvline must be drawn on axes[1] to appear on the forest plot.
* Suppress arviz_plots FutureWarning in prior_predictive
Broaden warnings.filterwarnings to ignore all FutureWarnings.
Covers both the MMMPlotSuite deprecation and the xarray join='outer'
deprecation from arviz_plots/plot_collection.py
* fix plot
* fix prior vs posterior
* hide input
---------
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] Time Slice CV (#2666)
* Runs and QAs the time slice cv notebook
* updates to arviz dark theme
* Add merge_group trigger to CI workflows for merge queue support (#2676)
* [Notebook Re-Run] MMM Batch 2 (#2665)
* rerun
* empty
* many axes plot
* add facets to channel contribution
* rm comment
* empty
* smaller image
* spit plot
* Fix MemoryError (std::bad_alloc) in mmm_evaluation notebook CI (#2669)
The "Test Notebooks" job for `mmm --start-idx 10` was failing with
`MemoryError: std::bad_alloc` while rendering the RMSE-distribution plot
in mmm_evaluation.ipynb.
Root cause: under CI the sampler is mocked (pm.sample -> mock_sample), so
the posterior-predictive draws are not meaningful and the resulting RMSE
distribution spans a huge range (up to ~6e6). The cell forced
`ax.set_xlim(0, 500)`, which compresses the data->display scale so that
the KDE line (extending to ~6e6) maps to an enormous physical extent. The
inline backend renders with `bbox_inches="tight"`, and `get_tightbbox`
does not respect axes clipping, so it computed a ~21,640-inch-wide figure
=> ~4.3M x 1.3k pixel Agg renderer => std::bad_alloc.
Fix: drop the hard-coded `ax.set_xlim(0, 500)` and let the axis
autoscale, matching the sibling R-squared cell (which has no xlim and was
always safe). For a real fit the RMSE distribution and both reference
lines sit in a narrow range, so the rendered figure is equivalent; under
the mocked CI sampler the figure now renders at a sane size.
Verified with the exact CI runner:
`uv run python scripts/run_notebooks/runner.py --notebooks docs/source/notebooks/mmm/mmm_evaluation.ipynb`
-> "Notebooks run successfully!"
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: daimon-pymclabs <daimon@pymc-labs.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: preserve metadata attrs on sample_prior/sample_posterior_predictive return values (#2675)
Pass keep_dataset=True to az.extract in both sample_prior_predictive and
sample_posterior_predictive to prevent xarray's Dataset.__getitem__ from
stripping group-level attrs when converting single-variable groups to DataArrays.
This restores metadata (created_at, inference_library, pymc_marketing_version, etc.)
on the returned Dataset, which was lost after the PyMC 6 / DataTree migration.
* [Notebook Re-Run] TVP Baseline (#2683)
* re-runs notebook and updates plot annotations
* adds deepcopy to sampler_config
* feat(mlflow): resolve `_log__` parameters in create_log_callback (#2594)
* feat(mlflow): resolve `_log__` parameters in create_log_callback
`create_log_callback` previously required users to pass the sampler-level
name of a variable (e.g. `sigma_log__` for a `HalfNormal`). Pass the
model-level name (`sigma`) and the callback now resolves it from
`draw.point` keys on the first draw. Existing callers passing the
transformed name still work because exact matches take priority.
The transform suffix list starts with `_log__` only per #1615. A comment
on `_TRANSFORM_SUFFIXES` documents the extension path for `_logodds__`,
`_interval__`, `_ordered__`, `_simplex__`, and others.
Closes #1615
* docs(mlflow): document `_TRANSFORM_SUFFIXES` extension caveats
Two notes for future contributors: only scalar-valued transforms are safe
to append because `mlflow.log_metric` is scalar-only, and custom user
transforms are out of scope because their `name` is unknown at module
load time.
* docs(mlflow): note scalar-only constraint on log_metric call
* fix(clv): restore (chain, draw) dims on ShiftedBetaGeo new-customer distributions (#2684)
* fix(clv): restore (chain, draw) dims on ShiftedBetaGeo new-customer distributions
The pymc 6 migration (#2616) added an explicit stack(sample=("chain","draw")).reset_index("sample") at the end of ShiftedBetaGeoModelIndividual._distribution_new_customer, flattening the output of distribution_new_customer_theta and distribution_new_customer_churn_time to a single sample dim. On pymc 6 the raw posterior_predictive dataset already carries (chain, draw), so the stack was the only thing collapsing it, a silent breaking change against the pre-migration public API and inconsistent with distribution_customer_churn_time and the other CLV models.
Return the dataset directly and revert the test assertions to (chain, draw), plus a dims check so a future regression is caught in CI.
Fixes #2651
* fix(clv): update sBG_individual notebook to (chain, draw) after dim restore
* refactor(clv): drop _prior suffix backwards-compat shim (#2576)
Remove the model_config rename loop in CLVModel.__init__ and the
_rename_posterior_variables hook in build_from_idata, plus the matching
tests. This was added in #1498 as a v1.0 deprecation and is one of the
items flagged for removal in #1516.
Also rename the _prior-suffixed keys in BetaGeoModel and ModifiedBetaGeoModel
covariate convergence tests, and in the bg_nbg_covariates_test_issues dev
notebook, which previously relied on the shim.
Refs #1516
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
* [Notebook Re-Run] clv_quickstart (#2687)
* docs(clv): re-run clv_quickstart notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): fix overlapping titles in clv_quickstart plots
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
* [Notebook Re-Run] bg_nbd (#2688)
* docs(clv): re-run bg_nbd notebook on v1.0.0, fix plot_dist parameter grid
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): fix plot layout issues in bg_nbd notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
* docs(clv): re-run mbg_nbd notebook on v1.0.0, fix plot_dist parameter grid (#2689)
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
* [Notebook Re-Run] pareto_nbd (#2691)
* docs(clv): re-run pareto_nbd notebook on v1.0.0, fix plot_dist grids
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): fix plot layout issues in pareto_nbd notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
* [Notebook Re-Run] gamma_gamma (#2692)
* docs(clv): re-run gamma_gamma notebook on v1.0.0, fix plot_dist cells
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): fix plot layout issues in gamma_gamma notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
* [Notebook Re-Run] MMM Batch 3 (#2672)
* [Notebook Re-Run] Migrate MMM notebooks to ArviZ 1.x plot suite
Migrate four MMM docs notebooks to ArviZ 1.x and the new namespace-based
plot suite, and re-run them end-to-end:
- Switch the global style to `arviz-darkgrid`.
- Opt in to `mmm.plot_suite = "new"` and move legacy `mmm.plot.*` calls to
the new namespaces (`transformation.saturation_scatterplot`,
`sensitivity.analysis`, `decomposition.channel_share_hdi`).
- Fix `arviz_plots` return handling (`plot_forest`/`plot_trace` now return a
`PlotCollection`; extract the figure before annotating).
- When aggregating a sensitivity sweep over `geo`, pass `cols=[]` so faceting
no longer requires the aggregated-away dimension.
- Add titles/legends to plots that were missing them.
Affected notebooks: mmm_media_saturation, mmm_multiplicative,
plot_interactive, mmm_gam_options.
* update
* correct some plots
* update
* [Notebook Re-Run] mmm_fivetran_connectors (#2714)
* docs(mmm): re-run mmm_fivetran_connectors notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): arviz-darkgrid style and printed docstrings in mmm_fivetran_connectors
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_multi_objective_optimization (#2713)
* docs(mmm): re-run mmm_multi_objective_optimization notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_multi_objective_optimization notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): arviz-darkgrid style and printed docstrings in mmm_multi_objective_optimization
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_allocation_assessment (#2712)
* docs(mmm): re-run mmm_allocation_assessment on v1.0.0, drop budget_allocation plot
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_allocation_assessment notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): arviz-darkgrid style and printed docstring in mmm_allocation_assessment
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_migration_guide (#2703)
* docs(mmm): re-run mmm_migration_guide notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): switch mmm_migration_guide notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* docs(clv): switch gamma_gamma notebook to arviz-darkgrid style (#2721)
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): switch mbg_nbd notebook to arviz-darkgrid style (#2720)
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): switch bg_nbd notebook to arviz-darkgrid style (#2719)
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): switch pareto_nbd notebook to arviz-darkgrid style (#2718)
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): switch clv_quickstart notebook to arviz-darkgrid style (#2717)
Co-authored-by: Cursor <cursoragent@cursor.com>
* [Notebook Re-Run] mmm_causal_reasoning_and_discovery (#2710)
* docs(mmm): re-run mmm_causal_reasoning_and_discovery notebook on v1.0.0, fix plot_dist grid
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_causal_reasoning_and_discovery notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): switch mmm_causal_reasoning_and_discovery notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_upper_funnel_causal_approach (#2709)
* docs(mmm): re-run mmm_upper_funnel_causal_approach notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_upper_funnel_causal_approach notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): switch mmm_upper_funnel_causal_approach notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_intro_upper_funnel (#2708)
* docs(mmm): re-run mmm_intro_upper_funnel notebook on v1.0.0, fix plot_dist axes
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_intro_upper_funnel notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): switch mmm_intro_upper_funnel notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_counterfactuals (#2707)
* docs(mmm): re-run mmm_counterfactuals notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_counterfactuals notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): switch mmm_counterfactuals notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* docs(mmm): re-run mmm_plot_suite_migration_guide notebook on v1.0.0 (#2705)
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_time_varying_media_example (#2702)
* docs(mmm): re-run mmm_time_varying_media_example notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_time_varying_media_example notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): switch mmm_time_varying_media_example notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mv_its_saturated (#2695)
* docs(customer_choice): re-run mv_its_saturated notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): switch mv_its_saturated notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mv_its_unsaturated (#2696)
* docs(customer_choice): re-run mv_its_unsaturated notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): fix plot layout issues in mv_its_unsaturated notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): switch mv_its_unsaturated notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mnl_logit (#2697)
* docs(customer_choice): re-run mnl_logit notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): switch mnl_logit notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] nested_logit (#2698)
* docs(customer_choice): re-run nested_logit notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): fix plot layout issues in nested_logit notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): switch nested_logit notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] sbg (#2693)
* docs(clv): re-run sbg notebook on v1.0.0, fix faceted plot_dist cells
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): fix plot layout issues in sbg notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): switch sbg notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] sBG_individual (#2694)
* docs(clv): re-run sBG_individual notebook on v1.0.0, overlay Figure 6 distributions
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): fix plot layout issues in sBG_individual notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(clv): switch sBG_individual notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_causal_identification (#2706)
* docs(mmm): re-run mmm_causal_identification notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): switch mmm_causal_identification notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* feat(model_builder): warn on unused model_config keys (#2632)
Closes #1256. When a user passes a model_config key that is not part of
default_model_config (e.g. a typo like "alphaa"), it was silently
merged in and ignored by the model. Emit a UserWarning listing the
unused keys and the valid ones so mistakes are visible.
Caches default_model_config in a local to avoid evaluating the property
twice, and adds tests for the warning and the no-warning paths.
* [Notebook Re-Run] consideration_set_logit (#2700)
* docs(customer_choice): re-run consideration_set_logit notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): switch consideration_set_logit notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* [Notebook Re-Run] mixed_logit (#2699)
* docs(customer_choice): re-run mixed_logit notebook on v1.0.0, fix string means from az.summary
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): fix plot layout issues in mixed_logit notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): switch mixed_logit notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Nathaniel <NathanielF@users.noreply.github.com>
* [Notebook Re-Run] maxdiff (#2701)
* docs(customer_choice): re-run maxdiff notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): fix plot layout issues in maxdiff notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(customer_choice): switch maxdiff notebook to arviz-darkgrid style
Co-authored-by: Cursor <cursoragent@cursor.com>
* Update notebook and fix optimisation error message
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
---------
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Nathaniel <NathanielF@users.noreply.github.com>
* feat(mlflow): autolog support for BassModel (#2624)
* feat(mlflow): autolog support for BassModel
* fix(mlflow): keep autolog running when model graph creation fails
* docs(mlflow): fix log_bass_configuration docstring and Bass examples
* test(mlflow): force pymc sampler for bass autolog metrics on v1
Under pymc6 the default sampler (nutpie) does not log sampling_time /
time_per_draw, so the strict metrics assertion in test_autolog_bass fails.
Force nuts_sampler=pymc, matching the v1 MMM/CLV autolog tests.
* Pin blackjax<1.6 to fix NUTS sampler test (#2730)
* Pin blackjax<1.6 to fix blackjax NUTS sampler test
blackjax 1.6 (released 2026-07-10) changed window_adaptation to forward
unknown kwargs to the sampling kernel, which now rejects the progress_bar
argument pymc's JAX sampler passes in (pymc/sampling/jax.py). This breaks
test_autolog_pymc_model[blackjax] with:
TypeError: build_kernel.<locals>.kernel() got an unexpected keyword
argument 'progress_bar'
Cap blackjax<1.6 until the upstream pymc fix lands.
* Update uv.lock for blackjax<1.6 pin
* Remove support for pre-v1.0.0 CLV API (#2723)
* remove t_unobserved plotting param
* remove pnbd fit_method param
* remove fit_method param
* remove data param from CLVModel
* WIP remove data param from all models
* remove data param from all models
* add uv.lock file to gitignore
* remove old API idata_to_init_kwargs
* CLVModel fit logic
* PPC plotting logic for unfit models
* BetaGeoModel build_model logic
* ParetoNBDModel build_model logic and tests
* BGBB and GGM build_model_logic
* GGM tests, MBG logic, build_model docstrings
* mbg tests update
* sBG build logic and unit test updates
* update API in bg_nbd and nuts_samplers notebooks
* re-add uv lock for CI runs
* API updates for CLV notebooks
* remove deprecated test
* sbg notebook API updates
* remove fit_method param from mlflow.py
* update runslow bg and mbg tests
* fix sbg notebook value error
* remove default data arg in mlflow patch_clv_fit
* rerun all edited notebooks
* CLV Quickstart improvements
* change default ggm priors to Weibull
* update unit tests
* rerun ggm notebook
* rerun ggm and quickstart nbs with new ggm priors
---------
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* mb skip key logic and CLV overrides (#2729)
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* Fix `xarray` combine_by_coords FutureWarning (#2728)
* unit test compat=override all CLV models
* pytest filterwarning refactor
* rerun sbg notebook to clear warnings
* pytest futurewarning regression testing
* remove `ShiftedBetaGeoModelIndividual` (#2734)
* remove sbg-individual and notebook
* remove obsolete cv dev nbs
* update dev notebooks for v1.0.0
* future warning emit
* [Notebook Re-Run] mmm_sensitivity_analysis (migrate to v1.0.0 plot namespace) (#2661)
* docs(mmm): re-run & migrate mmm_sensitivity_analysis to the v1.0.0 plot namespace
Part of #2614. Migrates docs/source/notebooks/mmm/mmm_sensitivity_analysis.ipynb
to pymc>=6 / arviz>=1 and the new namespace-based MMMPlotSuite v2.
- Opt in via `mmm.plot_suite = "new"`; import `from pymc_marketing.mmm import MMM`
- `mmm.plot.sensitivity_analysis/uplift_curve/marginal_curve` ->
`mmm.plot.sensitivity.analysis/uplift/marginal`
- New API has no `xlabel`/`ylabel`/`subplot_kwargs`: capture `(fig, axes)` and set
labels on the returned axes; `subplot_kwargs={"figsize":...}` -> `figsize=...`
- `aggregation` tuples -> lists to match the tightened type
- Control-level cell: pass `cols=["control"]` so the new suite facets per-control
(the new default overlays controls on a shared axis) — restores readable panels
- Dropped a spurious channel-aggregation on the single-control cell that the new
API correctly rejects (legacy silently ignored it)
Notebook re-runs clean end-to-end on v1.0.0: 0 errors, 0 FutureWarnings.
Theme left as `arviz-vibrant` (arviz-darkgrid needs arviz-plots>=1.2; the v1.0.0
pin resolves arviz-plots 1.1.0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Apply pre-commit auto-fixes (ruff, end-of-file-fixer)
* Use arviz-darkgrid theme to match Juan's notebook migrations
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Use arviz-vibrant style and re-run notebook
arviz-darkgrid does not exist in the v1.0.0 arviz-plots namespace
(resolves arviz-plots 1.1.0, whose styles are cetrino/tenui/tumma/
variat/vibrant), so it raised ValueError at runtime. Switch to
arviz-vibrant to match Juan's other v1.0.0 notebook migrations and
re-run the notebook end-to-end (papermill, 0 errors).
* Restore arviz-darkgrid and re-run notebook
arviz-darkgrid is the correct style (matches Juan's #2657 migration and
William's request). It resolves under arviz-plots 1.2.0, which this
branch's uv.lock pins. Re-ran the notebook end-to-end (papermill, 0
errors) against arviz 1.2.0. Reverts the erroneous switch to
arviz-vibrant in 5e84d49, which was caused by testing against a stale
arviz-plots 1.1.0 venv.
* fix ax
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: daimon-pymclabs <noreply@pymc-labs.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
Co-authored-by: Will Dean <57733339+williambdean@users.noreply.github.com>
* [Notebook Re-Run] MMM Custom models (#2662)
* init
* add true values
* rerun
* update case study
* correct plot
* typo
* ci: add git-ai workflow for authorship attribution (#2747)
* fix(clv): normalize dates before period bounds (#2745)
Signed-off-by: Floze <88098863+floze-the-genius@users.noreply.github.com>
Co-authored-by: Colt Allen <10178857+ColtAllen@users.noreply.github.com>
* Add PIE notebook (#2743)
* Add PIE notebook
* Fix CI/CD for variable importance
* Migrate PIE notebook to pymc 6 / arviz 1; exclude from mock notebook CI
* Respond to PR comments
---------
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [Notebook Re-Run] mmm_dims_migration_guide (#2704)
* docs(mmm): re-run mmm_dims_migration_guide notebook on v1.0.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): use arviz-darkgrid style in mmm_dims_migration_guide
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): strip ipywidgets state so plots render in mmm_dims_migration_guide
The re-run committed fresh ipywidgets progress-bar outputs (from
sample_prior) together with resolvable widget state in metadata.widgets.
In cells 14 and 18 the plot PNG sits after that widget output in the
same cell, so ReviewNB takes the interactive-widget rendering path and
never displays the plot ('some plots are not displayed'). Re-executed
the full notebook, then removed the two widget-view placeholder outputs
and metadata.widgets; the image/png outputs and all other outputs are
preserved and the notebook validates with nbformat.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* [Notebook Re-Run] mmm_budget_allocation_example (#2711)
* docs(mmm): re-run mmm_budget_allocation_example on v1.0.0, drop budget_allocation plot
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix plot layout issues in mmm_budget_allocation_example notebook
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): arviz-darkgrid style and printed docstrings in mmm_budget_allocation_example
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(mmm): fix silently-dropped target-response constraint in mmm_budget_allocation_example
The v1.0 BudgetOptimizer removed the custom_constraints /
default_constraints kwargs in favor of a single `constraints` field
(#2570). The notebook still passed the old kwargs, and pydantic silently
ignores unknown init kwargs, so the optimizer ran with the auto-added
default sum(budgets) == total_budget (2000) constraint instead of the
target-response constraint. With per-cell lower bounds of 500 x 4 cells,
the only feasible point was [500, 500, 500, 500], which SLSQP reported
as "success" after 2 iterations (degenerate multiplier -3.5e11). That is
what moved the green "Minimizing" curve in the two comparison plots
flagged in review: response ~132K instead of ~155.7K, and ROAS ~66
instead of ~29.
Fixes:
- Pass the target-response Constraint via `constraints=[...]` (a
non-empty list adds no default sum constraint, matching the old
`default_constraints=False` + `custom_constraints` semantics). The
optimizer now reproduces the original result exactly: allocation
[1410.76, 1247.28, 1429.60, 1254.87], total budget 5342.52, active
constraint (multiplier +0.42), plotted response 155,694.
- Restore the "Response N" values in the legend labels of the four
comparison plots (146,617 / 151,566 / 155,694 / 126,699, and
37 / 38 / 29 on the response-per-spend scale), matching the
pre-migration outputs so results can be compared at a glance.
- Disable point_estimate/credible_interval markers on the overlaid
plot_dist calls to match the original clean KDE look.
- Fix "Intial" -> "Initial" typo in the comparison plot titles.
Re-executed top to bottom with the worktree environment (sequential
execution counts 1-40, watermark updated, zero errors); all curve
positions and orderings match the pre-PR outputs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(bass): plotting methods for BassModel (#2628)
* feat(bass): plotting methods for BassModel
* fix(bass): store deterministics on posterior DataTree node
Under arviz>=1.2 InferenceData subclasses xarray.DataTree, so the
idata.posterior = compute_deterministics(...) assignment in BassModel.fit
sets a shadowing instance attribute and leaves the group unchanged. The
deterministics (adopters, innovators, imitators, peak) were dropped from
the fitted posterior. Assign to the idata["posterior"] node instead.
* refactor(bass): migrate plot_peak to arviz_plots.plot_dist
arviz.plot_posterior was removed in arviz 1.2. Use arviz_plots.plot_dist
and extract the figure and axes from the returned PlotCollection, faceting
by product for multi-product models.
* test(bass): guard the deterministics fix via the posterior accessor
test_fit_deterministics asserted against idata.posterior, which under
arviz>=1.2 returns a shadowing attribute and passes even when the
deterministics are missing from the DataTree node. Assert against the
public model.posterior accessor instead, so the test fails if fit stops
storing the deterministics on the node.
* fix(bass): move plot_decomposition legend outside the axes
Place the legend as a figure legend to the right of the grid instead of
inside the first subplot, where it overlapped the curves (williambdean).
* fix(bass): put plot_decomposition legend below the grid
A horizontal legend centered under the subplots reads better than the
right-side placement, which sat next to the empty facet cell (williambdean).
* refactor(bass): generalize the plotting facet dimension
The plot methods hardcoded a 'product' dimension. Infer the faceting
dimension from the data (the non-time, non-sample dim, the same one
plot_curve facets over), with an optional dim override and a coord
selector. So a model whose series dimension is named e.g. 'region'
plots and selects correctly with no extra arguments. Adds region-model
tests, including an observed-overlay guard (williambdean).
* [Notebook Re-Run] Lift Test Calibration (#2673)
* docs(nb): re-execute lift test calibration notebooks for v1.0.0
Migrate imports and style to v1.0.0 conventions, then re-execute with
real sampling to regenerate outputs.
- mmm_lift_test.ipynb
- mmm_geolift_calibration.ipynb
- mmm_roas.ipynb
Changes:
- Import MMM from pymc_marketing.mmm (not .mmm.mmm)
- Switch to arviz-darkgrid style
- Remove conflicting plt.style.use / rcParams settings
* fix(nb): correct forest plot axes targeting and plot_dist calls
Fix mmm_lift_test:
- Use pc.viz["plot"].sel(column="forest").item() instead of .axes[0]
so dashed true-value lines render in the intervals panel, not labels
- Replace plot_true_value in cells 22/23 with idiomatic pc.map(scatter_x)
Fix mmm_roas:
- Remove manual fig/ax creation before azp.plot_dist (no longer needed)
so channel distributions render through the correct PlotCollection
* fix: suppress SettingWithCopyWarning and seaborn layout warnings in notebooks
TDD: added test_data_conversion.py with two red tests, then fixed
data_conversion.py:121 to use .loc instead of chained indexing.
Also removed conflicting constrained_layout rcParam in
mmm_geolift_calibration to silence seaborn axisgrid UserWarning.
* chore: remove overkill data_conversion tests
The .loc fix in data_conversion.py is self-documenting best practice.
Testing pandas's own SettingWithCopyWarning is upstream territory.
* fix(nb): add col_wrap=1 to plot_dist calls for vertical channel layout
* fix(nb): use pc.map scatter_x for direct forest plots, simplify plot_true_value
- Cells 22/23: keep idiomatic pc.map(azp.visuals.scatter_x) for simple forest plots
- comparison cells: keep axvline via simplified plot_true_value (no split hack)
- plot_comparison now returns forest axes via pc.viz["plot"].sel(column="forest")
* fix(nb): add colored true value lines and legend to lift test forest plots
* fix(nb): address review feedback on lift test notebooks
- Use black dashed lines for true values (not conflicting C0/C1)
- Add legend to forest plot cells showing true value labels
- Fix squished subplot layout in mmm_geolift (add tight_layout)
- Fix escaped percent signs in LaTeX in mmm_geolift
* rerun
* roas nb update
* rerun
---------
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* Merge resolved conflicts into v1.0.0 (#2759)
* Merge branch 'main' into v1.0.0 - resolve merge conflicts
* Fix DataTree and arviz API compatibility for customer_choice modules
* Fix DataTree.extend -> update for BayesianBLP compatibility
* bayesian_nlp notebooks migration (#2760)
* fix(plot): use matplotlib date converter for datetime x-axis (#2685)
* fix(plot): use matplotlib date converter for datetime x-axis
plot_curve drew sample lines with pandas period ordinals while the HDI
band used matplotlib date ordinals, producing broken x-axis tick labels
on datetime coordinates. Pass x_compat=True so pandas uses the
matplotlib date converter. No-op for numeric x-axes.
Fixes #2682
* docs(mmm): refresh mmm_components event plot with corrected date axis
Re-run cell 68 so the AsymmetricGaussianBasis comparison shows proper
date ticks, and drop the fig.autofmt_xdate(rotation=30) workaround that
is no longer needed.
* Final merge — resolve v1.0.0 conflicts with main (#2764)
* Add v1.0.0 branch to CI triggers (#2610)
* Add v1.0.0 branch to CI triggers (#2618)
* Add v1.0.0 to codecov branch tracking
* chore: Update UML Diagrams (#2608)
Co-authored-by: williambdean <57733339+williambdean@users.noreply.github.com>
* chore(triage): add no releasenotes label to triage agent (#2618)
The triage agent now recognizes the 'no releasenotes' label for issues
about internal/process-only changes (CI/CD, test infrastructure,
automation, version bumps, agent config) that should be excluded from
release notes.
Key guardrails:
- Never applied alongside package-affecting labels (bug, enhancement, docs, API, MMM, CLV)
- Includes a gh pr list reference command for uncertain cases
* Use tmp_path for CLV save-load tests (#2617)
* [pre-commit.ci] pre-commit autoupdate (#2620)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.15 → v0.15.16](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.15...v0.15.16)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* chore: update test durations (#2619)
Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* Chore(deps): Bump codecov/codecov-action from 6 to 7 (#2622)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 6 to 7.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v6...v7)
---
updated-dependencies:
- dependency-name: codecov/codecov-action
dependency-version: '7'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* dependencies pin (#2623)
* exploring bayesian blp heterskedastic normal (#2524)
* exploring bayesian blp heterskedastic normal
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* updating bayesian blp with nevo example
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update nevo notebook
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update blp nevo notebook
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* tidying plots
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* tidying BLP notebook.
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* tidying the nevo example
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update nevo notebook
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update to add the nevo data csv
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* adding defensive coding
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* removing the diagnostic code
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update improving test coverage and adding gallery images
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update blp code
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* adding random effects on other features
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* tidying taste profiles code
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update adding an integration test
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* add more tests
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* add model graphs and likelihood explanation
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* uncomment slow tests
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* add variable table for BLP
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* update table formating in docstrings
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* Guard taste-profile functions against missing taste dimensions
taste_type_demand_share and plot_taste_profile_stacked hardcoded
halton[:, 0] as the price taste shock, silently mislabeling results
for models built without 'price' in random_coef_on; they now look up
the price dimension and raise a ValueError pointing at the fix.
Models with random_coef_on=[] crashed downstream with an opaque
einsum shape error; all taste-profile entry points now raise a clear
RuntimeError explaining there is no heterogeneity dimension to
profile.
* Reject market_size_col=None instead of building a degenerate likelihood
The None fallback set n to zeros, which makes the log-share-ratio
likelihood's variance (1/(n*s)) infinite — the model built but could
never be sampled. The 'normal_logshare' likelihood has no meaning
without a per-market sample size, so refuse None at construction with
a message explaining why.
* Use the delta-method variance of the log share ratio in the likelihood
The likelihood previously used (1 - s_j)/(n s_j) — the delta-method
variance of log(s_j) alone. The observed quantity is the difference
log(s_j) - log(s_0), whose multinomial-sampling variance is
1/(n s_j) + 1/(n s_0): the outside good's sampling noise enters too,
and it is the same order as the inside term whenever s_0 is not large,
so dropping it understated the measurement noise. The within-market
covariance across products (shared outside share) remains ignored;
this is now documented at the likelihood definition. A regression test
pins the per-cell logp against a hand-computed Normal with the correct
variance.
* Re-execute the synthetic BLP notebook under the corrected likelihood
Source fixes folded into this run: the likelihood derivation now states
the delta-method variance of the log share *ratio* (including the
outside-good term), the time-targeted counterfactual applies the same
10% hike as the full-panel comparison (the previous 20% contradicted
the "matches the full-panel counterfactual" claim and its own printed
output), and the summary no longer hardcodes a stale bias figure.
All outputs regenerated against the new variance: zero divergences in
both fits, parameter recovery intact, and the window invariants now
print exactly 0.0.
* Re-execute the Nevo notebook under the corrected likelihood
Outputs regenerated with the delta-method log-share-ratio variance:
zero divergences, all R-hats at 1.00, own-price elasticities in
[-2.98, -2.44] (textbook cereal band), IV-vs-no-IV bias direction
preserved, and the time-targeted counterfactual exactly zero outside
the shocked quarter.
Also fix two stale markdown passages: the diagnostics guidance now
matches the actual 4-chain x 2000-draw fit and explains the wide
beta_pop[mushy] interval via collinearity between time-invariant
characteristics and the brand fixed effects (rather than a low-ESS
claim the table no longer supports), and the caveats section now
states the fit uses random coefficients on price, sugar, and mushy
rather than price only.
---------
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
* fix(deps): upper bound matplotlib <3.11 (#2626)
* chore: update test durations (#2631)
Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com>
* [pre-commit.ci] pre-commit autoupdate (#2634)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.16 → v0.15.17](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.16...v0.15.17)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* chore: update test durations (#2636)
Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com>
* docs: lead landing page with credibility signals and a production-focused CTA (#2635)
* docs: lead landing page with credibility and a production-focused CTA
Restructures the docs landing page so the highest-intent visitors hit
trust signals and a clear next step before the feature inventory:
- Adds a 'Trusted in production' section directly after the intro with
named adopters (Bolt, HelloFresh) and a concrete, publicly-documented
proof point (HelloFresh: 20min -> 2min inference, 60% variance
reduction), plus download/stars/license signals.
- Surfaces a single outcome-framed primary CTA near the top instead of
only at the very bottom of the page.
- Adds GitHub stars and license badges alongside the download badges.
Rationale: a synthetic-audience test of MMM/CLV practitioners on the
landing page showed strong problem recognition followed by 'is this
mature / who is behind it?' skepticism, with the call-to-action too
diffuse and buried. This leads with the maturity and credibility
signals that resolve that doubt.
* docs: address review — soften credibility copy, de-dup proof points
Reword the 'research prototype' line to drop the defensive framing, and
remove the Bolt/HelloFresh proof points and Calendly CTA from the top
section since they already appear at the bottom (Resources/Case Studies
and the Need help CTA). Keeps a light credibility signal up top without
repeating the promotional material twice on the page.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: root <root@e2b.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* [pre-commit.ci] pre-commit autoupdate (#2641)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.17 → v0.15.18](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.17...v0.15.18)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Fix flaky test_log_model_graph_no_graphviz by scoping log capture (#2644)
The test asserted strict equality on caplog.messages while capturing INFO
records from the root logger. caplog's handler is attached to the root
logger, so it also captures unrelated third-party logs. When this test was
the first in a shard to touch the MLflow SQLite backend store, MLflow
emitted an INFO record ("Creating initial MLflow database tables...") that
landed in the capture, making the assertion order-dependent and failing CI
non-deterministically (consistently in test shard 1).
Two changes:
- pymc_marketing/mlflow.py: log via a module-level logger
(logging.getLogger(__name__)) instead of the root logger. Libraries
should not log to the root logger; this gives callers a named,
configurable logger.
- tests/test_mlflow.py: scope the capture to the pymc_marketing.mlflow
logger and filter caplog.records by logger name, so the assertion only
inspects messages our own code emits and is robust to third-party log
noise regardless of test order.
Co-authored-by: daimon-pymclabs <noreply@anthropic.com>
* Chore(deps): Bump actions/checkout from 6 to 7 (#2643)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)
---
updated-dependencies:
- dependency-name: actions/checkout
dependency-version: '7'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* chore: Update UML Diagrams (#2633)
Co-authored-by: williambdean <57733339+williambdean@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* fix(mmm): keep RootSaturation gradient finite at zero spend (#2640)
* fix(mmm): keep RootSaturation gradient finite at zero spend
`root_saturation(x, alpha) = x**alpha` has derivative
`d/dx (x**alpha) = alpha * x**(alpha - 1)`, which is infinite at `x == 0`
for `alpha < 1`. In an MMM the saturation input is a function of random
variables (e.g. adstocked spend) and channels routinely have exact
zero-spend periods, so this singularity produces NaN gradients and NUTS
fails to initialize (e.g. nutpie "All initialization points failed").
Note this is the gradient w.r.t. the *base*, not the `x**alpha * log(x)`
term w.r.t. the exponent — PyTensor already guards the latter with
`switch(eq(x, 0), 0, ...)`.
Shift the input by a tiny `eps` (default 1e-6) so the gradient stays
finite. Inputs are typically scaled to [0, 1], against which eps is
negligible. Add a regression test asserting `compile_dlogp` is finite
when the saturation input depends on a free RV and has exact zeros.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(mmm): use pt.where guard for root_saturation gradient at zero
Replace the additive eps shift with a pt.where guard pattern that keeps
f(0)=0 exactly and the gradient finite everywhere for x=0.
* fix(mmm): use .values to avoid XTensorVariable conversion error in root_saturation
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* [pre-commit.ci] pre-commit autoupdate (#2663)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.18 → v0.15.20](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.18...v0.15.20)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Fix mypy errors on main (#2667)
Resolve the 6 mypy failures blocking pre-commit.ci on main:
- customer_choice/synthetic_data.py: cast the np.where index array to
int so the loop variable and dict keys have a consistent int type
(the variable was previously bound to int via an earlier range loop).
- mmm/hsgp.py: coerce the scalar operands to float before max()/int()
so the function returns the annotated tuple[int, float].
- mmm/lift_test.py: widen the Index alias to also accept np.ndarray,
matching np.argmax's return type assigned into indices[col].
Co-authored-by: Daimon <noreply@anthropic.com>
* Add merge_group trigger to CI workflows for merge queue support (#2676) (#2678)
* refactor(mmm): rename optimize_budget **minimize_kwargs to **allocate_budget_kwargs (#2563)
The variadic on BudgetOptimizerWrapper.optimize_budget relays every
keyword to BudgetOptimizer.allocate_budget, not only the scipy
minimize options, so the previous name was misleading (callers could
end up passing minimize_kwargs={...} inside **minimize_kwargs).
Closes #1660
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
* ci: add git-ai workflow for authorship attribution (#2746)
* Chore(deps): Bump actions/setup-node from 6 to 7 (#2736)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v6...v7)
---
updated-dependencies:
- dependency-name: actions/setup-node
dependency-version: '7'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Chore(deps): Bump actions/labeler from 6 to 7 (#2753)
Bumps [actions/labeler](https://github.com/actions/labeler) from 6 to 7.
- [Release notes](https://github.com/actions/labeler/releases)
- [Commits](https://github.com/actions/labeler/compare/v6...v7)
---
updated-dependencies:
- dependency-name: actions/labeler
dependency-version: '7'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: group all actions/* updates with 7-day cooldown (#2755)
* Chore(deps): Bump astral-sh/setup-uv from 7 to 8.3.2 (#2756)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 7 to 8.3.2.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v7...v8.3.2)
---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
dependency-version: 8.3.2
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Nathaniel <NathanielF@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Nightt <87569709+nightt5879@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com>
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nathaniel <NathanielF@users.noreply.github.com>
Co-authored-by: Pablo Vena <37351096+anevolbap@users.noreply.github.com>
Co-authored-by: daimon-pymclabs <daimon@pymc-labs.com>
Co-authored-by: root <root@e2b.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Alvaro Duran Tovar <hermesdt@gmail.com>
Co-authored-by: Pablo de Roque <pablo.deroque@glovoapp.com>
* feat(mmm): DataVarMuEffect, MediaMuEffect, ControlMuEffect for xarray data referencing (#2757)
* feat(mmm): add DataVarMuEffect, MediaMuEffect, ControlMuEffect for xarray data referencing
Three new MuEffect subclasses enabling media and control effects that
read data directly from named variables in the training xr.Dataset.
- DataVarMuEffect: abstract base with create_data/set_data defaults
- MediaMuEffect: applies MediaTransformation to a named variable,
aggregates over configurable channel_dim
- ControlMuEffect: configurable prior per control variable, auto-sums
extra dimensions
Also extends the Model protocol with xarray_dataset property so all
MuEffects can access the canonical training data.
* fix review feedback: set_data on base, Field(min_length=1), rm dead effect_dims
- Lift set_data from MediaMuEffect/ControlMuEffect to DataVarMuEffect
base to eliminate byte-for-byte duplicate
- Add Annotated[Field(min_length=1)] to data_vars so empty lists
are caught at construction
- Remove stale effect_dims key from MediaMuEffect.to_dict since
it is derived from media_transformation.dims at runtime
- Update DataVarMuEffect docstring to reflect set_data is concrete
---------
Co-authored-by: Juan Orduz <juanitorduz@gmail.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Nathaniel <N…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consolidates all Dependabot updates for
actions/*into a single PR and adds a 7-day cooldown before updates are proposed, reducing PR noise.Changes:
groupsto batch allactions/*dependency updates into one PRcooldown.default-days: 7to wait 7 days after a new Action version is published before opening a PRThis prevents the flood of individual Dependabot PRs (e.g., #2753, #2752, #2736) by combining them into a single grouped update.
📚 Documentation preview 📚: https://pymc-marketing--2755.org.readthedocs.build/en/2755/