a
    d]#                     @   s   d dl mZmZmZmZmZmZ d dlZd dlmZ d dl	m
Z
 d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZmZ d d
lmZmZ esdgZddgiZG dd deZdS )    )AnyListOptionalSequenceTupleUnionN)Tensor)Module)NoTrainInceptionV3)Metric)rank_zero_warn)dim_zero_cat)_MATPLOTLIB_AVAILABLE_TORCH_FIDELITY_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEInceptionScore.plot)InceptionScorer   Ztorch_fidelityc                       s   e Zd ZU dZdZeed< dZeed< dZeed< dZ	e
ed< eed	< eed
< deeeef eeedd fddZeddddZeeef dddZdeeeee f  ee edddZ  ZS )r   a\  Calculate the Inception Score (IS) which is used to access how realistic generated images are.

    .. math::
        IS = exp(\mathbb{E}_x KL(p(y | x ) || p(y)))

    where :math:`KL(p(y | x) || p(y))` is the KL divergence between the conditional distribution :math:`p(y|x)`
    and the margianl distribution :math:`p(y)`. Both the conditional and marginal distribution is calculated
    from features extracted from the images. The score is calculated on random splits of the images such that
    both a mean and standard deviation of the score are returned. The metric was originally proposed in
    `inception ref1`_.

    Using the default feature extraction (Inception v3 using the original weights from `inception ref2`_), the input
    is expected to be mini-batches of 3-channel RGB images of shape ``(3xHxW)``. If argument ``normalize``
    is ``True`` images are expected to be dtype ``float`` and have values in the ``[0,1]`` range, else if
    ``normalize`` is set to ``False`` images are expected to have dtype uint8 and take values in the ``[0, 255]``
    range. All images will be resized to 299 x 299 which is the size of the original training data.

    .. note:: using this metric with the default feature extractor requires that ``torch-fidelity``
        is installed. Either install as ``pip install torchmetrics[image]`` or
        ``pip install torch-fidelity``

    As input to ``forward`` and ``update`` the metric accepts the following input

    - ``imgs`` (:class:`~torch.Tensor`): tensor with images feed to the feature extractor

    As output of `forward` and `compute` the metric returns the following output

    - ``fid`` (:class:`~torch.Tensor`): float scalar tensor with mean FID value over samples

    Args:
        feature:
            Either an str, integer or ``nn.Module``:

            - an str or integer will indicate the inceptionv3 feature layer to choose. Can be one of the following:
              'logits_unbiased', 64, 192, 768, 2048
            - an ``nn.Module`` for using a custom feature extractor. Expects that its forward method returns
              an ``(N,d)`` matrix where ``N`` is the batch size and ``d`` is the feature size.

        splits: integer determining how many splits the inception score calculation should be split among
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``feature`` is set to an ``str`` or ``int`` and ``torch-fidelity`` is not installed
        ValueError:
            If ``feature`` is set to an ``str`` or ``int`` and not one of ``('logits_unbiased', 64, 192, 768, 2048)``
        TypeError:
            If ``feature`` is not an ``str``, ``int`` or ``torch.nn.Module``

    Example:
        >>> import torch
        >>> _ = torch.manual_seed(123)
        >>> from torchmetrics.image.inception import InceptionScore
        >>> inception = InceptionScore()
        >>> # generate some images
        >>> imgs = torch.randint(0, 255, (100, 3, 299, 299), dtype=torch.uint8)
        >>> inception.update(imgs)
        >>> inception.compute()
        (tensor(1.0544), tensor(0.0117))

    Fis_differentiableThigher_is_betterfull_state_updateg        plot_lower_boundfeatures	inceptionlogits_unbiased
   N)featuresplits	normalizekwargsreturnc                    s   t  jf i | tdt t|ttfrnts6tdd}||vrXt	d| d| dt
