a
    dm                     @   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 d dl	m
Z
 d dlmZ d dlmZ dFeeed	  ed
ddZdGeee eed	  ddddZdHeeee ddddZdIeeeee eeeef dddZeeedddZdJeeed	  ed
ddZdKeeeeed	  ee eedddZdLeee eed	  dd d!d"ZdMeeeee dd#d$d%ZdNeeee eeeef d&d'd(Zeeeed)d*d+ZdOeeed	  ed
d,d-ZdPeeeeed	  ee eed.d/d0ZdQeeee eed	  dd1d2d3ZdReeeee dd4d5d6Z dSeeeeee eeeef d7d8d9Z!eeeed:d;d<Z"dTeeed	  ed
d=d>Z#dUeeeeeed	  ee eed?d@dAZ$dVeeedB eee ee eed	  ee eedC
dDdEZ%dS )W    )OptionalTupleN)Tensor)Literal)_check_same_shape)	_bincount)ClassificationTask)rank_zero_warn)truepredallnone)confmat	normalizereturnc                 C   s   d}||vrt d| |dur|dkr|  s:|  n| } |dkrZ| | jddd } n:|d	krv| | jd
dd } n|dkr| | jd
dgdd } | t|   }|rd| t| < t| d | S )a  Reduce an un-normalized confusion matrix.

    Args:
        confmat: un-normalized confusion matrix
        normalize: normalization method.
            - `"true"` will divide by the sum of the column dimension.
            - `"pred"` will divide by the sum of the row dimension.
            - `"all"` will divide by the sum of the full matrix
            - `"none"` or `None` will apply no reduction.

    Returns:
        Normalized confusion matrix

    r
   r   r   r   Nz4Argument `normalize` needs to one of the following: Nr   r
   T)dimZkeepdimr   r   r   zD NaN values found in confusion matrix have been replaced with zeros.)
ValueErroris_floating_pointfloatsumtorchisnanZnelementr	   )r   r   allowed_normalizeZnan_elements r   /var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/classification/confusion_matrix.py_confusion_matrix_reduce   s     r         ?)	thresholdignore_indexr   r   c                 C   sv   t | tr d|   krdks0n td|  d|durPt |tsPtd| d}||vrrtd| d	| ddS )
zValidate non tensor input.

    - ``threshold`` has to be a float in the [0,1] range
    - ``ignore_index`` has to be None or int
    - ``normalize`` has to be "true" | "pred" | "all" | "none" | None

    r      zHExpected argument `threshold` to be a float in the [0,1] range, but got .NLExpected argument `ignore_index` to either be `None` or an integer, but got r   +Expected argument `normalize` to be one of 
, but got )
isinstancer   r   int)r    r!   r   r   r   r   r   '_binary_confusion_matrix_arg_validation>   s     r)   )predstargetr!   r   c                 C   s   t | | t|}|du r4t|dk|dk@ }nt|dk|dk@ ||k@ }|r~td| d|du rpddgn|g d|  st| }t|dk|dk@ rtd| ddS )	zValidate tensor input.

    - tensors have to be of same shape
    - all values in target tensor that are not ignored have to be in {0, 1}
    - if pred tensor is not floating point, then all values also have to be in {0, 1}

    Nr   r"   +Detected the following values in `target`: ( but expected only the following values r#   *Detected the following values in `preds`: L but expected only the following values [0,1] since preds is a label tensor.)r   r   uniqueanyRuntimeErrorr   )r*   r+   r!   unique_valuescheckr   r   r   *_binary_confusion_matrix_tensor_validationS   s"    



