07_分类器不确定评估
描述
对于分类器,不光是预测一个测试点属于哪个列别,还要关心它对这个预测的置信度。
scikit-learn中有两个函数可以用于获取分类器的不确定度估计:descision_function和predic_proba。大多数分类器都至少有其中一个函数,多分类器两个都有。
二分类
构建一个 GradientBoostingClassifier 分类器(同时拥有 decision_function和 predict_proba 两个方法),看一下这两个函数对一个模拟的二维数据集的作用。
GradientBoostingClassifier :用于分类的梯度提升算法,该算法以一种前向分阶段的方式构建加性模型;它允许优化任意可微分的损失函数。在每个阶段,都会根据损失函数的负梯度(例如,二元或多元对数损失)拟合 n_classes_个回归树。
import pandas as pd
import numpy as np
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_splitX,Y = make_circles(noise=0.25,factor=0.5,random_state=1)
y_named = np.array(['blue','red'])[Y]
X_train,X_test,Y_train_named,Y_test_named,Y_train,Y_test=train_test_split(X,y_named,Y,random_state=0)
gbrt = GradientBoostingClassifier(random_state=0).fit(X_train,Y_train_named)
决策函数
对于二分类的情况,decision_function 返回值的形状是 (n_samples,),为每个样本都返回一个浮点数:
print('X_test shape:{}'.format(X_test.shape))
print('decision_function shape:{}'.format(gbrt.decision_function(X_test).shape))
decision_function返回值中,正值表示对正类的偏好,负值表示对“反类”的偏好
gbrt.decision_function(X_test)
可以通过仅查看决策函数的正负号来再现预测值
print(gbrt.decision_function(X_test)>0)
print(gbrt.predict(X_test))
对于二分类问题,“反”类始终是classes_属性的第一个元素,“正”类是classes_的第二个元素。想要完全再现 predict 的输出,需要利用 classes_ 属性:
greater_zero = (gbrt.decision_function(X_test)>0).astype(int)
pred = gbrt.classes_[greater_zero]
print("pred :{}".format(pred))
print("predict:{}".format(gbrt.predict(X_test)))
利用颜色编码在二维平面中画出所有点的 decision_function,还有决策边界:
import matplotlib.pyplot as plt
import mglearnfig,axes = plt.subplots(1,2,figsize=(13,5))
mglearn.tools.plot_2d_separator(gbrt,X,ax=axes[0],alpha=0.4,fill=True,cm=mglearn.cm2)
scores_image = mglearn.tools.plot_2d_scores(gbrt,X,ax=axes[1],alpha=0.4,cm=mglearn.ReBl)for ax in axes:mglearn.discrete_scatter(X_test[:,0],X_test[:,1],Y_test,markers='^',ax=ax)mglearn.discrete_scatter(X_train[:,0],X_train[:,1],Y_train,markers='^',ax=ax)ax.set_xlabel('feature 0')ax.set_ylabel('feature 1')cbar = plt.colorbar(scores_image,ax=axes.tolist())
axes[0].legend(["Test class 0", "Test class 1", "Train class 0","Train class 1"],ncol=4,loc=(0.1,1.1))
给出预测结果,又给出分类器的置信程度,这样给出的信息量更大。但在上面的图像中,很难分辨出两个类别之间的边界。
预测概率
predict_proba 的输出是每个类别的概率,通常比 decision_function 的输出更容易理解。对于二分类问题,它的形状始终是 (n_samples, 2):
print(gbrt.predict_proba(X_test).shape)
print(gbrt.predict_proba(X_test))
每行的第一个元素是第一个类别的估计概率,第二个元素是第二个类的估计概率。由于predict_proba的输出是第一概率,因此总是在0,1之间,两个类别的元素之和始终为1。只有一个类别的概率超过 50%,这个类别就是模型的预测结果。
分类器对大部分点的置信程度都是相对较高的,不确定度大小实际上反映了数据依赖模型和参数的不确定度。过拟合更强的模型可能会做出置信度更高的的预测,即使可能是错误的。复杂度越低的模型通常对预测的不确定度越大。如果模型给出的不确定度符合实际情况,那么这个模型被称为校正模型。在校正模型中,如果预测又70%的确定度,那么它在70%的情况下正确。
再次给出该数据集的决策边界,以及类别 1 的类别概率:
fig,axes=plt.subplots(1,2,figsize=(13,5))
mglearn.tools.plot_2d_separator(gbrt,X,ax=axes[0],alpha=0.4,fill=True,cm=mglearn.cm2)
scores_image = mglearn.tools.plot_2d_scores(gbrt,X,ax=axes[1],alpha=0.5,cm=mglearn.ReBl,function='predict_proba')for ax in axes:mglearn.discrete_scatter(X_test[:,0],X_test[:,1],Y_test,markers='^',ax=ax)mglearn.discrete_scatter(X_train[:,0],X_train[:,1],Y_train,markers='^',ax=ax)ax.set_xlabel('feature 0')ax.set_ylabel('feature 1')cbar = plt.colorbar(scores_image,ax=axes.tolist())
axes[0].legend(["Test class 0", "Test class 1", "Train class 0","Train class 1"],ncol=4,loc=(0.1,1.1))
执行上例,图中的边界更加明确,不确定的小块区域清晰可见。
多分类问题的不确定度
decision_function 和predict_proba 也适用于多分类问题,下面看一下鸢尾花的例子:
from sklearn.datasets import load_irisiris = load_iris()
X_train,X_test,Y_train,Y_test = train_test_split(iris.data,iris.target,random_state=42)
gbrt = GradientBoostingClassifier(random_state=0,learning_rate=0.01).fit(X_train,Y_train)
print(gbrt.decision_function(X_test).shape)
print(gbrt.decision_function(X_test))
对于多分类的情况,decision_function 的形状为 (n_samples, n_classes),每一列对应每个类别的“确定度分数”,分数较高的类别可能性更大,得分较低的类别可能性较小。
print(gbrt.predict(X_test))
print(np.argmax(gbrt.decision_function(X_test), axis=1)) # 效果同上
predict_proba 输出的形状相同,也是 (n_samples, n_classes)。同样,每个数据点所有可能类别的概率之和为 1
print(gbrt.predict_proba(X_test))
在多分类情况下,predict_proba 和 decision_function的形状始终相同都 是 (n_samples, n_classes)。