Ë
    ˆ\;ju>  ã                   ó&  — 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j                   ej"                  «      j$                   ej                   ej&                  «      j$                  dœZd„ Z G d	„ d
e	j,                  «      Zy)é    N)Ú
check_typeÚconvert_dtype)ÚVariable)Úexponential_family)Úin_dynamic_mode)Ú binary_cross_entropy_with_logitsÚsigmoidÚsoftplus)Úfloat32Úfloat64c                 ó€   — t         j                  |«      }t        j                  | |d|z
  ¬«      j	                  |«      S )z·Clip 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ÚpaddleÚclipÚastype)ÚprobsÚdtypeÚepss      úfG:\00. PROJECTS\API\Inventory\templateJSON\kerjaOCR\Lib\site-packages\paddle/distribution/bernoulli.pyÚ_clip_probsr   $   s3   € ô �'‰'�%‹.€CÜ�;‰;�u #¨1¨s©7Ô3×:Ñ:¸5ÓAÐAó    c                   óp   ‡ — e Zd ZdZdˆ fd„	Zed„ «       Zed„ «       Zd„ Zdd„Z	d„ Z
d„ Zd	„ Zd
„ Zd„ Zˆ x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)
    c                 ó,  •— |xs d| _         t        «       s"t        |dt        t        f| j                   «       | j                  |«      r"|| _        t        |j                  «      | _        n1| j                  |«      \  | _        t        j                  «       | _        t        «       r‚	 t        j                  | j                  dk  «      sTt        j                  | j                  dkD  «      s2t        j                  t        j                  | j                  «      «      rt        d«      ‚t        | j                  | j                  «      | _        | j!                  | j                  d¬«      | _        t$        ‰| �M  | j                  j(                  d¬	«       y )
Nr   r   r   r   z+The arg of `probs` must be in range [0, 1].T)Ú	is_binary© )Úbatch_shapeÚevent_shape)Únamer   r   Úfloatr   Ú_validate_argsr   r   r   Ú
_to_tensorr   Úget_default_dtypeÚanyÚisnanÚ
ValueErrorr   Ú_probs_to_logitsÚlogitsÚsuperÚ__init__Úshape)Úselfr   r#   Ú	__class__s      €r   r.   zBernoulli.__init__^   s"  ø€ ØÒ'˜KˆŒ	ÜÔ ÜØØÜœÐ!Ø—	‘	ô	ð ×Ñ˜uÔ%ØˆDŒJÜ& u§{¡{Ó3ˆD�JàŸ?™?¨5Ó1‰LˆTŒZÜ×1Ñ1Ó3ˆDŒJô ÔØNä—
‘
˜4Ÿ:™:¨™>Ô*Ü—:‘:˜dŸj™j¨1™nÔ-Ü—:‘:œfŸl™l¨4¯:©:Ó6Ô7ä Ð!NÓOÐOô ! §¡¨T¯Z©ZÓ8ˆŒ
Ø×+Ñ+¨D¯J©JÀ$Ð+ÓGˆŒä‰Ñ T§Z¡Z×%5Ñ%5À2ÐÕFr   c                 ó   — | j                   S )zjMean of Bernoulli distribution.

        Returns:
            Tensor: Mean value of distribution.
        )r   ©r0   s    r   ÚmeanzBernoulli.mean€   s   € ð �z‰zÐr   c                 ó\   — t        j                  | j                  d| j                  z
  «      S )zrVariance of Bernoulli distribution.

        Returns:
            Tensor: Variance value of distribution.
        r   )r   Úmultiplyr   r3   s    r   ÚvariancezBernoulli.variance‰   s!   € ô �‰˜tŸz™z¨A°·
±
©NÓ<Ð<r   c                 óœ  — | j                   dz   }t        «       s,t        |dt        j                  t
        t        t        f|«       t        |t        «      r|n
t        |«      }| j                  |«      }t        j                  «       5  t        j                  | j                  j                  |«      |¬«      cddd«       S # 1 sw Y   yxY w)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   Úno_gradÚ	bernoullir   Úexpand)r0   r/   r#   s      r   ÚsamplezBernoulli.sample’   s•   € ð@ �y‰y˜9Ñ$ˆÜÔ ÜØØÜ—‘œX¤t¬UÐ3Øô	ô $ E¬5Ô1‘´u¸U³|ˆØ×"Ñ" 5Ó)ˆä�^‰^ÕÜ×#Ñ# D§J¡J×$5Ñ$5°eÓ$<À4ÔH÷ ×Òús   Â0CÃCc           
      óâ  — | j                   dz   }t        «       s?t        |dt        j                  t
        t        t        f|«       t        |dt        f|«       t        |t        «      r|n
t        |«      }| j                  |«      }t        j                  d|| j                  ¬«      }| j                  j                  |«      }t        j                   || j                  ¬«      }t        j"                  t        j$                  t        j&                  |j)                  «       | j+                  «       «      t        j&                  |j)                  «       | j+                  «       «      «      |«      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)
        Ú_rsampler/   Útemperaturer    )r/   Ú
