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
PIG 16 - Model Priors API #4381
PIG 16 - Model Priors API #4381
Conversation
b7710e9
to
d34d118
Compare
Codecov Report
@@ Coverage Diff @@
## main #4381 +/- ##
==========================================
- Coverage 75.90% 75.62% -0.28%
==========================================
Files 223 226 +3
Lines 32312 33026 +714
==========================================
+ Hits 24527 24977 +450
- Misses 7785 8049 +264 see 61 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
docs/development/pigs/pig-026.rst
Outdated
Motivation | ||
========== | ||
|
||
Using priors on models and on parameters is the next step in full-fledged statistical analyses. |
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.
Using priors on models and on parameters is the next step in full-fledged statistical analyses. | |
Using priors on models or on parameters is the next step in full-fledged statistical analyses. |
docs/development/pigs/pig-026.rst
Outdated
========== | ||
|
||
Using priors on models and on parameters is the next step in full-fledged statistical analyses. | ||
A prior can incorporate the analysers' knowledge of the topic at hand, and yield more realistically and trustworthy results. |
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.
Maybe not only the analyser... Indeed, one idea to deal with the IRFs systematics was to use the priors mechanics. So, if it is implemented like that, the knowledge comes from the people making the IRFs...
By the use, do we add as use case the inclusion of IRFs systematics into priors?
Thanks a lot @nbiederbeck for this minimal draft. The overall structure is good and the content should be extended for details now:
These are just some thoughts for now, I'm sure I'll have some more... |
docs/development/pigs/pig-026.rst
Outdated
|
||
.. code:: python | ||
|
||
class L2Regularization(): |
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.
Note that this case actually corresponds to the GaussianPrior
on each of the individual parameters, where mu=0 and sigma=1
. The most general case I could imagine would be MultiVariateGaussianPrior
on a list of parameters. The case of L2
regularization would be included there...but probably we just keep it for convenience.
@katrinstreil kindly agreed to take over the writing and further development of the PIG. Please let us of know if you have any questions. |
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.
Thanks @katrinstreil @nbiederbeck . This already quite nice.
I would like to clarify a number of potential issues:
- it seems a bit complicated to me that priors can live and be defined and evaluated at different levels in the modeling package structure. I don't think that the
SkyModel
is the correct place anyway. We could have something to set priors on theModels
instance with e.g.models.set_prior(parameters, prior)
. - Parameters have units. How do we make sure that units are correctly handled?
- Is the
PriorFitStatistic
really needed? As far as I can see, it is mostly a single function. - Connected to this, I wonder if the mixing of two use cases in a single prior framework is not a bit confusing. We have:
- priors on individual parameters as usually done in e.g. sherpa, bxa, 3ML.
- penalization terms for the ML which are used for e.g. regularization in unfolding
Maybe this should be distinct features?
docs/development/pigs/pig-026.rst
Outdated
|
||
Future additional properties of the ``Prior`` classes: | ||
|
||
- Fittable parameters |
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.
Does this mean that Prior
has to contain Parameter
objects? Doesn't this cause problems?
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.
Yes, I think in general a prior should be treated much like a model. In general prior parameter can be fitted in a likelihood fit (maximum a posteriori) as well...so I think they should handle Parameter
objects.
docs/development/pigs/pig-026.rst
Outdated
self.mu = mu | ||
self.sigma = sigma | ||
|
||
def evaluate(self, value): |
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.
Should this follow the general scheme applied in models where evaluate
is a static method that takes all parameters on input?
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.
Yes, I agree that the .evaluate()
method should be static if possible. This will allows us to easier move to other tensor libraries later...The stateful call can happen in Prior.__call__
docs/development/pigs/pig-026.rst
Outdated
|
||
The prior classes are supposed to be set as ``.prior`` on: | ||
|
||
* Model-like classes, for instance the ``SkyModel`` class: |
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.
Does it really make sense to define the prior on the SkyModel
? I would assume the more logical place is Parameters
.
I suppose there are use cases where the prior applies to parameters of distinct SkyModel
.
You could still do model.parameters.prior = some_prior
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.
The reason why it should be attached to the Model
is bookkeeping. Priors should be serialized with the model. Parameters do not know, to which model they belong. The alternative is to handle it completely independent as we do for the covariance matrix and we would rely on the order of parameters. But in this case it would still be attached to the Model
.
docs/development/pigs/pig-026.rst
Outdated
def __call__(self, base): | ||
|
||
if isinstance(base, Parameter): | ||
return self.evaluate(base.value) |
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.
How does it deal with the Parameter
unit?
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 guess priors should be defined in such a way, that they are unit less (i.e. a likelihood after evaluation). But maybe we should add a check for this...
docs/development/pigs/pig-026.rst
Outdated
return np.sum(stat, dtype=np.float64) + PriorFitStatistic(weight=1).stat_sum(models = self.models) | ||
|
||
|
||
Where the ``PriorFitStatistic`` iterates the models and parameters, evaluates and combines the priors with the possibility to assign a weight. |
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.
The need of an additional class seems unclear at the moment. It does only stat_sum
, you could equivalently do something like this in Datasets.stat_sum()
:
def stat_sum(self):
"""Compute joint statistic function value."""
stat_sum = 0
for dataset in self:
stat_sum += dataset.stat_sum()
prior_stat_sum = self.models.parameters.prior_stat_sum()
return stat_sum + prior_stat_sum
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.
The idea of the additional class is just to make it explicit, that one changes to a MAP estimate. It's like a global switch to account for the prior or not. The alternative is indeed to always evaluate priors, if present...
Co-authored-by: Régis Terrier <regis.terrier@m4x.org>
Co-authored-by: Régis Terrier <regis.terrier@m4x.org>
I don't think they are not distinct features. If you do the math you will find the L2 regularization corresponds to a multivariate Gaussian prior in a Maximum A-Posteriori estimation. The information is all in the covariance matrix. I think the right approach here is to just introduce a |
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.
Thanks @katrinstreil .
Let's now send it to the CC.
@katrinstreil , you will also need to update the index.rst file to add the PIG to the list. |
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.
Thank you, @katrinstreil and @nbiederbeck
f3bcc8b
Co-authored-by: Régis Terrier <regis.terrier@m4x.org>
Review period is over. The PIG is accepted. Merging now. |
This pull request adds a rough PIG for
Prior
(andFitStatistic
). I anticipate I will add details with your assistance.