o
    yi5                     @   s   d dl mZmZ d dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
 d dlmZmZmZmZmZmZ d dlmZ d dlmZ G d	d
 d
eZG dd deZG dd dZdS )    )AnyOptionalN)Tensor)Literal)_exact_match_reduce_multiclass_exact_match_update_multilabel_exact_match_update)&_multiclass_stat_scores_arg_validation_multiclass_stat_scores_format)_multiclass_stat_scores_tensor_validation&_multilabel_stat_scores_arg_validation_multilabel_stat_scores_format)_multilabel_stat_scores_tensor_validation)Metric)dim_zero_catc                       sx   e Zd ZU dZdZdZdZeed< 			dde	de
d	 d
ee	 dededdf fddZdddZdefddZ  ZS )MulticlassExactMatchay
  Computes Exact match (also known as subset accuracy) for multiclass tasks. Exact Match is a stricter version
    of accuracy where all labels have to match exactly for the sample to be correctly classified.

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

    - ``preds`` (:class:`~torch.Tensor`): An int tensor of shape ``(N, ...)`` or float tensor of shape ``(N, C, ..)``.
      If preds is a floating point we apply ``torch.argmax`` along the ``C`` dimension to automatically convert
      probabilities/logits into an int tensor.
    - ``target`` (:class:`~torch.Tensor`): An int tensor of shape ``(N, ...)``.


    As output to ``forward`` and ``compute`` the metric returns the following output:

    - ``mcem`` (:class:`~torch.Tensor`): A tensor whose returned shape depends on the ``multidim_average`` argument:

        - If ``multidim_average`` is set to ``global`` the output will be a scalar tensor
        - If ``multidim_average`` is set to ``samplewise`` the output will be a tensor of shape ``(N,)``

    Args:
        num_classes: Integer specifing the number of labels
        multidim_average:
            Defines how additionally dimensions ``...`` should be handled. Should be one of the following:

            - ``global``: Additional dimensions are flatted along the batch dimension
            - ``samplewise``: Statistic will be calculated independently for each sample on the ``N`` axis.
              The statistics in this case are calculated over the additional dimensions.

        ignore_index:
            Specifies a target value that is ignored and does not contribute to the metric calculation
        validate_args: bool indicating if input arguments and tensors should be validated for correctness.
            Set to ``False`` for faster computations.

    Example (multidim tensors):
        >>> from torchmetrics.classification import MulticlassExactMatch
        >>> target = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[1, 1], [2, 0], [1, 2]]])
        >>> preds = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[2, 2], [2, 1], [1, 0]]])
        >>> metric = MulticlassExactMatch(num_classes=3, multidim_average='global')
        >>> metric(preds, target)
        tensor(0.5000)

    Example (multidim tensors):
        >>> from torchmetrics.classification import MulticlassExactMatch
        >>> target = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[1, 1], [2, 0], [1, 2]]])
        >>> preds = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[2, 2], [2, 1], [1, 0]]])
        >>> metric = MulticlassExactMatch(num_classes=3, multidim_average='samplewise')
        >>> metric(preds, target)
        tensor([1., 0.])
    FTfull_state_updateglobalNnum_classesmultidim_averager   
samplewiseignore_indexvalidate_argskwargsreturnc                    s   t  jdi | d\}}|rt||||| || _|| _|| _|| _| jd| jdkr3tj	dtj
dng | jdkr;dndd | jd	tj	dtj
d| jdkrPdnd
d d S )N)   Ncorrectr   r   dtypesumcatdist_reduce_fxtotalmean )super__init__r	   r   r   r   r   	add_statetorchzeroslong)selfr   r   r   r   r   top_kaverage	__class__r&   [/home/ubuntu/.local/lib/python3.10/site-packages/torchmetrics/classification/exact_match.pyr(   Z   s$   
zMulticlassExactMatch.__init__c                 C   s~   | j rt||| j| j| j t||d\}}t||| j\}}| jdkr/| j| || _	d S |  j|7  _|  j	|7  _	d S )Nr   r   )
r   r   r   r   r   r
   r   r   appendr$   r-   predstargetr   r$   r&   r&   r2   updatev   s   

