首页 > sklearn 阅读数:32

scikit-learn调整参数训练和测试模型

我们在上几节教程学习了 sklearn 的介绍,测试、安装和使用,本节教程我们接着学习 sklearn 调整参数和测试模型。

1. 超参数与调参

在 sklearn 中,机器学习的模型一般都有超参数。所谓的超参数是指在模型开始学习过程之前人为预先定义的参数,而不是通过训练得到的参数数据。这些参数用于定义模型更高层次的概念,如模型复杂性、学习能力等。通过调整超参数来训练模型的过程称为调参。调参的目的是寻找最佳模型,使训练后的模型检测样本更精确。调参可以看作一个多元函数优化问题。

在机器学习中,与超参数对应的有模型参数,模型参数是指模型在学习过程中学习的参数。如 KNN 模型只有超参数,没有模型参数。KNN 模型中最常用的超参数是 n_neighbors,也称为 K 参数,K 参数表示是从训练集中找到和新数据最接近的 K 条记录。

调参就是寻找 K 取多少值时为最优值。寻找最优超参数的方法,一种是依靠经验取值,另一种是依靠实验确定,如通过交叉验证(cross_validation)来验证模型优劣。

2. K 折交叉验证

K 折交叉验证的过程如下:

① 首先将整个数据集分为训练集和测试集两个部分。

② 使用不重复抽样将训练集的数据随机分为 K 份。

③ 将 K-1 份数据用于模型训练,剩下那一份数据用于验证模型。

④ 重复第三步 K 次,并保证每重复一次所选择的验证集和训练集是不相同的。

⑤ 重复 K 次后将得到 K 个模型和它的评估结果。为了减小由于数据分割引入的误差,通常K折交叉验证要随机使用不同的划分方法重复p次,常见的有 10 次 10 折交叉验证。然后计算 K 折交叉验证结果的平均值,并将该平均值作为参数/模型的性能评估。

使用 K 折交叉验证一旦寻找到最优参数,就要使用这组参数在原始数据集上的训练模型作为最终的模型。

10 折交叉验证过程如图 1 所示。其中黑色方框表示验证集,白色方框表示训练集。

10折交叉验证过程示意图
图 1:10 折交叉验证过程示意图

在 sklearn 中,当模型训练完成后,可获得 Estimator 对象 clf,该对象是从训练数据学习中得到的。Estimator 对象的参数可以在训练前初始化,也可以在训练之后更新,使用 clf.get_params() 可返回 Estimator 对象之前定义的参数。

score() 可对 Estimator 对象进行评分,分类模型使用“准确率”评分(Accuracy),代码如下:

cross_val_score(clf, X_train, y_train, cv=10, scoring='accuracy')


回归模型使用“决定系数”评分(Coefficient of Determination),代码如下:

cross_val_score(clf, X_train, y_train, cv=10,scoring='neg_mean_squared_error')

3. 测试模型

模型训练完成后,可在测试集上进行预测。利用 .predict(X_test) 可返回测试样本的预测标签,而利用 .score(X_test,y_test) 可根据预测值和真实值计算评分。

【例 1】以 sklearn 自带的鸢尾花数据集 iris() 为例,选择 KNN 模型,调整超参数 K 值,用 10 折交叉验证判断 K 值为 1~25 时的最优值。

其示例代码 test1.py 如下。
# -*- coding: utf-8 -*-
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt

iris = datasets.load_iris()
X = iris.data
y = iris.target
#划分训练集和测试集,测试集占总数据的33%,随机种子为10
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.33,
                                                   random_state=10)
k_range = range(1, 26)
v_scores = []
for n in k_range:
    clf = KNeighborsClassifier(n)
    scores = cross_val_score(clf, X_train, y_train, cv=10,
                             scoring='accuracy')
    cv_scores.append(scores.mean())

plt.plot(k_range, cv_scores)
plt.xlabel('K')
plt.ylabel('Accuracy')
plt.show()

#选择最优的K
best_clf = KNeighborsClassifier(n_neighbors=5)
best_clf.fit(X_train, y_train)
print('参数',best_clf.get_params())
print('准确率',best_clf.score(X_test, y_test))
print('预测的值',best_clf.predict(X_test))

运行结果如图 2所示。从图中可见 K 为 5 时是最佳值。

10折交叉验证结果输出
图 2:10折交叉验证结果输出

选择最优的 K=5,在测试集中预测,输出结果如下。

参数{'algorithm': 'auto', 'leaf_size': 30, 'metric': 'minkowski', 'metric_params':
None, 'n_jobs': 1, 'n_neighbors': 5, 'p': 2, 'weights': 'uniform'}
准确率 0.96
预测的值 [1 2 0 1 0 1 2 1 0 1 1 2 1 0 0 2 1 0 0 0 2 2 2 0 1 0 1 1 1 2 1 1 2 2 2 0 2
2 2 2 0 0 1 0 1 0 1 2 2 2]