在机器学习领域,选择合适的超参数对于模型的性能至关重要。随机搜索和网格搜索是两种常用的超参数优化方法。本文将对比这两种方法在优化线性SVM模型的随机梯度下降(SGD)训练中的性能和效率。
随机搜索和网格搜索在参数空间的探索上是相同的,但它们的搜索策略和效率有所不同。随机搜索通过随机抽样来选择参数组合,而网格搜索则系统地遍历所有可能的参数组合。在本研究中,发现随机搜索的运行时间显著低于网格搜索,尽管其性能可能略有下降。这种性能差异可能是由于随机搜索中的噪声效应,但在实际应用中,这种差异通常不会影响模型在独立测试集上的表现。
在实际应用中,通常不会使用网格搜索同时探索如此多的参数,而是选择那些被认为最重要的参数进行搜索。例如,随机搜索在15个候选参数设置中仅用了1.25秒,而模型的排名和平均验证分数如下:
# 模型排名:1
平均验证分数:0.991(标准差:0.006)
参数:{'alpha': np.float64(0.05063247886572012), 'average': False, 'l1_ratio': np.float64(0.13822072286080167)}
# 模型排名:2
平均验证分数:0.987(标准差:0.014)
参数:{'alpha': np.float64(0.010877306503748912), 'average': True, 'l1_ratio': np.float64(0.9226260871125187)}
# 模型排名:3
平均验证分数:0.976(标准差:0.023)
参数:{'alpha': np.float64(0.727148206404819), 'average': False, 'l1_ratio': np.float64(0.25183501383331797)}
相比之下,网格搜索在60个候选参数设置中用了4.04秒,其模型排名和平均验证分数如下:
# 模型排名:1
平均验证分数:0.993(标准差:0.011)
参数:{'alpha': np.float64(0.1), 'average': False, 'l1_ratio': np.float64(0.1111111111111111)}
# 模型排名:2
平均验证分数:0.987(标准差:0.013)
参数:{'alpha': np.float64(0.01), 'average': False, 'l1_ratio': np.float64(0.5555555555555556)}
# 模型排名:3
平均验证分数:0.987(标准差:0.007)
参数:{'alpha': np.float64(0.01), 'average': False, 'l1_ratio': np.float64(0.0)}
在实验中,使用了scikit-learn库中的SGDClassifier,并设置了损失函数为“hinge”,惩罚项为“elasticnet”,同时启用了截距项。还定义了一个辅助函数来报告最佳分数,并指定了参数和分布以进行抽样。
随机搜索的实现代码如下:
from sklearn.model_selection import RandomizedSearchCV
# 其他导入...
param_dist = {
"average": [True, False],
"l1_ratio": stats.uniform(0, 1),
"alpha": stats.loguniform(1e-2, 1e0),
}
n_iter_search = 15
random_search = RandomizedSearchCV(clf, param_distributions=param_dist, n_iter=n_iter_search)
start = time()
random_search.fit(X, y)
print("RandomizedSearchCV took {:.2f} seconds for {} candidates parameter settings.".format((time() - start), n_iter_search))
report(random_search.cv_results_)
网格搜索的实现代码如下:
from sklearn.model_selection import GridSearchCV
# 其他导入...
param_grid = {
"average": [True, False],
"l1_ratio": np.linspace(0, 1, num=10),
"alpha": np.power(10, np.arange(-2, 1, dtype=float)),
}
grid_search = GridSearchCV(clf, param_grid=param_grid)
start = time()
grid_search.fit(X, y)
print("GridSearchCV took {:.2f} seconds for {} candidate parameter settings.".format(time() - start, len(grid_search.cv_results_["params"])))
report(grid_search.cv_results_)