o
    .wi$                     @   s   d dl mZ d dl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sMdgZddgiZG dd deZdS )    )Sequence)AnyOptionalUnionN)Tensor)Module)NoTrainInceptionV3)Metric)rank_zero_warn)dim_zero_cat)_MATPLOTLIB_AVAILABLE_TORCH_FIDELITY_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEInceptionScore.plot)InceptionScorer   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
Zeed< 			ddeeeef dedededdf
 fddZdeddfddZdeeef fddZ	d deeeee f  dee def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 marginal 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.

    .. hint::
        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

    - ``inception_mean`` (:class:`~torch.Tensor`): float scalar tensor with mean inception score over subsets
    - ``inception_std`` (:class:`~torch.Tensor`): float scalar tensor with standard deviation of inception score
      over subsets

    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:
        >>> from torch import rand
        >>> 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.0549), tensor(0.0121))

    Fis_differentiableThigher_is_betterfull_state_updateg        plot_lower_boundfeatures	inceptionfeature_networklogits_unbiased
   featuresplits	normalizekwargsreturnNc                    s   t  jdi | tdt t|ttfr7tstdd}||vr,t	d| d| dt
dt|gd| _nt|tr@|| _ntd	t|tsMt	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)namefeatures_listz'Got unknown input to argument `feature`z*Argument `normalize` expected to be a boolr   )dist_reduce_fx )super__init__r
   UserWarning
isinstancestrintr   ModuleNotFoundError
ValueErrorr   r   r   	TypeErrorboolr   r   	add_state)selfr   r   r   r   valid_int_input	__class__r'   Y/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/image/inception.pyr)   m   s0   

zInceptionScore.__init__imgsc                 C   s0   | j r	|d  n|}| |}| j| dS )z)Update the state with extracted features.   N)r   byter   r   append)r3   r8   r   r'   r'   r7   update   s   
zInceptionScore.updatec                 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?   keepdim)mean).0pr'   r'   r7   
<listcomp>   s    z*InceptionScore.compute.<locals>.<listcomp>c                 S   s"   g | ]\}}}|||    qS r'   )log)rB   rC   log_pm_pr'   r'   r7   rD      s   " c                 S   s    g | ]}|j d d  qS )r=   r>   )sumrA   exp)rB   kr'   r'   r7   rD      s     )r   r   torchrandpermshapesoftmaxlog_softmaxchunkr   zipstackrA   std)r3   r   idxproblog_prob	mean_probkl_klr'   r'   r7   compute   s   

zInceptionScore.computevalaxc                 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   )rZ   _plot)r3   r[   r\   r'   r'   r7   plot   s   )r   )r   r   F)NN)__name__
__module____qualname____doc__r   r1   __annotations__r   r   r   floatlistr   r   r,   r   r-   r   r)   r   r<   tuplerZ   r   r   r   r   r^   __classcell__r'   r'   r5   r7   r   #   sB   
 @(r   )collections.abcr   typingr   r   r   rK   r   torch.nnr   torchmetrics.image.fidr   torchmetrics.metricr	   torchmetrics.utilitiesr
   torchmetrics.utilities.datar   torchmetrics.utilities.importsr   r   torchmetrics.utilities.plotr   r   __doctest_skip____doctest_requires__r   r'   r'   r'   r7   <module>   s   
