Skip to content

Add new create_inits() methods to other stanfit classes #791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from

Conversation

amas0
Copy link
Contributor

@amas0 amas0 commented May 8, 2025

Submission Checklist

  • [ x ] Run unit tests
  • [ x ] Declare copyright holder and open-source license: see below

Summary

This PR addresses #745. Implementation largely mirrors that for CmdStanPathfinder. In particular, this adds the following methods: CmdStanVB.create_inits(), CmdStanLaplace.create_inits(), CmdStanMLE.create_intis(), CmdStanMCMC.create_inits(). With the exception of MLE, inits are selected by sampling without replacement from draws. The MLE implementation will initialize all requested chains at the optimized parameter values.

Unit tests for all these methods are added as well.

I also updated the User's Guide example on creating inits from VI outputs to be more general and cover these new methods.

I assume this is already well-known but it seems like there is a cleaner library structure to have each of these different stanfit objects be implementations of the same parent (or abstract) class to unify these implementations (and those of other common methods). I haven't worked through the details, but it seemed possible given how similar the internal structures tend to be.

Copyright and Licensing

Please list the copyright holder for the work you are submitting (this will be you or your assignee, such as a university or company): myself

By submitting this pull request, the copyright holder is agreeing to license the submitted work under the following licenses:

@codecov-commenter
Copy link

codecov-commenter commented May 8, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 80.60%. Comparing base (650d2bb) to head (b18d450).
Report is 24 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #791      +/-   ##
===========================================
+ Coverage    80.24%   80.60%   +0.35%     
===========================================
  Files           25       25              
  Lines         3878     3949      +71     
===========================================
+ Hits          3112     3183      +71     
  Misses         766      766              

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

@WardBrian WardBrian left a comment

Choose a reason for hiding this comment

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

Thanks! Overall this looks great, I just have a few minor comments.

Re:

I assume this is already well-known but it seems like there is a cleaner library structure to have each of these different stanfit objects be implementations of the same parent (or abstract) class to unify these implementations (and those of other common methods).

Yes, we definitely could. So far most of what we've done in this style is using helper methods we throw in the utils subpackage for code re-use, but inheritance would also get us there, and maybe a bit more cleanly. In another project that deals with Stan outputs, I don't even differentiate between the different algorithms, I just have one 'StanOutput' class that can hold any of them.

if chains == 1:
return mle_inits
else:
return [mle_inits for _ in range(chains)]
Copy link
Member

Choose a reason for hiding this comment

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

Because the default behavior is if you pass a dictionary to sample, it uses it for every chain, I don't know if this is super necessary.

I do think this function should probably accept both a seed and chains argument, even if they're both unused, to let people write more generic code

Copy link
Member

Choose a reason for hiding this comment

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

(I also think this function might be exactly equivalent to self.stan_variables() after those changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the signature for compatibility. I also use stan_variables() in the function now, but because stan_variables() will currently return a float if the parameter is scalar, I just map everything to an np.array for type compatibility. It seems this is intended to be the future behavior of stan_variables() in 2.0, at which point it will be equivalent.

amas0 added 3 commits May 8, 2025 16:36
This change simplifies the create_inits() for the MLE
params to always return a dictionary of inits, rather
than a list for multiple chains. The default behavior
of the sample method is to initialize all chains
at the same init if only one is given per param.

The chains paramter is kept and the seed parameter is
added to the signature, despite being no-ops, for
the purposes of maintaining uniformity across the
other create_inits() methods on other stanfit objects.
@amas0
Copy link
Contributor Author

amas0 commented May 8, 2025

Thanks for the review -- responded to your comments and made changes where appropriate.

Not sure what's going on with that failed pytest check. Some of the cancelled jobs seem to have gotten through the testing stage without issue.

Going through the library, there are a number of references to a 2.0 version -- that might be a good opportunity to clean up some of these stanfit objects and such. Not sure if there are explicit plans for what that will contain (or timeline), just a thought. Happy to help out if there's a direction there.

@WardBrian
Copy link
Member

Because ADVI can be unstable it might be worth setting a known-good seed in the new test that runs it

@amas0
Copy link
Contributor Author

amas0 commented May 9, 2025

Okay, pinned some seeds that seemed fine and checks look good. Serendipitous that I went back and did that, because I found a bug in one of the tests I wrote, which I now have fixed.

I think this should be set?

@bob-carpenter
Copy link
Member

bob-carpenter commented May 12, 2025

Thanks. @mitzimorris may be able to review and approve sooner than @WardBrian for this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants