机器学习 - 模型评估指标

176

(本系列的 Jupyter Notebook 可以到我的码云下载。)

概述

在机器学习中,针对一个任务通常会训练若干个模型,然后对这些模型进行评估,最后选出一个或几个最佳的模型投入实际应用环境中。那么如何评估训练后的模型呢?这就是本篇教程要说明的问题。

在评估一个模型时,通常都会用到几个评估指标:混淆矩阵、正确率、精确率和召回率、受试者工作特征曲线等,下面分别来看一下这些指标。

混淆矩阵

假设我们已经训练了一个用来判断一张图片是不是狗的模型,并且在测试集(包含 $10000$ 张图片,其中 $5123$ 张狗图,$4877$ 张非狗图)上进行了测试,结果如下:

  • 在 $5123$ 张狗图中,模型正确识别出了 $4863$ 张狗图,也就是说模型将 $5123 - 4863 = 260$ 张狗图错误地识别成了非狗图
  • 在 $4877$ 张非狗图中,模正确型识别出了 $4648$ 张非狗图,也就是模型将 $4877 - 4648 = 229$ 张非狗图错误地识别成了狗图

为了更清晰的表述结果,将结果用一个矩阵的形式画出来,其中行表示实际的分类(actual class),列表示预测的分类(predicted class):


\begin{pmatrix} 4863 & 260 \\ 229 & 4648 \tag{1} \end{pmatrix}

上面矩阵中,第一行表示实际的狗图($4863 + 260 = 5123$ 张),第二行表示实际的非狗图($229 + 4648 = 4877$ 张),而第一列表示模型预测的狗图($4863$ 张正确,$229$ 张错误),第二列表示模型预测的非狗图($260$ 张错误,$4648$ 张正确)。

上面的矩阵就叫做混淆矩阵(Confusion Matrix)。下面我们再来看几个概念:

我们用正类(positive class)表示是什么什么(用$1$表示),负类(negative class)表示不是什么什么(用$0$表示)。在本例中,用正类表示是狗图,用负类表示不是狗图。在混淆矩阵中,预测为正类,实际也为正类的样本称为真正(true positives, TP),预测为负类,但实际为正类的样本称为假负(false negatives, FN),预测为正类,但实际为负类的样本称为假正(false positives, FP),预测为负类,实际也是负类的样本称为真负(true negatives, TN)。

混淆矩阵

于是本例的混淆矩阵就变成了下面的样子:


\begin{pmatrix} TP=4863 & FN=260 \\ FP=229 & TN=4648 \tag{2} \end{pmatrix}

可以很容易地猜想到,最完美的模型应该是 FN 和 FP 都为 0,也就是下面这个样子:


\begin{pmatrix} TP=5123 & FN=0 \\ FP=0 & TN=4877 \tag{3} \end{pmatrix}

而最差的模型就是 TP 和 TN 都为 0, 也就是下面这个样子:


\begin{pmatrix} TP=0 & FN=5123 \\ FP=4877 & TN=0 \tag{4} \end{pmatrix}

而通常的模型介于最完美的模型和最差的模型之间,比如 $(2)$ 这个混淆矩阵。

从以上的分析也可以知道 TP 和 TN 越大,就说明模型越好,TP 和 TN 越小,则说明模型越差。而精确率和召回率就是衡量 TP 和 TN 的指标。

正确率

正确率(Accuracy)是最简单的指标,指的是对于给定的测试集,分类器正确分类的样本数量与总样本数量之比。其中正确分类的样本数量包括两部分:一部分是原本是正类,预测结果也是正类的样本数量,即 TP;另一部分是原本是负类,预测结果也是负类的样本数量,即 TN。用公式表示正确率如下:


$$ accuracy = \frac{TP + TN}{TP + FN + FP + TN} \tag{5} $$

精确率和召回率

精确率(Precision)表示预测为正类实际也为正类的样本数量占预测为正类的样本数量的百分比,公式如下:


$$ precision = \frac{TP}{TP + FP} \tag{6} $$

而召回率(Recall)表示预测为正类实际也为正类的样本数量占实际为正类的样本数量的百分比,公式如下:


$$ recall = \frac{TP}{TP + FN} \tag{7} $$

对于上面的例子而言,精确率就表示在预测的所有狗图当中,有多少图真的是狗图,而召回率表示模型从实际的狗图中,识别出了多少张。以下是本例中模型的精确率和召回率:


