机器学习初学者——分类算法评价学习笔记

对于回归算法的评价指标有均方误差、均方根误差、R2等,而对于分类算法的评价我们之前接触过分类准确度。但是分类准确度这一指标在数据极度偏斜的情况下存在缺。比如某种癌症的患病率仅有0.01%,即人群中,一个人属于健康的概率有99.99%,对于一个病人,如果预测他属于健康,那么预测的准确率高达99.99%,若有一个模型的准确率为99%,表面上看,模型的准确率非常高,但相比于什么都不做而直接将所有人都预测为健康,该模型的准确率较差。
由此可见,用准确率来衡量分类模型的好坏对数据有特殊要求——每一类的样本数量不能相差过大。

(一)混淆矩阵

混淆矩阵(Confusion Matrix)
二分类问题的混淆矩阵,默认情况下,行(左边的两行0和1)代表真实值,列(上边的两列0和1)代表预测值,且先是0后是1。**0用N(Negative)表示,1用P(positive)表示。**多分类问题依次类推。

TN表示真实值和预测值均为0,FP表示预测值为1而真实值为0,FN表示预测值为0而真实值为1,TP表示预测值和真实值均为1

在这里插入图片描述

(二)Precision(精准率)、Recall(召回率)与F1 Score

2.1数学公式

精准率表示预测值为1的样本中,预测正确的概率。召回率表示真实值为1的所有样本中,预测正确的概率。F1 Score是兼顾前两者的一种指标,是precision与recall的调和平均值

调和平均值的特点:如果被调和的两者存在一个值非常低,一个特别高那么调和平均值也将特别低,只有两者均比较高,最终的结果才会较高

下面为三者的计算公式。以某种患病概率为0.01%的疾病为例,探讨精准率和召回率相对于准确率的优点。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
本例中,样本显然季度偏斜,将所有人都预测为健康,准确率为9990/(10000)=99.9%,但精准率和召回率都为0,对于疾病的预测,召回率非常重要,若将病人预测为健康,将导致病人失去最佳治疗时机。
F1 Score的取值范围是0-1,该指标用于同时保证精准率和召回率都比较高

2.2precision与recall的平衡

precision与recall是此消彼长的关系
以逻辑回归为例,构建一个逻辑回归分类器,不断改变决策边界,来改变模型的precision与recall。依据逻辑回归的数学原理可知,逻辑回归进行分类的决策边界是θT·Xb=0这条直线,如果改变决策边界θT·Xb=threshold(阈值),threshold取值不同,分类结果也将不同,样本本身的位置是固定不变的,但决策边界改变位置会使得某个样本前后的分类结果发生改变。那么如果要使得精准率较高,就会使决策边界向“1”那边偏,选择最有可能分类为“1”的样本,这样做的后果是,有些比较靠近“0”但实际为“1”的样本将会分类错误,这就使得召回率降低。同理,若要满足高的召回率,就会尽可能把左右可能是“1”的样本挑出来,这就使得有些原本属于“0”但比较接近“1”的样本被分类错误,导致精准率降低。
下面进行实例演示:

from sklearn.linear_model import LogisticRegeression
log_reg=LorgisticRegression()
log_reg.fit(x_train,y_train)
decision_score=log_reg.decision_function(x_test) #这里得出的结果是X·θ的值,介于负无穷和正无穷之间
那么逻辑回归中的决策边界就是decoision_score=0
接下来改变决策边界,比如:decoision_score=5
y_predict=np.array(decision_score>5,dtype='int')

以上会得出新的预测值,通过调用(四)中的混淆矩阵、精准率、召回率函数计算此时的precision与recall,发现与预测相同,即精准率升高,召回率降低。

2.3precision与recall曲线(P-R曲线)

在X·θ的取值范围内以一定的步长改变决策边界的值,得到每次的降准率和召回率的数值,之后在同一个图中绘制阈值不同时,两者的变化情况。

decision_min=np.min(decision_score)
decision_max=np.max(decision_score)
threshold=np.arange(decision_min,decision_max,step)
precision=[]
recall=[]
for i in range(len(threshold)):
	y_pre=np.array(decision_score>=threshold[i],dtype='int')
	pre_score=precision_score(y_test,y_pre)
	re_score=recall_score(y_test,y_pre)
	precision.append(pre_score)
	recall.append(re_score)
plt.plot(threshold,precision,label='p')
plt.plot(threshold,recall,label='R')
plt.legend()

在这里插入图片描述在这里插入图片描述
从图中可以看出,两者呈负相关关系。P-R曲线上有一个非常陡峭的点,在此之前,P会迅速下降,在此之后,R会迅速下降,该点处是精准率和召回率最好的平衡位置。
sklearn实现P-R曲线的绘制

from sklearn.mertics import precision_recall_curve
precision,recall,thresholds=precision_recall_curve(y_test,decision_score)
plt.plot(threshold,precision[:-1])
plt.plot(threshold,recall[:-1])
plt.plot(precision,recall)

注意:sklearn 中得到的threshold的值比precision和recall少了一个元素,缺少的是precision等于1,recall等于0的时候的对应的threshold。因此,在绘图时要注意preciison 和recall都要省去最后一个值。

(三)ROC曲线与模型优劣的衡量

