chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
+295
View File
@@ -0,0 +1,295 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
import math
import numbers
from typing import TYPE_CHECKING
import numpy as np
import paddle
from paddle.base import framework
from paddle.distribution.transformed_distribution import TransformedDistribution
from paddle.utils.decorator_utils import param_one_alias
if TYPE_CHECKING:
from collections.abc import Sequence
from paddle import Tensor
from paddle.distribution import Transform, Uniform
class Gumbel(TransformedDistribution):
r"""The Gumbel distribution with location `loc` and `scale` parameters.
Mathematical details
The probability density function (pdf) is
.. math::
pdf(x; mu, sigma) = exp(-(x - mu) / sigma - exp(-(x - mu) / sigma)) / sigma
In the above equation:
* :math:`loc = \mu`: is the mean.
* :math:`scale = \sigma`: is the std.
Args:
loc(int|float|tensor): The mean of gumbel distribution.The data type is int, float, tensor.
scale(int|float|tensor): The std of gumbel distribution.The data type is int, float, tensor.
Examples:
.. code-block:: pycon
>>> import paddle
>>> from paddle.distribution.gumbel import Gumbel
>>> # Gumbel distributed with loc=0, scale=1
>>> dist = Gumbel(paddle.full([1], 0.0), paddle.full([1], 1.0))
>>> # doctest: +SKIP("The sample results is randomized.")
>>> print(dist.sample([2]))
Tensor(shape=[2, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
[[0.40484068],
[3.19400501]])
>>> print(dist.rsample([2]))
Tensor(shape=[2, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
[[-0.95093185],
[ 0.32422572]])
>>> # doctest: -SKIP
>>> value = paddle.full([1], 0.5)
>>> print(dist.prob(value))
Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
[0.33070430])
>>> print(dist.log_prob(value))
Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
[-1.10653067])
>>> print(dist.cdf(value))
Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
[0.54523921])
>>> print(dist.entropy())
Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
[1.57721567])
"""
loc: Tensor
scale: Tensor
base_dist: Uniform
transforms: tuple[Transform, ...]
def __init__(self, loc: float | Tensor, scale: float | Tensor) -> None:
if not isinstance(
loc, (numbers.Real, framework.Variable, paddle.pir.Value)
):
raise TypeError(
f"Expected type of loc is Real|Variable|Value, but got {type(loc)}"
)
if not isinstance(
scale, (numbers.Real, framework.Variable, paddle.pir.Value)
):
raise TypeError(
f"Expected type of scale is Real|Variable|Value, but got {type(scale)}"
)
if isinstance(loc, numbers.Real):
loc = paddle.full(shape=(), fill_value=loc)
if isinstance(scale, numbers.Real):
scale = paddle.full(shape=(), fill_value=scale)
if loc.shape != scale.shape:
self.loc, self.scale = paddle.broadcast_tensors([loc, scale])
else:
self.loc, self.scale = loc, scale
finfo = np.finfo(dtype='float32')
self.base_dist = paddle.distribution.Uniform(
paddle.full_like(self.loc, float(finfo.tiny)),
paddle.full_like(self.loc, float(1 - finfo.eps)),
)
self.transforms = ()
super().__init__(self.base_dist, self.transforms)
@property
def mean(self) -> Tensor:
r"""Mean of distribution
The mean is
.. math::
mean = \mu + \sigma * γ
In the above equation:
* :math:`loc = \mu`: is the location parameter.
* :math:`scale = \sigma`: is the scale parameter.
* :math:`γ`: is the euler's constant.
Returns:
Tensor: mean value.
"""
return self.loc + self.scale * np.euler_gamma
@property
def variance(self) -> Tensor:
r"""Variance of distribution.
The variance is
.. math::
variance = \sigma^2 * \pi^2 / 6
In the above equation:
* :math:`scale = \sigma`: is the scale parameter.
Returns:
Tensor: The variance value.
"""
temp = paddle.full(
shape=self.loc.shape,
fill_value=math.pi * math.pi,
dtype=self.scale.dtype,
)
return paddle.pow(self.scale, 2) * temp / 6
@property
def stddev(self) -> Tensor:
r"""Standard deviation of distribution
The standard deviation is
.. math::
stddev = \sqrt{\sigma^2 * \pi^2 / 6}
In the above equation:
* :math:`scale = \sigma`: is the scale parameter.
Returns:
Tensor: std value
"""
return paddle.sqrt(self.variance)
def prob(self, value: Tensor) -> Tensor:
"""Probability density/mass function
Args:
value (Tensor): The input tensor.
Returns:
Tensor: probability.The data type is same with value.
"""
y = (self.loc - value.astype(self.loc.dtype)) / self.scale.astype(
self.loc.dtype
)
return paddle.exp(y - paddle.exp(y)) / self.scale.astype(y.dtype)
def log_prob(self, value: Tensor) -> Tensor:
"""Log probability density/mass function.
Args:
value (Tensor): The input tensor.
Returns:
Tensor: log probability.The data type is same with value.
"""
return paddle.log(self.prob(value))
def cdf(self, value: Tensor) -> Tensor:
"""Cumulative distribution function.
Args:
value (Tensor): value to be evaluated.
Returns:
Tensor: cumulative probability of value.
"""
return paddle.exp(
-paddle.exp(
-(value - self.loc.astype(value.dtype))
/ self.scale.astype(value.dtype)
)
)
def entropy(self) -> Tensor:
"""Entropy of Gumbel distribution.
Returns:
Entropy of distribution.
"""
return paddle.log(self.scale) + 1 + np.euler_gamma
@param_one_alias(["shape", "sample_shape"])
def sample(self, shape: Sequence[int] = []) -> Tensor:
"""Sample from ``Gumbel``.
Args:
shape (Sequence[int], optional): The sample shape. Defaults to [].
Returns:
Tensor: A tensor with prepended dimensions shape.The data type is float32.
"""
with paddle.no_grad():
return self.rsample(shape)
@param_one_alias(["shape", "sample_shape"])
def rsample(self, shape: Sequence[int] = []) -> Tensor:
"""reparameterized sample
Args:
shape (Sequence[int], optional): 1D `int32`. Shape of the generated samples. Defaults to [].
Returns:
Tensor: A tensor with prepended dimensions shape.The data type is float32.
"""
exp_trans = paddle.distribution.ExpTransform()
affine_trans_1 = paddle.distribution.AffineTransform(
paddle.full(
shape=self.scale.shape, fill_value=0, dtype=self.loc.dtype
),
-paddle.ones_like(self.scale),
)
affine_trans_2 = paddle.distribution.AffineTransform(
self.loc, -self.scale
)
return affine_trans_2.forward(
exp_trans.inverse(
affine_trans_1.forward(
exp_trans.inverse(self._base.sample(shape))
)
)
)