r5   T)r*   r+   r    r!   convert_to_labelsr   c                 C   sj   |   } |  }|dur0||k}| | } || }|  rbt| dk| dk sV|  } |rb| |k} | |fS )zConvert all input to label format.

    - Remove all datapoints that should be ignored
    - If preds tensor is floating point, applies sigmoid if pred tensor not in [0,1] range
    - If preds tensor is floating point, thresholds afterwards

    Nr   r"   )flattenr   r   r   sigmoid)r*   r+   r    r!   r6   idxr   r   r   _binary_confusion_matrix_formatv   s    r:   )r*   r+   r   c                 C   s,   |d |   tj}t|dd}|ddS )5Compute the bins to update the confusion matrix with.      Z	minlengthtor   longr   reshape)r*   r+   unique_mappingbinsr   r   r   _binary_confusion_matrix_update   s    rE   c                 C   s
   t | |S zsReduces the confusion matrix to it's final form.

    Normalization technique can be chosen by ``normalize``.

    r   r   r   r   r   r    _binary_confusion_matrix_compute   s    rI   )r*   r+   r    r   r!   validate_argsr   c                 C   sB   |rt ||| t| || t| |||\} }t| |}t||S )a  Compute the `confusion matrix`_ for binary tasks.

    Accepts the following input tensors:

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

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

    Args:
        preds: Tensor with predictions
        target: Tensor with true labels
        threshold: Threshold for transforming probability to binary (0,1) predictions
        normalize: Normalization mode for confusion matrix. Choose from:

            - ``None`` or ``'none'``: no normalization (default)
            - ``'true'``: normalization over the targets (most commonly used)
            - ``'pred'``: normalization over the predictions
            - ``'all'``: normalization over the whole matrix
        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.

    Returns:
        A ``[2, 2]`` tensor

    Example (preds is int tensor):
        >>> from torch import tensor
        >>> from torchmetrics.functional.classification import binary_confusion_matrix
        >>> target = tensor([1, 1, 0, 0])
        >>> preds = tensor([0, 1, 0, 0])
        >>> binary_confusion_matrix(preds, target)
        tensor([[2, 0],
                [1, 1]])

    Example (preds is float tensor):
        >>> from torchmetrics.functional.classification import binary_confusion_matrix
        >>> target = tensor([1, 1, 0, 0])
        >>> preds = tensor([0.35, 0.85, 0.48, 0.01])
        >>> binary_confusion_matrix(preds, target)
        tensor([[2, 0],
                [1, 1]])

    )r)   r5   r:   rE   rI   )r*   r+   r    r   r!   rJ   r   r   r   r   binary_confusion_matrix   s    7
rK   )num_classesr!   r   r   c                 C   sf   t | tr| dk r td|  |dur@t |ts@td| d}||vrbtd| d| ddS )	zValidate non tensor input.

    - ``num_classes`` has to be a int larger than 1
    - ``ignore_index`` has to be None or int
    - ``normalize`` has to be "true" | "pred" | "all" | "none" | None

    r<   zHExpected argument `num_classes` to be an integer larger than 1, but got Nr$   r   r%   r&   r#   )r'   r(   r   )rL   r!   r   r   r   r   r   +_multiclass_confusion_matrix_arg_validation   s    rM   )r*   r+   rL   r!   r   c                 C   s*  | j |j d kr\|  s td| jd |kr6td| jdd |jdd krtdn>| j |j kr| j|jkrtdd| j d	|j d
ntdtt|}|du r||kn
||d k}|rtd|du r|n|d  d| d|  s&tt| }||kr&td| d| ddS )a  Validate tensor input.

    - if target has one more dimension than preds, then all dimensions except for preds.shape[1] should match
    exactly. preds.shape[1] should have size equal to number of classes
    - if preds and target have same number of dims, then all dimensions should match
    - all values in target tensor that are not ignored have to be {0, ..., num_classes - 1}
    - if pred tensor is not floating point, then all values also have to be in {0, ..., num_classes - 1}

    r"   zSIf `preds` have one dimension more than `target`, `preds` should be a float tensor.zhIf `preds` have one dimension more than `target`, `preds.shape[1]` should be equal to number of classes.r<   NzIf `preds` have one dimension more than `target`, the shape of `preds` should be (N, C, ...), and the shape of `target` should be (N, ...).z4The `preds` and `target` should have the same shape,z got `preds` with shape=z and `target` with shape=r#   zEither `preds` and `target` both should have the (same) shape (N, ...), or `target` should be (N, ...) and `preds` should be (N, C, ...).zJDetected more unique values in `target` than `num_classes`. Expected only z but found z in `target`.zIDetected more unique values in `preds` than `num_classes`. Expected only z in `preds`.)ndimr   r   shapelenr   r0   r2   )r*   r+   rL   r!   Znum_unique_valuesr4   r   r   r   ._multiclass_confusion_matrix_tensor_validation   sP    

