赞
踩
交叉验证法先将数据集D划分为k个大小相似的互斥子集,每个子集都尽可能保持数据分布的一致性,然后每次用k-1个子集的并集作为训练集,余下的那个子集作为测试集,这样可以获得k组训练和测试并返回k个测试结果。
以k=10为例的10折交叉验证,其训练集和测试集数据分布如下所示:
在寻找超参数的过程中,为了评判模型的最终性能,通常把数据集分为训练数据和测试数据,测试数据是完全不参与模型训练的独立数据,一般通过 sklearn 自带的 train_test_split 方法进行随机分配,测试数据占比20%为经验值,剩下的80%数据作为训练数据。
训练数据又细分为训练数据和验证数据,这两份数据都会参与到模型的训练,首先由训练数据训练出模型,然后通过验证数据对模型进行性能评判,从而找到最佳超参数。训练数据和验证数据分配存在随机性,容易出现过拟合的现象,即找到的最佳超参数在测试数据集中表现并不良好。为了加大训练次数,提高模型的稳定性,所以需要对数据进行多次分隔多次训练。即使用交叉验证的方法进行多次训练。
训练数据:参与模型训练
验证数据:参与模型训练,调整超参数使用的数据集
测试数据:不参与模型训练,作为衡量最终模型性能的数据集
利用 cross_val_score(knn_clf, X_train, y_train, cv=cv)方法将数据进行交叉分割并传入模型中进行训练,参数依次为:
knn_clf:待训练的模型
X_train:待分割的输入空间数据集
y_train:待分割的输出空间数据集
cv:分割份数k,也称为k折交叉验证
cross_val_score 方法返回k个元素的list集合,即k份数据训练了k次分别得到的k个模型评分,将这个list元素求平均,就得到当前超参数组合下模型的平均评分,次评分具备稳定性,减弱了数据随机性对模型评价的影响。
利用for循环构造了一堆超参数值,通过以上方法不断循环训练,得到每组超参数的平均模型评分,找到最佳得分和对应的超参数组合,则实现了交叉验证法寻找超参数的应用,
Fitting 5 folds for each of 60 candidates, totalling 300 fits
交叉验证,将数据分成5份,10+5*10=60个参数,共训练300次
找到最佳参数组合和模型性能评分为:
best_score=0.9666666666666668, best_weights=distance, best_k=5, best_p=4
- # -*- coding: UTF-8 -*-
- from sklearn import datasets
- from sklearn.model_selection import cross_val_score, GridSearchCV, train_test_split
- from sklearn.neighbors import KNeighborsClassifier
- import numpy as np
-
-
- def CrossValidationTest(X_train, y_train, cv):
- best_score, best_weights, best_k, best_p = 0, 0, 0, 0
- for k in range(1, 11):
- for p in range(1, 6):
- knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)
- scores = cross_val_score(knn_clf, X_train, y_train, cv=cv)
- score = np.mean(scores)
- if score > best_score:
- best_score, best_weights, best_k, best_p = score, "distance", k, p
- for p in range(1, 6):
- knn_clf = KNeighborsClassifier(weights="uniform", n_neighbors=k)
- scores = cross_val_score(knn_clf, X_train, y_train, cv=cv)
- score = np.mean(scores)
- if score > best_score:
- best_score, best_weights, best_k, best_p = score, "distance", k, "null"
- print("best_score={}, best_weights={}, best_k={}, best_p={}".format(best_score,best_weights, best_k, best_p))
-

GridSearchCV网格搜索超参数方法其源码就是使用了交叉验证方法,默认cv=5,下面通过使用上述同样的数据进行网格搜索超参数:
Fitting 5 folds for each of 60 candidates, totalling 300 fits
交叉验证,将数据分成5份,10+5*10=60个参数,共训练300次
找到最佳参数组合和模型性能评分为:
best_score = 0.9666666666666668, best_estimator={'n_neighbors': 5, 'p': 4, 'weights': 'distance'}
代码实现如下:
- def GridSearchTest(X_train, y_train,cv):
- """
- Fitting 5 folds for each of 60 candidates, totalling 300 fits
- 交叉验证,将数据分成5份,10+5*10=60个参数,共训练300次
- """
- param_grid = [
- {
- 'weights': ['uniform'], # 不考虑距离权重的模式
- 'n_neighbors': [i for i in range(1, 11)] # 邻近点的个数
- },
- {
- 'weights': ['distance'], # 考虑距离权重的模式
- 'n_neighbors': [i for i in range(1, 11)],
- 'p': [i for i in range(1, 6)] # 明可夫斯基距离参数 p = (0:曼哈顿距离, 1:欧拉距离)
- }
- ]
- knn_clf = KNeighborsClassifier() # 实例化 KNN 算法
- grid_search = GridSearchCV(knn_clf, param_grid, n_jobs=-1, verbose=2,cv=cv) # n_jobs=-1 最大并行训练
- grid_search.fit(X_train, y_train) # 针对训练数据进行最佳超参数搜索
- best_estimator = grid_search.best_params_ # 这就是最终得到的最佳参数
- best_score = grid_search.best_score_ # 使用上诉训练到的最佳参数得到的分类得分
- print("best_score = {}, best_estimator={}".format(best_score, best_estimator))
-
-
- if __name__ == '__main__':
- iris = datasets.load_iris()
- data = iris.data # 特征数据
- target = iris.target # 标签数据
- X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=666)
- CrossValidationTest(X_train, y_train,5)
- GridSearchTest(X_train, y_train,5)

本文通过讲述k折交叉验证的原理,并基于sklearn提供的方法进行交叉验证的应用,实现了KNN邻近模型的超参数寻找,并针对同样的数据集使用网格搜索的方法寻找超参数,试验证明两种方法得到的超参数组合和模型性能评分结果一致。通过源码可知悉,网格搜索的底层实现就是使用到了交叉验证方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。