o
    yiLF                     @   s   d dl mZ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mZmZ d dlmZmZmZmZmZmZ d dlmZ d dlmZ G d	d
 d
eZG dd deZG dd deZG dd dZdS )    )AnyListOptionalTupleUnionN)Tensor)Literal)BinaryPrecisionRecallCurveMulticlassPrecisionRecallCurveMultilabelPrecisionRecallCurve)0_binary_recall_at_fixed_precision_arg_validation)_binary_recall_at_fixed_precision_compute1_multiclass_recall_at_fixed_precision_arg_compute4_multiclass_recall_at_fixed_precision_arg_validation1_multilabel_recall_at_fixed_precision_arg_compute4_multilabel_recall_at_fixed_precision_arg_validation)Metric)dim_zero_catc                       s   e Zd ZU dZdZeed< dZee ed< dZ	eed< 			dde
d	eeeee
 ef  d
ee dededdf fddZdeeef fddZ  ZS )BinaryRecallAtFixedPrecisiona  Computes the highest possible recall value given the minimum precision thresholds provided. This is done by
    first calculating the precision-recall curve for different thresholds and the find the recall for a given
    precision level.

    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:

    - ``recall`` (:class:`~torch.Tensor`): A scalar tensor with the maximum recall for the given precision level
    - ``threshold`` (:class:`~torch.Tensor`): A scalar tensor with the corresponding threshold level

    .. note::
       The implementation both supports calculating the metric in a non-binned but accurate version and a
       binned version that is less accurate but more memory efficient. Setting the `thresholds` argument to `None`
       will activate the non-binned  version that uses memory of size :math:`\mathcal{O}(n_{samples})` whereas setting
       the `thresholds` argument to either an integer, list or a 1d tensor will use a binned version that uses memory
       of size :math:`\mathcal{O}(n_{thresholds})` (constant memory).

    Args:
        min_precision: float value specifying minimum precision threshold.
        thresholds:
            Can be one of:

            - If set to `None`, will use a non-binned approach where thresholds are dynamically calculated from
              all the data. Most accurate but also most memory consuming approach.
            - If set to an `int` (larger than 1), will use that number of thresholds linearly spaced from
              0 to 1 as bins for the calculation.
            - If set to an `list` of floats, will use the indicated thresholds in the list as bins for the calculation
            - If set to an 1d `tensor` of floats, will use the indicated thresholds in the tensor as
              bins for the 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 BinaryRecallAtFixedPrecision
        >>> preds = torch.tensor([0, 0.5, 0.7, 0.8])
        >>> target = torch.tensor([0, 1, 1, 0])
        >>> metric = BinaryRecallAtFixedPrecision(min_precision=0.5, thresholds=None)
        >>> metric(preds, target)
        (tensor(1.), tensor(0.5000))
        >>> metric = BinaryRecallAtFixedPrecision(min_precision=0.5, thresholds=5)
        >>> metric(preds, target)
        (tensor(1.), tensor(0.5000))
    Fis_differentiableNhigher_is_betterfull_state_updateTmin_precision
thresholdsignore_indexvalidate_argskwargsreturnc                    s:   t  j||fddi| |rt||| || _|| _d S )Nr   F)super__init__r   r   r   )selfr   r   r   r   r   	__class__ i/home/ubuntu/.local/lib/python3.10/site-packages/torchmetrics/classification/recall_at_fixed_precision.pyr   b   s
   
z%BinaryRecallAtFixedPrecision.__init__c                 C   s6   | j d u rt| jt| jg}n| j}t|| j | jS N)r   r   predstargetconfmatr   r   r    stater#   r#   r$   computep   s   
z$BinaryRecallAtFixedPrecision.computeNNT)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   floatr   intr   r   r   r   r   r+   __classcell__r#   r#   r!   r$   r   %   s,   
 8r   c                          e Zd ZU dZdZeed< dZee ed< dZ	eed< 			dde
