Skip to content

InitContext, part 3 - Introduce InitContext #981

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

Draft
wants to merge 5 commits into
base: py/hasgetvalue
Choose a base branch
from

Conversation

penelopeysm
Copy link
Member

@penelopeysm penelopeysm commented Jul 9, 2025

Part 1: Adding hasvalue and getvalue to AbstractPPL
Part 2: Removing hasvalue and getvalue from DynamicPPL

This is Part 3/N of splitting up #967.


This PR solely adds the code for a new leaf context, InitContext. Its behaviour is to always override existing values inside a VarInfo.

A long-held goal of mine is to split up contexts.jl and context_implementations.jl such that each context is in its own file. To help get us to this stage, I've put all the InitContext-related code inside src/contexts/init.jl. This should, hopefully, also make reviewing easier.

InitContext comes in three forms:

  1. PriorInit: Samples values from the prior;
  2. UniformInit(min, max): Samples values from between min and max before invlinking them back into the support of the original distribution;
  3. ParamsInit(params): Takes values from params, which can be a NamedTuple or a Dict. Also takes a fallback strategy, which is used in case the varname is not found in params.

PriorInit and UniformInit have almost one-to-one correspondence with SampleFromPrior and SampleFromUniform. I haven't removed them yet because a LOT of stuff depends on SampleFromPrior. We will eventually remove all of it but doing it in a single PR would make it way too big.

However, ParamsInit is new. Its purpose is to set fixed values in a VarInfo in a principled manner. Right now, there is a fair amount of code that does low-level VarInfo manipulation by reaching inside and modifying the underlying arrays, such as initialise_values!!, and setval_and_resample!. This is prone to bugs, and also leads to (for example) the VarInfo's logp being out of sync. (All of that code will be removed in subsequent PRs.)

ParamsInit accomplishes the same in a much cleaner way, although in some cases it may necessitate one extra model evaluation. Because initialisation is not meant to happen within a tight loop (by definition it happens once), I don't consider performance to be an important issue.

Closes #375.

Copy link
Contributor

github-actions bot commented Jul 9, 2025

Benchmark Report for Commit b55c1e1

Computer Information

Julia Version 1.11.5
Commit 760b2e5b739 (2025-04-14 06:53 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 4 × AMD EPYC 7763 64-Core Processor
  WORD_SIZE: 64
  LLVM: libLLVM-16.0.6 (ORCJIT, znver3)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)

Benchmark Results

|                 Model | Dimension |  AD Backend |      VarInfo Type | Linked | Eval Time / Ref Time | AD Time / Eval Time |
|-----------------------|-----------|-------------|-------------------|--------|----------------------|---------------------|
| Simple assume observe |         1 | forwarddiff |             typed |  false |                  8.9 |                 1.6 |
|           Smorgasbord |       201 | forwarddiff |             typed |  false |                685.3 |                39.6 |
|           Smorgasbord |       201 | forwarddiff | simple_namedtuple |   true |                438.3 |                50.2 |
|           Smorgasbord |       201 | forwarddiff |           untyped |   true |               1189.0 |                30.1 |
|           Smorgasbord |       201 | forwarddiff |       simple_dict |   true |               6790.6 |                25.0 |
|           Smorgasbord |       201 | reversediff |             typed |   true |               1082.7 |                38.9 |
|           Smorgasbord |       201 |    mooncake |             typed |   true |               1057.1 |                 4.2 |
|    Loop univariate 1k |      1000 |    mooncake |             typed |   true |               6000.8 |                 3.9 |
|       Multivariate 1k |      1000 |    mooncake |             typed |   true |               1008.3 |                 9.1 |
|   Loop univariate 10k |     10000 |    mooncake |             typed |   true |              67843.0 |                 3.5 |
|      Multivariate 10k |     10000 |    mooncake |             typed |   true |               8979.8 |                 9.9 |
|               Dynamic |        10 |    mooncake |             typed |   true |                139.0 |                13.4 |
|              Submodel |         1 |    mooncake |             typed |   true |                 13.6 |                 6.1 |
|                   LDA |        12 | reversediff |             typed |   true |               1393.4 |                 1.8 |

Copy link
Contributor

DynamicPPL.jl documentation for PR #981 is available at:
https://TuringLang.github.io/DynamicPPL.jl/previews/PR981/

Copy link

codecov bot commented Jul 10, 2025

Codecov Report

Attention: Patch coverage is 86.44068% with 8 lines in your changes missing coverage. Please review.

Project coverage is 82.18%. Comparing base (21cf568) to head (b55c1e1).

Files with missing lines Patch % Lines
src/contexts/init.jl 89.58% 5 Missing ⚠️
src/model.jl 72.72% 3 Missing ⚠️
Additional details and impacted files
@@                Coverage Diff                 @@
##           py/hasgetvalue     #981      +/-   ##
==================================================
+ Coverage           81.92%   82.18%   +0.26%     
==================================================
  Files                  37       38       +1     
  Lines                3994     4048      +54     
==================================================
+ Hits                 3272     3327      +55     
+ Misses                722      721       -1     

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

Comment on lines -283 to -287
"""
prefix(model::Model, x::VarName)
prefix(model::Model, x::Val{sym})
prefix(model::Model, x::Any)

Copy link
Member Author

@penelopeysm penelopeysm Jul 10, 2025

Choose a reason for hiding this comment

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

This code was shifted verbatim to src/model.jl to avoid circular dependencies between files.

@penelopeysm penelopeysm changed the title Introduce InitContext InitContext, part 3 - Introduce InitContext Jul 10, 2025
@penelopeysm penelopeysm force-pushed the py/init-prior-uniform branch from f1d5f20 to 025aa8b Compare July 10, 2025 12:55
Note that, apart from being simpler code, Distributions.Uniform also
doesn't allow the lower and upper bounds to be exactly equal (but we
might like to keep that option open in DynamicPPL, e.g. if the user
wants to initialise all values to the same value in linked space).
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.

1 participant