分类准确度的问题
一个癌症预测系统,输入体检信息,可以判断是否有癌症:
预测准确度:99.9%
如果某种癌症的产生的概率只有0.1%
我们的系统预测所有人都是健康的,即可达到99.9%的准确率、
如果某种癌症的产生的概率只有0.01%
我们的系统预测所有人都是健康的,即可达到99.99%的准确率、
对于极度偏斜(Skewed Data)的数据,只使用分类准确度是远远不够的。
例如上面的例子
使用混淆矩阵做进一步的分析
混淆矩阵 Confusion Matrix
对于二分类问题:
对以上混淆矩阵的解释
P:样本数据中的正例数
N: 样本数据中的负例数
Y;通过模型预测出来的正例数
N; 通过模型预测出来的负例数
True Positives: 真阳性: 表示实际是正样本预测成正样本的样本数
False Positives: 假阳性: 表示实际是负样本预测成正样本的样本数
False Negatives: 假阴性:表示实际是正样本预测成负样本的样本数
True Negatives:真阴性:表示实际是负样本预测成负样本的样本数
- TP/P : 正阳性率(True Positive Rate, TPR) 也叫灵敏度(Sensitivity),召回率(recall),TPR = Sensitivity= recall = TP/P, 正确的预测出的正样例数站样本中正例总数的比例。真阳性率越大越好,越大代表在正样本中预测为正例的越多
- FP/N : 假阳性率(False Positive Rate, FPR),也叫误诊率。错误的预测出的正例数占样本中负例的比例。假阳性率越小越好,越小代表在负样本中预测为正例的减少。
- TP/Y: 正确率。也叫精确率,Precision = TP/(TP+FP),通过模型预测出来的真正是正例数占模型预测出来是正例数的比例,越大越好。
- (TP+TN)/(P+N): 准确率accuracy, 模型预测正确的例数占总样本的比例,越大越好
举例:假设现在有60个正样本,40个负样本,我们通过模型找出正样本50个,其中40个是真正的正样本,那么上面几个指标如下:
TP=40 FP=10
FN=20 TN=30
可知,一个模型的TP和TN越大越好。准确率=70/100=70%。精确率=40/50=80%。召回率=40/60=2/3。
以行列值代表的数据来看,看是预测值还是真实值
例如上图: 假设10000个人,
TN 9978个人健康而且预测也是健康,
FP 12个人健康但是预测得病
FN 2个人得病但是预测健康
TP 8个人得病且预测得病
精准率和召回率
-
精准率
为什么是将这一列叫精准率呢?因为我们在有偏的数据中,我们将1作为我们关注的对象 -
召回率
我们关注的事件发生了,我们成功的预测了多少
使用 digits数据进行测试
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,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) #0.9755555555555555
y_log_predict = log_reg.predict(X_test)
- TN
def TN(y_true,y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true==0)&(y_predict==0))
TN(y_test,y_log_predict) #403
- FP
def FP(y_true,y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true==0)&(y_predict==1))
FP(y_test,y_log_predict) #2
- FN
def FN(y_true,y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true==1)&(y_predict==0))
FN(y_test,y_log_predict) #9
- TP
def TP(y_true,y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true==1)&(y_predict==1))
TP(y_test,y_log_predict) #36
- 混淆矩阵 confusion_martix
def confusion_matrix(y_true,y_predict):
return np.array([
[TN(y_test,y_log_predict), FP(y_test,y_log_predict)],
[FN(y_test,y_log_predict), TP(y_test,y_log_predict)]
])
confusion_matrix(y_test,y_log_predict) #array([[403, 2],[ 9, 36]])
- 精准率 precision_score
def precision_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
precision_score(y_test,y_log_predict) # 0.9473684210526315
- 召回率 recall_score
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
recall_score(y_test,y_log_predic