o
    + icY                     @   s   d Z ddl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dlmZ g Zdd	d
Z					dddZdddZdS )z$
All layers just related to metric.
    N)_C_ops_legacy_C_ops)check_variable_and_dtype)Variable_create_tensorin_dygraph_modein_pir_mode)LayerHelper)ConstantInitializer   c                 C   s  t  r=|du rtdd}|du rtdd}t|tr"t|dn|}t| d|dd\}}t	|||||\}}	}	|S t
 rVtj| |dd\}}t	|||\}}	}	|S tdi t }
t| d
g dd	 |
j| jd}|
jdd}d| gi}t|tr|g|d< nd|i}d|d< |
jd|||g|gdd |
jdd}|du r|
jdd}|du r|
jdd}|
jd	|g|g|gd|g|g|gdd |S )a  

    accuracy layer.
    Refer to the https://en.wikipedia.org/wiki/Precision_and_recall
    This function computes the accuracy using the input and label.
    If the correct label occurs in top k predictions, then correct will increment by one.

    Note:
        the dtype of accuracy is determined by input. the input and label dtype can be different.

    Args:
        input(Tensor): The input of accuracy layer, which is the predictions of network. A Tensor with type float32,float64.
            The shape is ``[sample_number, class_dim]`` .
        label(Tensor): The label of dataset.  Tensor with type int32,int64. The shape is ``[sample_number, 1]`` .
        k(int, optional): The top k predictions for each class will be checked. Data type is int64 or int32. Default is 1.
        correct(Tensor, optional): The correct predictions count. A Tensor with type int64 or int32. Default is None.
        total(Tensor, optional): The total entries count. A tensor with type int64 or int32. Default is None.

    Returns:
        Tensor, The correct rate. A Tensor with type float32.

    Examples:
        .. code-block:: python

            >>> import numpy as np
            >>> import paddle
            >>> import paddle.static as static
            >>> import paddle.nn.functional as F
            >>> paddle.seed(2023)
            >>> paddle.enable_static()
            >>> data = static.data(name="input", shape=[-1, 32, 32], dtype="float32")
            >>> label = static.data(name="label", shape=[-1,1], dtype="int64")
            >>> fc_out = static.nn.fc(x=data, size=10)
            >>> predict = F.softmax(x=fc_out)
            >>> result = static.accuracy(input=predict, label=label, k=5)
            >>> place = paddle.CPUPlace()
            >>> exe = static.Executor(place)
            >>> exe.run(static.default_startup_program())
            >>> np.random.seed(1107)
            >>> x = np.random.rand(3, 32, 32).astype("float32")
            >>> y = np.array([[1],[0],[1]])
            >>> output = exe.run(feed={"input": x,"label": y},
            ...                  fetch_list=[result])
            >>> print(output)
            [array(0.33333334, dtype=float32)]

    Nint32dtyper   ksortedF)r   r   accuracyinput)Zfloat16Zuint16float32float64int64XKtop_k_v2)OutIndicestypeinputsattrsoutputsr   )r   r   Label)ZAccuracyZCorrectZTotalr   r   r   )r   )r   r   
isinstancer   nparrayitemr   r   r   r   paddletopkr   r	   localsr   "create_variable_for_type_inferencer   	append_op)r   labelr   ZcorrecttotalZ_kZtopk_outZtopk_indicesZ_acc_helperr   r   Zacc_out r/   c/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/paddle/static/nn/metric.pyr   #   s`   0






	r   ROC  c              
   C   sH  t  rV|du rtjddgddd}t| dddgd t|d	d
