-
Notifications
You must be signed in to change notification settings - Fork 10
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
BreadCrumbs interface: an easier way to feed pigeons #99
base: main
Are you sure you want to change the base?
Conversation
Codecov Report
❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more. @@ Coverage Diff @@
## main #99 +/- ##
==========================================
- Coverage 84.28% 84.22% -0.06%
==========================================
Files 79 80 +1
Lines 2214 2232 +18
==========================================
+ Hits 1866 1880 +14
- Misses 348 352 +4
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the name BreadCrumbs is super clever and cute, but maybe too cute. Can we name it something more descriptive?
@nikola-sur yeah we can definitely change it. To make it very explicit, we could call it "FunctionDistributionPair" or something like that. It conveys the specific inputs requested. At the same time, we should think if there are other use cases that could be captured with a similar interface. E.g. instead of a Distribution object, we could specify the reference as a generic logpdf function and a sampler function. |
Maybe we call it something like CustomLogPotential to keep in line with TuringLogPotential, Stan, Comrade? Then CustomLogPotential() can accept various forms of input (two or three arguments):
Also, can we compose distributions like Uniform * Uniform, Uniform ^100, etc? Or is that dangerous? |
Because Turing implicitly couples a reference and target and that's all contained in TuringLogPotential, maybe we should unify and do CustomLogPotential? That's my line of thought but am curious what others think. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice!!! See some thoughts below
eltype(bct.bc.reference_distribution)(-Inf) | ||
end | ||
end | ||
default_explorer(::BreadCrumbsTarget) = SliceSampler() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SliceSampler() is already the global default, no need to have that line.
|
||
The PT state is initialized using a random sample from the reference. | ||
""" | ||
struct BreadCrumbs{TRefDist <: Distributions.Distribution, TTarget} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use @auto instead? Otherwise the standard out gets cluttered with pages of mostly useless type information when showing the stack trace.
Also ref should be more general. We don't want Distributions to only work in BreadCrumbs. It should be seamless with the reference = ..
method as well. (unless we remove the reference = .. method; which I don't think is a good idea since it works well for PPLs).
Conversely, things that can be fed into reference = ..
should work in the target_log_potential argument. Similarly things that gets fed into target =
should work in target_log_potential (I think this is already the case?).
end | ||
|
||
# Target for a BreadCrumbs input | ||
struct BreadCrumbsTarget{TBC <: BreadCrumbs} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems superfluous?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I.e. instead can we write the dispatches on Distributions types directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! I think you're right! At least for the reference. I don't think people are thinking of passing the loglikelihood as a Distribution on the data given the parameter. That would also be very restrictive given that Distributions.jl only has simple models.
end | ||
# univariate case: need to wrap in vector to make the state mutable | ||
function initialization( | ||
bct::TBCT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this equivalent to bct::Distributions.UnivariateDistribution
? etc for the other arguments
@@ -63,7 +63,7 @@ const use_auto_exec_folder = "" | |||
|
|||
include("includes.jl") | |||
|
|||
export pigeons, Inputs, PT, | |||
export pigeons, Inputs, PT, BreadCrumbs, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to export it, but then the PR should contain documentation (in code and in the website).
About the naming: since it's subjective I suggest we discuss in person when I come back--or even better, over beers :) |
Further comments: one idea to get this merged faster is to split into two phases. First, a non-breaking PR which just adds Distribution.jl support to the existing API, i.e. via
Then we can discuss further API-changing PRs, e.g. user-facing BreadCrumbs, unifications of LogPotentials, etc. |
(in the above, we partly use the fact that the type |
This comment was marked as outdated.
This comment was marked as outdated.
Yeah that would be type piracy... But it would be nice to suggest them implement the product and power operator for distributions! |
This was precisely the reason why I needed to have special types so that initialization could talk to the reference through the pointer in the target object. But changing initialization seems like a more robust option going forward. Also: splitting the PR sounds good to me! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexandrebouchard unrelated to this PR but I had to change this limit so that the test would pass. Are you ok with lowering this limit?
@alexandrebouchard Since Pigeons.jl/src/replicas/replicas.jl Line 90 in 49c0560
It seems like the best option would be to make it accept the full Inputs object -- which already holds the pointer to the reference object -- and then have a default method that dispatches on the target alone. We could then also have methods that dispatch on the type of the reference object or any other thing in the Inputs. This approach would probably break the least stuff. |
Dispatching on full input obj may be a bit messy BC inputs has several type params, and for maintenance if we change input type params that would be on more thing to change. But not opposed if that's what makes most sense |
It seems doable! I'm almost done with a prototype but I have encountered a different difficulty. The issue with using a distribution directly as a reference is that making them callable within Pigeons would constitute type piracy, if I'm not mistaken. From this point of view, it would make sense to wrap the Distribution object inside another one created by us. What do you think? |
Ok I expanded on the above idea on a separate PR (#102 ) with a wrapping struct called |
No description provided.