-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
BUG: ETS multiplicative error models log-likelihood calculation #9137
base: main
Are you sure you want to change the base?
Changes from all commits
626bcb3
f7f8e18
a1031c3
834b0e4
cb4602a
da2daf0
1f905b0
370c013
97fc786
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 |
---|---|---|
|
@@ -1160,13 +1160,14 @@ def _loglike_internal( | |
res = self._residuals(yhat, data=data) | ||
logL = -self.nobs / 2 * (np.log(2 * np.pi * np.mean(res ** 2)) + 1) | ||
if self.error == "mul": | ||
# GH-7331: in some cases, yhat can become negative, so that a | ||
# multiplicative model is no longer well-defined. To avoid these | ||
# parameterizations, we clip negative values to very small positive | ||
# values so that the log-transformation yields very large negative | ||
# values. | ||
yhat[yhat <= 0] = 1 / (1e-8 * (1 + np.abs(yhat[yhat <= 0]))) | ||
logL -= np.sum(np.log(yhat)) | ||
# In some cases, yhat can become negative or zero, so that a | ||
# multiplicative model is no longer well-defined. Zero values | ||
# are replaced with 10^-32 (a very small number). For more | ||
# information on the derivation of the log-likelihood for the | ||
# multiplicative error models see: | ||
# https://openforecast.org/adam/ADAMETSEstimationLikelihood.html | ||
yhat[yhat == 0] = 1e-32 | ||
logL -= np.sum(np.log(np.abs(yhat))) | ||
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 don't think reflecting negatives is a good idea. Better to replace with small numbers. 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. Please note that the absolute value is not there to avoid negative numbers, but instead arises mathematically: If So, it is necessary to have it there for the correct calculation of the log-likelihood. The derivations are based on the Section 11.1 here: https://openforecast.org/adam/ADAMETSEstimationLikelihood.html 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. Thanks for reviewing the PR @bashtage and thanks for the additional explanation on the likelihood derivation @config-i1. Based on @config-i1's explanation and the other implementations, I think it makes sense to keep the |
||
return logL | ||
|
||
@contextlib.contextmanager | ||
|
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.
Really should leave the <=. == 0 is likely too strict, and if it really is ==0, then <=0 will catch all cases.
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.
Fun corner cases. FWIW, I don't think you need the clipping at all anymore. It's almost certainly not being triggered here, and if you do switch it to clip the negatives, then it becomes unstable again.