机器学习系列(三十)——F1 Score与Precision-Recall的平衡

本篇主要内容:F1 Score,Precision-Recall的平衡,P-R曲线

F1 Score

上篇我们提到,精准率和召回率这两个指标有时精准率低一些有时召回率低一些,有时可能都低。那么实际中用哪个指标比较好呢?这一般和应用场景有关,对于有些场景,我们更注重精准率,比如股票预测,假设预测的是一个二分类问题:股票会升还是降,显然为了利润我们关注的是升(即上升为类1),为什么这种情况下精准率指标更好呢?因为精准率是所有分类为1的预测中有多少是正确的,对本例也就是预测未来股票上升有多少是对的,这更复合我们的利润最大决策。而召回率是实际上升的股票中我们预测对了多少,基于风险投资理念,有很多股票会上升的时刻,我们就算落掉一些也是没有关系的,没有投资进去也就没有损失,更重要的是我们的决策中有多少能赚钱,所以在这种场景下,精准率更好。
而如果在医疗领域,则是召回率更加重要,也就是要能在实际得病的人中尽量预测的更加准确,我们不想漏掉任何真正患病的人,这样才更有可能挽回一些人的生命,而精准率低些(没病的被预测为有病)并不会导致特别严重的后果,只是进行了一些过度医疗。
不过并非所有场景都如上面两个例子般极端,只关注精准率或只关注召回率。更多的我们希望得到它们之间的一种平衡,即同时关注精准率和召回率。这种情况下我们有一个新的指标:F1 Score,它的计算公式为:
F1=\frac{2.precision.recall}{precision+recall}

如果两个都为0,则定义F1=0。本质上F1是精准率和召回率的调和平均\frac{1}{F1}=\frac{1}{2}(\frac{1}{precision}+\frac{1}{recall}),调和平均一个很重要的特性是如果两个数极度不平衡(一个很大一个很小),最终的的结果会很小,只有两个数都比较高时,调和平均才会比较高,这样便达到了平衡精准率和召回率的目的。下面编程实现一下F1 Score:

import numpy as np

def f1_score(precision,recall):
    try:
        return 2*precision*recall/(precision+recall)
    except:
        return 0.0

输入几组值进行测试:

调和平均测试

下面在真实数据集上来使用F1 Score,分类算法使用逻辑回归,数据集和上篇文章相同,是人工处理为2类的手写数字数据集:

import numpy as np
from sklearn import datasets
digits = datasets.load_digits()
X = digits.data
y = digits.target.copy()

'''人工加入偏斜'''
y[digits.target==9]=1
y[digits.target!=9]=0
'''10分类变为2分类,用Logistic分类'''
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=666)
from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X_train,y_train)
log_reg.score(X_test,y_test)

准确率:

准确率

精准率和召回率:

精准率和召回率
from sklearn.metrics import f1_score
f1_score(y_test,y_predict)

F1 Score:

F1_Score

可以看到F1的值是综合了精准率和召回率的,用它来衡量模型性能是比准确率要好的。


Precision-Recall的平衡

精准率和召回率是相互制约的,如果想要精准率提高,召回率则会下降,如果要召回率提高,精准率则会下降,我们需要找到二者之间的一个平衡。
下面通过调整决策边界导致的分类结果变化来观察一下这个现象,不过Logistic回归中并没有直接能调整决策边界的函数,可以通过decision_score来间接调节:

log_reg.decision_function(X_test)[:10]

decision_score的前10个值展示:

d_c

其值就是样本特征带入决策边界函数得到的结果,对于其中小于0的就被判别为类别0了,大于0的则是类别1。默认的决策边界函数是\theta^{T}.x_{b}=0,此时如果需要调节边界比如要调节为\theta^{T}.x_{b}=5,只需在计算时让\theta^{T}.x_{b}-5再与0比较即可:

'''如果阀值为5'''
y_predict_2 = np.array(decision_scores >= 5,dtype=int)
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test,y_predict_2)

此时的混淆矩阵为:

混淆矩阵

精准率和召回率:

精准率和召回率

F1 Score:

F1 Score

再调节决策边界为\theta^{T}.x_{b}=-5

'''如果阀值为-5'''
y_predict_3 = np.array(decision_scores >= -5,dtype=int)
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test,y_predict_3)

精准率、召回率和F1 Score:

精准率召回率和F1

从上面的结果可以观察到当精准率升高时召回率相应下降,召回率升高时精准率相应下降,我们希望模型尽量有比较平横的精准率和召回率,为了更好地观察它们之间的关系,可以绘制精准率召回率曲线(P-R曲线):

import matplotlib.pyplot as plt
precisions = []
recalls = []
thresholds = np.arange(np.min(decision_scores),np.max(decision_scores))

for threshold in thresholds:
    y_predict = np.array(decision_scores >= threshold,dtype=int)
    precisions.append(precision_score(y_test,y_predict))
    recalls.append(recall_score(y_test,y_predict))
plt.plot(thresholds,precisions)
plt.plot(thresholds,recalls)
plt.show()
P、R随阀值变化曲线
P-R曲线

从P-R曲线看出精准率和召回率是相互制约的,召回率的升高会带来精准率的下降。同样可以用sklearn中自带的P-R曲线绘制函数来绘制:

from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_test,decision_scores)
plt.plot(thresholds,precisions[:-1])
plt.plot(thresholds,recalls[:-1])
plt.show()
'''sklearn自动寻找最优部分的数据'''
P、R随阀值变化曲线
P-R曲线

在P-R曲线中,突然下降的位置很可能就是二者平衡的一个位置。
整体的,如果将两个模型的P-R曲线绘制到一个图中,则靠外的那个模型显然更优,也就是与两个轴围成的面积大的那个模型更好。

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

推荐阅读更多精彩内容