d	ed
eee
ee ef  dee
 dededdf fddZdeeef fddZ  ZS ) MulticlassRecallAtFixedPrecisiona:  Computes the highest possible recall value given the minimum precision thresholds provided. This is done by
    first calculating the precision-recall curve for different thresholds and the find the recall for a given
    precision level.

    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 a tuple of either 2 tensors or 2 lists containing:

    - ``recall`` (:class:`~torch.Tensor`): A 1d tensor of size ``(n_classes, )`` with the maximum recall for the
      given precision level per class
    - ``threshold`` (:class:`~torch.Tensor`): A 1d tensor of size ``(n_classes, )`` with the corresponding threshold
      level per class

    .. note::
       The implementation both supports calculating the metric in a non-binned but accurate version and a binned version
       that is less accurate but more memory efficient. Setting the `thresholds` argument to `None` will activate the
       non-binned  version that uses memory of size :math:`\mathcal{O}(n_{samples})` whereas setting the `thresholds`
       argument to either an integer, list or a 1d tensor will use a binned version that uses memory of
       size :math:`\mathcal{O}(n_{thresholds} \times n_{classes})` (constant memory).

    Args:
        num_classes: Integer specifing the number of classes
        min_precision: float value specifying minimum precision threshold.
        thresholds:
            Can be one of:

            - If set to `None`, will use a non-binned approach where thresholds are dynamically calculated from
              all the data. Most accurate but also most memory consuming approach.
            - If set to an `int` (larger than 1), will use that number of thresholds linearly spaced from
              0 to 1 as bins for the calculation.
            - If set to an `list` of floats, will use the indicated thresholds in the list as bins for the calculation
            - If set to an 1d `tensor` of floats, will use the indicated thresholds in the tensor as
              bins for the 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 MulticlassRecallAtFixedPrecision
        >>> preds = torch.tensor([[0.75, 0.05, 0.05, 0.05, 0.05],
        ...                       [0.05, 0.75, 0.05, 0.05, 0.05],
        ...                       [0.05, 0.05, 0.75, 0.05, 0.05],
        ...                       [0.05, 0.05, 0.05, 0.75, 0.05]])
        >>> target = torch.tensor([0, 1, 3, 2])
        >>> metric = MulticlassRecallAtFixedPrecision(num_classes=5, min_precision=0.5, thresholds=None)
        >>> metric(preds, target)
        (tensor([1., 1., 0., 0., 0.]), tensor([7.5000e-01, 7.5000e-01, 1.0000e+06, 1.0000e+06, 1.0000e+06]))
        >>> mcrafp = MulticlassRecallAtFixedPrecision(num_classes=5, min_precision=0.5, thresholds=5)
        >>> mcrafp(preds, target)
        (tensor([1., 1., 0., 0., 0.]), tensor([7.5000e-01, 7.5000e-01, 1.0000e+06, 1.0000e+06, 1.0000e+06]))
    Fr   Nr   r   Tnum_classesr   r   r   r   r   r   c                    >   t  jd|||dd| |rt|||| || _|| _d S )NF)r8   r   r   r   r#   )r   r   r   r   r   )r    r8   r   r   r   r   r   r!   r#   r$   r         	