$$ precision = \frac{TP}{TP + FP} = \frac{4863}{4863 + 229} = 0.9550274941084053 \tag{8} $$

$$ recall = \frac{TP}{TP + FN} = \frac{4863}{4863 + 260} = 0.9492484872145227 \tag{9} $$

有时希望同时根据精确率和召回率评估一个模型,这就引入了 $F_1$ 分数:


$$ F_1 = \frac{2}{\frac{1}{precision}+\frac{1}{recall}} = \frac{TP}{TP+\frac{FN+FP}{2}} \tag{10} $$

可以看到 $F_1$ 就是精确率和召回率的调和平均数。

现在来分析一下 $F_1$ 分数,假设精确率和召回率都很高,例如,假设 $precision \rightarrow 1,$ $recall \rightarrow 1$,很容易计算这时 $F_1 = 1$,这样很好,$F_1$ 在精确率和召回率都很高的情况下表现不错。但是在其中一个值很低时会发生什么情况呢?假设 $precision \rightarrow 1,$ $recall \rightarrow 0$, 这时由于 $\frac{1}{recall} \rightarrow \infty $,因此 $F_1 \rightarrow 0$,到此 $F_1$ 的缺陷就暴露出来了,$F_1$ 会给分数较低者较大的权重,而给分数较高者较小的权重。也就是说只要有一个指标特别小,那么 $F_1$ 的值就非常小了(好像一个人拉低了整条街的人的智商一样 ^_^ )。最后,假设两个指标的值都很小,那么同样可以计算 $F_1$ 的值也很小。

总结一下:

  • $F_1$ 将给较少分数的指标更多的权重。
  • $F_1$ 在精确率和召回率相近(同高或同低)的情况下表现很好。

但是实际情况并不总是要求精确率和召回率同时高,比如在做超市监控录像时,为了抓取偷窃者,我们希望有更高的召回率,而不太关心精确率(宁可错杀,不可放过)。而在判断一个电影是否对孩子安全时,我们希望有更高的精确率,而不太关心召回率(要做就做对)。

阈值对精确率和召回率的影响

在分类器进行分类时,一般有一个决策函数(decision function),该函数针对每个样本实例计算一个得分,如果该得分值大于某个阈值(threshold),那么该分类器就认为这个样本实例为正类(positive),否则为负类(negative),比如下面的一些样本表示正在分类的样本,竖线表示阈值:


$$ 猫\ 兔\ 兔\ 猫\ 狗\ 猫\ 狗 \underbrace{\mid}_{threshold} 狗\ 猫\ 狗\ 狗\ 狗\ $$

现在可以计算出精确率为 $precision = 4/5 = 80\%$(因为在分类结果中,有4个是正确的,1个是错误的),而召回率为 $recall = 4 / 6 = 67\%$(因为总样本中有6只狗,分类器只识别出了4个)。

现在增加阈值到如下位置:


$$ 猫\ 兔\ 兔\ 猫\ 狗\ 猫\ 狗\ 狗\ 猫 \underbrace{\mid}_{threshold} 狗\ 狗\ 狗\ $$

可以计算出精确率为 $precision = 3/3 = 100\%$,而召回率为 $recall = 3/6 = 50\%$

而如果减少阈值到如下位置:


$$ 猫\ 兔\ 兔\ 猫 \underbrace{\mid}_{threshold} 狗\ 猫\ 狗\ 狗\ 猫\ 狗\ 狗\ 狗\ $$

则 $precision = 6/8 = 75\%$,而 $recall = 6/6 = 100\%$

由此可以总结出:调高阈值,则会增加精确率并降低召回率;调低阈值,则会降低精确率并提高召回率。但是没办法使精确率和召回率同时增加,在实际问题中,就要根据需要对阈值进行调整,比如要提高精确率,那么就要调高阈值,要提高召回率,就要调低阈值。

精确率和召回率曲线

可以将精确率和召回率随着阈值变化的曲线花在同一张图上,如下图(关于如何画这张图,很快就会讲到):

精确率和召回率曲线(1)

有了这张图就可以轻易地根据需要选择决策函数的阈值了。比如上面的例子,在判断一个电影是否对孩子安全时,需要尽可能提高精确率,而不在乎召回率时,这时可以将阈值设置为 50000 .

