o
    yi"/                     @   s  d dl mZmZ d dlZd dlmZmZ d dlmZ d dlm	Z	m
Z
mZmZ d dlmZ deded	efd
dZd+dedee d	dfddZd+dededee d	dfddZdededed	eeef fddZ			d,dedededee ded	efddZ			d-dededed dee d	df
ddZ	d+dedededee d	df
d d!Z	d.dedededed d	eeef f
d"d#Z				d/dededededed dee ded	efd$d%Z					&d0deded'ed( dee deded dee ded	efd)d*ZdS )1    )OptionalTupleN)Tensortensor)Literal)_binary_confusion_matrix_format*_binary_confusion_matrix_tensor_validation#_multiclass_confusion_matrix_format._multiclass_confusion_matrix_tensor_validation)	to_onehotmeasuretotalreturnc                 C   s   | | S N )r   r   r   r   `/home/ubuntu/.local/lib/python3.10/site-packages/torchmetrics/functional/classification/hinge.py_hinge_loss_compute   s   r   squaredignore_indexc                 C   s@   t | tstd|  |d urt |tstd| d S d S )Nz2Expected argument `squared` to be an bool but got zLExpected argument `ignore_index` to either be `None` or an integer, but got )
isinstancebool
ValueErrorint)r   r   r   r   r   !_binary_hinge_loss_arg_validation!   s
   
r   predstargetc                 C   s(   t | || |  std| j d S NzdExpected argument `preds` to be floating tensor with probabilities/logits but got tensor with dtype )r   is_floating_pointr   dtype)r   r   r   r   r   r   $_binary_hinge_loss_tensor_validation(   s   r   c                 C   sv   |  }t| }| | ||< | |   || < d| }t|d}|r)|d}t|jd |jd}|jdd|fS )N   r      devicedim)	r   torch
zeros_likeclamppowr   shaper#   sum)r   r   r   marginmeasuresr   r   r   r   _binary_hinge_loss_update1   s   

r.   Fvalidate_argsc                 C   sJ   |rt || t| || t| |d|dd\} }t| ||\}}t||S )a  Computes the mean `Hinge loss`_ typically used for Support Vector Machines (SVMs) for binary tasks. It is
    defined as:

    .. 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.

    Accepts the following input tensors:

    - ``preds`` (float tensor): ``(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`` (int tensor): ``(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.

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

    Args:
        preds: Tensor with predictions
        target: Tensor with true labels
        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.

    Example:
        >>> from torchmetrics.functional.classification import binary_hinge_loss
        >>> preds = torch.tensor([0.25, 0.25, 0.55, 0.75, 0.75])
        >>> target = torch.tensor([0, 0, 1, 1, 1])
        >>> binary_hinge_loss(preds, target)
        tensor(0.6900)
        >>> binary_hinge_loss(preds, target, squared=True)
        tensor(0.6905)
    g        F)	thresholdr   convert_to_labels)r   r   r   r.   r   )r   r   r   r   r/   r-   r   r   r   r   binary_hinge_lossF   s   ,



r2   crammer-singernum_classesmulticlass_moder3   z
one-vs-allc                 C   sP   t || t| tr| dk rtd|  d}||vr&td| d| dd S )Nr!   zHExpected argument `num_classes` to be an integer larger than 1, but got r6   z1Expected argument `multiclass_mode` to be one of z
, but got .)r   r   r   r   )r4   r   r5   r   
allowed_mmr   r   r   %_multiclass_hinge_loss_arg_validation|   s   
r9   c                 C   s*   t | ||| |  std| j d S r   )r
   r   r   r   )r   r   r4   r   r   r   r   (_multiclass_hinge_loss_tensor_validation   s   r:   c                 C   s   t d| k| dk s| d} t|td| jd  }|dkr;| | }|t j| |  | jd dddd 8 }n| }t | }| | ||< | |   || < d| }t 	|d}|rd|
d}t|jd |jd}|jdd|fS )Nr   r    r!   r3   r$   r"   )r&   allsoftmaxr   maxr*   r   viewr'   r(   r)   r   r#   r+   )r   r   r   r5   r,   r-   r   r   r   r   _multiclass_hinge_loss_update   s    
,

r@   c           	      C   sP   |rt |||| t| ||| t| ||dd\} }t| |||\}}t||S )a
  Computes 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.

    Accepts the following input tensors:

    - ``preds`` (float tensor): ``(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`` (int tensor): ``(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).

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

    Args:
        preds: Tensor with predictions
        target: Tensor with true labels
        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.

    Example:
        >>> from torchmetrics.functional.classification import multiclass_hinge_loss
        >>> 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])
        >>> multiclass_hinge_loss(preds, target, num_classes=3)
        tensor(0.9125)
        >>> multiclass_hinge_loss(preds, target, num_classes=3, squared=True)
        tensor(1.1131)
        >>> multiclass_hinge_loss(preds, target, num_classes=3, multiclass_mode='one-vs-all')
        tensor([0.8750, 1.1250, 1.1000])
    F)r1   )r9   r:   r	   r@   r   )	r   r   r4   r   r5   r   r/   r-   r   r   r   r   multiclass_hinge_loss   s   9
rA   Ttask)binary
multiclassc                 C   sP   |dkrt | ||||S |dkr!t|tsJ t| ||||||S td| )a  Computes 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
    :func:`binary_hinge_loss` and :func:`multiclass_hinge_loss` for the specific details of
    each argument influence and examples.

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

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

        >>> target = torch.tensor([0, 1, 2])
        >>> preds = torch.tensor([[-1.0, 0.9, 0.2], [0.5, -1.1, 0.8], [2.2, -0.5, 0.3]])
        >>> hinge_loss(preds, target, task="multiclass", num_classes=3, multiclass_mode="one-vs-all")
        tensor([1.3743, 1.1945, 1.2359])
    rC   rD   zKExpected argument `task` to either be `'binary'` or `'multilabel'` but got )r2   r   r   rA   r   )r   r   rB   r4   r   r5   r   r/   r   r   r   
hinge_loss   s   "rE   r   )FNF)Fr3   N)r3   )Fr3   NF)NFr3   NT)typingr   r   r&   r   r   typing_extensionsr   7torchmetrics.functional.classification.confusion_matrixr   r   r	   r
   torchmetrics.utilities.datar   r   r   r   r   r   r.   r2   r9   r:   r@   rA   rE   r   r   r   r   <module>   s    	


8



!
E	