【tensorflow2.0】評價指標metrics


損失函數除了作為模型訓練時候的優化目標,也能夠作為模型好壞的一種評價指標。但通常人們還會從其它角度評估模型的好壞。

這就是評估指標。通常損失函數都可以作為評估指標,如MAE,MSE,CategoricalCrossentropy等也是常用的評估指標。

但評估指標不一定可以作為損失函數,例如AUC,Accuracy,Precision。因為評估指標不要求連續可導,而損失函數通常要求連續可導。

編譯模型時,可以通過列表形式指定多個評估指標。

如果有需要,也可以自定義評估指標。

自定義評估指標需要接收兩個張量y_true,y_pred作為輸入參數,並輸出一個標量作為評估值。

也可以對tf.keras.metrics.Metric進行子類化,重寫初始化方法, update_state方法, result方法實現評估指標的計算邏輯,從而得到評估指標的類的實現形式。

由於訓練的過程通常是分批次訓練的,而評估指標要跑完一個epoch才能夠得到整體的指標結果。因此,類形式的評估指標更為常見。即需要編寫初始化方法以創建與計算指標結果相關的一些中間變量,編寫update_state方法在每個batch后更新相關中間變量的狀態,編寫result方法輸出最終指標結果。

如果編寫函數形式的評估指標,則只能取epoch中各個batch計算的評估指標結果的平均值作為整個epoch上的評估指標結果,這個結果通常會偏離拿整個epoch數據一次計算的結果。

一,常用的內置評估指標

  • MeanSquaredError(平方差誤差,用於回歸,可以簡寫為MSE,函數形式為mse)

  • MeanAbsoluteError (絕對值誤差,用於回歸,可以簡寫為MAE,函數形式為mae)

  • MeanAbsolutePercentageError (平均百分比誤差,用於回歸,可以簡寫為MAPE,函數形式為mape)

  • RootMeanSquaredError (均方根誤差,用於回歸)

  • Accuracy (准確率,用於分類,可以用字符串"Accuracy"表示,Accuracy=(TP+TN)/(TP+TN+FP+FN),要求y_true和y_pred都為類別序號編碼)

  • Precision (精確率,用於二分類,Precision = TP/(TP+FP))

  • Recall (召回率,用於二分類,Recall = TP/(TP+FN))

  • TruePositives (真正例,用於二分類)

  • TrueNegatives (真負例,用於二分類)

  • FalsePositives (假正例,用於二分類)

  • FalseNegatives (假負例,用於二分類)

  • AUC(ROC曲線(TPR vs FPR)下的面積,用於二分類,直觀解釋為隨機抽取一個正樣本和一個負樣本,正樣本的預測值大於負樣本的概率)

  • CategoricalAccuracy(分類准確率,與Accuracy含義相同,要求y_true(label)為onehot編碼形式)

  • SparseCategoricalAccuracy (稀疏分類准確率,與Accuracy含義相同,要求y_true(label)為序號編碼形式)

  • MeanIoU (Intersection-Over-Union,常用於圖像分割)

  • TopKCategoricalAccuracy (多分類TopK准確率,要求y_true(label)為onehot編碼形式)

  • SparseTopKCategoricalAccuracy (稀疏多分類TopK准確率,要求y_true(label)為序號編碼形式)

  • Mean (平均值)

  • Sum (求和)

二, 自定義評估指標

我們以金融風控領域常用的KS指標為例,示范自定義評估指標。

KS指標適合二分類問題,其計算方式為 KS=max(TPR-FPR).

其中TPR=TP/(TP+FN) , FPR = FP/(FP+TN)

TPR曲線實際上就是正樣本的累積分布曲線(CDF),FPR曲線實際上就是負樣本的累積分布曲線(CDF)。

KS指標就是正樣本和負樣本累積分布曲線差值的最大值。

import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import layers,models,losses,metrics
 
# 函數形式的自定義評估指標
@tf.function
def ks(y_true,y_pred):
    y_true = tf.reshape(y_true,(-1,))
    y_pred = tf.reshape(y_pred,(-1,))
    length = tf.shape(y_true)[0]
    t = tf.math.top_k(y_pred,k = length,sorted = False)
    y_pred_sorted = tf.gather(y_pred,t.indices)
    y_true_sorted = tf.gather(y_true,t.indices)
    cum_positive_ratio = tf.truediv(
        tf.cumsum(y_true_sorted),tf.reduce_sum(y_true_sorted))
    cum_negative_ratio = tf.truediv(
        tf.cumsum(1 - y_true_sorted),tf.reduce_sum(1 - y_true_sorted))
    ks_value = tf.reduce_max(tf.abs(cum_positive_ratio - cum_negative_ratio)) 
    return ks_value
y_true = tf.constant([[1],[1],[1],[0],[1],[1],[1],[0],[0],[0],[1],[0],[1],[0]])
y_pred = tf.constant([[0.6],[0.1],[0.4],[0.5],[0.7],[0.7],[0.7],
                      [0.4],[0.4],[0.5],[0.8],[0.3],[0.5],[0.3]])
tf.print(ks(y_true,y_pred))

0.625

# 類形式的自定義評估指標
class KS(metrics.Metric):
 
    def __init__(self, name = "ks", **kwargs):
        super(KS,self).__init__(name=name,**kwargs)
        self.true_positives = self.add_weight(
            name = "tp",shape = (101,), initializer = "zeros")
        self.false_positives = self.add_weight(
            name = "fp",shape = (101,), initializer = "zeros")
 
    @tf.function
    def update_state(self,y_true,y_pred):
        y_true = tf.cast(tf.reshape(y_true,(-1,)),tf.bool)
        y_pred = tf.cast(100*tf.reshape(y_pred,(-1,)),tf.int32)
 
        for i in tf.range(0,tf.shape(y_true)[0]):
            if y_true[i]:
                self.true_positives[y_pred[i]].assign(
                    self.true_positives[y_pred[i]]+1.0)
            else:
                self.false_positives[y_pred[i]].assign(
                    self.false_positives[y_pred[i]]+1.0)
        return (self.true_positives,self.false_positives)
 
    @tf.function
    def result(self):
        cum_positive_ratio = tf.truediv(
            tf.cumsum(self.true_positives),tf.reduce_sum(self.true_positives))
        cum_negative_ratio = tf.truediv(
            tf.cumsum(self.false_positives),tf.reduce_sum(self.false_positives))
        ks_value = tf.reduce_max(tf.abs(cum_positive_ratio - cum_negative_ratio)) 
        return ks_value
 
y_true = tf.constant([[1],[1],[1],[0],[1],[1],[1],[0],[0],[0],[1],[0],[1],[0]])
y_pred = tf.constant([[0.6],[0.1],[0.4],[0.5],[0.7],[0.7],
                      [0.7],[0.4],[0.4],[0.5],[0.8],[0.3],[0.5],[0.3]])
 
myks = KS()
myks.update_state(y_true,y_pred)
tf.print(myks.result())

0.625

 

參考:

開源電子書地址:https://lyhue1991.github.io/eat_tensorflow2_in_30_days/

GitHub 項目地址:https://github.com/lyhue1991/eat_tensorflow2_in_30_days


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM