pytensor
pytensor copied to clipboard
Implement Rayleigh RV as a scaled Chi2
Description
Code:
def rayleigh(scale=1.0, *, size=None, **kwargs):
return chi2(df=2, size=size, **kwargs) * as_tensor_variable(scale)
from: https://github.com/pymc-devs/pytensor/pull/220#issuecomment-1435947464
Using a code along the above mentioned lines:
def rayleigh(scale=1.0, *, size=None, **kwargs):
return chisquare(df=2, size=size, **kwargs) * as_tensor_variable(scale)
, the test:
def test_rayleigh_samples():
compare_sample_values(rayleigh)
fails with traceback:
____________________________ test_rayleigh_samples ____________________________
def test_rayleigh_samples():
> compare_sample_values(rayleigh)
tests\tensor\random\test_basic.py:401:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests\tensor\random\test_basic.py:138: in compare_sample_values
np.testing.assert_allclose(pytensor_res_val, numpy_res)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
args = (<function assert_allclose.<locals>.compare at 0x00000187EBDF4180>, array(1.58225191), array(1.25787595))
kwds = {'equal_nan': True, 'err_msg': '', 'header': 'Not equal to tolerance rtol=1e-07, atol=0', 'verbose': True}
@wraps(func)
def inner(*args, **kwds):
with self._recreate_cm():
> return func(*args, **kwds)
E AssertionError:
E Not equal to tolerance rtol=1e-07, atol=0
E
E Mismatched elements: 1 / 1 (100%)
E Max absolute difference: 0.32437596
E Max relative difference: 0.25787595
E x: array(1.582252)
E y: array(1.257876)```
A test more along the chi2 lines also fails like this:
@pytest.mark.parametrize(
"size",
[
(None),
([]),
],
)
def test_rayleigh_samples(size):
compare_sample_values(rayleigh, size=size, test_fn=fixed_scipy_rvs("rayleigh"))
with traceback:
_________________________ test_rayleigh_samples[None] _________________________
size = None
@pytest.mark.parametrize(
"size",
[
(None),
([]),
],
)
def test_rayleigh_samples(size):
> compare_sample_values(rayleigh, size=size, test_fn=fixed_scipy_rvs("rayleigh"))
tests\tensor\random\test_basic.py:401:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests\tensor\random\test_basic.py:138: in compare_sample_values
np.testing.assert_allclose(pytensor_res_val, numpy_res)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
args = (<function assert_allclose.<locals>.compare at 0x0000011B227AA020>, array(0.47892931), array(0.69204719))
kwds = {'equal_nan': True, 'err_msg': '', 'header': 'Not equal to tolerance rtol=1e-07, atol=0', 'verbose': True}
@wraps(func)
def inner(*args, **kwds):
with self._recreate_cm():
> return func(*args, **kwds)
E AssertionError:
E Not equal to tolerance rtol=1e-07, atol=0
E
E Mismatched elements: 1 / 1 (100%)
E Max absolute difference: 0.21311788
E Max relative difference: 0.30795281
E x: array(0.478929)
E y: array(0.692047)
..\..\..\miniconda3\envs\pytensor-dev\Lib\contextlib.py:81: AssertionError
________________________ test_rayleigh_samples[size1] _________________________
size = []
@pytest.mark.parametrize(
"size",
[
(None),
([]),
],
)
def test_rayleigh_samples(size):
> compare_sample_values(rayleigh, size=size, test_fn=fixed_scipy_rvs("rayleigh"))
tests\tensor\random\test_basic.py:401:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests\tensor\random\test_basic.py:138: in compare_sample_values
np.testing.assert_allclose(pytensor_res_val, numpy_res)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
args = (<function assert_allclose.<locals>.compare at 0x0000011B228BB880>, array(1.7294089), array(1.31506992))
kwds = {'equal_nan': True, 'err_msg': '', 'header': 'Not equal to tolerance rtol=1e-07, atol=0', 'verbose': True}
@wraps(func)
def inner(*args, **kwds):
with self._recreate_cm():
> return func(*args, **kwds)
E AssertionError:
E Not equal to tolerance rtol=1e-07, atol=0
E
E Mismatched elements: 1 / 1 (100%)
E Max absolute difference: 0.41433898
E Max relative difference: 0.31506992
E x: array(1.729409)
E y: array(1.31507)
The values need not match if the draws are taken differently. We should double check the math is correct, and then you can see if the mean/std of a bunch of draws are close enough. There are some draws we already test with the CDF as well.
Assuming the math is correct, the only thing to be aware there with the scale on the outside is that we don't want the chi2 draws to broadcast. It should have one chi2 draw per output value. Similar to the problem we fixed recently in https://github.com/pymc-devs/pymc/pull/7288