细心的读者可能已经发现,上图中的精确率曲线不是平滑上升的,在右上角有一段曲线是波动上升的,这是为什么呢?还是考虑狗和非狗的例子:

假设现在阈值在下图所示的位置:


$$ 猫\ 兔\ 兔\ 猫\ 狗\ 猫\ 狗\ \underbrace{\mid}_{threshold} 狗\ 猫\ 狗\ 狗\ 狗\ $$

可以计算出精确率和召回率分别为: $ precision = 80\% \quad recall = 67\% $

现在将阈值提高一个单位:


$$ 猫\ 兔\ 兔\ 猫\ 狗\ 猫\ 狗\ 狗 \underbrace{\mid}_{threshold} 猫\ 狗\ 狗\ 狗\ $$

可以计算出精确率和召回率分别为: $ precision = 75\% \quad recall = 50\% $

注意因为右边少了一只狗,所以精确率有所下降!

再将阈值提高一个单位:


$$ 猫\ 兔\ 兔\ 猫\ 狗\ 猫\ 狗\ 狗\ 猫 \underbrace{\mid}_{threshold} 狗\ 狗\ 狗\ $$

这时精确率和召回率分别为:$ precision = 100\% \quad recall = 50\% $

注意因为少了一只猫,所以精确率又上升了。

以上就是精确率曲线波动的原因。

那么为什么随着阈值的增加,召回率曲线是平滑下降的呢?这是因为随着阈值的增加,狗的预测数量($TP$)只会减少(或保持不变),而实际狗的总数($TP + FN$)不变。因此召回率($\frac{TP}{TP+FN}$)曲线是一个平滑的递减曲线。

有时也会忽略阈值,将精确率和召回率画在同一张图上:

精确率和召回率曲线(2)

这张图更清晰地标明了精确率和召回率的相互制约关系。

受试者特征曲线

受试者特征(receiver operating characteristic, ROC)曲线是另一种评估模型的工具,用来衡量真正类率与假正类率的关系。

真正类率(true positive rate, TPR)是召回率的另一种叫法,表示预测为正类且实际也为正类的样本的数量(即 TP)占实际的正类样本的数量(即 TP + FN)的百分比。真正类率也称为敏感性(Sensitivity)。计算公式为:


$$ TPR = \frac{TP}{TP+FN} \tag{11} $$

而假正类率(false positive rate, FPR)表示预测为正类但实际为负类的样本的数量(即 FP)占实际的负类样本的数量(即 FP + TN)的百分比。计算公式为:


$$ FPR = \frac{FP}{FP+TN} \tag{12} $$

还有另外的一个评估指标,真负类率(true negative rate, TNR)表示预测为负类且实际也为负类的样本的数量(即 TN)占实际的负类样本的数量(即 FP + TN)的百分比。真负类率也称为特异性(Specificity)。计算公式为:


$$ TPR = \frac{TN}{FP+TN} \tag{13} $$

显然:


$$ FPR + TPR = 1 \tag{14} $$

在没有画出 ROC 曲线之前,先来分析一下 TPR 和 FPR 的关系,更确切地说,来考虑一下增加 TPR 会对 FPR 造成什么影响呢? FPR 是增加、不变还是减少?还是来考虑狗与非狗的问题,假设当前的阈值如下:


$$ \underbrace{猫\ 兔\ 兔\ 猫\ 狗\ 猫\ 狗}_{negative} \underbrace{\mid}_{threshold} \underbrace{狗\ 猫\ 狗\ 狗\ 狗}_{positive} $$

这时,$ TPR = \frac{4}{6} = 67\% \quad FPR = \frac{1}{6} = 17\% $

为了提高 TPR,把阈值向左移动三个单位:


$$ \underbrace{猫\ 兔\ 兔\ 猫}_{negative} \underbrace{\mid}_{threshold} \underbrace{狗\ 猫\ 狗\ 狗\ 猫\ 狗\ 狗\ 狗}_{positive} $$

现在,$ TPR = \frac{6}{6} = 100\% \quad FPR = \frac{2}{6} = 33\%$

由此可以看出,为了达到更大的 TPR,必须将阈值左移,将更多的狗纳入 positive ,而在左移的过程中,不可避免地将非狗也纳入了 positive,造成 FPR 也变大。

下面就是 ROC 曲线(关于如何画这张图,很快就会讲到),可以看到随着 TPR 的增加,FPR 也在增加,这就验证了我们推测:

ROC曲线