rQ   )r*   r+   r!   r6   r   c                 C   sx   | j |j d kr |r | jdd} |r,|  nt| ddd| jd } | }|durp||k}| | } || }| |fS )zConvert all input to label format.

    - Applies argmax if preds have one more dimension than target
    - Remove all datapoints that should be ignored

    r"   )r   r   N)rN   Zargmaxr7   r   movedimrB   rO   )r*   r+   r!   r6   r9   r   r   r   #_multiclass_confusion_matrix_format2  s    (rS   )r*   r+   rL   r   c                 C   s8   | tj| |  tj }t||d d}|||S )r;   r<   r>   r?   )r*   r+   rL   rC   rD   r   r   r   #_multiclass_confusion_matrix_updateM  s    rT   c                 C   s
   t | |S rF   rG   rH   r   r   r   $_multiclass_confusion_matrix_computeT  s    rU   )r*   r+   rL   r   r!   rJ   r   c                 C   sD   |rt ||| t| ||| t| ||\} }t| ||}t||S )a  Compute the `confusion matrix`_ for multiclass tasks.

    Accepts the following input tensors:

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

    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
        normalize: Normalization mode for confusion matrix. Choose from:

            - ``None`` or ``'none'``: no normalization (default)
            - ``'true'``: normalization over the targets (most commonly used)
            - ``'pred'``: normalization over the predictions
            - ``'all'``: normalization over the whole matrix
        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.

    Returns:
        A ``[num_classes, num_classes]`` tensor

    Example (pred is integer tensor):
        >>> from torch import tensor
        >>> from torchmetrics.functional.classification import multiclass_confusion_matrix
        >>> target = tensor([2, 1, 0, 0])
        >>> preds = tensor([2, 1, 0, 1])
        >>> multiclass_confusion_matrix(preds, target, num_classes=3)
        tensor([[1, 1, 0],
                [0, 1, 0],
                [0, 0, 1]])

    Example (pred is float tensor):
        >>> from torchmetrics.functional.classification import multiclass_confusion_matrix
        >>> target = tensor([2, 1, 0, 0])
        >>> preds = tensor([[0.16, 0.26, 0.58],
        ...                 [0.22, 0.61, 0.17],
        ...                 [0.71, 0.09, 0.20],
        ...                 [0.05, 0.82, 0.13]])
        >>> multiclass_confusion_matrix(preds, target, num_classes=3)
        tensor([[1, 1, 0],
                [0, 1, 0],
                [0, 0, 1]])

    )rM   rQ   rS   rT   rU   )r*   r+   rL   r   r!   rJ   r   r   r   r   multiclass_confusion_matrix_  s    <rV   )
num_labelsr    r!   r   r   c                 C   s   t | tr| dk r td|  t |tr@d|  kr>dksPn td| d|durpt |tsptd| d	}||vrtd
| d| ddS )a  Validate non tensor input.

    - ``num_labels`` should be an int larger than 1
    - ``threshold`` has to be a float in the [0,1] range
    - ``ignore_index`` has to be None or int
    - ``normalize`` has to be "true" | "pred" | "all" | "none" | None

    r<   zGExpected argument `num_labels` to be an integer larger than 1, but got r   r"   z5Expected argument `threshold` to be a float, but got r#   Nr$   r   r%   r&   )r'   r(   r   r   )rW   r    r!   r   r   r   r   r   +_multilabel_confusion_matrix_arg_validation  s     rX   )r*   r+   rW   r!   r   c                 C   s   t | | | jd |kr2td| jd  d| t|}|du r\t|dk|dk@ }nt|dk|dk@ ||k@ }|rtd| d|du rddgn|g d|  st| }t|dk|dk@ rtd	| d
dS )a:  Validate tensor input.

    - tensors have to be of same shape
    - the second dimension of both tensors need to be equal to the number of labels
    - all values in target tensor that are not ignored have to be in {0, 1}
    - if pred tensor is not floating point, then all values also have to be in {0, 1}

    r"   zaExpected both `target.shape[1]` and `preds.shape[1]` to be equal to the number of labels but got z and expected Nr   r,   r-   r#   r.   r/   )r   rO   r   r   r0   r1   r2   r   )r*   r+   rW   r!   r3   r4   r   r   r   ._multilabel_confusion_matrix_tensor_validation  s2    



