o
    "j<                     @   s   d dl Zd dlZd dlmZmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZmZmZ eejjeejjdZdd	 ZG d
d de	jZdS )    N)
check_typeconvert_dtype)Variable)exponential_family)in_dynamic_mode) binary_cross_entropy_with_logitssigmoidsoftplus)float32float64c                 C   s$   t |}tj| |d| d|S )zClip probs from [0, 1] to (0, 1) with ``eps``.

    Args:
        probs (Tensor): probs of Bernoulli.
        dtype (str): data type.

    Returns:
        Tensor: Clipped probs.
       )minmax)EPSgetpaddleZclipZastype)probsdtypeeps r   ^/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/distribution/bernoulli.py_clip_probs$   s   

r   c                       st   e Zd ZdZd fdd	Zedd Zedd Zd	d
 ZdddZ	dd Z
dd Zdd Zdd Zdd Z  ZS )	Bernoullia  Bernoulli distribution parameterized by ``probs``, which is the probability of value 1.

    In probability theory and statistics, the Bernoulli distribution, named after Swiss
    mathematician Jacob Bernoulli, is the discrete probability distribution of a random
    variable which takes the value 1 with probability ``p`` and the value 0 with
    probability ``q=1-p``.

    The probability mass function of this distribution, over possible outcomes ``k``, is

    .. math::

        {\begin{cases}
        q=1-p & \text{if }value=0 \\
        p & \text{if }value=1
        \end{cases}}

    Args:
        probs (float|Tensor): The ``probs`` input of Bernoulli distribution. The data type is float32 or float64. The range must be in [0, 1].
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Examples:

        .. code-block:: python

            >>> import paddle
            >>> from paddle.distribution import Bernoulli

            >>> # init `probs` with a float
            >>> rv = Bernoulli(probs=0.3)

            >>> print(rv.mean)
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            0.30000001)

            >>> print(rv.variance)
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            0.21000001)

            >>> print(rv.entropy())
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            0.61086434)
    Nc                    s   |pd| _ t st|dttf| j  | |r!|| _t|j| _n| 	|\| _t
 | _t rN	 t
| jdk sJt
| jdksJt
t
| jrNtdt| j| j| _| j| jdd| _t j| jjdd	 d S )
Nr   r   r   r   z+The arg of `probs` must be in range [0, 1].T)Z	is_binaryr   )Zbatch_shapeZevent_shape)namer   r   floatr   Z_validate_argsr   r   r   Z
_to_tensorr   Zget_default_dtypeanyisnan
ValueErrorr   Z_probs_to_logitslogitssuper__init__shape)selfr   r   	__class__r   r   r    ^   s2   


zBernoulli.__init__c                 C   s   | j S )zjMean of Bernoulli distribution.

        Returns:
            Tensor: Mean value of distribution.
        )r   r"   r   r   r   mean   s   zBernoulli.meanc                 C   s   t | jd| j S )zrVariance of Bernoulli distribution.

        Returns:
            Tensor: Variance value of distribution.
        r   )r   multiplyr   r%   r   r   r   variance   s   zBernoulli.variancec                 C   s   | j d }t st|dtjtttf| t|tr|nt|}| 	|}t
  t
j| j||dW  d   S 1 s>w   Y  dS )a  Sample from Bernoulli distribution.

        Args:
            shape (Sequence[int]): Sample shape.

        Returns:
            Tensor: Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Bernoulli

                >>> rv = Bernoulli(paddle.full((1), 0.3))
                >>> print(rv.sample([100]).shape)
                [100, 1]

                >>> rv = Bernoulli(paddle.to_tensor(0.3))
                >>> print(rv.sample([100]).shape)
                [100]

                >>> rv = Bernoulli(paddle.to_tensor([0.3, 0.5]))
                >>> print(rv.sample([100]).shape)
                [100, 2]

                >>> rv = Bernoulli(paddle.to_tensor([0.3, 0.5]))
                >>> print(rv.sample([100, 2]).shape)
                [100, 2, 2]
        _sampler!   r   N)r   r   r   npndarrayr   listtuple
isinstance_extend_shaper   Zno_gradZ	bernoullir   expand)r"   r!   r   r   r   r   sample   s   
 

$zBernoulli.sample      ?c              
   C   s   | j d }t st|dtjtttf| t|dtf| t	|tr#|nt|}| 
|}tjd|| jd}| j|}tj|| jd}ttt| |  t| |  |S )a
  Sample from Bernoulli distribution (reparameterized).

        The `rsample` is a continuously approximate of Bernoulli distribution reparameterized sample method.
        [1] Chris J. Maddison, Andriy Mnih, and Yee Whye Teh. The Concrete Distribution: A Continuous Relaxation of Discrete Random Variables. 2016.
        [2] Eric Jang, Shixiang Gu, and Ben Poole. Categorical Reparameterization with Gumbel-Softmax. 2016.

        Note:
            `rsample` need to be followed by a `sigmoid`, which converts samples' value to unit interval (0, 1).

        Args:
            shape (Sequence[int]): Sample shape.
            temperature (float): temperature for rsample, must be positive.

        Returns:
            Tensor: Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> paddle.seed(1)
                >>> from paddle.distribution import Bernoulli

                >>> rv = Bernoulli(paddle.full((1), 0.3))
                >>> print(rv.sample([100]).shape)
                [100, 1]

                >>> rv = Bernoulli(0.3)
                >>> print(rv.rsample([100]).shape)
                [100]

                >>> rv = Bernoulli(paddle.to_tensor([0.3, 0.5]))
                >>> print(rv.rsample([100]).shape)
                [100, 2]

                >>> rv = Bernoulli(paddle.to_tensor([0.3, 0.5]))
                >>> print(rv.rsample([100, 2]).shape)
                [100, 2, 2]

                >>> # `rsample` has to be followed by a `sigmoid`
                >>> rv = Bernoulli(0.3)
                >>> rsample = rv.rsample([3, ])
                >>> rsample_sigmoid = paddle.nn.functional.sigmoid(rsample)
                >>> print(rsample)
                Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
                [-1.46112013, -0.01239836, -1.32765460])
                >>> print(rsample_sigmoid)
                Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.18829606, 0.49690047, 0.20954758])

                >>> # The smaller the `temperature`, the distribution of `rsample` closer to `sample`, with `probs` of 0.3.
                >>> print(paddle.nn.functional.sigmoid(rv.rsample([1000, ], temperature=1.0)).sum())
                >>> # doctest: +SKIP('output will be different')
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                365.63122559)
                >>> # doctest: -SKIP

                >>> print(paddle.nn.functional.sigmoid(rv.rsample([1000, ], temperature=0.1)).sum())
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                320.15057373)
        Z_rsampler!   temperaturer   )r!   Z
