模型的重要参数:提供泛化性能的参数
网格搜索:尝试所有重要参数的可能组合
简单的网格搜索:将数据集划分为用于构建模型的训练集、用于选择模型参数的验证集/开发集、用于评估所选参数性能的测试集。使用嵌套循环对每种参数组合都训练一个训练集上模型,找到在验证集分数最高的那一组参数,最后经过测试集得到模型精度。
带交叉验证的网格搜索
带交叉验证的网格搜索:用交叉验证来评估每种参数组合的性能。
在SVM模型中使用交叉验证调参:
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
iris = load_iris()
# 用一个字典指定要搜索的参数,字典的值是要尝试的参数
param_grid = {'C':[0.001, 0.01, 0.1, 1, 10, 100], 'gamma':[0.001, 0.01, 0.1, 1, 10, 100]}
# 划分出测试集,防止过拟合
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=0)
# 一个估计器,使用交叉验证代替划分训练集和验证集
grid_search = GridSearchCV(SVC(), param_grid, cv=5)
grid_search.fit(x_train, y_train) # 对每一种参数组合都进行交叉验证并且自动拟合一个新模型
print(grid_search.score(x_test, y_test)) # 评估泛化能力。0.9736842105263158
GridSearchCV类以估计器的形式实现带交叉验证的网格搜索。需要传递(评估的模型,字典指定搜索的参数,交叉验证参数)。
实例化后的对象的行为类似分类器。可以调用fit、predict、score方法。拥有一些属性:best_params_属性保存找到的参数;best_score_属性保存交叉验证的最佳精度(平均精度,是不测试精度);best_estimator属性访问最佳参数对应的模型;cv_results属性用一个字典保存搜索的所有内容。
在非网格的空间中搜索
有一些参数可能不是每个模型都用的到。
在SVM模型中,kernel(内核)='linear’时,模型为线性,只需要c参数。扩展参数字典为列表,列表中的每个字典为一个独立的网格。
param_grid = [{'kernel':['rbf'],
'C':[0.001, 0.01, 0.1, 1, 10, 100],
'gamma':[0.001, 0.01, 0.1, 1, 10, 100]},
{'kernel':['linear'],
'C':[0.001, 0.01, 0.1, 1, 10, 100]}]
嵌套交叉验证划进行网格搜索
GridSearchCV仍使用单次划分为数据集和训练集,结果可能不稳定,会依赖于此次划分。
嵌套交叉验证:设置一个外循环,遍历将数据划分为训练集和测试集的所有划分,对每种划分都运行一次网格搜索。调用cross_val_score函数,返回值是由分数组成的列表。
from sklearn.model_selection import cross_val_score
scores = cross_val_score(GridSearchCV(SVC(), param_grid, cv=5),
iris.data, iris.target, cv=5)
print(scores) # [0.96666667 1. 0.9 0.96666667 1. ]
print(scores.mean()) # 0.9666666666666668
一共6* 6 * 5 * 5=900个模型。
改进
因为网格搜索构建大量模型,计算量可能很大,可以利用计算的并行,设置n_jobs参数增加使用的CPU内核数来提高速度。n_jobs=-1使用所有可用的内核。但是sklearn不允许并行操作的嵌套。如果使用的不是SVM而是随机森林,并且在模型中已使用n_jobs,将不能在GridSearchCV中使用它来搜索这个模型。