Skip to content
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

Refactor priors #329

Merged
merged 4 commits into from
Dec 11, 2024
Merged

Refactor priors #329

merged 4 commits into from
Dec 11, 2024

Conversation

dweindl
Copy link
Member

@dweindl dweindl commented Dec 4, 2024

Introduces Prior and Distribution classes for handling PEtab-specific prior distributions, and (PEtab-version-invariant) univariate probability distributions. Supports sampling from them, and evaluating negative log-priors (#312). Later on, this can be extended to noise models for measurements and computing loglikelihoods.
This also adds a notebook demonstrating the various prior options which are a common source confusion.

Closes #311.

👀 notebook: https://petab--329.org.readthedocs.build/projects/libpetab-python/en/329/example/distributions.html

@codecov-commenter
Copy link

codecov-commenter commented Dec 4, 2024

Codecov Report

Attention: Patch coverage is 82.63158% with 33 lines in your changes missing coverage. Please review.

Project coverage is 74.65%. Comparing base (d7f7e3a) to head (7ecc231).

Files with missing lines Patch % Lines
petab/v1/priors.py 84.09% 9 Missing and 5 partials ⚠️
petab/v1/distributions.py 88.50% 10 Missing ⚠️
petab/v1/sampling.py 25.00% 8 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #329      +/-   ##
===========================================
+ Coverage    74.51%   74.65%   +0.13%     
===========================================
  Files           53       54       +1     
  Lines         5222     5381     +159     
  Branches       910      923      +13     
===========================================
+ Hits          3891     4017     +126     
- Misses         984     1012      +28     
- Partials       347      352       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@dweindl dweindl force-pushed the 311_refactor_priors branch 5 times, most recently from 5313345 to b28e5c1 Compare December 4, 2024 22:38
@dweindl dweindl marked this pull request as ready for review December 4, 2024 22:47
@dweindl dweindl requested review from m-philipps and a team as code owners December 4, 2024 22:48
@dweindl dweindl self-assigned this Dec 4, 2024
@dweindl dweindl force-pushed the 311_refactor_priors branch 4 times, most recently from 721ba31 to d511639 Compare December 7, 2024 10:04
@dweindl dweindl marked this pull request as draft December 8, 2024 11:25
@dweindl dweindl force-pushed the 311_refactor_priors branch from d511639 to 9381d7c Compare December 9, 2024 13:42
@dweindl
Copy link
Member Author

dweindl commented Dec 9, 2024

Requires some clarification related to normalization of the prior density. Related to PEtab-dev/PEtab#402.

EDIT: Needs clarification, but the current implementation matches what was done before.

@dweindl dweindl force-pushed the 311_refactor_priors branch 4 times, most recently from a272255 to 86643ec Compare December 9, 2024 21:43
@dweindl dweindl marked this pull request as ready for review December 9, 2024 21:44
Copy link
Member

@dilpath dilpath left a comment

Choose a reason for hiding this comment

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

Looks good, thanks 👍

petab/v1/distributions.py Outdated Show resolved Hide resolved
Comment on lines 46 to 54
def __init__(
self,
type_: str,
transformation: str,
parameters: tuple,
bounds: tuple = None,
parameter_scale: bool = False,
):
Copy link
Member

Choose a reason for hiding this comment

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

Support supplying some rng: np.Generator = None and otherwise set self.rng = np.random.default_rng() in __init__?

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense. I'll add that separately. For now, it's handled the same way as before, using the default numpy random state.

petab/v1/distributions.py Outdated Show resolved Hide resolved
petab/v1/sampling.py Outdated Show resolved Hide resolved

# Kolmogorov-Smirnov test to check if the sample is drawn from the CDF
_, p = kstest(sample, cdf)
assert p > 0.05, (p, distribution)
Copy link
Member

Choose a reason for hiding this comment

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

Should this be higher than 0.05? e.g. p > 0.5 should also always work for 10000 samples, just guessing. Anyway, fine as is.

Copy link
Member Author

Choose a reason for hiding this comment

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

With p > 0.5 this will fail frequently. Even with p > 0.05 it fails often enough so that I set a seed.

Copy link
Member

Choose a reason for hiding this comment

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

That's surprising! I would have guessed that 10,000 samples from a "simple" distribution should be enough to say "these distributions look similar"... anyway fine 👍

@dweindl dweindl force-pushed the 311_refactor_priors branch 3 times, most recently from a6429c8 to 9013648 Compare December 10, 2024 08:25
Introduce `Distribution` classes for handling prior distributions and sampling from them.
Later on this can be extended to noise models for measurements.
@dweindl dweindl force-pushed the 311_refactor_priors branch from 9013648 to e25785f Compare December 10, 2024 08:26
@dweindl dweindl force-pushed the 311_refactor_priors branch 2 times, most recently from 0b704ba to cc6a7e7 Compare December 10, 2024 17:30
@dweindl dweindl requested a review from dilpath December 10, 2024 17:31
@dweindl dweindl force-pushed the 311_refactor_priors branch from cc6a7e7 to 047dc46 Compare December 10, 2024 17:41
Copy link
Member

@dilpath dilpath left a comment

Choose a reason for hiding this comment

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

Looks neat, thanks!

def __init__(self, log: bool | float = False):
if log is True:
log = np.exp(1)
self._log = log
Copy link
Member

Choose a reason for hiding this comment

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

I find this more readable in _undo_log and __apply_log

Suggested change
self._log = log
self._log_base = log

Comment on lines +92 to +115
match type_, transformation:
case (C.UNIFORM, _) | (C.PARAMETER_SCALE_UNIFORM, C.LIN):
self.distribution = Uniform(*parameters)
case (C.NORMAL, _) | (C.PARAMETER_SCALE_NORMAL, C.LIN):
self.distribution = Normal(*parameters)
case (C.LAPLACE, _) | (C.PARAMETER_SCALE_LAPLACE, C.LIN):
self.distribution = Laplace(*parameters)
case (C.PARAMETER_SCALE_UNIFORM, C.LOG):
self.distribution = Uniform(*parameters, log=True)
case (C.LOG_NORMAL, _) | (C.PARAMETER_SCALE_NORMAL, C.LOG):
self.distribution = Normal(*parameters, log=True)
case (C.LOG_LAPLACE, _) | (C.PARAMETER_SCALE_LAPLACE, C.LOG):
self.distribution = Laplace(*parameters, log=True)
case (C.PARAMETER_SCALE_UNIFORM, C.LOG10):
self.distribution = Uniform(*parameters, log=10)
case (C.PARAMETER_SCALE_NORMAL, C.LOG10):
self.distribution = Normal(*parameters, log=10)
case (C.PARAMETER_SCALE_LAPLACE, C.LOG10):
self.distribution = Laplace(*parameters, log=10)
case _:
raise ValueError(
"Unsupported distribution type / transformation: "
f"{type_} / {transformation}"
)
Copy link
Member

Choose a reason for hiding this comment

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

base 2? 😀

Copy link
Member Author

Choose a reason for hiding this comment

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

Once in PEtab 🙄

Comment on lines 37 to 39
# pdf -> cdf
def cdf(x):
return cumulative_trapezoid(distribution.pdf(x), x)
Copy link
Member

Choose a reason for hiding this comment

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

Makes sense to ensure that the samples match the PDF within PEtab. For the LIN transform cases, could you additionally compare to scipy.stats.(log)(uniform/normal/laplace)? I guess the LOG and LOG10 transforms will be dropped in v2 so less important to test I guess

@dweindl dweindl merged commit 8456635 into PEtab-dev:develop Dec 11, 2024
7 checks passed
@dweindl dweindl deleted the 311_refactor_priors branch December 11, 2024 08:49
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.

3 participants