zMulticlassExactMatch.updatec                 C   (   t | jtrt| jn| j}t|| jS N
isinstancer   listr   r   r$   r-   r   r&   r&   r2   compute      zMulticlassExactMatch.compute)r   NT)r   N)__name__
__module____qualname____doc__is_differentiablehigher_is_betterr   bool__annotations__intr   r   r   r(   r7   r   r>   __classcell__r&   r&   r0   r2   r   %   s.   
 0
r   c                       s   e Zd ZU dZdZdZdZeed< 				dde	d	e
d
ed dee	 dededdf fddZdededdfddZdefddZ  ZS )MultilabelExactMatcha  Computes Exact match (also known as subset accuracy) for multilabel tasks. Exact Match is a stricter version
    of accuracy where all labels have to match exactly for the sample to be correctly classified.

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

    - ``preds`` (:class:`~torch.Tensor`): An int tensor or float tensor of shape ``(N, C, ..)``. If preds is a
      floating point tensor with values outside [0,1] range we consider the input to be logits and will auto apply
      sigmoid per element. Addtionally, we convert to int tensor with thresholding using the value in ``threshold``.
    - ``target`` (:class:`~torch.Tensor`): An int tensor of shape ``(N, C, ...)``.


    As output to ``forward`` and ``compute`` the metric returns the following output:

    - ``mlem`` (:class:`~torch.Tensor`): A tensor whose returned shape depends on the ``multidim_average`` argument:

        - If ``multidim_average`` is set to ``global`` the output will be a scalar tensor
        - If ``multidim_average`` is set to ``samplewise`` the output will be a tensor of shape ``(N,)``

    Args:
        num_labels: Integer specifing the number of labels
        threshold: Threshold for transforming probability to binary (0,1) predictions
        multidim_average:
            Defines how additionally dimensions ``...`` should be handled. Should be one of the following:

            - ``global``: Additional dimensions are flatted along the batch dimension
            - ``samplewise``: Statistic will be calculated independently for each sample on the ``N`` axis.
              The statistics in this case are calculated over the additional dimensions.

        ignore_index:
            Specifies a target value that is ignored and does not contribute to the metric calculation
        validate_args: bool indicating if input arguments and tensors should be validated for correctness.
            Set to ``False`` for faster computations.

    Example (preds is int tensor):
        >>> from torchmetrics.classification import MultilabelExactMatch
        >>> target = torch.tensor([[0, 1, 0], [1, 0, 1]])
        >>> preds = torch.tensor([[0, 0, 1], [1, 0, 1]])
        >>> metric = MultilabelExactMatch(num_labels=3)
        >>> metric(preds, target)
        tensor(0.5000)

    Example (preds is float tensor):
        >>> from torchmetrics.classification import MultilabelExactMatch
        >>> target = torch.tensor([[0, 1, 0], [1, 0, 1]])
        >>> preds = torch.tensor([[0.11, 0.22, 0.84], [0.73, 0.33, 0.92]])
        >>> metric = MultilabelExactMatch(num_labels=3)
        >>> metric(preds, target)
        tensor(0.5000)

    Example (multidim tensors):
        >>> from torchmetrics.classification import MultilabelExactMatch
        >>> target = torch.tensor([[[0, 1], [1, 0], [0, 1]], [[1, 1], [0, 0], [1, 0]]])
        >>> preds = torch.tensor(
        ...     [
        ...         [[0.59, 0.91], [0.91, 0.99], [0.63, 0.04]],
        ...         [[0.38, 0.04], [0.86, 0.780], [0.45, 0.37]],
        ...     ]
        ... )
        >>> metric = MultilabelExactMatch(num_labels=3, multidim_average='samplewise')
        >>> metric(preds, target)
        tensor([0., 0.])
    FTr         ?r   N
num_labels	thresholdr   r   r   r   r   r   c                    s   t  jdi | |rt||d ||d || _|| _|| _|| _|| _| jd| jdkr3t	j
dt	jdng | jdkr;dndd | jd	t	j
dt	jd| jdkrPdnd
d d S )N)r/   r   r   r   r   r   r   r    r!   r"   r$   r%   r&   )r'   r(   r   rL   rM   r   r   r   r)   r*   r+   r,   )r-   rL   rM   r   r   r   r   r0   r&   r2   r(      s(   	

zMultilabelExactMatch.__init__r5   r6   c                 C   s   | j rt||| j| j| j t||| j| j| j\}}t||| j| j\}}| jdkr6| j	| || _
dS |  j|7  _|  j
|7  _
dS )z*Update state with predictions and targets.r   N)r   r   rL   r   r   r   rM   r   r   r3   r$   r4   r&   r&   r2   r7      s   

zMultilabelExactMatch.updatec                 C   r8   r9   r:   r=   r&   r&   r2   r>      r?   zMultilabelExactMatch.compute)rK   r   NT)r@   rA   rB   rC   rD   rE   r   rF   rG   rH   floatr   r   r   r(   r   r7   r>   rI   r&   r&   r0   r2   rJ      s4   
 ?rJ   c                   @   s`   e Zd ZdZ						dded ded	ee d
ee ded dee dede	de
fddZdS )
ExactMatcha  Computes Exact match (also known as subset accuracy). Exact Match is a stricter version of accuracy where
    all labels have to match exactly for the sample to be correctly classified.

    This module is a simple wrapper to get the task specific versions of this metric, which is done by setting the
    ``task`` argument to either ``'multiclass'`` or ``multilabel``. See the documentation of
    :mod:`MulticlassExactMatch` and :mod:`MultilabelExactMatch` for the specific details of
    each argument influence and examples.

        Legacy Example:
        >>> target = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[1, 1], [2, 0], [1, 2]]])
        >>> preds = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[2, 2], [2, 1], [1, 0]]])
        >>> metric = ExactMatch(task="multiclass", num_classes=3, multidim_average='global')
        >>> metric(preds, target)
        tensor(0.5000)

        >>> target = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[1, 1], [2, 0], [1, 2]]])
        >>> preds = torch.tensor([[[0, 1], [2, 1], [0, 2]], [[2, 2], [2, 1], [1, 0]]])
        >>> metric = ExactMatch(task="multiclass", num_classes=3, multidim_average='samplewise')
        >>> metric(preds, target)
        tensor([1., 0.])
    rK   Nr   Ttask)binary
multiclass
multilabelrM   r   rL   r   r   r   r   r   r   c           	      K   sp   | t|||d |dkrt|tsJ t|fi |S |dkr1t|ts(J t||fi |S td| )N)r   r   r   rR   rS   zOExpected argument `task` to either be `'multiclass'` or `'multilabel'` but got )r7   dictr;   rH   r   rJ   
ValueError)	clsrP   rM   r   rL   r   r   r   r   r&   r&   r2   __new__  s   zExactMatch.__new__)rK   NNr   NT)r@   rA   rB   rC   r   rN   r   rH   rF   r   r   rW   r&   r&   r&   r2   rO     s6    	
rO   )typingr   r   r*   r   typing_extensionsr   2torchmetrics.functional.classification.exact_matchr   r   r   2torchmetrics.functional.classification.stat_scoresr	   r
   r   r   r   r   torchmetrics.metricr   torchmetrics.utilities.datar   r   rJ   rO   r&   r&   r&   r2   <module>   s    dy