那么如何对模型进行评估,最终选择最合适的模型在呢?Scikit 库中,提供了测试集评分的方法。让我们看一个简单的例子。
#导入相关模块
In [1]: from sklearn.model_selection import train_test_split
...: from sklearn import datasets
...: from sklearn import neighbors
#导入相关数据,这里导入鸢尾花数据集
In [2]: iris = datasets.load_iris()
#查看数据集属性数据形状
In [3]: iris['data'].shape
Out[3]: (150, 4)
#查看数据集目标变量数据形状
In [4]: iris['target'].shape
Out[4]: (150,)
#将数据集分割为训练集和测试集,这里分割比例是4:1。
In [5]: X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target,
test_size=0.2, random_state=0)
#查看训练集数据
In [6]: X_train.shape
Out[6]: (120, 4)
#查看训练集数据
In [7]: y_train.shape
Out[7]: (120,)
#查看学习集数据
In [8]: X_test.shape
Out[8]: (30, 4)
#查看学习集数据
In [9]: y_test.shape
Out[9]: (30,)
#创建knn分类器对象
In [10]: knn = neighbors.KNeighborsClassifier(3)
#训练模型
In [11]: knn.fit(X_train, y_train)
Out[11]:
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=1, n_neighbors=3, p=2,
weights='uniform')
#对测试结果进行评分
In [12]: knn.score(X_test,y_test)
Out[12]: 0.9666666666666667
从以上结果看,该模型的得分不错。我们可以调整模型的参数,对每一次最后的得分进行比较,然后选择得分较高的参数模型作为最终结果。
但是,可能在某次实验上,测试集和训练集同时出现了过度拟合的情况,从而导致真实的应用过程中泛化能力降低的结果,如图 1 所示:
为了避免这种情况,我们需要设置一个验证集,当模型训练完成以后,先在验证集上对模型进行评估,然后选择评估分数最高的模型,再在测试集上进行最终的测试,如图 2 所示:
这是比较标准的模型评估过程,但是这并不是最优的办法。虽然验证集的设置可以有效避免测试集出现过度拟合的情况,但是现在元数据被分为 3 部分:训练集、验证集和测试集,训练集的数据量会大大减少,这可能造成训练模型的效果很差。另外,由于验证集和测试集是一次选择,所以最后的模型评估结果有很大的随机性。交叉验证(Cross-validation)很好地解决了上面两个问题,这在下一节会做详细介绍。