a
    d "                     @   s   d dl mZ d dl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mZ d d
lmZ esdgZdeeedddZG dd deZdS )    deepcopy)AnyDictOptionalSequenceUnionN)apply_to_collection)Tensor)
ModuleList)Metric)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPE)WrapperMetricBootStrapper.plotpoisson)sizesampling_strategyreturnc                 C   sb   |dkr8t jd}|| f}t | j| ddS |dkrVt jt | | ddS t	dd	S )
zResample a tensor along its first dimension with replacement.

    Args:
        size: number of samples
        sampling_strategy: the strategy to use for sampling, either ``'poisson'`` or ``'multinomial'``

    Returns:
        resampled tensor

    r      r   dimmultinomialT)Znum_samplesreplacementzUnknown sampling strategyN)
torchdistributionsZPoissonsampleZarangeZrepeat_interleavelongr   Zones
ValueError)r   r   pn r"   l/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/wrappers/bootstrapping.py_bootstrap_sampler   s    r$   c                       s   e Zd ZU dZdZee ed< dee	eeee
eef  eeedd	 fd	d
ZeeddddZeeef dddZeeed fddZdee
eee f  ee edddZ  ZS )BootStrappera  Using `Turn a Metric into a Bootstrapped`_.

    That can automate the process of getting confidence intervals for metric values. This wrapper
    class basically keeps multiple copies of the same base metric in memory and whenever ``update`` or
    ``forward`` is called, all input tensors are resampled (with replacement) along the first dimension.

    Args:
        base_metric: base metric class to wrap
        num_bootstraps: number of copies to make of the base metric for bootstrapping
        mean: if ``True`` return the mean of the bootstraps
        std: if ``True`` return the standard diviation of the bootstraps
        quantile: if given, returns the quantile of the bootstraps. Can only be used with pytorch version 1.6 or higher
        raw: if ``True``, return all bootstrapped values
        sampling_strategy:
            Determines how to produce bootstrapped samplings. Either ``'poisson'`` or ``multinomial``.
            If ``'possion'`` is chosen, the number of times each sample will be included in the bootstrap
            will be given by :math:`n\sim Poisson(\lambda=1)`, which approximates the true bootstrap distribution
            when the number of samples is large. If ``'multinomial'`` is chosen, we will apply true bootstrapping
            at the batch level to approximate bootstrapping over the hole dataset.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example::
        >>> from pprint import pprint
        >>> from torchmetrics.wrappers import BootStrapper
        >>> from torchmetrics.classification import MulticlassAccuracy
        >>> _ = torch.manual_seed(123)
        >>> base_metric = MulticlassAccuracy(num_classes=5, average='micro')
        >>> bootstrap = BootStrapper(base_metric, num_bootstraps=20)
        >>> bootstrap.update(torch.randint(5, (20,)), torch.randint(5, (20,)))
        >>> output = bootstrap.compute()
        >>> pprint(output)
        {'mean': tensor(0.2205), 'std': tensor(0.0859)}

    Tfull_state_update
   NFr   )	base_metricnum_bootstrapsmeanstdquantilerawr   kwargsr   c           
         s   t  jf i | t ts*td  t fddt|D | _|| _|| _	|| _
|| _|| _d}	||	vrtd|	 d| || _d S )NzKExpected base metric to be an instance of torchmetrics.Metric but received c                    s   g | ]}t  qS r"   r   ).0_r(   r"   r#   
<listcomp>l       z)BootStrapper.__init__.<locals>.<listcomp>)r   r   z5Expected argument ``sampling_strategy`` to be one of z but recieved )super__init__
isinstancer   r   r   rangemetricsr)   r*   r+   r,   r-   r   )
selfr(   r)   r*   r+   r,   r-   r   r.   Zallowed_sampling	__class__r1   r#   r5   [   s&    
zBootStrapper.__init__)argsr.   r   c           
      O   s   t | jD ]}t|tt}tt|tt}t|dkr@|d }nt|dkrV|d }ntdt|| jd	| j
}t|ttjd|d}t|ttjd|d}	| j| j|i |	 q
dS )ztUpdate the state of the base metric.

        Any tensor passed in will be bootstrapped along dimension 0.

        r   zMNone of the input contained tensors, so could not determine the sampling size)r   )r   indexN)r7   r)   r	   r
   lenlistr   r$   r   toZdevicer   Zindex_selectr8   update)
r9   r<   r.   idxZ
args_sizesZkwargs_sizesr   Z
sample_idxnew_argsZ
new_kwargsr"   r"   r#   rA   |   s    

zBootStrapper.update)r   c                 C   sx   t jdd | jD dd}i }| jr4|jdd|d< | jrJ|jdd|d< | jdurft || j|d< | jrt||d	< |S )
zCompute the bootstrapped metric values.

        Always returns a dict of tensors, which can contain the following keys: ``mean``, ``std``, ``quantile`` and
        ``raw`` depending on how the class was initialized.

        c                 S   s   g | ]}|  qS r"   )compute)r/   mr"   r"   r#   r2      r3   z(BootStrapper.compute.<locals>.<listcomp>r   r   r*   r+   Nr,   r-   )r   stackr8   r*   r+   r,   r-   )r9   Zcomputed_valsZoutput_dictr"   r"   r#   rD      s    
zBootStrapper.computec                    s   t t| j|i |S )z9Use the original forward method of the base metric class.)r4   r   forward)r9   r<   r.   r:   r"   r#   rG      s    zBootStrapper.forward)valaxr   c                 C   s   |  ||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.wrappers import BootStrapper
            >>> from torchmetrics.regression import MeanSquaredError
            >>> metric = BootStrapper(MeanSquaredError(), num_bootstraps=20)
            >>> metric.update(torch.randn(100,), torch.randn(100,))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.wrappers import BootStrapper
            >>> from torchmetrics.regression import MeanSquaredError
            >>> metric = BootStrapper(MeanSquaredError(), num_bootstraps=20)
            >>> values = [ ]
            >>> for _ in range(3):
            ...     values.append(metric(torch.randn(100,), torch.randn(100,)))
            >>> fig_, ax_ = metric.plot(values)

        )Z_plot)r9   rH   rI   r"   r"   r#   plot   s    *r   )r'   TTNFr   )NN)__name__
__module____qualname____doc__r&   r   bool__annotations__r   intr   floatr
   strr   r5   rA   r   rD   rG   r   r   r   rJ   __classcell__r"   r"   r:   r#   r%   6   s6   
"      ! r%   )r   )copyr   typingr   r   r   r   r   r   Zlightning_utilitiesr	   r
   Ztorch.nnr   Ztorchmetrics.metricr   Ztorchmetrics.utilities.importsr   Ztorchmetrics.utilities.plotr   r   Ztorchmetrics.wrappers.abstractr   Z__doctest_skip__rQ   rS   r$   r%   r"   r"   r"   r#   <module>   s$    