a
    d=                     @   s   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mZmZmZmZmZ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mZ esddgZG dd deZG dd deZ G dd de
Z!dS )    )AnyOptionalSequenceUnionN)Tensor)Literal)_ClassificationTaskWrapper)	_binary_confusion_matrix_format!_binary_hinge_loss_arg_validation$_binary_hinge_loss_tensor_validation_binary_hinge_loss_update_hinge_loss_compute#_multiclass_confusion_matrix_format%_multiclass_hinge_loss_arg_validation(_multiclass_hinge_loss_tensor_validation_multiclass_hinge_loss_update)Metric)ClassificationTaskNoMultilabel)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEBinaryHingeLoss.plotMulticlassHingeLoss.plotc                       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< d	Ze
ed
< eed< eed< deee eedd fddZeeddddZedddZdeeeee f  ee edddZ  ZS )BinaryHingeLossa(  Compute the mean `Hinge loss`_ typically used for Support Vector Machines (SVMs) for binary tasks.

    .. math::
        \text{Hinge loss} = \max(0, 1 - y \times \hat{y})

    Where :math:`y \in {-1, 1}` is the target, and :math:`\hat{y} \in \mathbb{R}` is the prediction.

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

    - ``preds`` (:class:`~torch.Tensor`): A float tensor of shape ``(N, ...)``. Preds should be a tensor containing
      probabilities or logits for each observation. If preds has values outside [0,1] range we consider the input
      to be logits and will auto apply sigmoid per element.
    - ``target`` (:class:`~torch.Tensor`): An int tensor of shape ``(N, ...)``. Target should be a tensor containing
      ground truth labels, and therefore only contain {0,1} values (except if `ignore_index` is specified). The value
      1 always encodes the positive class.

    .. note::
       Additional dimension ``...`` will be flattened into the batch dimension.

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

    - ``bhl`` (:class:`~torch.Tensor`): A tensor containing the hinge loss.

    Args:
        squared:
            If True, this will compute the squared hinge loss. Otherwise, computes the regular hinge loss.
        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.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example:
        >>> from torchmetrics.classification import BinaryHingeLoss
        >>> preds = torch.tensor([0.25, 0.25, 0.55, 0.75, 0.75])
        >>> target = torch.tensor([0, 0, 1, 1, 1])
        >>> bhl = BinaryHingeLoss()
        >>> bhl(preds, target)
        tensor(0.6900)
        >>> bhl = BinaryHingeLoss(squared=True)
        >>> bhl(preds, target)
        tensor(0.6905)

    Tis_differentiableFhigher_is_betterfull_state_update        plot_lower_bound      ?plot_upper_boundmeasurestotalN)squaredignore_indexvalidate_argskwargsreturnc                    sb   t  jf i | |r t|| || _|| _|| _| jdtddd | jdtddd d S )Nr!   r   sumdefaultZdist_reduce_fxr"   r   )	super__init__r
   r%   r#   r$   	add_statetorchtensor)selfr#   r$   r%   r&   	__class__ j/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/classification/hinge.pyr,   _   s    
zBinaryHingeLoss.__init__predstargetr'   c                 C   s^   | j rt||| j t||d| jdd\}}t||| j\}}|  j|7  _|  j|7  _dS )Update metric state.r   F)	thresholdr$   convert_to_labelsN)r%   r   r$   r	   r   r#   r!   r"   r0   r6   r7   r!   r"   r3   r3   r4   updatep   s    
zBinaryHingeLoss.updater'   c                 C   s   t | j| jS zCompute metric.r   r!   r"   r0   r3   r3   r4   compute{   s    zBinaryHingeLoss.computevalaxr'   c                 C   s   |  ||S )a5  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 object and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value
            >>> from torch import rand, randint
            >>> from torchmetrics.classification import BinaryHingeLoss
            >>> metric = BinaryHingeLoss()
            >>> metric.update(rand(10), randint(2,(10,)))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> from torch import rand, randint
            >>> from torchmetrics.classification import BinaryHingeLoss
            >>> metric = BinaryHingeLoss()
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(rand(10), randint(2,(10,))))
            >>> fig_, ax_ = metric.plot(values)

        Z_plotr0   rC   rD   r3   r3   r4   plot   s    (r   )FNT)NN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   floatr    r   r   intr   r,   r<   rA   r   r   r   r   rG   __classcell__r3   r3   r1   r4   r   )   s2   
