Skip to content

Implement MultiDimensionalMMM with pymc.dims#2204

Draft
ricardoV94 wants to merge 9 commits intopymc-labs:mainfrom
ricardoV94:mmm_dims
Draft

Implement MultiDimensionalMMM with pymc.dims#2204
ricardoV94 wants to merge 9 commits intopymc-labs:mainfrom
ricardoV94:mmm_dims

Conversation

@ricardoV94
Copy link
Contributor

@ricardoV94 ricardoV94 commented Jan 20, 2026

TODO:

  • Dev migration guide
  • Adapt new incrementality code
  • Censored Prior

Closes #1981
Closes #1514
Closes #1630 (just a regression test, it worked fine before)


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

@review-notebook-app
Copy link

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 MMM labels Jan 20, 2026
@ricardoV94 ricardoV94 changed the title POC implement MultiDimensionalMMM with dimmed variables POC implement MultiDimensionalMMM with pymc.dims Jan 20, 2026
name="channel_contribution",
var=baseline_channel_contribution * media_broadcast,
dims=("date", *self.dims, "channel"),
channel_contribution = pmd.Deterministic(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's awesome.

@codecov
Copy link

codecov bot commented Jan 20, 2026

Codecov Report

❌ Patch coverage is 95.63025% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.52%. Comparing base (26ef53f) to head (3d37c19).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pymc_marketing/mmm/utility.py 81.25% 9 Missing ⚠️
pymc_marketing/mmm/components/base.py 89.47% 4 Missing ⚠️
pymc_marketing/special_priors.py 88.88% 4 Missing ⚠️
pymc_marketing/mmm/hsgp.py 94.54% 3 Missing ⚠️
pymc_marketing/mmm/incrementality.py 0.00% 3 Missing ⚠️
pymc_marketing/mmm/sensitivity_analysis.py 94.11% 2 Missing ⚠️
pymc_marketing/mmm/linear_trend.py 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2204      +/-   ##
==========================================
- Coverage   93.20%   88.52%   -4.69%     
==========================================
  Files          79       80       +1     
  Lines       12477    12485       +8     
==========================================
- Hits        11629    11052     -577     
- Misses        848     1433     +585     

☔ 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.

Copy link
Contributor

@cetagostini cetagostini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey! I found a few typos while reviewing the pymc.dims implementation. See inline comments below 👇

Copy link
Contributor

@cetagostini cetagostini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more inconsistencies I noticed - some return type annotations say TensorVariable but the code actually returns XTensorVariable 🤔

@cetagostini
Copy link
Contributor

Function Equivalence Testing Results 🧪

I tested the transformation functions to verify they produce equivalent outputs with the new pymc.dims API. Here's what I found:

✅ All Functions Pass Numerical Equivalence

Function Match
logistic_saturation
tanh_saturation
hill_function
michaelis_menten
root_saturation
geometric_adstock weights

⚠️ Important Finding: Dimension Ordering

When broadcasting with xtensor, the dimension order may differ from numpy!

# Example:
x_2d = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])  # (3 dates, 2 channels)
lam_channel = np.array([0.3, 0.7])  # per-channel lambda

# Old API (numpy-style):
# Output shape: (3, 2) → (date, channel) order preserved

# New API (xtensor):
# Output shape: (2, 3) → (channel, date) order CHANGED!

The values are correct (match after transpose), but any code relying on axis indices (axis=0, axis=1) instead of dimension names may break.

This is expected behavior for xarray-like semantics, but worth noting for anyone working with the codebase! 👍

@ricardoV94
Copy link
Contributor Author

Yes order doesn't matter while in xtensor land. You can always transpose explicitly to another order, which you should do if you need to go to tensor land (via .values).

Note even if not so relevant, dimension order matches the same as xarray

@ricardoV94 ricardoV94 force-pushed the mmm_dims branch 2 times, most recently from 2a75405 to c2193c6 Compare February 2, 2026 15:43
@ricardoV94 ricardoV94 force-pushed the mmm_dims branch 2 times, most recently from aa79d7b to c9a5a89 Compare February 2, 2026 18:36
budgets_expanded * self._budget_distribution_over_period_tensor
) # Shape: (num_periods, num_optimized_budgets)
budgets_optimized * self._budget_distribution_over_period_tensor
).transpose("date", "budgets_flat")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very nice!

@ricardoV94 ricardoV94 force-pushed the mmm_dims branch 3 times, most recently from d8bfaaa to 872eeec Compare February 6, 2026 22:27
@ricardoV94 ricardoV94 force-pushed the mmm_dims branch 2 times, most recently from 9c0e68c to 26d9b9b Compare February 24, 2026 18:01
@ricardoV94
Copy link
Contributor Author

ricardoV94 commented Feb 24, 2026

Legacy MMM/Optimizer now work with pymc.dims and the refactored components.

This PR now depends on pymc-devs/pymc-extras#657 to help with the transition into dim world, so the CI will be ready until we re-sync

@ricardoV94 ricardoV94 added this to the 1.0 milestone Feb 25, 2026
@ricardoV94 ricardoV94 force-pushed the mmm_dims branch 6 times, most recently from f699e67 to b825820 Compare February 25, 2026 17:01
@github-actions github-actions bot added the customer choice Related to customer choice module label Feb 25, 2026
@ricardoV94 ricardoV94 force-pushed the mmm_dims branch 5 times, most recently from e72dfa2 to 5c0b641 Compare February 26, 2026 10:07
@ricardoV94
Copy link
Contributor Author

Failing test depends on pymc-devs/pymc#8124
Notebook failing due to prior.Censored not being implented with pymc.dims yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bass model Dealing with the Bass Defusion model bug Something isn't working customer choice Related to customer choice module docs Improvements or additions to documentation MMM multidimensional Prior class tests TVPs Related to time varying parameters

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Basis functions fail with multidimensional events single channel MMMs don't work Handle dims for intercept

6 participants