dgd t|dddgd tjd|d gdd}tjd|d gdd}t| ||||||d\}	}
}|	|
|fS tdi t }|du rmtj	j
ddgddd}t| dddgd t|d	d
dgd t|dddgd |jdd}	|jdd}|jddd| |d  d gd}
|jddd| |d  d gd}|jddd|d gd}|jddd|d gd}|
|||fD ]}||tddd q|jd| g|g|
g|gd|||d|g|
g|gdd |jd| g|g|g|gd||dd|	g|g|gdd |	||
|||gfS )a5  
    **Area Under the Curve (AUC) Layer**

    This implementation computes the AUC according to forward output and label.
    It is used very widely in binary classification evaluation.

    Note: If input label contains values other than 0 and 1, it will be cast
    to `bool`. Find the relevant definitions `here <https://en.wikipedia.org    /wiki/Receiver_operating_characteristic#Area_under_the_curve>`_.

    There are two types of possible curves:

        1. ROC: Receiver operating characteristic;
        2. PR: Precision Recall

    Args:
        input(Tensor): A floating-point 2D Tensor, values are in the range
                         [0, 1]. Each row is sorted in descending order. This
                         input should be the output of topk. Typically, this
                         Tensor indicates the probability of each label.
                         A Tensor with type float32,float64.
        label(Tensor): A 2D int Tensor indicating the label of the training
                         data. The height is batch size and width is always 1.
                         A Tensor with type int32,int64.
        curve(str, optional): Curve type, can be 'ROC' or 'PR'. Default 'ROC'.
        num_thresholds(int, optional): The number of thresholds to use when discretizing
                             the roc curve. Default 4095.
        topk(int, optional): only topk number of prediction output will be used for auc.
        slide_steps(int, optional): when calc batch auc, we can not only use step currently but the previous steps can be used. slide_steps=1 means use the current step, slide_steps=3 means use current step and the previous second steps, slide_steps=0 use all of the steps.
        ins_tag_weight(Tensor, optional): A 2D int Tensor indicating the data's tag weight, 1 means real data, 0 means fake data. Default None, and it will be assigned to a tensor of value 1.
                         A Tensor with type float32,float64.

    Returns:
        Tensor: A tuple representing the current AUC. Data type is Tensor, supporting float32, float64.
        The return tuple is auc_out, batch_auc_out, [batch_stat_pos, batch_stat_neg, stat_pos, stat_neg ]

            auc_out: the result of the accuracy rate
            batch_auc_out: the result of the batch accuracy
            batch_stat_pos: the statistic value for label=1 at the time of batch calculation
            batch_stat_neg: the statistic value for label=0 at the time of batch calculation
            stat_pos: the statistic for label=1 at the time of calculation
            stat_neg: the statistic for label=0 at the time of calculation


    Examples:
        .. code-block:: python
            :name: example-1

            >>> # doctest: +SKIP("This has diff in xdoctest env")
            >>> import paddle
            >>> import numpy as np
            >>> paddle.enable_static()

            >>> paddle.seed(2023)
            >>> data = paddle.static.data(name="input", shape=[-1, 32,32], dtype="float32")
            >>> label = paddle.static.data(name="label", shape=[-1], dtype="int64")
            >>> fc_out = paddle.static.nn.fc(x=data, size=2)
            >>> predict = paddle.nn.functional.softmax(x=fc_out)
            >>> result=paddle.static.auc(input=predict, label=label)

            >>> place = paddle.CPUPlace()
            >>> exe = paddle.static.Executor(place)

            >>> exe.run(paddle.static.default_startup_program())
            >>> np.random.seed(1107)
            >>> x = np.random.rand(3,32,32).astype("float32")
            >>> y = np.array([1,0,1])
            >>> output= exe.run(feed={"input": x,"label": y},
            ...                 fetch_list=[result[0]])
            >>> print(output)
            [array(1.)]


        .. code-block:: python
            :name: example-2

            # you can learn the usage of ins_tag_weight by the following code.

            >>> # doctest: +SKIP("This has diff in xdoctest env")
            >>> import paddle
            >>> import numpy as np
            >>> paddle.enable_static()

            >>> paddle.seed(2023)
            >>> data = paddle.static.data(name="input", shape=[-1, 32,32], dtype="float32")
            >>> label = paddle.static.data(name="label", shape=[-1], dtype="int64")
            >>> ins_tag_weight = paddle.static.data(name='ins_tag_weight', shape=[-1,16], dtype='float64')
            >>> fc_out = paddle.static.nn.fc(x=data, size=2)
            >>> predict = paddle.nn.functional.softmax(x=fc_out)
            >>> result=paddle.static.auc(input=predict, label=label, ins_tag_weight=ins_tag_weight)

            >>> place = paddle.CPUPlace()
            >>> exe = paddle.static.Executor(place)

            >>> exe.run(paddle.static.default_startup_program())
            >>> np.random.seed(1107)
            >>> x = np.random.rand(3,32,32).astype("float32")
            >>> y = np.array([1,0,1])
            >>> z = np.array([1,0,1]).astype("float64")
            >>> output= exe.run(feed={"input": x,"label": y, "ins_tag_weight":z},
            ...                 fetch_list=[result[0]])
            >>> print(output)
            [array(1.)]

    Nr   r         ?)shaper   Z
fill_valuer   r   aucr+   r   r   ins_tag_weight)r4   r   r   r4   r   valuer   TZpersistabler   r4           Fr8   Z	force_cpu)ZPredictr    ZStatPosZStatNeg)curvenum_thresholdsslide_steps)ZAUCZ
StatPosOutZ
StatNegOutr   )r5   )r   r&   fullr   Zzerosr   r5   r	   r(   tensorfill_constantr)   create_global_variableset_variable_initializerr
   r*   )r   r+   r<   r=   r'   r>   r6   Zstat_posZstat_negZauc_outZbatch_stat_posZbatch_stat_negr.   Zbatch_auc_outvarr/   r/   r0   r5      s   r


	