,    r   c                	       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< d	Ze
ed
< dZeed< eed< eed< deeed ee eedd fddZeeddddZedddZdeeeee f  ee edddZ  ZS ) MulticlassHingeLossa  Compute the mean `Hinge loss`_ typically used for Support Vector Machines (SVMs) for multiclass tasks.

    The metric can be computed in two ways. Either, the definition by Crammer and Singer is used:

    .. math::
        \text{Hinge loss} = \max\left(0, 1 - \hat{y}_y + \max_{i \ne y} (\hat{y}_i)\right)

    Where :math:`y \in {0, ..., \mathrm{C}}` is the target class (where :math:`\mathrm{C}` is the number of classes),
    and :math:`\hat{y} \in \mathbb{R}^\mathrm{C}` is the predicted output per class. Alternatively, the metric can
    also be computed in one-vs-all approach, where each class is valued against all other classes in a binary fashion.

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

    - ``preds`` (:class:`~torch.Tensor`): A float tensor of shape ``(N, C, ...)``. Preds should be a tensor
      containing probabilities or logits for each observation. If preds has values outside [0,1] range we consider
      the input to be logits and will auto apply softmax per sample.
    - ``target`` (:class:`~torch.Tensor`): An int tensor of shape ``(N, ...)``. Target should be a tensor containing
      ground truth labels, and therefore only contain values in the [0, n_classes-1] range (except if `ignore_index`
      is specified).

    .. note::
       Additional dimension ``...`` will be flattened into the batch dimension.

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

    - ``mchl`` (:class:`~torch.Tensor`): A tensor containing the multi-class hinge loss.

    Args:
        num_classes: Integer specifing the number of classes
        squared:
            If True, this will compute the squared hinge loss. Otherwise, computes the regular hinge loss.
        multiclass_mode:
            Determines how to compute the metric
        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.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example:
        >>> from torchmetrics.classification import MulticlassHingeLoss
        >>> preds = torch.tensor([[0.25, 0.20, 0.55],
        ...                       [0.55, 0.05, 0.40],
        ...                       [0.10, 0.30, 0.60],
        ...                       [0.90, 0.05, 0.05]])
        >>> target = torch.tensor([0, 1, 2, 0])
        >>> mchl = MulticlassHingeLoss(num_classes=3)
        >>> mchl(preds, target)
        tensor(0.9125)
        >>> mchl = MulticlassHingeLoss(num_classes=3, squared=True)
        >>> mchl(preds, target)
        tensor(1.1131)
        >>> mchl = MulticlassHingeLoss(num_classes=3, multiclass_mode='one-vs-all')
        >>> mchl(preds, target)
        tensor([0.8750, 1.1250, 1.1000])

    Tr   Fr   r   r   r   r   r    ZClassplot_legend_namer!   r"   crammer-singerNrS   z
