Ë
    ýÿæiÚR  ã                   ó   — d dl mZ d dl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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mZ esg d¢Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Zy)é    )ÚSequence)ÚAnyÚOptionalÚUnion)ÚTensor)ÚLiteral)Ú_ClassificationTaskWrapper)Ú	BinaryROCÚMulticlassROCÚMultilabelROC)Ú_eer_compute)ÚMetric)ÚClassificationTask)Ú_MATPLOTLIB_AVAILABLE)Ú_AX_TYPEÚ_PLOT_OUT_TYPE)zBinaryEER.plotzMulticlassEER.plotzMultilabelEER.plotc                   ó\   ‡ — e Zd ZdZdefˆ fd„Z	 ddeeeee   f      dee	   de
fd„Zˆ xZS )Ú	BinaryEERaî  Compute Equal Error Rate (EER) for multiclass classification task.

    .. math::
        \text{EER} = \frac{\text{FAR} + \text{FRR}}{2}, \text{where} \min_t abs(FAR_t-FRR_t)

    The Equal Error Rate (EER) is the point where the False Positive Rate (FPR) and True Positive Rate (TPR) are
    equal, or in practise minimized. A lower EER value signifies higher system accuracy.

    As input to ``forward`` and ``update`` the metric accepts the following input:

    - ``preds`` (:class:`~torch.Tensor`): A float tensor of shape ``(N, ...)`` 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, ...)`` 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.

    As output to ``forward`` and ``compute`` the metric returns the following output:

    - ``b_eer`` (:class:`~torch.Tensor`): A single scalar with the eer score.

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

    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:
        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 torch import tensor
        >>> from torchmetrics.classification import BinaryEER
        >>> preds = tensor([0, 0.5, 0.7, 0.8])
        >>> target = tensor([0, 1, 1, 0])
        >>> metric = BinaryEER(thresholds=None)
        >>> metric(preds, target)
        tensor(0.5000)
        >>> b_eer = BinaryEER(thresholds=5)
        >>> b_eer(preds, target)
        tensor(0.7500)

    Úreturnc                 ó@   •— t         ‰| �  «       \  }}}t        ||«      S ©úCompute metric.©ÚsuperÚcomputer   ©ÚselfÚfprÚtprÚ_Ú	__class__s       €út/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/torchmetrics/classification/eer.pyr   zBinaryEER.compute_   ó"   ø€ ä‘g‘oÓ'‰ˆˆS�!Ü˜C Ó%Ð%ó    ÚvalÚaxc                 ó&   — | j                  ||«      S )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 and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single
            >>> import torch
            >>> from torchmetrics.classification import BinaryEER
            >>> metric = BinaryEER()
            >>> metric.update(torch.rand(20,), torch.randint(2, (20,)))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.classification import BinaryEER
            >>> metric = BinaryEER()
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(torch.rand(20,), torch.randint(2, (20,))))
            >>> fig_, ax_ = metric.plot(values)

        ©Ú_plot©r   r%   r&   s      r"   ÚplotzBinaryEER.plotd   ó   € ðP �z‰z˜#˜rÓ"Ð"r$   ©NN©Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r   r+   Ú__classcell__©r!   s   @r"   r   r   $   sS   ø„ ñ8ðt&˜õ &ð _cñ(#Ø˜E &¨(°6Ñ*:Ð":Ñ;Ñ<ð(#ØIQÐRZÑI[ð(#à	÷(#r$   r   c                   ó\   ‡ — e Zd ZdZdefˆ fd„Z	 ddeeeee   f      dee	   de
fd„Zˆ xZS )ÚMulticlassEERa;  Compute Equal Error Rate (EER) for multiclass classification task.

    .. math::
        \text{EER} = \frac{\text{FAR} + (1 - \text{FRR})}{2}, \text{where} \min_t abs(FAR_t-FRR_t)

    The Equal Error Rate (EER) is the point where the False Positive Rate (FPR) and True Positive Rate (TPR) are
    equal, or in practise minimized. A lower EER value signifies higher system accuracy.

    As input to ``forward`` and ``update`` the metric accepts the following input:

        - ``preds`` (:class:`~torch.Tensor`): A float tensor of shape ``(N, C, ...)`` 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, ...)`` containing ground truth labels, and
          therefore only contain values in the [0, n_classes-1] range (except if `ignore_index` is specified).

    As output to ``forward`` and ``compute`` the metric returns the following output:

        - ``mc_eer`` (:class:`~torch.Tensor`): If `average=None` then a 1d tensor of shape (n_classes, ) will
          be returned with eer score per class. If `average="macro"|"micro"` then a single scalar will be returned.

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

    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 specifying the number of classes
        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.

        average:
            If aggregation of curves should be applied. By default, the curves are not aggregated and a curve for
            each class is returned. If `average` is set to ``"micro"``, the metric will aggregate the curves by one hot
            encoding the targets and flattening the predictions, considering all classes jointly as a binary problem.
            If `average` is set to ``"macro"``, the metric will aggregate the curves by first interpolating the curves
            from each class at a combined set of thresholds and then average over the classwise interpolated curves.
            See `averaging curve objects`_ for more info on the different averaging methods.
        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.

    Examples:
        >>> from torch import tensor
        >>> from torchmetrics.classification import MulticlassEER
        >>> preds = 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 = tensor([0, 1, 3, 2])
        >>> metric = MulticlassEER(num_classes=5, average="macro", thresholds=None)
        >>> metric(preds, target)
        tensor(0.4667)
        >>> mc_eer = MulticlassEER(num_classes=5, average=None, thresholds=None)
        >>> mc_eer(preds, target)
        tensor([0.0000, 0.0000, 0.6667, 0.6667, 1.0000])

    r   c                 ó@   •— t         ‰| �  «       \  }}}t        ||«      S r   r   r   s       €r"   r   zMulticlassEER.compute×   r#   r$   r%   r&   c                 ó&   — | j                  ||«      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 and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single
            >>> import torch
            >>> from torchmetrics.classification import MulticlassEER
            >>> metric = MulticlassEER(num_classes=3)
            >>> metric.update(torch.randn(20, 3), torch.randint(3,(20,)))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.classification import MulticlassEER
            >>> metric = MulticlassEER(num_classes=3)
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(torch.randn(20, 3), torch.randint(3, (20,))))
            >>> fig_, ax_ = metric.plot(values)

        r(   r*   s      r"   r+   zMulticlassEER.plotÜ   r,   r$   r-   r.   r4   s   @r"   r6   r6   �   sT   ø„ ñEðN&˜õ &ð _cñ(#Ø˜E &¨(°6Ñ*:Ð":Ñ;Ñ<ð(#ØIQÐRZÑI[ð(#à	÷(#r$   r6   c                   ó\   ‡ — e Zd ZdZdefˆ fd„Z	 ddeeeee   f      dee	   de
fd„Zˆ xZS )ÚMultilabelEERaº  Compute Equal Error Rate (EER) for multiclass classification task.

    .. math::
        \text{EER} = \frac{\text{FAR} + (1 - \text{FRR})}{2}, \text{where} \min_t abs(FAR_t-FRR_t)

    The Equal Error Rate (EER) is the point where the False Positive Rate (FPR) and True Positive Rate (TPR) are
    equal, or in practise minimized. A lower EER value signifies higher system accuracy.

    As input to ``forward`` and ``update`` the metric accepts the following input:

    - ``preds`` (:class:`~torch.Tensor`): A float tensor of shape ``(N, C, ...)`` 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, C, ...)`` containing ground truth labels, and
      therefore only contain {0,1} values (except if `ignore_index` is specified).

    As output to ``forward`` and ``compute`` the metric returns the following output:

    - ``ml_eer`` (:class:`~torch.Tensor`): A 1d tensor of shape (n_classes, ) will be returned with eer score per label.

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

    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 specifying the number of labels
        average: Defines the reduction that is applied over labels. Should be one of the following:

            - ``micro``: Sum score over all labels
            - ``macro``: Calculate score for each label and average them
            - ``weighted``: calculates score for each label and computes weighted average using their support
            - ``"none"`` or ``None``: calculates score for each label and applies no reduction

        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 torch import tensor
        >>> from torchmetrics.classification import MultilabelEER
        >>> preds = 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 = tensor([[1, 0, 1],
        ...                  [0, 0, 0],
        ...                  [0, 1, 1],
        ...                  [1, 1, 1]])
        >>> ml_eer = MultilabelEER(num_labels=3, thresholds=None)
        >>> ml_eer(preds, target)
        tensor([0.5000, 0.5000, 0.1667])

    r   c                 ó@   •— t         ‰| �  «       \  }}}t        ||«      S r   r   r   s       €r"   r   zMultilabelEER.computeL  r#   r$   r%   r&   c                 ó&   — | j                  ||«      S )a2  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 and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single
            >>> import torch
            >>> from torchmetrics.classification import MultilabelEER
            >>> metric = MultilabelEER(num_labels=3)
            >>> metric.update(torch.rand(20,3), torch.randint(2, (20,3)))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.classification import MultilabelEER
            >>> metric = MultilabelEER(num_labels=3)
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(torch.rand(20,3), torch.randint(2, (20,3))))
            >>> fig_, ax_ = metric.plot(values)

        r(   r*   s      r"   r+   zMultilabelEER.plotQ  r,   r$   r-   r.   r4   s   @r"   r:   r:     sT   ø„ ñBðH&˜õ &ð _cñ(#Ø˜E &¨(°6Ñ*:Ð":Ñ;Ñ<ð(#ØIQÐRZÑI[ð(#à	÷(#r$   r:   c                   ó¬   — e Zd ZdZ	 	 	 	 	 	 dded    ded   deeee	e
   ef      dee   dee   d	eed
      dee   dededefd„Zdededdfd„Zdd„Zy)ÚEERa  Compute Equal Error Rate (EER) for multiclass classification task.

    .. math::
        \text{EER} = \frac{\text{FAR} + (1 - \text{FRR})}{2}, \text{where} \min_t abs(FAR_t-FRR_t)

    The Equal Error Rate (EER) is the point where the False Positive Rate (FPR) and True Positive Rate (TPR) are
    equal, or in practise minimized. A lower EER value signifies higher system accuracy.

    This module 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
    :class:`~torchmetrics.classification.BinaryEER`, :class:`~torchmetrics.classification.MulticlassEER` and
    :class:`~torchmetrics.classification.MultilabelEER` for the specific details of each argument influence and
    examples.

    Legacy Example:
        >>> from torch import tensor
        >>> preds = tensor([0.13, 0.26, 0.08, 0.19, 0.34])
        >>> target = tensor([0, 0, 1, 1, 1])
        >>> eer = EER(task="binary")
        >>> eer(preds, target)
        tensor(0.5833)

        >>> preds = tensor([[0.90, 0.05, 0.05],
        ...                       [0.05, 0.90, 0.05],
        ...                       [0.05, 0.05, 0.90],
        ...                       [0.85, 0.05, 0.10],
        ...                       [0.10, 0.10, 0.80]])
        >>> target = tensor([0, 1, 1, 2, 2])
        >>> eer = EER(task="multiclass", num_classes=3)
        >>> eer(preds, target)
        tensor([0.0000, 0.4167, 0.4167])

    NÚclsÚtask)ÚbinaryÚ
