o
    yi                     @   s   d dl mZ d dl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	ed
edefddZG dd deZdS )    deepcopy)AnyDictOptionalUnionN)Tensor)
ModuleList)Metric)apply_to_collectionpoissonsizesampling_strategyreturnc                 C   sb   |dkrt jd}|| f}t | j| ddS |dkr-t jt | | dd}|S t	d)	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)num_samplesreplacementzUnknown sampling strategy)
torchdistributionsPoissonsamplearangerepeat_interleavelongr   ones
ValueError)r   r   pnidx r"   W/home/ubuntu/.local/lib/python3.10/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ded	e	d
ededee
eef  dedededdf fddZdededdfddZdeeef f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 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di | t tstd  t fddt|D | _|| _|| _	|| _
|| _|| _d}	||	vrBt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>e       z)BootStrapper.__init__.<locals>.<listcomp>)r   r   z5Expected argument ``sampling_strategy`` to be one of z but recieved r"   )super__init__
isinstancer
   r   r	   rangemetricsr)   r*   r+   r,   r-   r   )
selfr(   r)   r*   r+   r,   r-   r   r.   allowed_sampling	__class__r1   r#   r5   T   s&   

zBootStrapper.__init__argsc           
      O   s   t | jD ]T}t|tt}tt|tt}t|dkr |d }nt|dkr+|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 )ztUpdates 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   todevicer   index_selectr8   update)
r9   r=   r.   r!   
args_sizeskwargs_sizesr   
sample_idxnew_args
new_kwargsr"   r"   r#   rD   u   s   

zBootStrapper.updatec                 C   sx   t jdd | jD dd}i }| jr|jdd|d< | jr%|jdd|d< | jdur3t || j|d< | jr:||d	< |S )
zComputes 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   computed_valsoutput_dictr"   r"   r#   rJ      s   
zBootStrapper.compute)r'   TTNFr   )__name__
__module____qualname____doc__r&   r   bool__annotations__r
   intr   floatr   strr   r5   rD   r   rJ   __classcell__r"   r"   r;   r#   r%   0   s<   
 !	
!r%   )r   )copyr   typingr   r   r   r   r   r   torch.nnr	   torchmetrics.metricr
   torchmetrics.utilitiesr   rU   rW   r$   r%   r"   r"   r"   r#   <module>   s    
