beta.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import numbers
  15. import paddle
  16. from paddle.distribution import dirichlet, exponential_family
  17. class Beta(exponential_family.ExponentialFamily):
  18. r"""
  19. Beta distribution parameterized by alpha and beta.
  20. In probability theory and statistics, the beta distribution is a family of
  21. continuous probability distributions defined on the interval [0, 1]
  22. parameterized by two positive shape parameters, denoted by alpha and beta,
  23. that appear as exponents of the random variable and control the shape of
  24. the distribution. The generalization to multiple variables is called a
  25. Dirichlet distribution.
  26. The probability density function (pdf) is
  27. .. math::
  28. f(x; \alpha, \beta) = \frac{1}{B(\alpha, \beta)}x^{\alpha-1}(1-x)^{\beta-1}
  29. where the normalization, B, is the beta function,
  30. .. math::
  31. B(\alpha, \beta) = \int_{0}^{1} t^{\alpha - 1} (1-t)^{\beta - 1}\mathrm{d}t
  32. Args:
  33. alpha (float|Tensor): Alpha parameter. It supports broadcast semantics.
  34. The value of alpha must be positive. When the parameter is a tensor,
  35. it represents multiple independent distribution with
  36. a batch_shape(refer to ``Distribution`` ).
  37. beta (float|Tensor): Beta parameter. It supports broadcast semantics.
  38. The value of beta must be positive(>0). When the parameter is tensor,
  39. it represent multiple independent distribution with
  40. a batch_shape(refer to ``Distribution`` ).
  41. Examples:
  42. .. code-block:: python
  43. >>> import paddle
  44. >>> # scale input
  45. >>> beta = paddle.distribution.Beta(alpha=0.5, beta=0.5)
  46. >>> print(beta.mean)
  47. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  48. 0.50000000)
  49. >>> print(beta.variance)
  50. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  51. 0.12500000)
  52. >>> print(beta.entropy())
  53. Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
  54. -0.24156499)
  55. >>> # tensor input with broadcast
  56. >>> beta = paddle.distribution.Beta(alpha=paddle.to_tensor([0.2, 0.4]), beta=0.6)
  57. >>> print(beta.mean)
  58. Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
  59. [0.25000000, 0.40000001])
  60. >>> print(beta.variance)
  61. Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
  62. [0.10416666, 0.12000000])
  63. >>> print(beta.entropy())
  64. Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
  65. [-1.91923141, -0.38095081])
  66. """
  67. def __init__(self, alpha, beta):
  68. if isinstance(alpha, numbers.Real):
  69. alpha = paddle.full(shape=[], fill_value=alpha)
  70. if isinstance(beta, numbers.Real):
  71. beta = paddle.full(shape=[], fill_value=beta)
  72. self.alpha, self.beta = paddle.broadcast_tensors([alpha, beta])
  73. self._dirichlet = dirichlet.Dirichlet(
  74. paddle.stack([self.alpha, self.beta], -1)
  75. )
  76. super().__init__(self._dirichlet._batch_shape)
  77. @property
  78. def mean(self):
  79. """Mean of beta distribution."""
  80. return self.alpha / (self.alpha + self.beta)
  81. @property
  82. def variance(self):
  83. """Variance of beat distribution"""
  84. sum = self.alpha + self.beta
  85. return self.alpha * self.beta / (sum.pow(2) * (sum + 1))
  86. def prob(self, value):
  87. """Probability density function evaluated at value
  88. Args:
  89. value (Tensor): Value to be evaluated.
  90. Returns:
  91. Tensor: Probability.
  92. """
  93. return paddle.exp(self.log_prob(value))
  94. def log_prob(self, value):
  95. """Log probability density function evaluated at value
  96. Args:
  97. value (Tensor): Value to be evaluated
  98. Returns:
  99. Tensor: Log probability.
  100. """
  101. return self._dirichlet.log_prob(paddle.stack([value, 1.0 - value], -1))
  102. def sample(self, shape=()):
  103. """Sample from beta distribution with sample shape.
  104. Args:
  105. shape (Sequence[int], optional): Sample shape.
  106. Returns:
  107. Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`.
  108. """
  109. shape = shape if isinstance(shape, tuple) else tuple(shape)
  110. return paddle.squeeze(self._dirichlet.sample(shape)[..., 0], axis=-1)
  111. def entropy(self):
  112. """Entropy of dirichlet distribution
  113. Returns:
  114. Tensor: Entropy.
  115. """
  116. return self._dirichlet.entropy()
  117. @property
  118. def _natural_parameters(self):
  119. return (self.alpha, self.beta)
  120. def _log_normalizer(self, x, y):
  121. return paddle.lgamma(x) + paddle.lgamma(y) - paddle.lgamma(x + y)