-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
cauchy.py
113 lines (86 loc) · 3.04 KB
/
cauchy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import warnings
import numpy
import chainer
from chainer.backends import cuda
from chainer import distribution
from chainer.functions.math import exponential
from chainer.functions.math import trigonometric
from chainer.utils import cache
def _cauchy_icdf(x):
x = chainer.as_variable(x)
h = (x - 0.5) * numpy.pi
y = chainer.functions.tan(h)
return y
class Cauchy(distribution.Distribution):
"""Cauchy Distribution.
The probability density function of the distribution is expressed as
.. math::
p(x;x_0,\\gamma) = \\frac{1}{\\pi}\\frac{\\gamma}{(x-x_0)^2+\\gamma^2}
Args:
loc(:class:`~chainer.Variable` or :ref:`ndarray`): Parameter of
distribution representing the location :math:`x_0`.
scale(:class:`~chainer.Variable` or :ref:`ndarray`): Parameter of
distribution representing the scale :math:`\\gamma`.
"""
def __init__(self, loc, scale):
super(Cauchy, self).__init__()
self.__loc = loc
self.__scale = scale
@cache.cached_property
def loc(self):
return chainer.as_variable(self.__loc)
@cache.cached_property
def scale(self):
return chainer.as_variable(self.__scale)
@property
def batch_shape(self):
return self.loc.shape
def cdf(self, x):
return (
(1 / numpy.pi
* trigonometric.arctan((x - self.loc) / self.scale))
+ 0.5)
@cache.cached_property
def entropy(self):
return exponential.log(4 * numpy.pi * self.scale)
@property
def event_shape(self):
return ()
def icdf(self, x):
return self.loc + self.scale * _cauchy_icdf(x)
@property
def _is_gpu(self):
return isinstance(self.loc.data, cuda.ndarray)
def log_prob(self, x):
return (
- numpy.log(numpy.pi)
+ exponential.log(self.scale)
- exponential.log((x - self.loc)**2 + self.scale**2))
@cache.cached_property
def mean(self):
warnings.warn('Mean of the cauchy distribution is undefined.',
RuntimeWarning)
xp = chainer.backend.get_array_module(self.loc)
return chainer.as_variable(xp.full_like(self.loc.data, xp.nan))
@property
def params(self):
return {'loc': self.loc, 'scale': self.scale}
def sample_n(self, n):
xp = chainer.backend.get_array_module(self.loc)
if xp is cuda.cupy:
eps = xp.random.standard_cauchy(
(n,)+self.loc.shape, dtype=self.loc.dtype)
else:
eps = xp.random.standard_cauchy(
(n,)+self.loc.shape).astype(self.loc.dtype)
noise = self.scale * eps + self.loc
return noise
@property
def support(self):
return 'real'
@cache.cached_property
def variance(self):
warnings.warn('Variance of the cauchy distribution is undefined.',
RuntimeWarning)
xp = chainer.backend.get_array_module(self.loc)
return chainer.as_variable(xp.full_like(self.loc.data, xp.nan))