注意上图左上角的拐点,FPR 会在大约 TPR 为 90% 的时候急速上涨。也就是说 FPR 达到了 90% 以后,要想再提高那就只能引入更多的负类。反过来说,如果要保证不引入更多负类的话,那么当前这个模型只能保证 90% 的 TPR。进一步,如果有一个模型可以在不引入更多负类的情况下,可以保证 95% 的 TPR,那么这个模型就是一个更好的模型。反应在图中,就是更好的模型的拐点会更接近左上角。更进一步的,如果一个分类器的 ROC 曲线拐点完全与左上角重合,那么这个分类器就是一个完美的分类器(FPR 达到 100%,而且完全不会引入负类)。根据图像很容易得到,一个完美的分类器的 ROC 曲线下方的面积 为 1 . 这个面积有一个专用术语,叫做ROC曲线下面积(area under the curve, AUC)。

另外,注意到中间的对角虚线,该条虚线表示一个分类器的分类结果完全是随机的。也就是说任何 TPR 的提升都会增加同样的 FPR(在上面的例子中,相当于增加了若干狗的数量到预测的正类中,同时也引入了同样多的非狗的数量)。这是最差的分类器,一个最差的分类器 AUC 为 0.5 .(当然较真的读者可能认为最差的分类器应该与右下角重合,也就是 AUC 为 0,如果真有这样的分类器,那也是很牛的,毕竟成千上万道二选一的选择题,总是选错也很难得 ^_^)

为了更清晰地阐述模型的评估指标,下面我们一起看一个例子,该例子用来分类钻石的价格。

示例:钻石价格分类

本例所用的数据可以在Kaggle官网下载,如果无法在官网下载,也可以点击这里在本站下载。该数据集收集了 53940 个钻石样本,每个样本实例都有价格(price)、克拉(carat)、切工等级(cut)、颜色等级(color)、净度(clarity)、长度(x)、宽度(y)、深度(z)、总深比(depth)、台面(table)等9个属性组成,详细的说明可以参考官网,这里引用如下:

Context

This classic dataset contains the prices and other attributes of almost 54,000 diamonds. It’s a great dataset for beginners learning to work with data analysis and visualization.

Content

price price in US dollars (\$326–\$18,823)
carat weight of the diamond (0.2–5.01)
cut quality of the cut (Fair, Good, Very Good, Premium, Ideal)
color diamond colour, from J (worst) to D (best)
clarity a measurement of how clear the diamond is (I1 (worst), SI2, SI1, VS2, VS1, VVS2, VVS1, IF (best))
x length in mm (0–10.74)
y width in mm (0–58.9)
z depth in mm (0–31.8)
depth total depth percentage = z / mean(x, y) = 2 * z / (x + y) (43–79)
table width of top of diamond relative to widest point (43–95)

我们将提取出价格作为标签,并根据其他特征判断一个钻石的价格是否大于 $10000 美元。

加载数据

当然第一步需要加载数据,因为数据集文件是 csv 格式的,为了方便起见,这里使用 pandas 来加载数据:

1
2
3
import pandas as pd

df = pd.read_csv('diamonds.csv', index_col=0)

注意 csv 文件的第一列为索引,因此这里指定 index_col=0 .

审查数据

加载数据之后,来看看数据是长什么样子的,好有个基本印象:

1
print(df.head())

打印结果如下:

1
2
3
4
5
6
   carat      cut color clarity  depth  table  price     x     y     z
1 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
2 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
3 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
4 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
5 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75

我们发现切工(cut)、颜色(color)以及净度(clarity)都是用字符串表示的类别类型,而在训练模型时,通常需要将这些类别类型转换为数字,以方便计算。为此,需要对这些数据做一些整理。

整理数据

使用如下的代码,将切工、颜色和净度转换为数值类型。

1
2
3
for attr in ('cut', 'color', 'clarity'):
df[attr] = df[attr].astype('category').cat.codes
print(df.head())

上面程序中 df[attr].astype('category') 将由字符串表示的类别类型转换为类别(category)类型,df[attr].astype('category').cat 则获取类别,df[attr].astype('category').cat.codes 就是获取类别编码(数字),最后,df[attr] = df[attr].astype('category').cat.codes 将获取的编码赋值给原数据,这样原数据就变成数值类型了。

打印结果如下:

1
2
3
4
5
6
   carat  cut  color  clarity  depth  table  price     x     y     z
