o
    .wi0                     @   s   d dl mZ d dlmZ d dlmZmZmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ dd	giZG d
d de	ZG dd deZdS )    )Sequence)	lru_cache)AnyOptionalUnion)Module)MetricCollection)Metric)rank_zero_warn)FeatureSharetorch_fidelityc                       sF   e Zd ZdZddededdf fddZd	ed
edefddZ  Z	S )NetworkCachezCreate a cached version of a network to be shared between metrics.

    Because the different metrics may invoke the same network multiple times, we can save time by caching the input-
    output pairs of the network.

    d   networkmax_sizereturnNc                    s0   t    || _|| _t| jd|j| j_d S )N)maxsize)super__init__r   r   r   forward)selfr   r   	__class__ `/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/wrappers/feature_share.pyr   #   s   
zNetworkCache.__init__argskwargsc                 O   s   | j |i |S )z*Call the network with the given arguments.)r   )r   r   r   r   r   r   r   )   s   zNetworkCache.forward)r   )
__name__
__module____qualname____doc__r   intr   r   r   __classcell__r   r   r   r   r      s    r   c                       sL   e Zd ZdZ	ddeeee eeef f de	e
 ddf fddZ  ZS )	r   as  Specialized metric collection that facilitates sharing features between metrics.

    Certain metrics rely on an underlying expensive neural network for feature extraction when computing the metric.
    This wrapper allows to share the feature extraction between multiple metrics, which can save a lot of time and
    memory. This is achieved by making a shared instance of the network between the metrics and secondly by caching
    the input-output pairs of the network, such the subsequent calls to the network with the same input will be much
    faster.

    Args:
        metrics: One of the following:

            * list or tuple (sequence): if metrics are passed in as a list or tuple, will use the metrics class name
              as key for output dict. Therefore, two metrics of the same class cannot be chained this way.


            * dict: if metrics are passed in as a dict, will use each key in the dict as key for output dict.
              Use this format if you want to chain together multiple of the same metric with different parameters.
              Note that the keys in the output dict will be sorted alphabetically.

        max_cache_size: maximum number of input-output pairs to cache per metric. By default, this is none which means
            that the cache will be set to the number of metrics in the collection meaning that all features will be
            cached and shared across all metrics per batch.

    Example::
        >>> import torch
        >>> from torchmetrics.wrappers import FeatureShare
        >>> from torchmetrics.image import FrechetInceptionDistance, KernelInceptionDistance
        >>> # initialize the metrics
        >>> fs = FeatureShare([FrechetInceptionDistance(), KernelInceptionDistance(subset_size=10, subsets=2)])
        >>> # update metric
        >>> fs.update(torch.randint(255, (50, 3, 64, 64), dtype=torch.uint8), real=True)
        >>> fs.update(torch.randint(255, (50, 3, 64, 64), dtype=torch.uint8), real=False)
        >>> # compute metric
        >>> fs.compute()
        {'FrechetInceptionDistance': tensor(15.1700), 'KernelInceptionDistance': (tensor(-0.0012), tensor(0.0014))}

    Nmetricsmax_cache_sizer   c           	   
      s@  t  j|dd |d u rt| }t|tstd| ztt|  }t|j	t
s/tdt||j	}W n! tyG } ztd|d }~w tyW } ztd|d }~ww t||d}|  D ];\}}t|dsstd	| d
t|j	t
std| dt
t||j	t
|krtd| dt t||j	| qbd S )NF)r#   compute_groupsz-max_cache_size should be an integer, but got z1The `feature_network` attribute must be a string.zTried to extract the network to share from the first metric, but it did not have a `feature_network` attribute. Please make sure that the metric has an attribute with that name, else it cannot be shared.zOThe `feature_network` attribute must be a string representing the network name.)r   feature_networkzTried to set the cached network to all metrics, but one of the metrics did not have a `feature_network` attribute. Please make sure that all metrics have a attribute with that name, else it cannot be shared. Failed on metric .zMetric z0's `feature_network` attribute must be a string.zQThe network to share between the metrics is not the same for all metrics. Metric zU has a different network than the first metric. This may lead to unexpected behavior.)r   r   len
isinstancer!   	TypeErrornextitervaluesr&   strgetattrAttributeErrorr   itemshasattrr
   UserWarningsetattr)	r   r#   r$   	first_netnetwork_to_shareerr
cached_netmetric_namemetricr   r   r   r   U   sP   


zFeatureShare.__init__)N)r   r   r   r    r   r	   r   dictr.   r   r!   r   r"   r   r   r   r   r   .   s    )r   N)collections.abcr   	functoolsr   typingr   r   r   torch.nnr   torchmetrics.collectionsr   torchmetrics.metricr	   torchmetrics.utilitiesr
   __doctest_requires__r   r   r   r   r   r   <module>   s   
