目录
- 一、网格搜索
- 1、介绍
- 2、代码示例
- 二、HalvingGridSearch
- 1、介绍
- 2、代码示例
- 三、随机搜索
- 1、介绍
- 2、代码示例
- 三、贝叶斯搜索
- 1、介绍
- 2、代码示例
- 四、参数搜索总结
- 五、流形学习
- 1、LLE
- 1、介绍
- 2、官方代码示例
- 2、t-SNE
- 1、介绍
- 2、官方代码示例
一、网格搜索
1、介绍
网格搜索(grid search)是一种用来选择模型超参数的方法。它通过遍历超参数的所有可能组合来寻找最优的超参数。通常,网格搜索和交叉验证结合使用,以便在选择超参数时考虑模型的泛化能力。
如图,每个格子都是一组参数,使用交叉验证测试参数效果。但是效率低下。
2、代码示例
from sklearn.model_selection import GridSearchCV
param = {"n_estimators": np.arange(100,150,20), # 启,止,步长
"max_depth": np.arange(3,6,2),
"subsample": [0.8, 0.9],
"colsample_bytree": [0.8, 0.9]}
XGB = XGBClassifier()
grid_XGB = GridSearchCV(XGB, param, cv=3, n_jobs=-1)
grid_XGB.fit(Xtrain, Ytrain_spreading)
print("AUC: ", roc_auc_score(Ytest, grid_XGB.predict_proba(Xtest)[:, 1]))
grid_XGB.best_params_ #最优参数
grid_XGB.best_estimator_ # 最优学习器
二、HalvingGridSearch
1、介绍
HalvingGridSearchCV使用连续减半搜索策略来评估指定的参数值。搜索开始时,使用少量资源(默认为样本数量)评估所有候选参数组合,并在后续的迭代中逐步增加资源量,同时仅选择表现最佳的候选参数组合进行进一步的评估。
-
工作流程
- 初始化:从全数据集中无放回随机抽样出一个很小的子集(d0),并在该子集上验证全部参数组合的性能。
- 淘汰:根据d0上的验证结果,淘汰评分排在后一半的参数组合。
- 迭代:从全数据集中无放回抽样出一个比前一个子集大一倍的子集(如d1),并在该子集上验证剩余参数组合的性能。继续淘汰评分较低的参数组合。
- 循环:重复上述步骤,每次迭代都使用更大的数据集,直到备选参数组合只剩下1组或剩余可用数据不足为止
-
优点
- 加速搜索:由于HalvingGridSearchCV在开始时使用较小的数据集评估参数组合,并在后续迭代中逐渐增加数据量,因此能够显著减少计算量,加速搜索过程。
- 高效利用资源:通过逐步增加资源量并仅保留表现最佳的参数组合,HalvingGridSearchCV能够更高效地利用计算资源。
-
优点
- 数据集大小:HalvingGridSearchCV在处理大数据集时效果最佳。如果数据集本身较小,可能无法充分发挥其优势。
- 初始数据集选择:初始数据集(d0)的选择对最终结果有重要影响。为了确保结果的准确性,初始数据集应该尽可能反映整体数据的分布情况。
- 实验性特性:HalvingGridSearchCV是Scikit-Learn中的一个实验性特性,其预测和API可能会在没有任何弃用周期的情况下发生变化。因此,在使用时需要谨慎,并随时关注Scikit-Learn的更新
-
参数说明
estimator:评估器对象,实现了scikit-learn估计器接口。 param_grid:字典或字典列表,指定要搜索的参数空间。 factor:整数或浮点数,默认为3。表示每次后续迭代选择的候选者比例。例如,factor=3表示每次迭代仅保留评分最高的1/3候选者。 resource:字符串,指定用于调整资源分配的策略。默认为'n_samples',表示根据样本数量进行调整。 max_resources:整数或'auto',指定最大资源量。默认为'auto',表示使用完整数据集作为最大资源量
2、代码示例
from sklearn.experimental import enable_halving_search_cv # noqa
from sklearn.model_selection import HalvingGridSearchCV
param = {"n_estimators": np.arange(100,150,1), # 启,止,步长
"max_depth": np.arange(3,6,1),
"subsample": np.arange(0.5,1,0.1),
"colsample_bytree": np.arange(0.5,1,0.1)}
XGB = XGBClassifier()
Hal_XGB = HalvingGridSearchCV(XGB, param, factor=3, cv=3, verbose=1, n_jobs=-1) # 输出训练日志
Hal_XGB.fit(Xtrain, Ytrain_spreading)
print("AUC: ", roc_auc_score(Ytest, Hal_XGB.predict_proba(Xtest)[:, 1]))
Hal_XGB.best_params_ #最优参数
Hal_XGB.best_estimator_
三、随机搜索
1、介绍
随机搜索(random search)与网格搜索类似,但不是遍历所有可能的超参数组合,而是从超参数空间中随机采样一定数量的组合进行评估。随机搜索的优点是计算成本较低,且在高维超参空间中表现良好,缺点是可能无法找到全局最优解。可以搜索小数点后很多位的情况,而网格搜索和Halving Search均不行。
2、代码示例
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform
param = dict(n_estimators= np.arange(100,150,1), # 启,止,步长
max_depth= np.arange(3,6,1),
subsample= uniform(loc=0.5, scale=0.5), # 启,增加量,即搜索范围为0.5~1之间均匀分布的随机抽样
colsample_bytree= uniform(loc=0.5, scale=0.5))
XGB = XGBClassifier()
Rand_XGB = RandomizedSearchCV(XGB, param, cv=3, n_iter=50, verbose=1, n_jobs=-1)
Rand_XGB.fit(Xtrain, Ytrain_spreading)
print("AUC: ", roc_auc_score(Ytest, Rand_XGB.predict_proba(Xtest)[:, 1]))
Rand_XGB.best_params_ #最优参数
Rand_XGB.best_estimator_
为防止抽样时遗漏最优解,可增加采样次数,根据大数定律,抽样次数足够多时,肯定会找到最优解。
三、贝叶斯搜索
1、介绍
- 贝叶斯优化上一种全局优化方法,用于寻找黑盒函数的全局最优解,它通过构建一个概率模型来描述目标函数,并使用这个模型来指导下一步的采样点选择。
- 贝叶斯优化的核心思想上利用贝叶斯定理来更新对目标函数的先验知识。在每一步迭代中,它都会选择一个新的采样点,并使用这个采样点的观测值来更新概率模型。然后它使用一个获取函数来缺点下一个采样点,以便在探索和利用之间取得平衡。贝叶斯优化常用于机器学习的超参数选择,因为它能够在较少的迭代次数内找到全局最优解,并对噪声数据有很好的容错性。
优点: - 贝叶斯调参采用高斯过程,考虑之前的参数信息,不断更新先验
- 迭代次数少,速度快
- 针对凸问题依然稳健
2、代码示例
import optuna
def objective(trial):
param = {
'lambda_l2': trial.suggest_float('lambda_l2', 0.01, 10.0),
'num_leaves': trial.suggest_int('num_leaves', 2, 256),
'feature_fraction': trial.suggest_float('feature_fraction', 0.4, 1.0),
'bagging_fraction': trial.suggest_float('bagging_fraction', 0.4, 1.0),
}
model = lightgbm.train(params= param, train_set= train, valid_sets= test) # 建模
AUC= roc_auc_score(Ytest, model.predict(Xtest)) # matric
return AUC
lgb_opt = optuna.create_study(direction='maximize')
lgb_opt.optimize(objective, n_trials=100) # 100次迭代
# 打印结果
lgb_opt.best_params
lgb_opt.best_value
四、参数搜索总结
理论上random search可以更快地将整个参数空间都覆盖到,而不是像grid search一样从局部一点点去搜索。但是grid search和random search,都属于无先验式的搜索,有些地方称之为uninformed search(盲目搜索),即每一步的搜索都不考虑已经探索的点的情况,这也是grid/random search的主要问题,都是“偷懒式搜索”,闭眼乱找一通。
而贝叶斯优化,则是一种informed search(启发式搜索),会利用签名已经搜索过的参数的表现,来推测下一步怎么走会比较好,从而减少搜索空间,提高搜索效率。某种意义上贝叶斯优化和人工调参比较像,因为人工调参也会根据已有的结果及经验来判断下一步如何调参。
五、流形学习
Manifold learning(流形学习)是一种高级的机器学习技术,主要用于非线性降维。其核心思想是识别和利用数据中潜在的低维结构,这种结构被认为是嵌入在高维空间中的流形(manifold)。
Manifold learning通过探索数据的内在几何和拓扑结构,揭示数据之间复杂的关系。适用于多种类型的数据的降维,尤其是那些线性方法难以处理的复杂数据集。
常用的Manifold learning方法有:LLE(Local Linear Embedding)和 t-SNE(t-Distributed Stochastic Neighbor Embedding)
1、LLE
1、介绍
LLE(Local Linear Embedding)LLE的工作原理可以分为三个主要步骤:
-
邻域选择:对于每个数据点,LLE首先找到其在高维空间中的最近邻。这些邻域可以通过固定的“邻域大小”(即固定数量的最近邻)或固定的“半径”(即距离范围内的所有邻居)来确定。
-
局部重建权重计算:LLE的核心假设是每个数据点都可以由其邻域内的其他点的线性组合来近似表示。因此,算法计算一组权重,这些权重最好地重建每个点作为其邻居的线性组合。具体地,LLE最小化每个点和它的重建之间的均方差,以找到最佳的重建权重。
-
嵌入到低维空间:在获得重建权重之后,LLE将数据映射到低维空间,同时尽量保持原有的重建权重。这意味着每个点在低维空间中的位置是由它在高维空间中的邻居的位置决定的。通过最小化重建误差,LLE寻找一个低维表示,其中每个点仍然尽可能接近于其高维邻居的线性组合。
优点:与其他降维方法相比,LLE不需要过多的参数调整。最主要的参数是邻域的大小。
缺点:LLE对邻域大小的选择相对敏感,不同的选择可能导致完全不同的降维结果。并且LLE有时可能陷入局部最优解,特别是在降维到非常低的维度时。
2、官方代码示例
import matplotlib.pyplot as plt
from sklearn import datasets, manifold
sr_points, sr_color = datasets.make_swiss_roll(n_samples=1500, random_state=0)
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection="3d")
fig.add_axes(ax)
ax.scatter(
sr_points[:, 0], sr_points[:, 1], sr_points[:, 2], c=sr_color, s=50, alpha=0.8
)
ax.set_title("Swiss Roll in Ambient Space")
ax.view_init(azim=-66, elev=12)
_ = ax.text2D(0.8, 0.05, s="n_samples=1500", transform=ax.transAxes)
sr_lle, sr_err = manifold.locally_linear_embedding(
sr_points, n_neighbors=12, n_components=2
)
sr_tsne = manifold.TSNE(n_components=2, perplexity=40, random_state=0).fit_transform(
sr_points
)
fig, axs = plt.subplots(figsize=(8, 8), nrows=2)
axs[0].scatter(sr_lle[:, 0], sr_lle[:, 1], c=sr_color)
axs[0].set_title("LLE Embedding of Swiss Roll")
axs[1].scatter(sr_tsne[:, 0], sr_tsne[:, 1], c=sr_color)
_ = axs[1].set_title("t-SNE Embedding of Swiss Roll")
2、t-SNE
1、介绍
t-SNE(t-Distributed Stochastic Neighbor Embedding)t-SNE的工作原理可以分为三个主要步骤:
-
高维空间中的相似性:t-SNE首先在高维空间中计算每一对数据点之间的相似性。这种相似性通常通过高斯分布(正态分布)来建模,并且是基于欧几里得距离的。对于每一个点 x i x_i xi,我们计算它和其他所有点 x j x_j xj之间的条件概率 P j ∣ i P_{j|i} Pj∣i,这个概率反映了点 x j x_j xj被选择为 x i x_i xi的邻居的可能性。
-
低维空间中的相似性:然后,t-SNE在低维空间中为每个数据点创建一个对应点,并计算低维空间中点之间的相似性。在低维空间中,相似性通过t分布来计算,这有助于解决高维空间中的“拥挤问题”(crowding problem)。
-
最小化Kullback-Leibler(KL)散度:t-SNE的目标是使高维空间和低维空间中的相似性尽可能接近。这通过最小化KL散度来实现,KL散度是一种度量两个概率分布差异的方法。通过优化过程,t-SNE调整低维空间中的点,使得KL散度最小化。
优点:t-SNE通常会在低维表示中形成不同的簇,这些簇可以揭示数据中的固有分组。因此在大多数真实数据中,t_SNE的表现是最好的。
缺点:t-SNE对邻域大小(参数名为“困惑度”)的选择非常敏感,它会直接影响局部与全局结构的平衡。
2、官方代码示例
sh_points, sh_color = datasets.make_swiss_roll(
n_samples=1500, hole=True, random_state=0
)
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection="3d")
fig.add_axes(ax)
ax.scatter(
sh_points[:, 0], sh_points[:, 1], sh_points[:, 2], c=sh_color, s=50, alpha=0.8
)
ax.set_title("Swiss-Hole in Ambient Space")
ax.view_init(azim=-66, elev=12)
_ = ax.text2D(0.8, 0.05, s="n_samples=1500", transform=ax.transAxes)
sh_lle, sh_err = manifold.locally_linear_embedding(
sh_points, n_neighbors=12, n_components=2
)
sh_tsne = manifold.TSNE(
n_components=2, perplexity=40, init="random", random_state=0
).fit_transform(sh_points)
fig, axs = plt.subplots(figsize=(8, 8), nrows=2)
axs[0].scatter(sh_lle[:, 0], sh_lle[:, 1], c=sh_color)
axs[0].set_title("LLE Embedding of Swiss-Hole")
axs[1].scatter(sh_tsne[:, 0], sh_tsne[:, 1], c=sh_color)
_ = axs[1].set_title("t-SNE Embedding of Swiss-Hole")