-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Added icdf for Rice and skewnormal distributions #7095
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,6 +76,9 @@ def polyagamma_cdf(*args, **kwargs): | |
from scipy import stats | ||
from scipy.interpolate import InterpolatedUnivariateSpline | ||
from scipy.special import expit | ||
from scipy.stats import norm | ||
from scipy.optimize import newton | ||
from scipy.special import ive, iv | ||
|
||
from pymc.distributions import transforms | ||
from pymc.distributions.dist_math import ( | ||
|
@@ -2993,6 +2996,29 @@ def logp(value, mu, sigma, alpha): | |
tau > 0, | ||
msg="tau > 0", | ||
) | ||
def icdf(prob, mu, sigma, alpha, max_iter=100, tol=1e-8): | ||
def cdf_difference(x): | ||
return norm.cdf(x) - 2 * norm.cdf(alpha * x) - prob | ||
|
||
x0 = norm.ppf(prob) | ||
x = x0 | ||
|
||
for _ in range(max_iter): | ||
diff = cdf_difference(x) | ||
|
||
if pt.abs(diff) < tol: | ||
return mu + sigma * x | ||
|
||
derivative = norm.pdf(x) - 2 * alpha * norm.pdf(alpha * x) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does |
||
x -= derivative | ||
|
||
res = mu + sigma * x | ||
res = check_icdf_value(res, prob) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain in words (or math) what is going on here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The provided code defines a function icdf that aims to find the inverse cumulative distribution function (ICDF) for a specific probability distribution. Calculates the cumulative distribution function (CDF) for a given input Calculates the derivative of the CDF with respect to Uses the Newton-Raphson method to iteratively find a value of x such that Performs some checks on the calculated ICDF value (res) and potentially modifies it. Checks whether certain parameters, in this case, The main function icdf combines these components to find the ICDF for a given probability (prob) using the Newton-Raphson method. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry to ask but are you a bot? The code will clearly not work with PyTensor variables. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. I am not a bot There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll fix everything and make a new pull request There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What do you mean by "likely indicating", "potentially modifies it"? This wording seems strange to me. Again, none of this will work with PyTensor variables. If you are relying on AI to generate responses and code changes, we cannot accept them |
||
return check_parameters( | ||
res, | ||
sigma > 0, | ||
msg="sigma > 0" | ||
) | ||
|
||
|
||
class Triangular(BoundedContinuous): | ||
|
@@ -3348,7 +3374,22 @@ def logp(value, b, sigma): | |
b >= 0, | ||
msg="sigma >= 0, b >= 0", | ||
) | ||
|
||
def icdf(prob, nu, sigma, x0=1.0, max_iter=100, tol=1e-8): | ||
def cdf(x): | ||
return (1 + x / sigma**2) * pt.exp(-x**2 / (2 * sigma**2)) * iv(0, x * nu / sigma**2) - prob | ||
|
||
def cdf_derivative(x): | ||
return ((1 - x**2 / sigma**2) * pt.exp(-x**2 / (2 * sigma**2)) * iv(0, x * nu / sigma**2) | ||
+ (x / sigma**2) * pt.exp(-x**2 / (2 * sigma**2)) * ive(0, x * nu / sigma**2)) * nu / sigma**2 | ||
|
||
approx_icdf = newton(cdf, x0, fprime=cdf_derivative, tol=tol, maxiter=max_iter) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will |
||
res = approx_icdf | ||
res = check_icdf_value(res, prob) | ||
return check_parameters( | ||
res, | ||
sigma > 0, | ||
msg="sigma > 0" | ||
) | ||
|
||
class Logistic(Continuous): | ||
r""" | ||
|
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.
What justifies the
icdf
method having a different signature compared to thelogp
method mentioned above?