本文主要介绍交叉验证和网格搜索,以及如何利用在KNN近邻算法中。
交叉验证
什么是交叉验证?
简单来说交叉验证将训练数据集又分为训练数据集和验证数据集,通过确定折数,来决定将训练数据集分为几份。
训练集是可以看到的,但是验证集是不可见的,用来评估此次超参数构建模型的优劣。
什么是超参数?超参数就是需要在模型训练之前就指定好的参数。
在一些存在着超参数的机器学习算法中,需要找到最优超参数,比如在KNN算法中,邻居的个数K就是超参数。交叉验证目的是为了让被评估的模型更加准确可信。
比如在某次的KNN训练过程中,K的取值为1-10,要从中找到一个最优的超参数,构建一个最优的模型。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris # 假设使用鸢尾花数据集
# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target
# 设置K值的范围
k_values = list(range(1, 21)) # 选择1到20的K值范围
# 通过交叉验证评估每个K值的性能
for k in k_values:
knn = KNeighborsClassifier(n_neighbors=k)
scores = cross_val_score(knn, X, y, cv=5) # 使用5折交叉验证
print(f"K = {k}, Mean Accuracy: {scores.mean():.4f}")
通过不同K的取值,构建出不同的模型,比较这些模型在验证集中的表现,选出最优的作为最佳超参数。
但一般不同上述这种方式,而是利用封装好的网格搜索。
网格搜索
而网格搜索就是构建超参数网格:如不同的K值,利用不同的K值构造多个模型,利用网格搜索来找到最优模型。
交叉验证就是将训练集分为训练、验证集,多次训练,评估每一个模型的性能。网格搜索就是利用超参数的不同取值找到最优的超参数。它们两个通常在一起使用。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV, cross_val_score,train_test_split
from sklearn.datasets import load_iris
# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
param_grid = {
'n_neighbors': list(range(1, 21))
}
# 创建KNN模型
knn = KNeighborsClassifier()
# 创建GridSearchCV对象
grid_search = GridSearchCV(knn, param_grid, cv=5, scoring='accuracy')
# 在训练集上进行网格搜索和交叉验证
grid_search.fit(X_train, y_train)
# 输出最佳K值和对应的性能
print("Best K:", grid_search.best_params_)
print("Best Accuracy:", grid_search.best_score_)
网格搜索的API为:from sklearn.model_selection import GridSearchCV
他有四个重要的参数:
第一个参数:是采用什么训练器进行训练,上述代码采用KNN,故传入knn训练器。
第二个参数:param_grid,就是你构建的超参数网格
第三个参数:cv是交叉验证的折数,cv=5就代表五折,验证集占训练集其中的约五分之一。
第四个参数:采用什么评估方式来衡量各个模型之间的优劣,上述代码采用accuracy。
最优超参数为grid_search.best_params_,最高的准确率为grid_search.best_score_。
这里再强调一下验证集的事情,验证集不等于测试集,虽然它们二者都是对于模型不可见,但是验证集是包含在训练集中的,是采用交叉验证时对模型的评估和打分。而测试集是独立于训练集的,是在整个模型训练完毕后,最后的测试环节。