fill_valuer   )r   )r#   r   r   r;   r<   r   r=   r>   r$   r?   r@   r   Úfullr   r   rC   ÚrandÚdivideÚaddÚsubtractÚlogÚlog1p)r0   r/   rG   r#   r   Úuniformss         r   ÚrsamplezBernoulli.rsampleÁ   s  € ð~ �y‰y˜:Ñ%ˆÜÔ ÜØØÜ—‘œX¤t¬UÐ3Øô	ô ØØÜ�Øô	ô $ E¬5Ô1‘´u¸U³|ˆØ×"Ñ" 5Ó)ˆä—k‘kØ °D·J±Jô
ˆð —
‘
×!Ñ! %Ó(ˆÜ—;‘;˜u¨D¯J©JÔ7ˆÜ�}‰}Ü�J‰JÜ—‘ §¡£°(°×0AÑ0AÓ0CÓDÜ—‘ §	¡	£¨u¨f¯^©^Ó-=Ó>óð ó
ð 	
r   c                 ó¼  — | j                   dz   }t        «       st        |dt        |«       | j	                  | j
                  |«      }t        j                  | j
                  |g«      \  }}t        j                  |«      }t        j                  |«      }t        j                  |dk  |t        j                  |dk  t        j                  ||«      |«      |¬«      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.])
        Ú_cdfÚvaluer   r   r:   )r#   r   r   r   Ú_check_values_dtype_in_probsr   r   Úbroadcast_tensorsÚ
zeros_likeÚ	ones_likeÚwhererM   )r0   rT   r#   r   ÚzerosÚoness         r   ÚcdfzBernoulli.cdf   s¶   € ð< �y‰y˜6Ñ!ˆÜÔ Ü�u˜g¤x°Ô6à×1Ñ1°$·*±*¸eÓDˆÜ×/Ñ/°·±¸UÐ0CÓD‰ˆˆuä×!Ñ! %Ó(ˆÜ×Ñ Ó&ˆä�|‰|Ø�A‰IØÜ�L‰L˜ ™¤F§O¡O°D¸%Ó$@À$ÓGØô	
ð 	
r   c                 óø   — | j                   dz   }t        «       st        |dt        |«       | j	                  | j
                  |«      }t        j                  | j                  |g«      \  }}t        ||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])
        Ú	_log_probrT   Únone©Ú	reductionr#   )
r#   r   r   r   rU   r   r   rV   r,   r   )r0   rT   r#   r,   s       r   Úlog_probzBernoulli.log_probO  st   € ð* �y‰y˜;Ñ&ˆÜÔ Ü�u˜g¤x°Ô6à×1Ñ1°$·*±*¸eÓDˆÜ×0Ñ0°$·+±+¸uÐ1EÓF‰ˆ�Ü0Ø�E V°$ô
ð 
ð 	
r   c                 óš   — | j                   dz   }t        «       st        |dt        |«       | j	                  |«      j                  |¬«      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])
        Ú_probrT   r:   )r#   r   r   r   rb   Úexp)r0   rT   r#   s      r   ÚprobzBernoulli.probn  sC   € ð: �y‰y˜7Ñ"ˆÜÔ Ü�u˜g¤x°Ô6à�}‰}˜UÓ#×'Ñ'¨TÐ'Ó2Ð2r   c                 óf   — | j                   dz   }t        | j                  | j                  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)
        Ú_entropyr_   r`   )r#   r   r,   r   )r0   r#   s     r   ÚentropyzBernoulli.entropy‘  s0   € ð0 �y‰y˜:Ñ%ˆä/Ø�K‰K˜Ÿ™¨v¸Dô
ð 	
r   c           
      ó6  — | j                   dz   }t        «       st        |dt        |«       | j                  }|j                  }t        | «       }t        | «       }t        |«      }t        | «      }t        |«       }	t        |«       }
t        j                  t        j                  t        j                  ||«      t        j                  ||«      «      t        j                  t        j                  |	|«      t        j                  |
|«      «      «      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)
        Ú_kl_divergenceÚother)r#   r   r   r   r,   r
   r	   r   rL   rM   r6   )r0   rl   r#   Úa_logitsÚb_logitsÚlog_paÚlog_pbÚpaÚone_minus_paÚlog_one_minus_paÚlog_one_minus_pbs              r   Úkl_divergencezBernoulli.kl_divergence¯  sí   € ð: �y‰yÐ+Ñ+ˆÜÔ Ü�u˜g¤y°$Ô7à—;‘;ˆØ—<‘<ˆä˜H˜9Ó%Ð%ˆÜ˜H˜9Ó%Ð%ˆä�XÓˆÜ ˜yÓ)ˆä$ XÓ.Ð.ÐÜ$ XÓ.Ð.Ðä�z‰zÜ�O‰OÜ—‘ ¨Ó+¬V¯_©_¸VÀRÓ-Hóô �O‰OÜ—‘Ð 0°,Ó?Ü—‘Ð 0°,Ó?óó	
ð 	
r   )N)g      ð?)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r.   Úpropertyr4   r7   rD   rQ   r\   rb   rf   ri   ru   Ú__classcell__)r1   s   @r   r   r   2   sa   ø„ ñ)õV GðD ñó ðð ñ=ó ð=ò-Ió^]
ò~-
ò^
ò>!3òF
ö<5
r   r   )Únumpyr;   r   Úpaddle.base.data_feederr   r   Úpaddle.base.frameworkr   Úpaddle.distributionr   Úpaddle.frameworkr   Úpaddle.nn.functionalr   r	   r
   Úfinfor   r   r   r   r   ÚExponentialFamilyr   r    r   r   Ú<module>r„      sw   ðó  ã ß =Ý *Ý 2Ý ,÷ñ ð ˆv�|‰|˜FŸN™NÓ+×/Ñ/Øˆv�|‰|˜FŸN™NÓ+×/Ñ/ñ€òBôr
Ð"×4Ñ4õ r
r   