在使用sklearn训练完分类模型后,下一步就是要验证一下模型的预测结果,对于分类模型,sklearn中通常提供了predict_proba、predict、decision_function三种方法来展示模型对于输入样本的评判结果。

说明一下,在sklearn中,对于训练好的分类模型,模型都有一个classes_属性,classes_属性中按顺序保存着训练样本的类别标记。下面是使用Logistic Regression分类器在为例,展示一下分类器的classes_属性。

1、先看一下样本标签从0开始的场景下训练分类模型

import numpy as np
from sklearn.linear_model import LogisticRegression
x = np.array(
        [-1, -1],
        [-2, -1],
        [1, 1],
        [2, 1],
        [-1, 1],
        [-1, 2],
        [1, -1],
        [1, -2]
y = np.array([2, 2, 3, 3, 0, 0, 1, 1])
clf = LogisticRegression()
clf.fit(x, y)
print(clf.classes_)
    输出结果:[0 1 2 3]

2、下面看一下样本标签不是从0开始的场景下训练分类模型

import numpy as np
from sklearn.linear_model import LogisticRegression
x = np.array(
        [-1, -1],
        [-2, -1],
        [1, 1],
        [2, 1],
        [-1, 1],
        [-1, 2],
        [1, -1],
        [1, -2]
y = np.array([6, 6, 2, 2, 4, 4, 8, 8])
clf = LogisticRegression()
clf.fit(x, y)
print(clf.classes_)
    输出结果:[2 4 6 8]

注意观察上述两种情况下classes_属性的输出结果,该输出结果的顺序就对应后续要说predict_proba、predict、decision_function输出结果的顺序或顺序组合。

在了解了分类模型classes_的标签顺序之后,下面看一下分类模型predict_proba、predict、decision_function三种函数输出结果的含义,以及他们之间的相关性。

1、predict_proba:  模型预测输入样本属于每种类别的概率,概率和为1,每个位置的概率分别对应classes_中对应位置的类别标签。以上述类别标签为[2 4 6 8]的那个分类器为例,查看一下分类模型预测的概率。

输入的[-1, -1]刚好是训练分类器时使用的数据,训练数据中[-1, -1]属于类别6,在predict_proba输出概率中,最大概率值出现在第三个位置上,第三个位置对应的classes_类别刚好也是类别6。这也就是说,predict_proba输出概率最大值索引位置对应的classes_元素就是样本所属的类别。下面就来看一下predict的预测结果与predict_proba的预测结果是否一致。

2、predict: 模型预测输入样本所属的类别,是则输出1,不是则输出0。

在上一步中知道了predict_proba是输出样本属于各个类别的概率,且取概率最大的类别作为样本的预测结果,下面看一下predict的预测结果与predict_proba的最大值是否一致。

predict的预测结果为类别6,对应于classes_中的第三个元素,也同时对应于predict_proba中的第三个元素,且是概率值最大的元素。

对于分类模型来说,通常知道模型的预测结果predict和预测概率predict_proba就可以了,那分类模型中的decision_function是干什么的呢?

3、decision_function:  帮助文档中给出的解释是“The confidence score for a sample is the signed distance of that sample to the hyperplane.”。意思就是使用样本到分隔超平面的有符号距离来度量预测结果的置信度,反正我是有点懵逼。放大招,灵魂三问。他是谁?他从哪里来?他到哪里去?

看一下支持向量机SVM中关于decision_function的解释是怎样的?

说了两件事情,其一是说评估样本X的的decision_function(等于没说,哈哈哈),其二是说,如果decision_dunction_shape='ovr',则输出的decison_function形状是(n_samples, n_classes), n_samples是输入样本的数量,n_classes是训练样本的类别数。这里再补充一点,如果decision_dunction_shape='ovo,则输出的decison_function形状是(n_samples, n_classes * (n_classes - 1) / 2)。‘ovr’和‘ovo’又是啥?莫急,莫急。暂且知道是用于训练多分类的就行。

大致解释下decison_function就是用来衡量待预测样本到分类模型各个分隔超平面的距离(没找到太直观的解释方法)。

他从哪里来?

据说这家伙来自遥远的SVM星球。上面说这哥们能和分隔超平面扯上关系,熟悉SVM的会知道,SVM中通过支持向量来选择分隔超平面,分隔超平面将训练样本分为正反两派,支持向量的作用就是使得选择的分隔超平面离两边的类别都比较远,这样模型具有更强的健壮性。

他到哪里去?

说了半天,decison_function这玩意到底有啥用?莫急,莫急。下面先说一下上面提到的'ovr'和'ovo'分别是什么东东?

我们常见的分类器,比如LR和SVM都是只能支持二分类的,回想一下LR分类器,通过判断线性模型的预测结果是否大于0,进而判断sigmoid的输出结果是否大于0.5来判断模型属于正类还是负类。SVM也一样,前面讲了,SVM通过分隔超平面将样本分到两边去,也就是进行二分类。那么怎么能将二分类的分类算法应用到多分类任务上去呢?这就是‘ovr’和‘ovo’要解决的问题。

'ovr':全称是One-vs-Rest。就是一个人和对面一群人干一次架(群殴)。假如我们训练数据中包含[0, 1, 2, 3]四个分类,那么分别将0, 1, 2, 3作为正样本,其余的123, 023, 013, 012作为负样本,训练4个分类器,每个分类器预测的结果表示属于对应正类也就是0, 1, 2, 3 的概率。这样对于一个输入样本就相当于要进行4个二分类,然后取输出结果最大的数值对应的classes_类别。

‘ovo’:全称是One-vs-One。就是一个人分别和对面的每个人干一次架(单挑,车轮战术)。同样,假如我们训练数据中包含[0, 1, 2, 3]四个分类,先将类别0作为正样本,类别1,类别2,类别3依次作为负样本训练3个分类器,然后以类别1为正样本,类别0,类别2, 类别3作为负样本训练3个分类器,以此类推。由于类别0为正样本,类别1为负样本和类别1为正样本、类别0为负样本实质上是一样的,所以不需要重复训练。

通过上面的描述可知,假如训练样本有n_classes个类别,则'ovr'模式需要训练n_classes个分类器,‘ovo’模式需要训练n_classes * (n_classes - 1) / 2 个分类器。那么问题来了,有多少个分类器是不是就得有多少个分隔超平面,有多少个分隔超平面是不是就得有多少个decision_function值。这也就对应了“他是谁?”那部分所说的decison_function输出形状的描述。

下面进入正题,来看一下decision_function的真面目。

1、二分类的decison_function

二分类模型中,decision_function返回的数组形状等于样本个数,也就是一个样本返回一个decision_function值。并且,此时的decision_function_shape参数失效 ,因为只需要训练一个分类器就行了,就不存在是单挑还是群殴的问题了。下面以SVM二分类的实例来看一下结果:

import numpy as np
from sklearn.svm import SVC
x = np.array([[1,2,3],
                    [1,3,4],
                    [2,1,2],
                    [4,5,6],
                    [3,5,3],
                    [1,7,2]])
y = np.array([3, 3, 3, 2, 2, 2])
clf = SVC(probability=True)
clf.fit(x, y)
print(clf.decision_function(x))
# 返回array([2, 3]),其中2为negetive,3为positive
print(clf.classes_)

在二分类的情况下,分类模型的decision_function返回结果的形状与样本数量相同,且返回结果的数值表示模型预测样本属于positive正样本的可信度。并且,二分类情况下classes_中的第一个标签代表是负样本,第二个标签代表正样本。

模型在训练集上的decision_function以及predict_procaba、predict结果如下:

还记得前面讲过的decision_function是有符号的吧,大于0表示正样本的可信度大于负样本,否则可信度小于负样本。所以对于前3个样本,decison_function都认为是正样本的可信度高,后3个样本是负样本的可信度高。那么再看一下predict的结果,前3个预测为正样本3(ps:二分类情况下正样本对应的是classes_中的第二个类别),后3个样本预测为负样本2。再看一下predict_proba预测的样本所属的类别概率,可以看到前3个样本属于类别3的概率更大,后3个样本属于类别2的概率更大。

2、多分类的decision_function

多分类模型中,decision_function返回的数组形状依据使用的模式是‘ovr’还是‘ovo’而分别返回n_classes个和n_classes * (n_classes - 1) / 2个数值。下面以SVM多分类的实例来看一下结果:

One-vs-Rest多分类实例:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
X = np.array(
        [-1, -1],
        [-2, -1],
        [1, 1],
        [2, 1],
        [-1, 1],
        [-1, 2],
        [1, -1],
        [1, -2]
y = np.array([2, 2, 3, 3, 0, 0, 1, 1])
# SVC多分类模型默认采用ovr模式
clf = SVC(probability=True, decision_function_shape="ovr")
clf.fit(X, y)
# 计算样本距离每个分类边界的距离
# One-vs-One 按照decision_function的得分[01, 02, 03, 12, 13, 23]判断每个分类器的分类结果,然后进行投票
# One-vs-Rest 选择decision_function的得分[0-Rest, 1-Rest, 2-Rest, 3-Rest]最大的作为分类结果
print("decision_function:\n", clf.decision_function(X))
# precidt预测样本对应的标签类别
print("predict:\n", clf.predict(X))
# predict_proba 预测样本对应各个类别的概率
print("predict_proba:\n", clf.predict_proba(X)) #这个是得分,每个分类器的得分,取最大得分对应的类。
print("classes_:", clf.classes_)

模型在训练集上的decision_function以及predict_procaba、predict结果如下:

在ovr场景下,decision_function输出的最大值对应的正样本类别就是decision_function认为置信度最高的预测类别。下面看一下One-vs-One场景下的多分类。

One-vs-One多分类实例:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
X = np.array(
        [-1, -1],
        [-2, -1],
        [1, 1],
        [2, 1],
        [-1, 1],
        [-1, 2],
        [1, -1],
        [1, -2]
y = np.array([2, 2, 3, 3, 0, 0, 1, 1])
# SVC多分类模型默认采用ovr模式
clf = SVC(probability=True, decision_function_shape="ovo")
clf.fit(X, y)
# 计算样本距离每个分类边界的距离
# One-vs-One 按照decision_function的得分[01, 02, 03, 12, 13, 23]判断每个分类器的分类结果,然后进行投票
# One-vs-Rest 选择decision_function的得分[0-Rest, 1-Rest, 2-Rest, 3-Rest]最大的作为分类结果
print("decision_function:\n", clf.decision_function(X))
# precidt预测样本对应的标签类别
print("predict:\n", clf.predict(X))
# predict_proba 预测样本对应各个类别的概率
print("predict_proba:\n", clf.predict_proba(X)) #这个是得分,每个分类器的得分,取最大得分对应的类。
print("classes_:", clf.classes_)

模型在训练集上的decision_function以及predict_procaba、predict结果如下:

ovo模式下,4个类别的训练数据,需要训练6个二分类器,得到6个decition_function值,依照classes_的类别顺序,6个二分类器分别是[01, 02, 03, 12, 13, 23],前面的数字表示正类,后面的表示负类。以decision_function的第一行输出结果为例:

-0.07609727 对应 01分类器,且数值小于0,则分类结果为后者,即类别1
-1.00023294  对应 02分类器,且数值小于0,则分类结果为后者,即类别2
0.27849207  对应 03分类器,且数值大于0,则分类结果为前者,即类别0
-0.834258626  对应 12分类器,且数值小于0,则分类结果为后者,即类别2
0.24756982  对应 13分类器,且数值大于0,则分类结果为前者,即类别1
1.00006256 对应 23分类器,且数值大于0,则分类结果为前者,即类别2
最终得票数:{类别0: 1, 类别1: 2, 类别2: 3, 类别3: 0}
对以上分类结果voting投票,多数获胜,即最终分类结果为类别2。

通过上面讲的这些大概也能得出decision_function、predict_procaba、predict之间的联系了:

decision_function:输出样本距离各个分类器的分隔超平面的置信度,并由此可以推算出predict的预测结果

predict_procaba:输出样本属于各个类别的概率值,并由此可以推算出predict的预测结果

predict:输出样本属于具体类别的预测结果

说了这么多,也知道decision_function的具体含义了,那么使用decison_function可以干什么呢?(没用说个毛线)

还是以SVM分类器为例,SVM分类器有个参数用来控制是否输出预测样本的概率值,probability=True时SVM分类器具有predict_proba函数,可以输出样本的预测概率,但是当probability=False,SVM分类器没有predict_proba函数,也就没办法得到样本预测结果的置信度(简单理解为概率)。但是我们又知道,当我们想要计算分类器的性能时,常常需要用到ROC和AUC,ROC曲线表示分类器预测结果FPR和TPR的变化趋势,AUC表示ROC曲线以下的面积。也就是说,要想得到ROC和AUC,就需要得到一组FPR和TPR,FPR和TPR的计算通常是基于一组样本的预测置信度,分别选择不同的置信度阈值,得到一组FPR和TPR值,然后得到ROC曲线的。现在没有predict_proba就得不到样本预测的置信度。But,还记得我们前面解释decison_function时说过的,decision_function表示通过度量样本距离分隔超平面距离的来表示置信度。那么我们是不是可以使用decision_function的置信度来计算ROC呢?答案当然是可以的啦。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
from sklearn.metrics import roc_curve, roc_auc_score, auc, plot_roc_curve
from sklearn.multiclass import OneVsOneClassifier, OneVsRestClassifier
from sklearn.preprocessing import label_binarize
from sklearn import datasets
from sklearn.model_selection import train_test_split
np.random.seed(100)
# 加载iris数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
print(X.shape, y.shape)
n_samples, n_features = X.shape
# iris数据集加入噪声,使得ROC不是那么完美
X = np.c_[X, np.random.randn(n_samples, 50 * n_features)]
# y = label_binarize(y, classes=[0, 1, 2])
# n_classes = y.shape[1]
# 训练样本的类别数量
n_classes = 3
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5, random_state=0)
print(X_train.shape, y_train.shape)
print(X_test.shape, y_test.shape)
# 使用One-vs-Rest模式训练SVM分类器
clf = OneVsRestClassifier(SVC(kernel="linear"))
clf.fit(X_train, y_train)
# 计算分类器在测试集上的决策值
y_scores = clf.decision_function(X_test)
print(y_scores.shape)
# 绘制每个类别的ROC曲线
fig, axes = plt.subplots(2, 2, figsize=(8, 8))
colors = ["r", "g", "b", "k"]
markers = ["o", "^", "v", "+"]
y_test = label_binarize(y_test, classes=clf.classes_)
for i in range(n_classes):
    # 计算每个类别的FPR, TPR 
    fpr, tpr, thr = roc_curve(y_test[:, i], y_scores[:, i])
#     print("classes_{}, fpr: {}, tpr: {}, threshold: {}".format(i, fpr, tpr, thr))
    # 绘制ROC曲线,并计算AUC值
    axes[int(i / 2), i % 2].plot(fpr, tpr, color=colors[i], marker=markers[i], label="AUC: {:.2f}".format(auc(fpr, tpr)))
    axes[int(i / 2), i % 2].set_xlabel("FPR")
    axes[int(i / 2), i % 2].set_ylabel("TPR")
    axes[int(i / 2), i % 2].set_title("Class_{}".format(clf.classes_[i]))
    axes[int(i / 2), i % 2].legend(loc="lower right")
print("AUC:", roc_auc_score(y_test, clf.decision_function(X_test), multi_class="ovr", average=None))

输出结果如下:AUC: [0.99470899 0.5962963  0.8619281 ]

在使用sklearn训练完分类模型后,下一步就是要验证一下模型的预测结果,对于分类模型,sklearn中通常提供了predict_proba、predict、decision_function三种方法来展示模型对于输入样本的评判结果。说明一下,在sklearn中,对于训练好的分类模型,模型都有一个classes_属性,classes_属性中按顺序保存着训练样本的类别标记。下面是使用Logistic Regression分类器在为例,展示一下分类器的classes_属性。1、先看一下样本标签从0...
发现个很有用的方法——predict_proba 今天在做数据预测的时候用到了,感觉很不错,所以记录分享一下,以后可能会经常用到。 我的理解:predict_proba不同于predict,它返回的预测值为,获得所有结果的概率。(有多少个分类结果,每行就有多少个概率,以至于它对每个结果都有一个可能,如0、1就有两个概率) 获取数据及预测代码: from sklearn.linear_model import LogisticRegression import numpy as np train_X = np.array(np.random.randint(0,10,size=30).
predict_proba返回的是一个 n 行 k 列的数组, 第 i 行 第 j 列上的数值是模型预测 第 i 个预测样本为某个标签的概率,并且每一行的概率和为1。 # conding :utf-8 from sklearn.linear_model import LogisticRegression import numpy as np x_train = np.array([[1,2,3], [1,3,4],
在使用sklearn训练完分类模型后,下一步就是要验证一下模型的预测结果,对于分类模型,sklearn通常提供了predict_probapredict、decision_function三种方法来展示模型对于输入样本的评判结果。 说明一下,在sklearn,对于训练好的分类模型,模型都有一个classes_属性,classes_属性按顺序保存着训练样本的类别标记。下面是使用Logistic Regression分类器在为例,展示一下分类器的class...
一、Sklearn工具包介绍   scikit-learn,又写作sklearn,是一个开源的基于python语言的机器学习工具包。它通过NumPy, SciPy和Matplotlib等python数值计算的库实现高效的算法应用,并且涵盖了几乎所有主流机器学习算法。   官网:https://scikit-learn.org/stable/index.html 1、常用模块   Skle...
在模型评估过程,分类问题、排序问题、回归问题往往需要使用不同的指标进行评估。在诸多的评估指标,大部分指标只能片面地反映模型的一部分性能。如果不能合理地运用评估指标,不仅不能发现模型本身的问题,而且会得出错误的结论。 与线性回归问题不同,分类问题,或者说逻辑回归问题输出的是离散值,即判断某件事物属于哪个类别。事实上,逻辑回归模型输出的是一个概率值,通过将这个概率预测值与设定的分类阈值(threshold)进行比较,若大于阈值则分为正类,否则为反类。 准确率(Accuracy),精确率(Preci
Python基础学习:逻辑回归理论(第一天)1 文章内容Python基础学习:逻辑回归理论(第一天)[^1]1.逻辑回归理论简介2.逻辑回归应用2.1 简单示例2.1.1 导入库函数2.1.2 创建实例演示数据可视化可视化决策边界可视化预测新样本进行预测2.2 基于鸢尾花(iris)数据集的逻辑回归分类实践3.逻辑回归原理 1.逻辑回归理论简介 优点:模型简单、解释性强 2.逻辑回归应用 2.1 简单示例 2.1.1 导入库函数 基本库:numpy 画图库:matplotlib、seaborn 逻辑回归函数
输入:一组有标签的训练数据(也称观察和评估),标签表明了这些数 据(观察)的所署类别。 输出:分类模型根据这些训练数据,训练自己的模型参数,学习出一个 适合这组数据的分类器,当有新数据(非训练数据)需要进行类别判断,就 可以将这组新数据作为输入送给学好的分类器进行判断。 划分数据集 训练集(training set):顾名思义用来训练模型的已标注数据,用来建 立模型,发现规律。 测试集(...
decision function是sklearn机器学习框架的分类器类的一种method。该method基本上返回一个Numpy数组,其每个元素表示分类器对x_test的预测样本是位于超平面的右侧还是左侧,以及离超平面有多远。 它还告诉我们,分类器为x_test预测的每个值是正值(大幅度正值),还是负值(大幅度负值),以及相应的信任程度。 decision function method背后的数学: 让我们考虑SVM对于线性可分二进制类的分类问题: 损失函数: 这种线性可分的二分类的假设:
混淆矩阵可以用来评估分类模型的性能,而predict_proba方法可以用来预测样本属于不同类别的概率。在Python可以使用scikit-learn的confusion_matrix函数来计算混淆矩阵,同时使用predict_proba方法来生成预测概率。 以下是一个示例代码,假设我们有一个二分类模型,并使用了测试集数据进行预测: ```python from sklearn.metrics import confusion_matrix from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression import numpy as np # 生成一些示例数据 X = np.random.rand(100, 5) y = np.random.randint(0, 2, 100) # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 创建逻辑回归模型 model = LogisticRegression() # 训练模型 model.fit(X_train, y_train) # 在测试集上进行预测 y_pred = model.predict(X_test) y_prob = model.predict_proba(X_test) # 计算混淆矩阵 cm = confusion_matrix(y_test, y_pred) print(cm) # 打印预测概率 print(y_prob) 输出结果为: [[6 3] [5 6]] [[0.81361409 0.18638591] [0.46066079 0.53933921] [0.56876484 0.43123516] [0.39281249 0.60718751] [0.75502283 0.24497717] [0.26495575 0.73504425] [0.35415558 0.64584442] [0.62834073 0.37165927] [0.61243835 0.38756165] [0.3007459 0.6992541 ] [0.42665468 0.57334532] [0.32375545 0.67624455]] 其,混淆矩阵的行表示真实标签,列表示预测标签,对角线上的值表示预测正确的样本数。预测概率的输出是一个二维数组,每一行表示一个测试样本的预测概率,第一列是属于类别0的概率,第二列是属于类别1的概率。