o
    .wi=                     @   s   d dl mZ d dl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s\ddgZG dd deZ G dd deZ!G dd deZ"dS )    )Sequence)AnyOptional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de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	d deeeee f  dee def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.

    .. tip::
       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di | |rt|| || _|| _|| _| jdtddd | jdtddd d S )Nr!   r   sumdefaultdist_reduce_fxr"   r    )	super__init__r
   r%   r#   r$   	add_statetorchtensor)selfr#   r$   r%   r&   	__class__r,   ^/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/classification/hinge.pyr.   a   s   
zBinaryHingeLoss.__init__predstargetc                 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"   r2   r6   r7   r!   r"   r,   r,   r5   updater   s   
zBinaryHingeLoss.updatec                 C      t | j| jS zCompute metric.r   r!   r"   r2   r,   r,   r5   compute}      zBinaryHingeLoss.computevalaxc                 C      |  ||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)

        _plotr2   rC   rD   r,   r,   r5   plot      (r   )FNTNN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   floatr    r   r   intr   r.   r<   rA   r   r   r   r   rI   __classcell__r,   r,   r3   r5   r   *   sB   
 -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%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	d&d!eeeee f  d"ee def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).

    .. tip::
       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 specifying 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    Classplot_legend_namer!   r"   crammer-singerNnum_classesr#   multiclass_moderX   z
one-vs-allr$   r%   r&   r'   c                    s   t  jdi | |rt|||| || _|| _|| _|| _|| _| jd| jdkr.t	
dnt	|dd | jdt	
ddd d S )	Nr!   rX   r   r(   r)   r"   r   r,   )r-   r.   r   r%   rY   r#   rZ   r$   r/   r0   r1   zeros)r2   rY   r#   rZ   r$   r%   r&   r3   r,   r5   r.      s$   	

	zMulticlassHingeLoss.__init__r6   r7   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   rY   r$   r   r   r#   rZ   r!   r"   r;   r,   r,   r5   r<     s   zMulticlassHingeLoss.updatec                 C   r=   r>   r?   r@   r,   r,   r5   rA     rB   zMulticlassHingeLoss.computerC   rD   c                 C   rE   )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)

        rF   rH   r,   r,   r5   rI     rJ   r   )FrX   NTrK   )rL   rM   rN   rO   r   rP   rQ   r   r   r   rR   r    rW   strr   rS   r   r   r   r.   r<   rA   r   r   r   r   rI   rT   r,   r,   r3   r5   rU      sN   
 :	rU   c                   @   sb   e Zd ZdZ					dded  ded d	ee d
edeed  dee dede	de
f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])

    NFrX   Tclstask)binary
multiclassrY   r#   rZ   r[   r$   r%   r&   r'   c                 K   s   t |}|||d |t jkrt|fi |S |t jkrDt|ts.tdt	| d|dvr:td| dt
|||fi |S td| d)	zInitialize task metric.)r$   r%   z+`num_classes` is expected to be `int` but `z was passed.`r[   zQ`multiclass_mode` is expected to be one of 'crammer-singer' or 'one-vs-all' but `z` was passed.zUnsupported task ``)r   from_strr<   BINARYr   
MULTICLASS
isinstancerS   
ValueErrortyperU   )r_   r`   rY   r#   rZ   r$   r%   r&   r,   r,   r5   __new__d  s   



zHingeLoss.__new__)NFrX   NT)rL   rM   rN   rO   ri   r   r   rS   rP   r   r   rj   r,   r,   r,   r5   r^   F  s4     
	r^   )#collections.abcr   typingr   r   r   r0   r   typing_extensionsr    torchmetrics.classification.baser   ,torchmetrics.functional.classification.hinger	   r
   r   r   r   r   r   r   r   torchmetrics.metricr   torchmetrics.utilities.enumsr   torchmetrics.utilities.importsr   torchmetrics.utilities.plotr   r   __doctest_skip__r   rU   r^   r,   r,   r,   r5   <module>   s$   ,  