multiclassÚ
multilabelÚ
thresholdsÚnum_classesÚ
num_labelsÚaverage)ÚmacroÚmicroÚignore_indexÚvalidate_argsÚkwargsr   c                 óÐ  — t        j                  |«      }|j                  |||dœ«       |t         j                  k(  rt	        di |¤ŽS |t         j
                  k(  r6t        |t        «      st        dt        |«      › d�«      ‚t        |fd|i|¤ŽS |t         j                  k(  r4t        |t        «      st        dt        |«      › d�«      ‚t        |fi |¤ŽS t        d|› d�«      ‚)	zInitialize task metric.)rD   rJ   rK   z+`num_classes` is expected to be `int` but `z was passed.`rG   z*`num_labels` is expected to be `int` but `zTask z not supported!© )r   Úfrom_strÚupdateÚBINARYr   Ú
MULTICLASSÚ
isinstanceÚintÚ
ValueErrorÚtyper6   Ú
MULTILABELr:   )	r?   r@   rD   rE   rF   rG   rJ   rK   rL   s	            r"   Ú__new__zEER.__new__Ÿ  sê   € ô "×*Ñ*¨4Ó0ˆØ�‰ ZÀÐ`mÑnÔoØÔ%×,Ñ,Ò,ÜÑ&˜vÑ&Ð&ØÔ%×0Ñ0Ò0Ü˜k¬3Ô/Ü Ð#NÌtÐT_ÓO`ÐNaÐanÐ!oÓpÐpÜ  ÑH°gÐHÀÑHÐHØÔ%×0Ñ0Ò0Ü˜j¬#Ô.Ü Ð#MÌdÐS]ÓN^ÐM_Ð_lÐ!mÓnÐnÜ  Ñ6¨vÑ6Ð6Ü˜5   oÐ6Ó7Ð7r$   Úargsc                 óF   — t        | j                  j                  › d�«      ‚)zUpdate metric state.zM metric does not have a global `update` method. Use the task specific metric.©ÚNotImplementedErrorr!   r/   )r   rY   rL   s      r"   rP   z
EER.update¹  s%   € ä!Ø�~‰~×&Ñ&Ð'Ð'tÐuó
ð 	
r$   c                 óF   — t        | j                  j                  › d�«      ‚)r   zN metric does not have a global `compute` method. Use the task specific metric.r[   )r   s    r"   r   zEER.compute¿  s%   € ä!Ø�~‰~×&Ñ&Ð'Ð'uÐvó
ð 	
r$   )NNNNNT)r   N)r/   r0   r1   r2   rV   r   r   r   rT   ÚlistÚfloatr   Úboolr   r   rX   rP   r   rN   r$   r"   r>   r>   |  sØ   „ ñ ðJ AEØ%)Ø$(Ø7;Ø&*Ø"ñ8Ø�%‰[ð8àÐ:Ñ;ð8ð ˜U 3¨¨U©°VÐ#;Ñ<Ñ=ð8ð ˜c‘]ð	8ð
 ˜S‘Mð8ð ˜'Ð"2Ñ3Ñ4ð8ð ˜s‘mð8ð ð8ð ð8ð 
ó8ð4
˜Cð 
¨3ð 
°4ó 
ô
r$   r>   N) Úcollections.abcr   Útypingr   r   r   Útorchr   Útyping_extensionsr   Ú torchmetrics.classification.baser	   Útorchmetrics.classification.rocr
   r   r   Ú*torchmetrics.functional.classification.eerr   Útorchmetrics.metricr   Útorchmetrics.utilities.enumsr   Útorchmetrics.utilities.importsr   Útorchmetrics.utilities.plotr   r   Ú__doctest_skip__r   r6   r:   r>   rN   r$   r"   Ú<module>rm      sz   ðõ %ß 'Ñ 'å Ý %å G÷ñ õ
 DÝ &Ý ;Ý @ß @áÚUÐôh#�	ô h#ôVu#�Mô u#ôpr#�Mô r#ôjG
Ð
$õ G
r$   