o
    .wil                     @   s  d dl 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 d d	lmZ 	dCd
edeed  defddZ			dDdedee deed  ddfddZ	dCdededee ddfddZ			dEdedededee dedeeef fddZdededefddZ	dCd
edeed  defdd Z				dFdedededeed  dee d!edefd"d#Z		dGd$edee deed  ddfd%d&Z	dCdeded$edee ddf
d'd(Z		dHdededee dedeeef f
d)d*Zdeded$edefd+d,Z	dCd
edeed  defd-d.Z			dIdeded$edeed  dee d!edefd/d0Z 			dDd1ededee deed  ddf
d2d3Z!	dCdeded1edee ddf
d4d5Z"			dEdeded1ededee d6edeeef fd7d8Z#deded1edefd9d:Z$	dCd
edeed  defd;d<Z%				dFdeded1ededeed  dee d!edefd=d>Z&						dJdeded?ed@ ded$ee d1ee deed  dee d!edefdAdBZ'dS )K    )OptionalN)Tensor)Literal)_check_same_shape)normalize_logits_if_needed)	_bincount)ClassificationTask)rank_zero_warnconfmat	normalize)truepredallnonereturnc                 C   s   d}||vrt d| |durc|dkrc|  s|  n| } |dkr-| | jddd } n|d	kr;| | jd
dd } n|dkrJ| | jd
dgdd } | t|   }|rcd| 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)dimkeepdimr   r   r   zD NaN values found in confusion matrix have been replaced with zeros.)
ValueErroris_floating_pointfloatsumtorchisnannelementr	   )r
   r   allowed_normalizenan_elements r   t/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/functional/classification/confusion_matrix.py_confusion_matrix_reduce   s    r!         ?	thresholdignore_indexc                 C   sv   t | trd|   krdksn td|  d|dur(t |ts(td| d}||vr9t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targetc                 C   s   t | | tj|dd}|du rt|dk|dk@ }nt|dk|dk@ ||k@ }|rAtd| d|du r:ddgn|g d|  s_tj| dd}t|dk|dk@ ratd| d	dS 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}

    Nr   r   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_validationT   s&   

r9   Tconvert_to_labelsc                 C   sV   |   } |  }|dur||k}| | } || }|  r't| d} |r'| |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

    Nsigmoid)flattenr   r   )r-   r.   r#   r$   r:   idxr   r   r    _binary_confusion_matrix_formatw   s   
r>   c                 C   s,   |d |   tj}t|dd}|ddS )5Compute the bins to update the confusion matrix with.      	minlengthtor   longr   reshape)r-   r.   unique_mappingbinsr   r   r    _binary_confusion_matrix_update   s   rJ   c                 C   
   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      
rO   validate_argsc                 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. Additionally,
      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,   r9   r>   rJ   rO   )r-   r.   r#   r   r$   rQ   r
   r   r   r    binary_confusion_matrix   s   7

rR   num_classesc                 C   sf   t | tr	| dk rtd|  |dur t |ts td| d}||vr1t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   )rS   r$   r   r   r   r   r    +_multiclass_confusion_matrix_arg_validation   s   rT   c              	   C   s  | j |j d kr.|  std| jd |krtd| jdd |jdd kr-tdn| j |j krI| j|jkrHtdd| j d	|j d
ntd|du rS|n|d }|  se|dff| dff ndD ]\}}ttj|dd}||krtd| d| d| dqgd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, ...).r.   r-   r   r/   z Detected more unique values in `z` than expected. Expected only z but found z in `target`.)ndimr   r   shapelenr   r4   r6   )r-   r.   rS   r$   check_valuetnamenum_unique_valuesr   r   r    ._multiclass_confusion_matrix_tensor_validation   sB   (r\   c                 C   sx   | j |j d kr|r| jdd} |r|  nt| ddd| jd } | }|dur8||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)rU   argmaxr<   r   movedimrG   rV   )r-   r.   r$   r:   r=   r   r   r    #_multiclass_confusion_matrix_format)  s   (r_   c                 C   s8   | tj| |  tj }t||d d}|||S )r?   r@   rB   rD   )r-   r.   rS   rH   rI   r   r   r    #_multiclass_confusion_matrix_updateD  s   r`   c                 C   rK   rL   rM   rN   r   r   r    $_multiclass_confusion_matrix_computeK  rP   ra   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 specifying 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]])

    )rT   r\   r_   r`   ra   )r-   r.   rS   r   r$   rQ   r
   r   r   r    multiclass_confusion_matrixV  s   <
rb   
num_labelsc                 C   s   t | tr	| dk rtd|  t |tr d|  krdks(n td| d|dur8t |ts8td| d	}||vrIt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   )rc   r#   r$   r   r   r   r   r    +_multilabel_confusion_matrix_arg_validation  s    rd   c                 C   s   t | | | jd |krtd| jd  d| tj|dd}|du r0t|dk|dk@ }nt|dk|dk@ ||k@ }|rUtd| d|du rNddgn|g d	|  sstj| dd}t|dk|dk@ rutd
| ddS 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   r0   r1   r&   r2   r3   )r   rV   r   r   r4   r5   r6   r   )r-   r.   rc   r$   r7   r8   r   r   r    ._multilabel_confusion_matrix_tensor_validation  s6   

re   should_thresholdc                 C   s   |   rt| d} |r| |k} t| ddd|} t|ddd|}|durA|  } | }||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   r^   rG   clone)r-   r.   rc   r#   r$   rf   r=   r   r   r    #_multilabel_confusion_matrix_format  s   
ri   c                 C   sN   d| |  dt j|| jd   }||dk }t|d| d}||ddS )r?   r@   rA   )devicer   rB   )r   arangerj   r<   r   rG   )r-   r.   rc   rH   rI   r   r   r    #_multilabel_confusion_matrix_update  s   $rl   c                 C   rK   rL   rM   rN   r   r   r    $_multilabel_confusion_matrix_compute  rP   rm   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. Additionally,
      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 specifying 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]]])

    )rd   re   ri   rl   rm   )r-   r.   rc   r#   r   r$   rQ   r
   r   r   r    multilabel_confusion_matrix  s   ;
rn   task)binary
multiclass
multilabelc	           	      C   s   t |}|t jkrt| |||||S |t jkr0t|ts'tdt| dt	| |||||S |t j
krNt|tsDtdt| dt| ||||||S td| d)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.)r   from_strBINARYrR   
MULTICLASSr*   r+   r   typerb   
MULTILABELrn   )	r-   r.   ro   r#   rS   rc   r   r$   rQ   r   r   r    confusion_matrixU  s   
/




rx   )N)r"   NN)r"   NT)r"   NNT)NN)NT)NNT)r"   NNNNT)(typingr   r   r   typing_extensionsr   torchmetrics.utilities.checksr   torchmetrics.utilities.computer   torchmetrics.utilities.datar   torchmetrics.utilities.enumsr   torchmetrics.utilities.printsr	   r!   r   r+   r,   r9   booltupler>   rJ   rO   rR   rT   r\   r_   r`   ra   rb   rd   re   ri   rl   rm   rn   rx   r   r   r   r    <module>   s  

%


&





A


2





F


.

"	



G
	
