美文网首页
算法模型的性能度量

算法模型的性能度量

作者: 巴拉巴拉_9515 | 来源:发表于2020-03-19 14:25 被阅读0次

    性能度量是指模型泛化能力的衡量,泛化能力可以理解为对于未知数据的预判能力

    1、回归场景

    (1)均方误差MSE

    回归预测最常用的性能度量是“均方误差”(MSE mean squared error), 又称为L2范数损失。
    预测值与实际值的差值平方求和求平均的过程

    E(f,D) = \frac{1}{m}\sum_{i=1}^m(f(x_i)-y_i)^2

    实践测试
    调用python的sklearn快速计算一下。显然y_pred_2的预测效果比y_pred_1效果好,与y_true更接近。

    from sklearn.metrics import mean_squared_error
    y_true = [3000,1323,4234,6567]
    y_pred_1 = [4212,2000,5002,6004]
    y_pred_2 = [4124,1252,4341,6534]
    print(mean_squared_error(y_true,y_pred_1))  # 708516.5
    print(mean_squared_error(y_true,y_pred_2))  # 320238.75
    

    看来MSE值越小说明预测能力越好(其实看公式也能看出来的)

    (2)RMSE

    提到均方误差(MSE,mean squared error)就不能不说说均方根误差(RMSE,root mean squared error)
    RMSE = \sqrt{MSE}

    两者有什么差异吗?说是RMSE消除了对量纲的影响。

    import numpy as np
    print(np.sqrt(mean_squared_error(y_true,y_pred_1)))  # 841.7342217113428
    print(np.sqrt(mean_squared_error(y_true,y_pred_2)))  # 565.8964127824102
    

    算法评估为什么要消除量纲?误差相关值不是越小就可以了吗?而且做完根号以后值还是很大的啊?不多运行比较几次都不知道拟合效果好不好?(解答待定)

    (3)R^2

    R²(亦称可决系数、确定系数),取值范围在0-1之间,值越大模型的越好。

    from sklearn.metrics import r2_score
    y_true = [3000,1323,4234,6567]
    y_pred_1 = [4212,2000,5002,6004]
    y_pred_2 = [4124,1252,4341,6534]
    r2_score(y_true, y_pred_1)  # 0.8061345958233034
    r2_score(y_true, y_pred_2)  # 0.9123757672520116
    

    既然R2那么好用,但实际上我们比较常见的还是mse、rmse这类性能度量指标,R2有什么局限吗?(解答待定)

    2、分类场景

    (1)错误率和精度

    错误率(error rate) = 分类错误数a/总数m
    精度(accuracy) = 分类正确数1-a/总数m

    • 虽然常用,但局限比较大
    • 适用于二分类、多分类
    # 分为5类:0,1,2,3,4
    from sklearn.metrics import accuracy_score
    y_true = [0, 2, 1, 3,4,4,3,1,0]
    y_pred = [1, 2, 1, 4,2,4,3,2,0]  # 4个分错
    accuracy_score(y_true, y_pred)  # 0.55555556
    
    (2)TP、FP、TN、FN
    预测正例 预测反例
    实际正例 TP(true positive) FN(false negative)
    实际反例 FP(false positive) TN(true negative)

    在TP、FP、TN、FN做文章的相关性能度量有:查准率precision、查全率recall、P-R曲线、ROC曲线、F1

    (3)查准率与查全率

    查准率又叫准确率,查全率又叫召回率。

    查准率(准确率)precision = \frac{TP}{TP+FP},指所有预测为正例的数据中,真正例所占的比例(越大越好)
    查全率(召回率)recall = \frac{TP}{TP+FN},指预测为正例的数据占所有真正例数据的比例(越大越好)

    from sklearn import metrics
    y_true =  [0, 1, 1, 0,0,1,0,1,0,0,0,0,1,0,0,0,1]
    y_pred = [0, 0, 0, 0,0,1,0,1,0,0,0,0,0,0,1,0,1]
    metrics.precision_score(y_true, y_pred, average='binary')  # 0.75
    metrics.recall_score(y_true, y_pred, average='binary')  # 0.5
    

    在准确率和召回率的基础上扩建的概念有P-R曲线F1两个概念,与P-R曲线类似的有ROC曲线

    (4)P-R曲线

    以precision为纵轴,recall为横轴绘制P-R曲线,一般用于模型选择和参数调优。

    【疑问】上面计算precision和recall不是都只有一个值吗?怎么能绘制曲线?
    算法对样本进行分类时,都会有阈值(threshold),我们一般设置阈值为0.5,如果预测为1的概率大于0.5,则判断分类结果为1,否则分类为0。
    通过调节阈值,改变预测正例的数量,从而改变precision和recall的值。详细案例可参考P-R曲线过程如何理解一文

    【参数调优】因此P-R权限调优的参数是这个“阈值”threshold,选择使P-R曲线面积最大的阈值。

    【模型选择】根据面积与BEP选择最优模型

    1)例如模型C的P-R曲线完全被A,B包裹,显然AB模型对于该样本更合适。
    2)对于P-R曲线相交的情况,我们比较曲线的平衡点(Break-Event Point, BEP),是准确率与召回率一致时的得分,显然A模型在该样本上优于B模型。


    (5)F1

    F1是precision和recall的调和平均,同时兼顾了分类模型的精确率和召回率,取值范围在0-1之间,当然还是越大越好。
    \frac{1}{F1} = \frac{1}{2}(\frac{1}{P} + \frac{1}{R})

    # P = 0.75; R = 0.5
    metrics.f1_score(y_true, y_pred, average='binary')  # 0.6
    
    (6)ROC曲线

    基本原理与P-R曲线相似,也是通过改变阈值threshold来获得横轴与纵轴值的变更,主要在于横轴与纵轴的变化。

    【纵轴】纵轴为真正例率(TPR,True positive rate,真阳率)
    TPR = \frac{TP}{TP+FN}
    可以发现Recall = TPR(当然P-R曲线纵轴是P,横轴是R),这里TPR为纵轴。真正例率,越大越好。

    【横轴】横轴为假正例率(FPR,False positive rate,假阳率)
    FPR = \frac{FP}{TN+FP}
    假正例率,当然是值越小越好

    【ROC曲线】

    怎样理解ROC曲线呢?先来看一下四个顶点(0,0),(0,1),(1,0),(1,1)
    (0,0),FPR=0,TPR=0,即TP=0,FP=0,实际为正例的预测为反例,实际为反例的也全预测为反例,即该模型对正例的预测无效。
    (0,1),FPR=0,TPR=1,即FP=0,FN=0,那就是实际为正例的全部预测为正例,实际为反例的全部预测为反例,最完美的模式。
    (1,0),FPR=1,TPR=0,即TN=0,TP=0,不管正例反例都没判断对
    (1,1),FPR=1,TPR=1,即TN=0,FN=0,实际为正例的预测为正例,实际为反例的也全预测为正例,即该模型对反例的预测无效。

    使用AUC(Area Under ROC Curve)描述曲面下的面积,AUC值越大表示模型的预测能力越好。

    三、多分类场景

    对于多分类场景,可以使用哪些性能衡量指标呢?

    性能度量指标 描述 是否适用多分类
    accuracy 预测正确/总量 yes
    error 预测错误/总量 yes
    precision 转型升级 yes
    recall 转型升级 yes
    F1 转型升级 yes
    ROC 转型升级 yes

    多分类问题除了accuracy和error的衡量外,也有precision、recall、F1的度量,不过需要做个转型升级。

    (1)macro宏

    先计算出每个分类的precision、recall、F1,然后计算平均值,作为该模型对多分类的macro-P、macro-R、macro-F1。

    结合代码按步骤进行计算

    计算案例的macro-P、macro-R、macro-F1
    1、把目标类设置为1,其他为0,模拟每个类的二分类场景
    2、计算每个类的P、R、F1
    3、macro-P、macro-R、macro-F1为均值
    具体代码参见附录macro-P、macro-R、macro-F1,计算结果为macro-P = 0.6389,macro-R= 0.5633、macro-F1=0.5790

    from sklearn.metrics import confusion_matrix
    from sklearn.metrics import precision_score,recall_score,f1_score
    y_true = [0, 2, 1, 3,4,4,3,1,0,0,0,1,1,2,3,2,2,4,2,1]
    y_pred = [1, 2, 1, 4,2,4,3,2,0,0,0,1,2,3,2,2,2,2,2,1]
    confusion_matrix(y_true,y_pred)
    precision_score(y_true,y_pred,labels=[0,1,2,3,4],average='macro')  # 0.638888888888889
    recall_score(y_true,y_pred,labels=[0,1,2,3,4],average='macro')  # 0.5633333333333335
    f1_score(y_true,y_pred,labels=[0,1,2,3,4],average='macro')  # 0.5790476190476189
    

    和直接调用sklearn结果是一样的。

    (2)micro微

    先计算出每个分类的TP,TN,FP,FN,然后获得TP,TN,FP,FN的平均值,带入precision、recall、F1的计算公式即可获得micro-P、micro-R、micro-F1

    结合代码按步骤进行计算

    计算案例的micro-P、micro-R、micro-F1
    1、把目标类设置为1,其他为0,模拟每个类的二分类场景
    2、计算每个类的TP,TN,FP,FN
    3、计算每个类的TP,TN,FP,FN均值
    4、带入公式,计算micro-P、micro-R、micro-F1
    具体代码参见附录macro-P、macro-R、macro-F1,计算结果为micro-P = 0.6,micro-R= 0.6、micro-F1=0.6,与直接调用sklearn计算结果一致

    # micro微
    precision_score(y_true,y_pred,labels=[0,1,2,3,4],average='micro')
    recall_score(y_true,y_pred,labels=[0,1,2,3,4],average='micro')
    f1_score(y_true,y_pred,labels=[0,1,2,3,4],average='micro')
    
    (3)多分类的ROC曲线

    多分类问题可以把目标类设置为1,其他为0,模拟每个类的二分类场景。

    • macro-roc:对n条ROC曲线取平均,即可得到最终的ROC曲线
    • micro-roc:对每一类TP,TN,FP,FN取均值,然后计算TPR,FPR
      多分类ROC曲线一文写的挺清楚的

    但感觉多分类的roc曲线用起来一点也不方便,不像二分类的ROC一个函数解决,有点麻烦不是很想用

    【问题】
    • 某些性能度量是不是只有二分类场景可以用?
    • 准确率与精度的概念紊乱
      accuracy = 分类正确数/总数,叫精度
      precision = TP/(TP+FP) ,叫准确率
    • 那么多性能衡量指标要怎么选?适用什么场景?一般使用那个数值衡量模型?
      例如PR曲线的两个指标(TPR真正例率,FPR假正例率)都聚焦于正例,主要关心正例,对于类别不平衡、比较关系正例判断能力的时候比较适用

    四、聚类场景

    聚类算法的性能衡量指标是什么?不像有监督学习那样可以根据标签计算accuracy、error等值。
    聚类是将样本划分为若干互不相交的子集,簇内相似度高,簇间相似度低。聚类的性能度量指标分为外部指标和内部指标

    聚类性能度量 指标名称
    外部指标 jaccard系数(jaccard coefficient,JC)
    FM指数(fowlkes and Mallows Index, FMI)
    Rand指数(Rand Index, RI)
    内部指标 DB指数
    Dunn指数

    详细性能度量指标可以参考聚类性能度量和距离计算一文。

    参考资料

    [1]《机器学习》周志华
    [2] P-R曲线过程如何理解:https://www.zhihu.com/question/348073311/answer/837781413
    [3] 聚类的性能度量:https://blog.csdn.net/qq_36396104/article/details/78166317

    附录

    1、precision与recall的计算

    import numpy as np
    from sklearn.metrics import confusion_matrix
    from sklearn.metrics import accuracy_score
    y_true =  [0, 1, 1, 0,0,1,0,1,0,0,0,0,1,0,0,0,1]
    y_pred = [0, 0, 0, 0,0,1,0,1,0,0,0,0,0,0,1,0,1]
    accuracy_score(y_true, y_pred)
    confusion_matrix(y_true,y_pred)
    # 判断为1实际也为1
    TP = np.sum(np.logical_and(np.equal(y_true,1),np.equal(y_pred,1)))
    # 判断为0实际也为0
    TN = np.sum(np.logical_and(np.equal(y_true,0),np.equal(y_pred,0)))
    # 判断为1实际为0
    FP = np.sum(np.logical_and(np.equal(y_true,0),np.equal(y_pred,1)))
    # 判断为0实际为1
    FN = np.sum(np.logical_and(np.equal(y_true,1),np.equal(y_pred,0)))
    precision = TP/(TP+FP)  # 0.75
    recall = TP/(TP+FN)  # 0.5
    

    2、macro-P、macro-R、macro-F1

    # 数据处理:把目标类设置为1,其他为0,模拟该类的二分类
    def deal_list(y,labels):
        new_list = []
        for i in y:
            if i==labels:
                new_list.append(1)
            else:
                new_list.append(0)
        return new_list
    
    # 计算目标类的P、R、F1
    def count_p_r_f1(y_true,y_pred,labels):
        new_true = deal_list(y_true,labels)
        new_pred = deal_list(y_pred,labels)
        a = precision_score(new_true, new_pred, average='binary')
        b = recall_score(new_true, new_pred, average='binary')
        c = f1_score(new_true, new_pred, average='binary')
        return a,b,c
    
    y_true = [0, 2, 1, 3,4,4,3,1,0,0,0,1,1,2,3,2,2,4,2,1]
    y_pred = [1, 2, 1, 4,2,4,3,2,0,0,0,1,2,3,2,2,2,2,2,1]
    p_score = []
    r_score = []
    f1 = []
    for i in range(5):
        a,b,c = count_p_r_f1(y_true,y_pred,i)
        p_score.append(a)
        r_score.append(b)
        f1.append(c)
    
    # 计算macro-P,macro-R,macro-F1
    def count_mean(score_list):
        s = sum(score_list)/len(score_list)
        return s
    count_mean(p_score)  # 0.638888888888889
    count_mean(r_score)  # 0.5633333333333335
    count_mean(f1)  # 0.5790476190476189
    

    3、 计算micro-P,micro-R,micro-F1

    import numpy as np
    def count_tp_tn_fp_fn(new_true,new_pred):
        # 判断为1实际也为1
        TP = np.sum(np.logical_and(np.equal(new_true,1),np.equal(new_pred,1)))
        # 判断为0实际也为0
        TN = np.sum(np.logical_and(np.equal(new_true,0),np.equal(new_pred,0)))
        # 判断为1实际为0
        FP = np.sum(np.logical_and(np.equal(new_true,0),np.equal(new_pred,1)))
        # 判断为0实际为1
        FN = np.sum(np.logical_and(np.equal(new_true,1),np.equal(new_pred,0)))
        return TP,TN,FP,FN
    
    y_true = [0, 2, 1, 3,4,4,3,1,0,0,0,1,1,2,3,2,2,4,2,1]
    y_pred = [1, 2, 1, 4,2,4,3,2,0,0,0,1,2,3,2,2,2,2,2,1]
    TP_list,TN_list,FP_list,FN_list = [],[],[],[]
    for i in range(5):
        new_true = deal_list(y_true,i)
        new_pred = deal_list(y_pred,i)
        TP,TN,FP,FN = count_tp_tn_fp_fn(new_true,new_pred)
        TP_list.append(TP)
        TN_list.append(TN)
        FP_list.append(FP)
        FN_list.append(FN)
    
    TP_mean = count_mean(TP_list)
    TN_mean = count_mean(TN_list)
    FP_mean = count_mean(FP_list)
    FN_mean = count_mean(FN_list)
    
    precision = TP_mean/(TP_mean+FP_mean)  # 0.6
    recall = TP_mean/(TP_mean+FN_mean)  # 0.6
    f1 = 2*precision*recall/(precision+recall)  # 0.6
    

    相关文章

      网友评论

          本文标题:算法模型的性能度量

          本文链接:https://www.haomeiwen.com/subject/uyjyjhtx.html