fill_valuer   )r   )r   r   r   r+   r,   r   r-   r.   r   r/   r0   r   fullr   r   r1   Zranddivideaddsubtractloglog1p)r"   r!   r4   r   r   Zuniformsr   r   r   rsample   s8   
?
zBernoulli.rsamplec              
   C   s   | j d }t st|dt| | | j|}t| j|g\}}t|}t	|}tj
|dk |t
|dk t||||dS )a
  Cumulative distribution function(CDF) evaluated at value.

        .. math::

            { \begin{cases}
            0 & \text{if } value \lt  0 \\
            1 - p & \text{if } 0 \leq value \lt  1 \\
            1 & \text{if } value \geq 1
            \end{cases}
            }

        Args:
            value (Tensor): Value to be evaluated.

        Returns:
            Tensor: CDF evaluated at value.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Bernoulli

                >>> rv = Bernoulli(0.3)
                >>> print(rv.cdf(paddle.to_tensor([1.0])))
                Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
                [1.])
        Z_cdfvaluer   r   r*   )r   r   r   r   _check_values_dtype_in_probsr   r   broadcast_tensorsZ
zeros_likeZ	ones_likewherer8   )r"   r<   r   r   ZzerosZonesr   r   r   cdf   s   


zBernoulli.cdfc                 C   sR   | j d }t st|dt| | | j|}t| j|g\}}t	||d|d S )a=  Log of probability densitiy function.

        Args:
            value (Tensor): Value to be evaluated.

        Returns:
            Tensor: Log of probability densitiy evaluated at value.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Bernoulli

                >>> rv = Bernoulli(0.3)
                >>> print(rv.log_prob(paddle.to_tensor([1.0])))
                Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
                [-1.20397282])
        Z	_log_probr<   noneZ	reductionr   )
r   r   r   r   r=   r   r   r>   r   r   )r"   r<   r   r   r   r   r   log_probO  s   
zBernoulli.log_probc                 C   s0   | j d }t st|dt| | |j|dS )a  Probability density function(PDF) evaluated at value.

        .. math::

            { \begin{cases}
                q=1-p & \text{if }value=0 \\
                p & \text{if }value=1
                \end{cases}
            }

        Args:
            value (Tensor): Value to be evaluated.

        Returns:
            Tensor: PDF evaluated at value.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Bernoulli

                >>> rv = Bernoulli(0.3)
                >>> print(rv.prob(paddle.to_tensor([1.0])))
                Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.29999998])
        Z_probr<   r*   )r   r   r   r   rC   exp)r"   r<   r   r   r   r   probn  s   
zBernoulli.probc                 C   s   | j d }t| j| jd|dS )a&  Entropy of Bernoulli distribution.

        .. math::

            {
                entropy = -(q \log q + p \log p)
            }

        Returns:
            Tensor: Entropy of distribution.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Bernoulli

                >>> rv = Bernoulli(0.3)
                >>> print(rv.entropy())
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                0.61086434)
        Z_entropyrA   rB   )r   r   r   r   )r"   r   r   r   r   entropy  s   
zBernoulli.entropyc              
   C   s   | j d }t st|dt| | j}|j}t|  }t|  }t|}t| }t| }	t| }
tt	t
||t
||t	t
|	|t
|
|S )a  The KL-divergence between two Bernoulli distributions.

        .. math::

            {
                KL(a || b) = p_a \log(p_a / p_b) + (1 - p_a) \log((1 - p_a) / (1 - p_b))
            }

        Args:
            other (Bernoulli): instance of Bernoulli.

        Returns:
            Tensor: kl-divergence between two Bernoulli distributions.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Bernoulli

                >>> rv = Bernoulli(0.3)
                >>> rv_other = Bernoulli(0.7)

                >>> print(rv.kl_divergence(rv_other))
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                0.33891910)
        Z_kl_divergenceother)r   r   r   r   r   r	   r   r   r7   r8   r'   )r"   rG   r   Za_logitsZb_logitsZlog_paZlog_pbpaZone_minus_paZlog_one_minus_paZlog_one_minus_pbr   r   r   kl_divergence  s(   





zBernoulli.kl_divergence)N)r3   )__name__
__module____qualname____doc__r    propertyr&   r(   r2   r;   r@   rC   rE   rF   rI   __classcell__r   r   r#   r   r   2   s    +"


/_/#r   )numpyr+   r   Zpaddle.base.data_feederr   r   Zpaddle.base.frameworkr   Zpaddle.distributionr   Zpaddle.frameworkr   Zpaddle.nn.functionalr   r   r	   Zfinfor
   r   r   r   r   ZExponentialFamilyr   r   r   r   r   <module>   s   