Sure. Here’s get_alpha_beta()
:
@staticmethod
def get_alpha_beta(alpha, beta, mu, sd):
if (alpha is not None):
if (beta is not None):
pass
else:
beta = 1
elif (mu is not None) and (sd is not None):
alpha = (2 * sd**2 + mu**2)/sd**2
beta = mu * (mu**2 + sd**2) / sd**2
else:
raise ValueError('Incompatible parameterization. Either use '
'alpha and (optionally) beta, or mu and sd to specify '
'distribution.')
return alpha, beta
…and this is the message I get from pytest:
______________________________________________________ TestMatchesScipy.test_inverse_gamma _______________________________________________________
self = <pymc3.tests.test_distributions.TestMatchesScipy object at 0x1261176a0>
def test_inverse_gamma(self):
self.pymc3_matches_scipy(
InverseGamma, Rplus, {'alpha': Rplus, 'beta': Rplus},
lambda value, alpha, beta: sp.invgamma.logpdf(value, alpha, scale=beta))
self.pymc3_matches_scipy(
InverseGamma, Rplus, {'mu': Rplus, 'sd': Rplus},
lambda value, mu, sd: sp.invgamma.logpdf(value, InverseGamma.get_alpha_beta(mu, sd)[0],
scale=InverseGamma.get_alpha_beta(mu, sd)[1]))
> def test_pareto(self):
pymc3/tests/test_distributions.py:709:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
pymc3/tests/test_distributions.py:438: in pymc3_matches_scipy
self.check_logp(model, value, domain, paramdomains, logp, decimal=decimal)
pymc3/tests/test_distributions.py:448: in check_logp
assert_almost_equal(logp(pt), logp_reference(pt), decimal=decimal, err_msg=str(pt))
pymc3/tests/test_distributions.py:437: in logp
return scipy_dist(**args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
value = array(1.5), mu = array(100.), sd = array(0.9)
> def test_pareto(self):
E TypeError: get_alpha_beta() missing 2 required positional arguments: 'mu' and 'sd'
pymc3/tests/test_distributions.py:709: TypeError
when I look at the test code, it looks like I should be passing pymc3_matches_scipy
a function of three arguments, value
, mu
, and sd
(i.e., value
and the parameters of the distribution), but this is what’s giving me the error. Looking at the code for TestMatchesScipy
it looks almost like this is used in a curried way – like the parameters to the distribution are passed first, and then the points to evaluate the logp
are plugged in separately, but TBH I really don’t understand the testing code at all.
Actually, a quick follow up: the type error makes it look like the function was passed a pair of singleton arrays for mu
and sd
which my code definitely wouldn’t expect. But the error message says that it’s missing two arguments. So this error message is pretty confusing. It shows three arguments, value
, mu
, and sd
, getting arrays of 1.5
, 100
, and 0.9
, respectively, but then it says that two of the arguments are missing.
Final follow-up: the call to the scipy function is made by scipy_dist(**args)
(shouldn’t that be **kwargs
to be more pythonic?).
So my guess is that this is going awry because of something involving my simple lambda getting an argument dictionary.
But if that’s the case, since my lambda looks like others in distribution_tests.py
, I’m still puzzled by the error. That is, the following test form in the same test definition works correctly:
self.pymc3_matches_scipy(
InverseGamma, Rplus, {'alpha': Rplus, 'beta': Rplus},
lambda value, alpha, beta: sp.invgamma.logpdf(value, alpha, scale=beta))
… so I’m still a little lost here.