z)MulticlassRecallAtFixedPrecision.__init__c                 C   s:   | j d u rt| jt| jg}n| j}t|| j| j | jS r%   )r   r   r&   r'   r(   r   r8   r   r)   r#   r#   r$   r+      s   
z(MulticlassRecallAtFixedPrecision.computer,   r-   r.   r/   r0   r   r1   r2   r   r   r   r4   r3   r   r   r   r   r   r   r+   r5   r#   r#   r!   r$   r7   x   s0   
 >r7   c                       r6   ) MultilabelRecallAtFixedPrecisionaN  Computes the highest possible recall value given the minimum precision thresholds provided. This is done by
    first calculating the precision-recall curve for different thresholds and the find the recall for a given
    precision level.

    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 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 a tuple of either 2 tensors or 2 lists containing:

    - ``recall`` (:class:`~torch.Tensor`): A 1d tensor of size ``(n_classes, )`` with the maximum recall for the
      given precision level per class
    - ``threshold`` (:class:`~torch.Tensor`): A 1d tensor of size ``(n_classes, )`` with the corresponding threshold
      level per class

    .. note::
       The implementation both supports calculating the metric in a non-binned but accurate version and a binned version
       that is less accurate but more memory efficient. Setting the `thresholds` argument to `None` will activate the
       non-binned  version that uses memory of size :math:`\mathcal{O}(n_{samples})` whereas setting the `thresholds`
       argument to either an integer, list or a 1d tensor will use a binned version that uses memory of
       size :math:`\mathcal{O}(n_{thresholds} \times n_{labels})` (constant memory).

    Args:
        num_labels: Integer specifing the number of labels
        min_precision: float value specifying minimum precision threshold.
        thresholds:
            Can be one of:

            - If set to `None`, will use a non-binned approach where thresholds are dynamically calculated from
              all the data. Most accurate but also most memory consuming approach.
            - If set to an `int` (larger than 1), will use that number of thresholds linearly spaced from
              0 to 1 as bins for the calculation.
            - If set to an `list` of floats, will use the indicated thresholds in the list as bins for the calculation
            - If set to an 1d `tensor` of floats, will use the indicated thresholds in the tensor as
              bins for the 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 MultilabelRecallAtFixedPrecision
        >>> preds = torch.tensor([[0.75, 0.05, 0.35],
        ...                       [0.45, 0.75, 0.05],
        ...                       [0.05, 0.55, 0.75],
        ...                       [0.05, 0.65, 0.05]])
        >>> target = torch.tensor([[1, 0, 1],
        ...                        [0, 0, 0],
        ...                        [0, 1, 1],
        ...                        [1, 1, 1]])
        >>> metric = MultilabelRecallAtFixedPrecision(num_labels=3, min_precision=0.5, thresholds=None)
        >>> metric(preds, target)
        (tensor([1., 1., 1.]), tensor([0.0500, 0.5500, 0.0500]))
        >>> mlrafp = MultilabelRecallAtFixedPrecision(num_labels=3, min_precision=0.5, thresholds=5)
        >>> mlrafp(preds, target)
        (tensor([1., 1., 1.]), tensor([0.0000, 0.5000, 0.0000]))
    Fr   Nr   r   T
num_labelsr   r   r   r   r   r   c                    r9   )NF)r=   r   r   r   r#   )r   r   r   r   r   )r    r=   r   r   r   r   r   r!   r#   r$   r     r:   z)MultilabelRecallAtFixedPrecision.__init__c                 C   s>   | j d u rt| jt| jg}n| j}t|| j| j | j| jS r%   )	r   r   r&   r'   r(   r   r=   r   r   r)   r#   r#   r$   r+   -  s   
z(MultilabelRecallAtFixedPrecision.computer,   r;   r#   r#   r!   r$   r<      s0   
 Ar<   c                   @   sl   e Zd ZdZ					dded dedeeee	e e
f  dee d	ee d
ee dededefddZdS )RecallAtFixedPrecisiona  Computes the highest possible recall value given the minimum precision thresholds provided. This is done by
    first calculating the precision-recall curve for different thresholds and the find the recall for a given
    precision level.

    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
    :mod:`BinaryRecallAtFixedPrecision`, :func:`MulticlassRecallAtFixedPrecision` and
    :func:`MultilabelRecallAtFixedPrecision` for the specific details of each argument influence and examples.
    NTtask)binary
multiclass
multilabelr   r   r8   r=   r   r   r   r   c           	      K   s   |dkrt ||||fi |S |dkr&t|tsJ t|||||fi |S |dkr=t|ts1J t|||||fi |S td| )Nr@   rA   rB   z[Expected argument `task` to either be `'binary'`, `'multiclass'` or `'multilabel'` but got )r   
isinstancer4   r7   r<   
ValueError)	clsr?   r   r   r8   r=   r   r   r   r#   r#   r$   __new__B  s&   

zRecallAtFixedPrecision.__new__)NNNNT)r-   r.   r/   r0   r   r3   r   r   r4   r   r   r1   r   r   rF   r#   r#   r#   r$   r>   7  s4    	
r>   )typingr   r   r   r   r   torchr   typing_extensionsr   2torchmetrics.classification.precision_recall_curver	   r
   r   @torchmetrics.functional.classification.recall_at_fixed_precisionr   r   r   r   r   r   torchmetrics.metricr   torchmetrics.utilities.datar   r   r7   r<   r>   r#   r#   r#   r$   <module>   s    S^a