ROC(Receiver Operation Characteristic Curve)描述的是TPR(true positive rate)与FPR(false positive rate)之间的关系
在这里插入图片描述在这里插入图片描述在这里插入图片描述
随着threshold的降低,二者的分母都不变,而FP和TP都会增加,因此,FPR和TPR都随着threshold的降低而增加。只是增加的程度不同。绘制ROC曲线的方法与绘制PR曲线的方法相同。
sklearn中实现绘制ROC的方法是:

from sklearn.metrics import roc_curve
fpr,tpr,threshold=roc_curve(y_test,decision_score)

在这里插入图片描述在这里插入图片描述
这里ROC曲线下面的面积越大说明模型的效果越好,这是因为,面积越大说明,当fpr较小的时候,tpr越大,也就是recall越大
求取面积的方法:

from sklearn.metrics import roc_auc_score
rco_auc_score(y_test,decision_score)

另外:P-R曲线也能够衡量模型的优劣
在这里插入图片描述
如果有两个模型,其中一个模型对应的P-R曲线在另一个模型的外部,说明当两者的precision相等时,外部的(面积大)recall大于内部的(面积小),同样,两者的recall相等时,外部的precision大于内部的。这说明外部的曲线对应的模型优于内部曲线对应的模型。

(四)算法实现

首先编写一个极度偏斜的数据,

digits=datasets.load_digits()
x=digits.data
y=digits.target.copy()
y[digits.target==9]=1
y[digits.target!=9]=0

def confusion_matrix(y_true,y_predict):
    assert len(y_true)==len(y_predict)
    TN=np.sum(y_predict[y_true==0]==0)
    FN=np.sum(y_predict[y_true==1]==0)
    FP=np.sum(y_predict[y_true==0]==1)    
    TP=np.sum(y_predict[y_true==1]==1)
    return np.array(([TN,FP],
                     [FN,TP]))
def precision_score(y_true,y_predict):
    FP=np.sum(y_predict[y_true==0]==1)    
    TP=np.sum(y_predict[y_true==1]==1)
    return TP/(TP+FP)
def recall_score(y_true,y_predict):   
    FN=np.sum(y_predict[y_true==1]==0)
    TP=np.sum(y_predict[y_true==1]==1)
    return TP/(TP+FN)
def f1_score(precision,recall):
	try:
		return 2*precision*recall/(precision+recall)
	except:
		return 0.0

sklearn中的混淆矩阵、precision、recall

from sklearn.matrics import confusion_matrix
from sklearn.matrics import precision_score
from sklearn.matrics import recall_score
from sklearn.matrics import f1_score
confusion_matrix(y_true,y_predict)
precision_score(y_true,y_predict)
recall_score(y_true,y_predict)
f1_score(y_true,y_predict)

(五)多分类问题的混淆矩阵

由于precision_score、recall_score默认情况下只能解决二分类问题,因此当y_true是多值时,precision_score(y_true,y_predict)将会报错,提示中的average=‘binary’意思就是二分类。

digits=datasets.load_digits()
x=digits.data
y=digits.target.copy()
x_train,x_test,y_train,y_test=train_test_split(x,y,random_state=666)
log=LogisticRegression()
log.fit(x_train,y_train)
y_pre=log.predict(x_test)
from sklearn.metrics import precision_score
precision=precision_score(y_test,y_pre,average='micro')
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test,y_pre)

这里是十分类问题。得出的混淆矩阵如下,与二分类相同,行代表真实值,列代表预测值。
[[45, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[ 0, 37, 0, 0, 0, 0, 0, 0, 3, 0],
[ 0, 0, 49, 1, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 49, 0, 1, 0, 0, 3, 0],
[ 0, 1, 0, 0, 47, 0, 0, 0, 0, 0],
[ 0, 0, 0, 1, 0, 36, 0, 0, 1, 0],
[ 0, 0, 0, 0, 0, 1, 38, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 42, 0, 1],
[ 0, 2, 0, 0, 0, 0, 0, 0, 46, 0],
[ 0, 1, 0, 1, 1, 1, 0, 0, 0, 41]],
用灰度值表示数值的大小,越量的地方表示数值越大,显然对角线上的亮度较大,这符合事实,对角线上代表预测正确。

c=confusion_matrix(y_test,y_pre)
plt.matshow(c,cmap=plt.cm.gray)

在这里插入图片描述
但是单纯的看预测正确的数量是没有意义的,可能各类样本的数量也不相同,且更加关注的是错误的概率。因此,下面先将数值转换成比例,再将对角线处的数值填充为‘0’,这样以来,原矩阵中比对角线暗比0亮的方块就会凸显出来,最终形成的矩阵中,亮度越大说明预测错误的比重越大。如图中将1、3预测成8和将8预测成1的比率都比较大。这就说明模型容易混淆1和8、3和8,这就给我们调整模型提供了借鉴,将多分类问题转化成二分类,比如1和8两类,分类时调整阈值来调整模型的准确率。

row_sum=np.sum(c,axis=1)
err_matrix=c/row_sum
np.fill_diagonal(err_matrix,0)
plt.matshow(err_matrix,cmap=plt.cm.gray)

在这里插入图片描述

*细节补充*:若a是一个array数组,将a赋值给b,那么如果对b做修改,a也会随之发生改变,为了不改变a的值,需要copy操作,即b=a.copy()

Python3.7IDLE的安装过程,需要注意,安装过程中有一个竖向的列表,要做选择,应该选择3、4、5三个选项。另外,交互界面与MATLAB类似,不能实现换行,因此用Ctrl+N来新建一个文本编辑器,也可以保存为py文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值