one-vs-all)num_classesr#   multiclass_moder$   r%   r&   r'   c                    s   t  jf i | |r$t|||| || _|| _|| _|| _|| _| jd| jdkr\t	
dnt	|dd | jdt	
ddd d S )Nr!   rS   r   r(   r)   r"   r   )r+   r,   r   r%   rU   r#   rV   r$   r-   r.   r/   zeros)r0   rU   r#   rV   r$   r%   r&   r1   r3   r4   r,      s$    		zMulticlassHingeLoss.__init__r5   c                 C   sd   | j rt||| j| j t||| jdd\}}t||| j| j\}}|  j|7  _|  j	|7  _	dS )r8   F)r:   N)
r%   r   rU   r$   r   r   r#   rV   r!   r"   r;   r3   r3   r4   r<     s    zMulticlassHingeLoss.updater=   c                 C   s   t | j| jS r>   r?   r@   r3   r3   r4   rA     s    zMulticlassHingeLoss.computerB   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 object and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value per class
            >>> from torch import randint, randn
            >>> from torchmetrics.classification import MulticlassHingeLoss
            >>> metric = MulticlassHingeLoss(num_classes=3)
            >>> metric.update(randn(20, 3), randint(3, (20,)))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting a multiple values per class
            >>> from torch import randint, randn
            >>> from torchmetrics.classification import MulticlassHingeLoss
            >>> metric = MulticlassHingeLoss(num_classes=3)
            >>> values = []
            >>> for _ in range(20):
            ...     values.append(metric(randn(20, 3), randint(3, (20,))))
            >>> fig_, ax_ = metric.plot(values)

        rE   rF   r3   r3   r4   rG     s    (r   )FrS   NT)NN)rH   rI   rJ   rK   r   rL   rM   r   r   r   rN   r    rR   strr   rO   r   r   r   r,   r<   rA   r   r   r   r   rG   rP   r3   r3   r1   r4   rQ      s:   
9    	 rQ   c                
   @   sB   e Zd ZdZded ee eeed  ee eee	dd	d
Z
dS )	HingeLossa  Compute the mean `Hinge loss`_ typically used for Support Vector Machines (SVMs).

    This function is a simple wrapper to get the task specific versions of this metric, which is done by setting the
    ``task`` argument to either ``'binary'`` or ``'multiclass'``. See the documentation of
    :class:`~torchmetrics.classification.BinaryHingeLoss` and :class:`~torchmetrics.classification.MulticlassHingeLoss`
    for the specific details of each argument influence and examples.

    Legacy Example:
        >>> from torch import tensor
        >>> target = tensor([0, 1, 1])
        >>> preds = tensor([0.5, 0.7, 0.1])
        >>> hinge = HingeLoss(task="binary")
        >>> hinge(preds, target)
        tensor(0.9000)

        >>> target = tensor([0, 1, 2])
        >>> preds = tensor([[-1.0, 0.9, 0.2], [0.5, -1.1, 0.8], [2.2, -0.5, 0.3]])
        >>> hinge = HingeLoss(task="multiclass", num_classes=3)
        >>> hinge(preds, target)
        tensor(1.5551)

        >>> target = tensor([0, 1, 2])
        >>> preds = tensor([[-1.0, 0.9, 0.2], [0.5, -1.1, 0.8], [2.2, -0.5, 0.3]])
        >>> hinge = HingeLoss(task="multiclass", num_classes=3, multiclass_mode="one-vs-all")
        >>> hinge(preds, target)
        tensor([1.3743, 1.1945, 1.2359])

    NFrS   T)binaryZ
multiclassrT   )taskrU   r#   rV   r$   r%   r&   r'   c                 K   s   t |}|||d |t jkr4t|fi |S |t jkrt|ts\tdt	| d|dvrttd| dt
|||fi |S td| dd	S )
zInitialize task metric.)r$   r%   z+`num_classes` is expected to be `int` but `z was passed.`rT   zQ`multiclass_mode` is expected to be one of 'crammer-singer' or 'one-vs-all' but `z` was passed.zUnsupported task ``N)r   Zfrom_strr<   BINARYr   Z
MULTICLASS
isinstancerO   
ValueErrortyperQ   )clsr[   rU   r#   rV   r$   r%   r&   r3   r3   r4   __new__a  s    



zHingeLoss.__new__)NFrS   NT)rH   rI   rJ   rK   r   r   rO   rL   r   r   rb   r3   r3   r3   r4   rY   C  s          
rY   )"typingr   r   r   r   r.   r   Ztyping_extensionsr   Z torchmetrics.classification.baser   Z,torchmetrics.functional.classification.hinger	   r
   r   r   r   r   r   r   r   Ztorchmetrics.metricr   Ztorchmetrics.utilities.enumsr   Ztorchmetrics.utilities.importsr   Ztorchmetrics.utilities.plotr   r   Z__doctest_skip__r   rQ   rY   r3   r3   r3   r4   <module>   s    ,  