r5   c                 C   s  |du rt jjddgddd}| j|jksJ td"i t }|jdddgd}|jdddgd}|jdddgd}|jdddgd}|jdddgd}|jdddgd}	|jd	dd
gd}
|jd	dd
gd}|jd	dd
gd}|jd	ddgd}|jd	ddgd}|jd	ddgd}|jd	ddgd}|jd	ddgd}|jd	ddgd}||||||||||||	fD ]}||t jj	j
ddd q|jd| g|gdd|
gid |jdd|
gid|gid |jd|g|gdd|gid |jdd|
gid|gid |jd|g|gdd|gid |jdd| gid|gid |jd|g|gdd|gid |jdd| gid|gid |jdd|gid|gid |jdd|gid|gid |jd|g|gdd|gid |jdd|id|gid
dg|jddd |jdd|gid|gid d|i}ddgi}dg|d< dg|d< |jd||d|id |jd d}|jd!|g|gdd|gid |id |jd|g|	gdd|	gid |jd!|g|gdd|gid |id |jd|g|gdd|gid ||||||	fS )#a  
    ctr related metric layer

    This function help compute the ctr related metrics: RMSE, MAE, predicted_ctr, q_value.
    To compute the final values of these metrics, we should do following computations using
    total instance number:
    MAE = local_abserr / instance number
    RMSE = sqrt(local_sqrerr / instance number)
    predicted_ctr = local_prob / instance number
    q = local_q / instance number
    Note that if you are doing distribute job, you should all reduce these metrics and instance
    number first

    Args:
        input(Tensor): A floating-point 2D Tensor, values are in the range
                         [0, 1]. Each row is sorted in descending order. This
                         input should be the output of topk. Typically, this
                         Tensor indicates the probability of each label.
        label(Tensor): A 2D int Tensor indicating the label of the training
                         data. The height is batch size and width is always 1.
        ins_tag_weight(Tensor): A 2D int Tensor indicating the ins_tag_weight of the training
                         data. 1 means real data, 0 means fake data.
                         A DenseTensor or Tensor with type float32,float64.

    Returns:
        local_sqrerr(Tensor): Local sum of squared error
        local_abserr(Tensor): Local sum of abs error
        local_prob(Tensor): Local sum of predicted ctr
        local_q(Tensor): Local sum of q value
        local_pos_num (Tensor): Local number of positive examples
        local_ins_num (Tensor): Local number of instances

    Examples:
        .. code-block:: python
            :name: example-1

            >>> # doctest: +SKIP("This has diff in xdoctest env")
            >>> import paddle
            >>> paddle.enable_static()
            >>> data = paddle.static.data(name="data", shape=[-1, 32], dtype="float32")
            >>> label = paddle.static.data(name="label", shape=[-1, 1], dtype="int32")
            >>> predict = paddle.nn.functional.sigmoid(paddle.static.nn.fc(x=data, size=1))
            >>> auc_out = paddle.static.ctr_metric_bundle(input=predict, label=label)

        .. code-block:: python
            :name: example-2

            >>> # doctest: +SKIP("This has diff in xdoctest env")
            >>> import paddle
            >>> paddle.enable_static()
            >>> data = paddle.static.data(name="data", shape=[-1, 32], dtype="float32")
            >>> label = paddle.static.data(name="label", shape=[-1, 1], dtype="int32")
            >>> predict = paddle.nn.functional.sigmoid(paddle.static.nn.fc(x=data, size=1))
            >>> ins_tag_weight = paddle.static.data(name='ins_tag_weight', shape=[-1, 1], dtype='int64')
            >>> auc_out = paddle.static.ctr_metric_bundle(input=predict, label=label, ins_tag_weight=ins_tag_weight)
    Nr   r   r3   r7   ctr_metric_bundleTr9   Fr:   r;   Zelementwise_sub)r   Yr   r!   Zsquared_l2_normr   Zelementwise_addZl1_normZ
reduce_sumZsigmoidZfill_constant_batch_size_likeZInput)r   r   r   r   Zaxesr   ZstartsZendsslicer   axisZelementwise_mul)rE   )r&   r@   rA   r4   r	   r(   rB   rC   nnZinitializerr
   r*   r   kwargsget)r   r+   r6   r.   Zlocal_abserrZlocal_sqrerrZ
local_probZlocal_qZlocal_pos_numZlocal_ins_numZtmp_res_elesubZtmp_res_sigmoidZtmp_onesZ
batch_probZbatch_abserrZbatch_sqrerrZbatch_qZbatch_pos_numZbatch_ins_numrD   Zinputs_slicer   rI   r/   r/   r0   rE   u  sb  9




rE   )r   NN)r1   r2   r   r   N)N)__doc__numpyr#   r&   r   r   Zpaddle.base.data_feederr   Zpaddle.base.frameworkr   r   r   r   Zpaddle.base.layer_helperr	   Zpaddle.nn.initializerr
   __all__r   r5   rE   r/   r/   r/   r0   <module>   s$   
i
 m