1 0.23 2 1 3 61.5 55.0 326 3.95 3.98 2.43
2 0.21 3 1 2 59.8 61.0 326 3.89 3.84 2.31
3 0.23 1 1 4 56.9 65.0 327 4.05 4.07 2.31
4 0.29 3 5 5 62.4 58.0 334 4.20 4.23 2.63
5 0.31 1 6 3 63.3 58.0 335 4.34 4.35 2.75

可以看到所有类别都换成了数值。

准备数据

接下来就要准备模型需要的数据了,在这一步需要做两件事情:

  • 把数据的特征和标签分开,以方便训练
  • 数据归一化
  • 把数据集分成训练集和测试集

拆分数据

先将数据拆分成特征和标签。

由于要训练的是一个判断钻石是否大于 $\$10000$ 美元的二分类模型,因此我们将大于 $\$10000$ 美元的标签设置为 1,而小于等于的则设置为 0,这可以通过以下程序实现:

1
2
sr_target = df['price']
target = (sr_target.values > 10000).astype(int)

接着将价格列删除,从而得到特征数据:

1
2
df_data = df.drop(['price'], axis=1)
print(df_data.head())

输出如下:

1
2
3
4
5
6
   carat  cut  color  clarity  depth  table     x     y     z
1 0.23 2 1 3 61.5 55.0 3.95 3.98 2.43
2 0.21 3 1 2 59.8 61.0 3.89 3.84 2.31
3 0.23 1 1 4 56.9 65.0 4.05 4.07 2.31
4 0.29 3 5 5 62.4 58.0 4.20 4.23 2.63
5 0.31 1 6 3 63.3 58.0 4.34 4.35 2.75

归一化

接下来对特征数据进行归一化处理:

1
2
3
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
data = scaler.fit_transform(df_data)

准备训练集和测试集

为了保留一部分数据作为测试集来验证最后的模型,将数据集拆分为训练集和测试集,这里用 $80\%$ 的数据作为训练集,剩下 $20\%$ 的数据作为测试集,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

np.random.seed(42)

dataset_size = df.shape[0]
indices = np.random.permutation(dataset_size)

data_shuffled = data[indices]
target_shuffled = target[indices]

train_data_ratio = 0.8
train_data_size = int(dataset_size * train_data_ratio)

train_data = data_shuffled[:train_data_size]
train_target = target_shuffled[:train_data_size]
test_data = data_shuffled[train_data_size:]
test_target = target_shuffled[train_data_size:]

训练

sklearn 训练模型的套路都很相似,首先创建一个分类模型对象(或回归模型对象)并传递相应的参数,然后调用 fit() 就可以训练模型了。这里用的是一个随机梯度下降分类器(sklearn.linear_model.SGDClassifier)。关于梯度下降,我们将在以后的教程中讲解。

1
2
3
4
from sklearn.linear_model import SGDClassifier

sgd_clf = SGDClassifier(random_state=42, max_iter=10)
sgd_clf.fit(train_data, train_target)

评估模型

交叉验证

为了验证模型的正确率,使用 sklearn.model_selection.cross_val_score 来进行:

1
2
3
4
from sklearn.model_selection import cross_val_score

cv_scores = cross_val_score(sgd_clf, train_data, train_target, cv=3, scoring="accuracy")
print(cv_scores)

输出如下:

1
[0.96503059 0.96822859 0.9689238 ]

可以看到正确率还不错,达到了 96.5% 以上。

混淆矩阵

为了构造混淆矩阵,需要预测的结果,如何获取预测的结果呢?可以通过不带参数的 sklearn.model_selection.cross_val_predict 来获取:

1
2
3
from sklearn.model_selection import cross_val_predict

train_pred = cross_val_predict(sgd_clf, train_data, train_target, cv=3)

接下来,通过 sklearn.metrics.confusion_matrix 获取混淆矩阵:

1
2
3
4
from sklearn.metrics import confusion_matrix

conf_matrix = confusion_matrix(train_target, train_pred)
print(conf_matrix)

打印的结果如下:

1
2
[[38483   472]
[ 935 3262]]

精确率和召回率曲线

首先绘制带决策分数(即阈值的取值范围)的精确率和召回率曲线,为了获取决策分数,仍然使用 sklearn.model_selection.cross_val_predict 来获取,不同的是,这次传递 method="decision_function" 来获取决策函数返回的分数值。

