准确度陷阱
我们首先看一下这个例子
- 何为准确度陷阱?
对于极度偏斜的数据,只使用分类准确度是远远不够的,我们很容易完全没法判断算法的好坏。
混淆矩阵(二分类问题)
二分类精准率和召回率
-
精准率:预测为真的情况下预测正确的概率
(例如在癌症预测系统中,精准率就代表了预测癌症预测的成功率)
精准率 - 召回率:真实发生我数据中我们成功预测的概率
(例如在癌症预测系统中,召回率代表患癌症总人数中我们通过算法预测成功的概率)
召回率
现在我们回到开头的那个问题,我们使用精准率和召回率进行分析
对比
我们意识到准确率没法判断的作用,而精准率和召回率可以用来判断
下面进行代码实现
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#构造出一个极度偏斜的数据
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=666)
#实际上这里size默认是0.2
from sklearn.linear_model import LogisticRegression
log_reg=LogisticRegression()
log_reg.fit(x_train,y_train)
log_reg.score(x_test,y_test)
这里我们发现准确度很高,实际上全部判断为0也会很高
高准确度
y_log_predict=log_reg.predict(x_test)
def TN(y_true,y_predict):
return np.sum((y_true==0)&(y_predict==0))
def FP(y_true,y_predict):
return np.sum((y_true==0)&(y_predict==1))
def FN(y_true,y_predict):
return np.sum((y_true==1)&(y_predict==0))
def TP(y_true,y_predict):
return np.sum((y_true==1)&(y_predict==1))
def confusion_matrix(y_true,y_predict):
return np.array([
[TN(y_true,y_predict),FP(y_true,y_predict)],
[FN(y_true,y_predict),TP(y_true,y_predict)]
])
我们可以看到混淆矩阵
混淆矩阵
def precesion_score(y_true,y_predict):
tp=TP(y_true,y_predict)
fp=FP(y_true,y_predict)
try:
return tp/(tp+fp)#异常检测,正如前面的例子,唯一的异常便是分母为零的情况
except:
return 0
def recall_score(y_true,y_predict):
tp=TP(y_true,y_predict)
fn=FN(y_true,y_predict)
try:
return tp/(tp+fn)
except:
return 0
我们分别可以得到其精准率和召回率
精准率
召回率
利用sklearn中的函数实现
#sklearn中的
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test,y_log_predict)
from sklearn.metrics import precision_score
precesion_score(y_test,y_log_predict)
from sklearn.metrics import recall_score
recall_score(y_test,y_log_predict)
我们也可以得到相同的答案
sklearn实现
指标的选择
我们同时拥有精准率和召回率两个指标,那么我们依据哪一个去判断呢?
- 有时候我们会注重精准率,如股票预测,我们更加关系预测的数据中正确的概率
- 有时候我们会注重召回率,如病人诊断,我们更加关心实际数据中成功预测概率
-
二者兼顾:F1 Score,是二者的调和平均值
F1 Score
对前面的代码进行一次总结同时使用F1Score
def f1_score(precesion,recall):
try:
return 2*precesion*recall/(precesion+recall)
except:
return 0
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#构造出一个极度偏斜的数据
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=666)
#实际上这里size默认是0.2
from sklearn.linear_model import LogisticRegression
log_reg=LogisticRegression()
log_reg.fit(x_train,y_train)
y_log_predict=log_reg.predict(x_test)
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test,y_log_predict)
from sklearn.metrics import precision_score
precesion_score(y_test,y_log_predict)
from sklearn.metrics import recall_score
recall_score(y_test,y_log_predict)
from sklearn.metrics import f1_score
f1_score(y_test,y_log_predict)
- 我们实际中会发现精准率和召回率之间互相矛盾,不可能同时较高,这时我们要做出取舍选择。
-
我们回顾一下逻辑回归中的决策边界,我们可以通过改变常数项来移动这根线
决策边界
移动
如图,改变常数(即阈值)我们会相应的改变精准率和召回率
下面我们在前述代码中继续实现这个部分
decision_scores=log_reg.decision_function(x_test)#返回一个向量,元素为score值
y_predict2=np.array(decision_scores>=5,dtype='int')#这里选定阈值为5,之前阈值为0
confusion_matrix(y_test,y_predict2)
precision_score(y_test,y_predict2)
recall_score(y_test,y_predict2)
我们可以看到,精准率上升而召回率下降
阈值为5
我们将阈值改为-5,可以看到,精确率下降而召回率上升
y_predict3=np.array(decision_scores>=-5,dtype='int')
confusion_matrix(y_test,y_predict3)
precision_score(y_test,y_predict3)
recall_score(y_test,y_predict3)
阈值-5
这也再次说明了,这两者是相互制约的,一者上升一者下降,不会出现理想的两者都上升的理想局面。
可以通过可视化的方式来看到这一特性
精确率和召回率
我们也可以使用sklearn找到Precesion-Recall曲线
from sklearn.metrics import precision_recall_curve
precesions,recalls,thresholds=precision_recall_curve(y_test,decision_scores)
precesions.shape
recalls.shape
thresholds.shape#少一个元素
import matplotlib.pyplot as plt
plt.plot(thresholds,precesions[:-1])#去掉一个值
plt.plot(thresholds,recalls[:-1])
plt.show
plt.plot(precesions,recalls)
plt.show
对应于代码我们有如下结果
向量大小
曲线1
曲线2
ROC曲线——描述TPR和FPR之间的关系
- TPR=Recall(True Positive Rate)
-
FPR(False Positive Rate)
TPR&FPR
两者同时增加减少
这里仅使用sklearn演示roc
from sklearn.metrics import roc_curve
fprs,tprs,thresholds = roc_curve(y_test,decision_scores)
plt.plot(fprs,tprs)
plt.show
FTP、TPR
我们意识到面积可以作为指标(面积最大为1)
from sklearn.metrics import roc_auc_score
roc_auc_score(y_test,decision_scores)
ROC可以用于比较模型的优劣,我们会选面积更大的模型
网友评论