o
    "j4                     @   sf   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 G dd de	jZdS )	    N)
check_typeconvert_dtype)Variable)distribution)in_dynamic_mode)multinomialc                   @   sB   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dS )Categoricala	  
    Categorical distribution is a discrete probability distribution that
    describes the possible results of a random variable that can take on
    one of K possible categories, with the probability of each category
    separately specified.

    The probability mass function (pmf) is:

    .. math::

        pmf(k; p_i) = \prod_{i=1}^{k} p_i^{[x=i]}

    In the above equation:

    * :math:`[x=i]` : it evaluates to 1 if :math:`x==i` , 0 otherwise.

    Args:
        logits(list|tuple|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64.
        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 Categorical

            >>> paddle.seed(100) # on CPU device
            >>> x = paddle.rand([6])
            >>> print(x)
            Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

            >>> paddle.seed(200) # on CPU device
            >>> y = paddle.rand([6])
            >>> print(y)
            Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.77663314, 0.90824795, 0.15685187, 0.04279523, 0.34468332, 0.79557180])

            >>> cat = Categorical(x)
            >>> cat2 = Categorical(y)

            >>> paddle.seed(1000) # on CPU device
            >>> print(cat.sample([2,3]))
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[0, 1, 5],
            [3, 4, 5]])

            >>> print(cat.entropy())
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            1.77528250)

            >>> print(cat.kl_divergence(cat2))
            Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.07195196])

            >>> value = paddle.to_tensor([2,1,3])
            >>> print(cat.probs(value))
            Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.00608027, 0.10829761, 0.26965630])

            >>> print(cat.log_prob(value))
            Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [-5.10270691, -2.22287226, -1.31060708])
    Nc                 C   s   t  st|dtjtttfd |dur|nd| _d| _| 	|r*|| _
t|j| _n,t|tjr;t|jdv r;|j| _| |d | _
| jt| j
jkrVtj| j
| jd| _
tj| j
dd	d
}| j
| | _dS )a1  
        Args:
            logits(list|tuple|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64.
            name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
        logitsr   Nfloat32)r
   Zfloat64r   )dtypeTaxiskeepdim)r   r   npZndarrayr   listtuplenamer   Z_validate_argsr	   r   
isinstancestrZ
_to_tensorpaddlecastsum_prob)selfr	   r   Zdist_sum r   `/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/distribution/categorical.py__init__[   s&   
zCategorical.__init__c           	      C   s   | j d }t st|dtd tt|}t| jj}t	|dkr>||dd  }t
| jt|dd |d g}n|}| j}t| ||d}tt| }|d|d ||}t
j|||d	S )
a  Generate samples of the specified shape.

        Args:
            shape (list): Shape of the generated samples.

        Returns:
            Tensor: A tensor with prepended dimensions shape.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> # doctest: +SKIP
                >>> cat = Categorical(x)
                >>> paddle.seed(1000) # on CPU device
                >>> print(cat.sample([2,3]))
                Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
                [[0, 1, 5],
                [3, 4, 5]])
        _sampleshapesample   Nr   Tr   r   )r   r   r   r   r   prodarrayr	   r   lenr   reshaper   Z_logits_to_probsrangediminsertpopZ	transpose)	r   r   r   Znum_samplesZlogits_shapeZsample_shaper	   Zsample_indexZpermuter   r   r   r    {   s&   

zCategorical.samplec                 C   s   | j d }t st|dtd | jtj| jddd }|jtj|jddd }t|}t|}tj|ddd}tj|ddd}|| }	tj|	|t	| | t	|  dd|d}
|
S )a  The KL-divergence between two Categorical distributions.

        Args:
            other (Categorical): instance of Categorical. The data type is float32.

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

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> paddle.seed(200) # on CPU device
                >>> y = paddle.rand([6])
                >>> print(y)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.77663314, 0.90824795, 0.15685187, 0.04279523, 0.34468332, 0.79557180])

                >>> cat = Categorical(x)
                >>> cat2 = Categorical(y)

                >>> print(cat.kl_divergence(cat2))
                Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.07195196])
        Z_kl_divergenceotherkl_divergencer   Tr   )r   r   r   )
r   r   r   r   r	   r   maxexpr   log)r   r+   r   r	   Zother_logitse_logitsZother_e_logitszZother_zprobklr   r   r   r,      s*   
"

zCategorical.kl_divergencec                 C   st   | j d }| jtj| jddd }t|}tj|ddd}|| }tj||t|  dd}tj|d|d}|S )a  Shannon entropy in nats.

        Returns:
            Tensor: Shannon entropy of Categorical distribution. The data type is float32.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> cat = Categorical(x)

                >>> print(cat.entropy())
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                1.77528250)
        Z_entropyr   Tr   r   g      )scaler   )r   r	   r   r-   r.   r   r/   r5   )r   r   r	   r0   r1   r2   Zneg_entropyentropyr   r   r   r6      s   

zCategorical.entropyc                 C   s   | j d }t| jjdkr"tj| j|jdg|d|dj|j|dS t|jdkrDtj| jtj|t| jjd dg dg |dddS tj| j|ddS )a  Probabilities of the given category (``value``).

        If ``logits`` is 2-D or higher dimension, the last dimension will be regarded as
        category, and the others represents the different distributions.
        At the same time, if ``vlaue`` is 1-D Tensor, ``value`` will be broadcast to the
        same number of distributions as ``logits``.
        If ``value`` is not 1-D Tensor, ``value`` should have the same number distributions
        with ``logits. That is, ``value[:-1] = logits[:-1]``.

        Args:
            value (Tensor): The input tensor represents the selected category index.

        Returns:
            Tensor: probability according to the category index.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> cat = Categorical(x)

                >>> value = paddle.to_tensor([2,1,3])
                >>> print(cat.probs(value))
                Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.00608027, 0.10829761, 0.26965630])
        Z_probsr!   r   r"   r4   )r   r%   r   r   r   Zgatherr&   Ztake_along_axisr   valuer   r   r   r   probs  s$   
#
zCategorical.probsc                 C   s   | j d }tj| ||dS )a  Log probabilities of the given category. Refer to ``probs`` method.

        Args:
            value (Tensor): The input tensor represents the selected category index.

        Returns:
            Tensor: Log probability.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> cat = Categorical(x)

                >>> value = paddle.to_tensor([2,1,3])
                >>> print(cat.log_prob(value))
                Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
                [-5.10270691, -2.22287226, -1.31060708])
        Z	_log_probr"   )r   r   r/   r9   r7   r   r   r   log_probE  s   
zCategorical.log_prob)N)
__name__
__module____qualname____doc__r   r    r,   r6   r9   r:   r   r   r   r   r      s    
A 99"6r   )numpyr   r   Zpaddle.base.data_feederr   r   Zpaddle.base.frameworkr   Zpaddle.distributionr   Zpaddle.frameworkr   Zpaddle.tensorr   Distributionr   r   r   r   r   <module>   s   