当前位置: > > > Python - 机器学习算法库Scikit-Leran使用详解12(模型参数调优、交叉验证)

Python - 机器学习算法库Scikit-Leran使用详解12(模型参数调优、交叉验证)

    机器学习方法(深度学习是机器学习中的一种)往往涉及很多参数甚至超参数,因此实践过程中需要对这些参数进行适当地选择和调整。本文将以 KNN 为例介绍模型参数调整的一些方法。

十三、模型参数调优、交叉验证

1,基本介绍

(1)对于 KNN 算法来说,k 就是需要调整的超参数。一般我们会采用称为 GridSearch 的穷举调参方法来寻找最合适的参数。即在所有候选的参数中,通过循环遍历,尝试每一种的可能性,表现最好的参数就是最终的结果。而选择哪些数据集进行调参,又分为如下几种方式:
  • 方式一:选择整个数据集进行测试。这种方法有一个非常明显的问题,那就是设定 k=1 总是最好的,因为每个测试样本的位置总是与整个训练集中的自己最接近。
  • 方式二:将整个数据集拆分成训练集和测试集,然后在测试集中选择合适的超参数。这里也会存在一个问题,那就是不清楚这样训练出来的算法模型对于接下来的新的测试数据的表现会如何。
  • 方法三:将整个数据集拆分成训练集、验证集和测试集,然后在验证集中选择合适的超参数,最后在测试集上进行测试。这个方法相对来说比之前两种方法好很多,也是在实践中经常使用的方法。
  • 方法四:使用交叉验证,将数据分成若干份,将其中的各份作为验证集之后给出平均准确率,最后将评估得到的合适的超参数在测试集中进行测试。这个方法更加严谨,但实践中常在较小的数据集上使用,在深度学习中很少使用。

(2)特别需要注意的是,不能使用测试集来进行调优。当我们在设计机器学习算法的时候,应该将测试集看作非常珍贵的资源,不到最后一步,绝不使用它。
原因:如果我们使用测试集来调优,即使算法看起来效果不错,但真正的危险在于在算法实际部署后,算法对测试集过拟合,也就是说在实际应用的时候,算法模型对于新的数据预测的准确率将会大大下降。从另一个角度来说,如果使用测试集来调优,那么实际上就是将测试集当作训练集,由测试集训练出来的算法再运行同样的测试集,性能看起来自然会很好,但其实是有一点自欺欺人了,实际部署起来,效果就会差很多。所以,到最终测试的时候再使用测试集,可以很好地近似度量你所设计的分类器的泛化性能。

2,演示样例

(1)下面我们以 Sklearn 自带的鸢尾花数据集进行 KNN 算法分类预测进行演示,通过交叉验证法选取最佳 K 值:
#导入 sklearn 提供的鸢尾花数据
from sklearn.datasets import load_iris
#导入 sklearn 提供的KNN分类算法
from sklearn.neighbors import KNeighborsClassifier
#导入skleran 提供的分割数据集的方法
from sklearn.model_selection import train_test_split
#导入skleran 提供的标准化缩放器
from sklearn.preprocessing import StandardScaler
#导入skleran 提供交叉验证方法
from sklearn.model_selection import cross_val_score
#导入pandas
import pandas as pd
  
#加载数据集
iris = load_iris()
#分割数据集训练集,测试集
x_train,x_test,y_train,y_test=train_test_split(iris['data'],iris['target'],random_state=0)

#创建标准化缩放器
standardscaler = StandardScaler() 
#训练标准化缩放器
standardscaler.fit(x_train)
#缩放训练集
x_train = standardscaler.transform(x_train) 
#缩放测试集
x_test = standardscaler.transform(x_test) 

#k的值一般选择1~20以内
k_range = range(1, 20)
#用来放每个模型的结果值
cv_scores = [] 

print("--- 开始进行交叉验证 ---")
#循环k值
for i in k_range:
    model=KNeighborsClassifier(n_neighbors=i)
    # cv=10 表示将全部样本划分成10个大小相等的样本子集;
    #     依次遍历这k个子集,每次把当前子集作为验证集,其余所有样本作为训练集,进行模型的训练和评估;
    # scoring='accuracy' accuracy表示评价指标是准确度
    scores = cross_val_score(model,x_train, y_train, cv=10, scoring='accuracy')
    cv_scores.append(scores.mean())
 
#画图,x轴为k值,y值为准确度
plt.plot(k_range, cv_scores)
plt.xlabel('Value of K in KNN')
plt.ylabel('Accuracy')
plt.show()
#找到最优的k值
k_best = cv_scores.index(max(cv_scores))+1
print("通过交叉验证最佳的k值为:",k_best, ",平均准确率为:",max(cv_scores))

print("--- 使用最佳k值构建模型 ---")
#使用最优的k值构建模型
model=KNeighborsClassifier(n_neighbors=k_best)
#训练模型
model.fit(x_train,y_train)
#训练后用测试集对模型进行评分
print("对测试集进行预测,模型评分:",model.score(x_test,y_test))

(2)运行结果如下:
评论0