dt|gd| _nt|tr|| _ntd	t|tst	d
|| _|| _| jdg d d d S )NzMetric `InceptionScore` will save all extracted features in buffer. For large datasets this may lead to large memory footprint.zInceptionScore metric requires that `Torch-fidelity` is installed. Either install as `pip install torchmetrics[image]` or `pip install torch-fidelity`.)r   @      i   i   z3Integer input to argument `feature` must be one of z
, but got .zinception-v3-compat)nameZfeatures_listz'Got unknown input to argument `feature`z*Argument `normalize` expected to be a boolr   )Zdist_reduce_fx)super__init__r   UserWarning
isinstancestrintr   ModuleNotFoundError
ValueErrorr
   r   r	   	TypeErrorboolr   r   Z	add_state)selfr   r   r   r   Zvalid_int_input	__class__ e/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/image/inception.pyr&   h   s0    

zInceptionScore.__init__)imgsr    c                 C   s0   | j r|d  n|}| |}| j| dS )z)Update the state with extracted features.   N)r   byter   r   append)r/   r4   r   r2   r2   r3   update   s    
zInceptionScore.update)r    c                 C   s   t | j}t|jd }|| }|jdd}|jdd}|j| jdd}|j| jdd}dd |D }dd t	|||D }dd |D }t
|}| | fS )zCompute metric.r      dimc                 S   s   g | ]}|j d ddqS )r   T)r;   Zkeepdim)mean).0pr2   r2   r3   
<listcomp>       z*InceptionScore.compute.<locals>.<listcomp>c                 S   s"   g | ]\}}}|||    qS r2   )log)r=   r>   Zlog_pZm_pr2   r2   r3   r?      r@   c                 S   s    g | ]}|j d d  qS )r9   r:   )sumr<   exp)r=   kr2   r2   r3   r?      r@   )r   r   torchZrandpermshapeZsoftmaxZlog_softmaxchunkr   zipstackr<   Zstd)r/   r   idxZprobZlog_probZ	mean_probZkl_klr2   r2   r3   compute   s    

zInceptionScore.compute)valaxr    c                 C   s   |p|   d }| ||S )a  Plot a single or multiple values from the metric.

        Args:
            val: Either a single result from calling `metric.forward` or `metric.compute` or a list of these results.
                If no value is provided, will automatically call `metric.compute` and plot that result.
            ax: An matplotlib axis object. If provided will add plot to that axis

        Returns:
            Figure and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value
            >>> import torch
            >>> from torchmetrics.image.inception import InceptionScore
            >>> metric = InceptionScore()
            >>> metric.update(torch.randint(0, 255, (50, 3, 299, 299), dtype=torch.uint8))
            >>> fig_, ax_ = metric.plot()  # the returned plot only shows the mean value by default

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.image.inception import InceptionScore
            >>> metric = InceptionScore()
            >>> values = [ ]
            >>> for _ in range(3):
            ...     # we index by 0 such that only the mean value is plotted
            ...     values.append(metric(torch.randint(0, 255, (50, 3, 299, 299), dtype=torch.uint8))[0])
            >>> fig_, ax_ = metric.plot(values)

        r   )rL   Z_plot)r/   rM   rN   r2   r2   r3   plot   s    )r   )r   r   F)NN)__name__
__module____qualname____doc__r   r.   __annotations__r   r   r   floatr   r	   r   r)   r*   r   r&   r   r8   r   rL   r   r   r   r   rO   __classcell__r2   r2   r0   r3   r   "   s0   
=   ( r   )typingr   r   r   r   r   r   rE   r   Ztorch.nnr	   Ztorchmetrics.image.fidr
   Ztorchmetrics.metricr   Ztorchmetrics.utilitiesr   Ztorchmetrics.utilities.datar   Ztorchmetrics.utilities.importsr   r   Ztorchmetrics.utilities.plotr   r   Z__doctest_skip__Z__doctest_requires__r   r2   r2   r2   r3   <module>   s    
