算法模型的性能度量

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

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342