1
scores_pred = cross_val_predict(sgd_clf, train_data, train_target, cv=3, method="decision_function")

得到了决策函数返回的分数,就可以根据不同分数来获取精确率、召回率和阈值了,这可以通过 sklearn.metrics.precision_recall_curve 来获得:

1
2
3
from sklearn.metrics import precision_recall_curve

precisions, recalls, thresholds = precision_recall_curve(train_target, scores_pred)

下面就可以根据精确率、召回率和阈值绘制曲线了:

1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib.pyplot as plt

def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
plt.plot(thresholds, precisions[:-1], "b--", label="Precision")
plt.plot(thresholds, recalls[:-1], "g-", label="Recall")
plt.xlabel("Thredshold")
plt.legend(loc="upper left", fontsize=18)
plt.ylim([0, 1])

plt.figure(figsize=(10, 6))
plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
plt.show()

带阈值的精确率和召回率

也可以绘制不带阈值的精确率和召回率曲线:

1
2
3
4
5
6
7
8
9
def plot_precision_vs_recall(precisions, recalls):
plt.plot(recalls, precisions, "b-", linewidth=2)
plt.xlabel("Recall", fontsize=16)
plt.ylabel("Precision", fontsize=16)
plt.axis([0, 1, 0, 1])

plt.figure(figsize=(10, 6))
plot_precision_vs_recall(precisions, recalls)
plt.show()

不带阈值的精确率和召回率曲线

ROC 曲线

绘制 ROC 曲线也很容易,首先需要计算 FPR 和 TPR,sklearn 提供了 sklearn.metrics.roc_curve 专门用于做这件事情:

1
2
3
from sklearn.metrics import roc_curve

fpr, tpr, thresholds = roc_curve(train_target, scores_pred)

有了 FPR 和 TPR,就可以绘制 ROC 了:

1
2
3
4
5
6
7
8
9
10
def plot_roc_curve(fpr, tpr, label=None):
plt.plot(fpr, tpr, linewidth=2, label=label)
plt.plot([0, 1], [0, 1], 'k--')
plt.axis([0, 1, 0, 1])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')

plt.figure(figsize=(8, 6))
plot_roc_curve(fpr, tpr)
plt.show()

ROC曲线

下面用随机深林(随机深林将在后面的教程中讲解)分类器再训练一次模型,并同样绘制 ROC 曲线:

1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.ensemble import RandomForestClassifier

forest_clf = RandomForestClassifier(random_state=42)
y_proba_forest = cross_val_predict(forest_clf, train_data, train_target, cv=3, method="predict_proba")
scores_forest = y_proba_forest[:, 1] # socre = proba of positive class
fpr_forest, tpr_forest, thresholds_forest = roc_curve(train_target, scores_forest)

plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, "b:", label="SGD")
plot_roc_curve(fpr_forest, tpr_forest, "Random Forest")
plt.legend(loc="lower right")
plt.show()

ROC曲线对比

可以看到随机深林分类器有着比随机梯度下降分类器更大的 AUC,因此更好。

测试模型

好了,是时候拿出测试数据集来测试我们的模型了,下面分别测试随机梯度下降分类器和随机深林分类器:

测试随机梯度下降分类器:

1
2
3
sgd_clf.fit(test_data, test_target)
accuracy = sgd_clf.score(test_data, test_target)
print("Test accuracy of SGD: ", accuracy)

输出为:

1
Test accuracy of SGD:  0.9683908045977011

测试随机深林分类器:

1
2
3
forest_clf.fit(test_data, test_target)
accuracy = forest_clf.score(test_data, test_target)
print("Test accuracy of Random Forest: ", accuracy)

输出为:

1
Test accuracy of Random Forest:  0.9978680014831294

可以看到随机梯度下降分类器的正确率达到了 96.8%,而随机深林分类器的正确率竟然达到了 99.7%!由此可见就本例而言随机深林分类器要比随机梯度下降分类器的效果更好。

总结

本篇教程我们讲解了一些模型评估的指标,包括混淆矩阵、正确率、精确率和召回率、受试者工作特征曲线等。在比较各个模型优劣的时候,都是很有用的工具。


感谢阅读!如果有任何疑问和建议,请在留言区留言!

版权声明:本文为原创文章,转载请注明出处。http://cynhard.com/2018/06/13/ML-Performance-Measures/

推荐文章