rY   )r*   r+   rW   r    r!   should_thresholdr   c                 C   s   |   r2t| dk| dk s&|  } |r2| |k} t| ddd|} t|ddd|}|dur|  } | }||k}d| | |< d| ||< | |fS )a  Convert all input to label format.

    - If preds tensor is floating point, applies sigmoid if pred tensor not in [0,1] range
    - If preds tensor is floating point, thresholds afterwards
    - Mask all elements that should be ignored with negative numbers for later filtration

    r   r"   r   N)r   r   r   r8   rR   rB   clone)r*   r+   rW   r    r!   rZ   r9   r   r   r   #_multilabel_confusion_matrix_format  s    r]   )r*   r+   rW   r   c                 C   sN   d| |  dt j|| jd   }||dk }t|d| d}||ddS )r;   r<   r=   )devicer   r>   )r   Zaranger^   r7   r   rB   )r*   r+   rW   rC   rD   r   r   r   #_multilabel_confusion_matrix_update	  s    $r_   c                 C   s
   t | |S rF   rG   rH   r   r   r   $_multilabel_confusion_matrix_compute  s    r`   )r*   r+   rW   r    r   r!   rJ   r   c                 C   sJ   |r t |||| t| ||| t| ||||\} }t| ||}t||S )a 	  Compute the `confusion matrix`_ for multilabel tasks.

    Accepts the following input tensors:

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

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

    Args:
        preds: Tensor with predictions
        target: Tensor with true labels
        num_labels: Integer specifing the number of labels
        threshold: Threshold for transforming probability to binary (0,1) predictions
        normalize: Normalization mode for confusion matrix. Choose from:

            - ``None`` or ``'none'``: no normalization (default)
            - ``'true'``: normalization over the targets (most commonly used)
            - ``'pred'``: normalization over the predictions
            - ``'all'``: normalization over the whole matrix
        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.

    Returns:
        A ``[num_labels, 2, 2]`` tensor

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

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

    )rX   rY   r]   r_   r`   )r*   r+   rW   r    r   r!   rJ   r   r   r   r   multilabel_confusion_matrix  s    ;ra   )binaryZ
multiclassZ
multilabel)
r*   r+   taskr    rL   rW   r   r!   rJ   r   c	           	      C   s   t |}|t jkr&t| |||||S |t jkr`t|tsNtdt| dt	| |||||S |t j
krt|tstdt| dt| ||||||S td| ddS )a  Compute the `confusion matrix`_.

    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'``, ``'multiclass'`` or ``multilabel``. See the documentation of
    :func:`~torchmetrics.functional.classification.binary_confusion_matrix`,
    :func:`~torchmetrics.functional.classification.multiclass_confusion_matrix` and
    :func:`~torchmetrics.functional.classification.multilabel_confusion_matrix` for
    the specific details of each argument influence and examples.

    Legacy Example:
        >>> from torch import tensor
        >>> from torchmetrics.classification import ConfusionMatrix
        >>> target = tensor([1, 1, 0, 0])
        >>> preds = tensor([0, 1, 0, 0])
        >>> confmat = ConfusionMatrix(task="binary")
        >>> confmat(preds, target)
        tensor([[2, 0],
                [1, 1]])

        >>> target = tensor([2, 1, 0, 0])
        >>> preds = tensor([2, 1, 0, 1])
        >>> confmat = ConfusionMatrix(task="multiclass", num_classes=3)
        >>> confmat(preds, target)
        tensor([[1, 1, 0],
                [0, 1, 0],
                [0, 0, 1]])

        >>> target = tensor([[0, 1, 0], [1, 0, 1]])
        >>> preds = tensor([[0, 0, 1], [1, 0, 1]])
        >>> confmat = ConfusionMatrix(task="multilabel", num_labels=3)
        >>> confmat(preds, target)
        tensor([[[1, 0], [0, 1]],
                [[1, 0], [1, 0]],
                [[0, 1], [0, 1]]])

    z+`num_classes` is expected to be `int` but `z was passed.`z*`num_labels` is expected to be `int` but `zTask z not supported.N)r   Zfrom_strBINARYrK   Z
MULTICLASSr'   r(   r   typerV   Z
MULTILABELra   )	r*   r+   rc   r    rL   rW   r   r!   rJ   r   r   r   confusion_matrix_  s    /





rf   )N)r   NN)N)r   NT)N)r   NNT)NN)N)NT)N)NNT)r   NN)N)r   NT)N)r   NNT)r   NNNNT)&typingr   r   r   r   Ztyping_extensionsr   Ztorchmetrics.utilities.checksr   Ztorchmetrics.utilities.datar   Ztorchmetrics.utilities.enumsr   Ztorchmetrics.utilities.printsr	   r   r   r(   r)   r5   boolr:   rE   rI   rK   rM   rQ   rS   rT   rU   rV   rX   rY   r]   r_   r`   ra   rf   r   r   r   r   <module>   sB   %   
 
&   
     
A  
 :  
    
F   
 .   
#	     
G      
