Skip to content

Conversation

williambdean
Copy link
Contributor

@williambdean williambdean commented Jun 16, 2025

This using pymc-extras to allow for custom priors. Might need to adjust the remaining a bit to work.

Closes #387


@drbenvincent did some work to:

  • get remote tests passing
  • add docstrings
  • add tests

Copy link
Collaborator

@drbenvincent drbenvincent left a comment

Choose a reason for hiding this comment

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

This is very cool!

As far as I can tell, these changes are currently entirely invisible to the end user, right?

Before we do a new release I will follow up with another PR that adds some documentation. This will most likely be in the form of just giving a couple of worked examples

Main request is to add custom-ness to the Dirichlet for the WeightedSumFitter class. Like I say in a comment, I mostly see people wanting to customise the hyperparams, not the distribution itself.

Inference data...
""" # noqa: W605

default_priors = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

need to add @property decorator here? Or is that remembered from it being done in the PyMCModel base class?

Getting an Pylance warning: Type "dict[str, Prior]" is not assignable to declared type "property"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What line of code bring that on? Maybe having a setter will help?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree, if you want a property, maybe we can have a setter method? (not a blocker for now and maybe create an issue?)

n_predictors = X.shape[1]
X = pm.Data("X", X, dims=["obs_ind", "coeffs"])
y = pm.Data("y", y[:, 0], dims="obs_ind")
beta = pm.Dirichlet("beta", a=np.ones(n_predictors), dims="coeffs")
Copy link
Collaborator

Choose a reason for hiding this comment

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

We definitely want a custom prior for the Dirichlet. I think the Dirichlet would be used always (or nearly always), but there are plenty of real world use cases where the user might want to change the hyper parameters (currently a=np.ones(n_predictors)).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright. since it is function of data, we will have to handle differently

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've address this with dc20e3e. If user wants to change, they can add to the "priors" at initialization.
Take a look and let me know what you think.

Copy link

codecov bot commented Jun 20, 2025

Codecov Report

❌ Patch coverage is 99.34211% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 95.43%. Comparing base (77f8d59) to head (4be4cdd).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
causalpy/pymc_models.py 96.42% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #488      +/-   ##
==========================================
+ Coverage   95.19%   95.43%   +0.23%     
==========================================
  Files          28       28              
  Lines        2457     2586     +129     
==========================================
+ Hits         2339     2468     +129     
  Misses        118      118              

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

@drbenvincent
Copy link
Collaborator

tests pass :)

@juanitorduz
Copy link
Collaborator

Excited about this PR!

n_predictors = X.shape[1]

return {
"beta": Prior("Dirichlet", a=np.ones(n_predictors), dims="coeffs"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just realised that n_predictors will equal length of the "coeffs" dim. Does that have to be the case in fact? If so, do we need priors_from_data?

Not saying I don't want it, it could be really cool. But just wondering more generally if it's needed or not. Will try to think more with a fresh head in the morning, but does this spark off any thoughts?

@drbenvincent
Copy link
Collaborator

drbenvincent commented Jul 17, 2025

So I spent some time doing a gnarly merge from main into this dev branch. There were some widespread changes in main, so it took me a while to get all the tests passing. But it should make your life easier :)

Remote doctests failing. They pass for me locally. Seems maybe like an import error in pymc? Any ideas @williambdean ?

- Updated LinearRegression default_priors to support multi-unit architecture
- Resolved print_coefficients method conflicts
- Added patsy import back for dmatrix usage
- Regenerated interrogate_badge.svg with updated coverage
- Use Prior class create_likelihood_variable method for model definitions
- Updated print_coefficients to handle both sigma and y_hat_sigma variables
- Simplified PropensityScore to use Prior class exclusively
- Deleted interrogate badge to be regenerated
@drbenvincent
Copy link
Collaborator

This seems to be the reason why the remote tests are failing: pymc-devs/pymc-extras#541

@drbenvincent
Copy link
Collaborator

The issue is that pymc-extras 0.3.0+ requires Python >=3.11, but the CI is running on Python 3.10.18. That's why pip can't find a compatible version.

Added '# pragma: no cover' to NotImplementedError and ValueError branches in PyMCModel to exclude them from test coverage reporting.
@drbenvincent
Copy link
Collaborator

Remote tests back to passing :)

Copy link
Collaborator

@juanitorduz juanitorduz left a comment

Choose a reason for hiding this comment

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

Great! There is a comment by @williambdean which we could tackle later (please create an issue :) )

Inference data...
""" # noqa: W605

default_priors = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree, if you want a property, maybe we can have a setter method? (not a blocker for now and maybe create an issue?)

@drbenvincent
Copy link
Collaborator

Thanks for the review @juanitorduz. My feeling at the moment is...

The current workflow is that computation is kicked off automatically when creating an experiment object instance. As in, you don't first create the experiment then manually call a fit method, for example. Because we have that workflow, then having a setter doesn't makes sense.

Changed PyMCModel.default_priors from a @property method to a class attribute to match how it's implemented in all subclasses (LinearRegression, WeightedSumFitter, PropensityScore). The property decorator was causing Pylance type warnings since subclasses were defining default_priors as dictionaries rather than properties. Since priors are static configuration data that don't depend on instance state, using a class attribute is more appropriate and provides better performance (no method call overhead). This change maintains backward compatibility while making the codebase consistent and eliminating type checker warnings.

@drbenvincent drbenvincent dismissed their stale review October 3, 2025 08:49

Can deal with this (if at all) in another PR

@drbenvincent drbenvincent merged commit 540893b into pymc-labs:main Oct 3, 2025
6 checks passed
@williambdean williambdean deleted the custom-priors branch October 3, 2025 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow users to define custom priors
3 participants