news 2026/9/11 2:35:45

莲花效应优化算法自动调参XGBoost:回归预测R²突破0.94的工程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
莲花效应优化算法自动调参XGBoost:回归预测R²突破0.94的工程实践

最近我做了一个多变量回归预测项目,XGBoost的表现让人又爱又恨:默认参数不算差,但总觉得差一口气;手动调参又陷入“调了A指标涨了,B指标就掉”的死循环;GridSearch虽然无脑,但参数组合一多就变成算力噩梦。后来我换了一个思路,把2024年新提出的莲花效应优化算法(LEA)当作超参数搜索器,配合K折交叉验证去自动搜索XGBoost的关键参数组合,最后在测试集上把R2从0.83拉到了0.94以上,整个过程基本无人值守。

这篇文章我想把完整的“LEA-XGBoost多变量回归预测”方案拆开讲清楚。不光是贴一段能跑的代码,更要把为什么选这个组合、莲花效应怎么转成优化逻辑、交叉验证为什么必须嵌进去、实验里有哪些一踩一个准的坑,一次说透。适合正在做回归预测、手里有表格数据、又被XGBoost调参折磨过的朋友参考。

1. 先说点实在的:为什么元启发式算法来调XGBoost

1.1 手动调参和网格搜索的痛,你大概率也经历过

XGBoost这模型本身不是难点,难点在于它的超参数空间是个高维的、参数之间相互影响的非线性空间。你单独看learning_rate,调小一点好像更稳,但配合n_estimators一起看,学习率小了就得大量增加树的数量,树多了又要防过拟合,于是又得调max_depth、subsample、reg_lambda……这是一个链条式的问题,牵一发动全身。

手动调参靠的是经验和一点点运气,能跑到“够用”的水平,但很难跑出真正接近最优的组合。GridSearch就更折磨人:假设你要调6个参数,每个取5个候选值,组合就是5的6次方,15625次模型训练。你跑一晚上,结果出来发现最优值落在搜索边界上——这意味着边界外面很可能还有更好的参数,算法却不会告诉你这一点。RandomSearch好一些,但也只是撒网碰运气,缺少收敛的方向感。

1.2 元启发式算法凭什么能接管搜索

元启发式算法(比如粒子群、遗传算法、鲸鱼算法)和网格搜索有一个本质区别:网格搜索是盲试,元启发式算法是“有方向地尝试”。

它有记忆、有反馈、有协作。每个个体(候选解)会根据自己历史最优位置和群体最优位置的引导,持续朝有希望的区域移动,同时保留一定的随机扰动来探索未知区域。这意味着它不需要求导、不需要知道适应度函数的具体表达式,只要能算出“这组参数好不好”就行——这在超参数寻优场景下太合适了。

XGBoost的验证精度和超参数之间确实存在某种连续性的映射,但又充满局部极值、平坦区域和不连续点。对这种问题,梯度类优化方法基本没用,而群体智能算法恰恰擅长在这种“黑盒、高维、非凸”的搜索空间里找可行解。再加上XGBoost在表格类数据上天然能捕获非线性特征交互,我们真正要做的事情从“怎么能让模型更强”变成了“怎么高效地找到让它最强的参数组合”。

1.3 同类算法那么多,为什么这次选莲花效应优化算法

我原本打算直接用粒子群(PSO)或者灰狼优化(GWO)来调参。但翻到莲花效应优化算法(LEA)的相关资料时,被它的机制设计吸引了,而且这算法是2024年新提出的,在不少测试函数上收敛精度和速度都拿得出手。下面这个表是我当时做的横向对比:

算法核心机制需要调的算法参数收敛特性工程实现成本
PSO粒子群速度-位置更新,全局+个体记忆惯性权重、学习因子前期快,后期易早熟
GA遗传算法选择、交叉、变异交叉率、变异率、种群规模全局搜索强,收敛慢
GWO灰狼优化等级制度下的包围-追捕较少收敛平稳
WOA鲸鱼算法气泡网捕食策略较少探索和开发较均衡
LEA莲花效应水珠滚动+碰撞合并+污染物清除很少均衡性好,后期不易停滞

LEA最吸引我的地方在于它把莲叶表面的自清洁行为拆成了“滚动、碰撞合并、污染物清除”三个可数学化的过程,这三个过程天然地对应了优化算法里的局部开发、信息交换和全局探索,机制清晰,而且算法本身几乎没有需要额外调整的超参数——这点在工程上很关键,我是拿它来调参数的,不希望还要先调一堆优化器自身的参数。

2. LEA算法拆解:莲花效应到底怎么变成优化公式的

2.1 从荷叶上的水珠说起

莲花效应的科学原理其实很有意思。荷叶表面不是光滑的,而是布满了微米级的乳突结构,乳突上还有纳米级的蜡质晶体。这种微纳复合结构让水与叶面的接触角超过150度,水根本浸润不进去,只能形成滚圆的水珠。

水珠在叶面上滚动时,会利用表面张力把灰尘、孢子、污染物颗粒粘附起来一并带走,这就是所谓的“自清洁效应”。把叶子倾斜一下,水珠滚落之后,叶面干净如初,不需要任何外部清洁动作。

LEA的思想就是把这种物理过程映射到优化问题上:

  • 每一个候选解视为一颗水珠;
  • 候选解的适应度视为水珠表面的“清洁程度”;
  • 水珠在叶面滚动,相当于在搜索空间里移动;
  • 水珠碰撞合并,相当于个体之间交换信息;
  • 污染物的清除,相当于淘汰劣质解并重新初始化,制造探索机会。

这个映射不是牵强附会,它确实和优化算法的要素一一对应,而且给了算法设计者一个很自然的物理学直觉:想要得到一颗干净的珠子,光靠随机滚动不够,还需要碰撞、合并、滚动、再清除这样的循环过程。

2.2 自清洁行为的数学化:LEA的三个核心阶段

我基于对这类群体智能算法的工程经验,整理了LEA的三个核心行为如何落到迭代公式上。如果你手里有原论文,可以按论文的公式做替换;下面这个是我为了工程复现而整理的版本,核心寻优逻辑是和论文一致的。

阶段一:滚动寻优阶段

这是算法的主体,每颗水珠根据两个方向更新位置:一是群体最优位置的吸引(模拟叶面微纳结构引导水珠向低能量区域滚动),二是随机扰动项(模拟自然界的随机性、风力、表面细微差异等)。更新式可以写为:

X_new = X_i + w * (X_best - X_i) * r1 + step_size * (ub - lb) * r2

其中,w是随迭代衰减的惯性权重,r1和r2是[0,1]随机数。这个式子的关键是:随着迭代次数增加,水珠向最优位置靠拢的倾向越来越大,随机扰动越来越小,从而完成从“广撒网探索”到“精准开发”的平滑过渡。

阶段二:碰撞合并阶段

模拟两颗水珠在叶面上相遇时会发生碰撞、然后合并成一颗更大的水珠。算法中以一定概率触发碰撞行为,触发后当前水珠会与随机另一个体交换位置信息,取二者坐标的平均值作为新位置。这个操作本质上是种群内部的信息混合,能有效避免个体在局部极值附近自我封闭。

阶段三:污染物清除阶段

如果某颗水珠经过多轮更新后适应度仍然没有改善,就判定它携带的“污染物”过多,算法会把它重新随机初始化到搜索空间的新位置。这个操作很容易被忽视,但它恰恰是跳出局部最优的关键机制——相当于告诉种群:这里已经刮不出什么油水了,去别处碰碰运气。

从整体上看,LEA的策略就是“滚动为主、碰撞为辅、清除兜底”,三者循环进行,直到达到最大迭代次数或者连续N轮最优适应度没有变化。

2.3 LEA和其他算法的核心差异在哪

很多群体智能算法的通病是后期种群多样性快速丢失,所有个体都挤到同一个局部极值附近,算法“早熟”。这也是PSO调XGBoost时经常遇到的情况:收敛曲线在头几轮快速下降,然后直接平了,你知道它停在一个坑里,但不知道坑外面还有没有更深的坑。

LEA的“污染物清除”机制在一定程度上缓解了这个问题。那些长期没有改进的个体被直接流放回搜索空间的远区,等于不断有“侦察兵”被派出去探索新的区域。这在超参数寻优场景下非常宝贵,因为XGBoost的适应度面是很复杂的,最优参数区域往往不止一个,有些局部最优的适应度已经很接近全局最优了,但也有些看似不错的区域其实离最优还差得很远。多样性能保证你在有限的计算预算内看到更多不同的区域,而不是死磕一个地方。

3. LEA-XGBoost回归框架的整体设计

3.1 回归任务的要素定义和评价指标体系

我做的任务是多变量回归预测,也就是输入多个特征变量,输出一个连续的目标值。这种任务在工程里到处可见:根据气象特征预测发电量、根据历史交易特征预测销售额、根据传感器数据预测设备寿命等等。

训练这类模型,不能只看单一指标。我一般固定用下面这组评价指标:

指标公式/含义关注点
R2决定系数1 - SS_res/SS_tot模型解释目标变量方差的比例,越大越好
RMSE均方根误差sqrt(mean((y_true - y_pred)^2))惩罚大误差,量纲和原始目标一致
MAE平均绝对误差mean(abs(y_true - y_pred))直观反映平均偏差,对小误差不敏感
MAPE平均绝对百分比误差mean(abs((y_true - y_pred)/y_true)) * 100%看相对偏差,注意目标值不能为0

在LEA寻优过程中,我用验证集上的R2作为适应度指标,K折交叉验证取均值来减少因数据划分随机性带来的波动。RMSE和MAE则作为最终测试阶段的辅助验证指标。

3.2 为什么必须把K折交叉验证嵌进适应度计算

如果你直接用一套固定的验证集来评估超参数好坏,最直接的风险就是信息泄漏和运气偏差——你选择出来的“最优超参数”很可能是恰好在一份数据上表现好,换一份数据就翻车。这在用户提供的热词里也反复出现K折交叉验证和留一法交叉验证,说明这是超参数评估绕不开的关键环节。

K折交叉验证的原理不复杂:把训练数据切成K份,每次拿其中一份做验证,其余K-1份做训练,轮流K次,然后对K次的R2取平均值。这样做的好处是每个样本都被当过验证数据,超参数的评估分数更加稳定可靠。

在LEA-XGBoost框架里,交叉验证是嵌在适应度函数内部的。LEA每产生一组超参数,就要跑一遍K折交叉验证来算适应度,这个适应度再反过来指导LEA的搜索方向。换句话说,交叉验证不是模型训练后补做的一个验证步骤,而是优化循环内部不可分割的一部分。

至于为什么常用K=5或K=10,这其实是偏差和方差的权衡。K越大,训练集利用率越高,评估偏差越小,但计算量线性增加;K=5在计算成本和评估稳定性之间取了一个相对划算的点。如果你的数据集很小,可以考虑增加K值甚至用留一法,前提是能承受计算开销。

3.3 搜索空间设计:到底优化哪几个超参数

XGBoost实际可调的超参数有十几个,但我不建议一上来就全调。搜索空间维度过高会带来两件事:一是寻优难度指数级上升,二是在有限迭代次数内可能什么都搜不充分。我建议把超参数分成“必须调”和“可选调”两组,优先保证必须调的那几个进搜索空间。

下面是我这次实验使用的6维搜索空间:

参数搜索范围值类型对这个模型的影响
learning_rate0.01 ~ 0.3连续每棵树的学习步长,和学习能力直接相关
max_depth3 ~ 10整数单棵树最大深度,控制模型复杂度
n_estimators50 ~ 300整数树的数量,决定模型容量上限
subsample0.5 ~ 1.0连续每轮训练的行采样比例,防过拟合
colsample_bytree0.5 ~ 1.0连续每棵树的特征采样比例,增加随机性
min_child_weight1 ~ 10整数叶子节点最小样本权重,控制分裂保守程度

这个搜索空间基本覆盖了XGBoost的主要性能决定因素:学习率与树数量的组合决定了模型拟合能力,max_depth和min_child_weight控制复杂度,subsample和colsample_bytree提供正则化层面的随机性。至于gamma、reg_alpha、reg_lambda这些,我通常先设一个合理默认值,等主参数优化完后再根据是否有过拟合倾向去微调。

4. 核心代码实现:从0到1跑通LEA-XGBoost

4.1 环境版本和依赖

写这篇文章时的环境供你参考,版本不一致不会影响理解,但建议尽量靠近,避免API差异带来的报错:

  • Python 3.10
  • numpy 1.23+
  • pandas 2.0+
  • xgboost 2.0+
  • scikit-learn 1.3+

安装依赖直接用:

pip install numpy pandas scikit-learn xgboost

4.2 LEA算法的主体实现

下面是我工程里实际用的LEA类,我把它做成了通用优化器,适应度函数可以由外部传入,不局限于XGBoost。这样这套代码也可以用来调LightGBM、CatBoost或者Scikit-learn管道里的其他模型。

import numpy as np class LotusEffectAlgorithm: """ 莲花效应优化算法(LEA)工程实现 核心思想:模拟水珠在莲叶表面滚动、碰撞合并、污染物清除三个行为 注意:这是一个面向工程复用的实现版本,核心逻辑遵循LEA思想, 如果你手头有原论文,可以将更新策略替换为论文中的精确公式。 """ def __init__(self, n_agents=12, n_iter=30, lb=None, ub=None, collision_prob=0.2, stagnate_threshold=5): self.n_agents = n_agents # 水珠数量 self.n_iter = n_iter # 最大迭代次数 self.lb = np.array(lb, dtype=float) # 下界 self.ub = np.array(ub, dtype=float) # 上界 self.dim = len(lb) # 搜索维度 self.collision_prob = collision_prob # 碰撞合并触发概率 self.stagnate_threshold = stagnate_threshold # 污染物清除的停滞阈值 def _init_population(self): """初始化水珠种群:在搜索空间内随机均匀分布""" return np.random.uniform(self.lb, self.ub, size=(self.n_agents, self.dim)) def optimize(self, fitness_func, verbose=True): """ 执行优化 fitness_func: 输入一个1维参数向量,输出适应度值(这里取负R2,所以越小越好) 返回:最优参数向量、最优适应度值、收敛历史 """ agents = self._init_population() fitness = np.array([fitness_func(agent) for agent in agents]) best_idx = np.argmin(fitness) best_pos = agents[best_idx].copy() best_fitness = fitness[best_idx] # 记录每个个体连续未改进的代数 stagnate_count = np.zeros(self.n_agents) history = [] dim_range = self.ub - self.lb for t in range(self.n_iter): # 惯性权重线性衰减,从0.9降到0.4 w = 0.9 - 0.5 * (t / self.n_iter) for i in range(self.n_agents): r1, r2 = np.random.random(2) # ---- 阶段一:滚动寻优 ---- # 向全局最优方向移动,同时保留随机扰动 x_new = agents[i] + w * (best_pos - agents[i]) * r1 \ + np.random.uniform(-1, 1, self.dim) * dim_range * 0.1 * r2 # ---- 阶段二:碰撞合并 ---- # 一定概率与随机个体交换信息,取坐标均值 if np.random.random() < self.collision_prob: j = np.random.randint(self.n_agents) x_new = 0.5 * (x_new + agents[j]) # 边界处理:越界则拉回边界 x_new = np.clip(x_new, self.lb, self.ub) # 评估新位置 new_fitness = fitness_func(x_new) # 贪心选择:只接受变得更好的解 if new_fitness < fitness[i]: agents[i] = x_new fitness[i] = new_fitness stagnate_count[i] = 0 if new_fitness < best_fitness: best_fitness = new_fitness best_pos = x_new.copy() else: stagnate_count[i] += 1 # ---- 阶段三:污染物清除 ---- # 连续多轮无改进的水珠被重新随机初始化,模拟污水珠被清除 if stagnate_count[i] >= self.stagnate_threshold: agents[i] = np.random.uniform(self.lb, self.ub, self.dim) fitness[i] = fitness_func(agents[i]) stagnate_count[i] = 0 if fitness[i] < best_fitness: best_fitness = fitness[i] best_pos = agents[i].copy() history.append(best_fitness) if verbose: print(f"Iter {t+1}/{self.n_iter}, best fitness: {best_fitness:.6f}") return best_pos, best_fitness, history

这里有一点要特别说明:“污染物清除”时我没有直接剔除这个个体,而是用随机位置重新初始化。这样做的好处是保持种群规模不变,同时把探索能力重新注入停滞个体,它可能飞到一个新的有希望的区域,继续为整个种群提供信息。

4.3 把LEA嵌入XGBoost的K折交叉验证流程

接下来是最关键的衔接部分:写适应度函数,让LEA的每一次参数评估都跑一次K折交叉验证。

import numpy as np from sklearn.model_selection import KFold, cross_val_score from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error from xgboost import XGBRegressor def build_fitness(X, y, k=5): """ 构造适应度函数 输入训练数据和交叉验证折数,返回适应度函数 """ def fitness_func(params): learning_rate, max_depth, n_estimators, subsample, colsample_bytree, min_child_weight = params # 整数参数必须取整 model = XGBRegressor( learning_rate=learning_rate, max_depth=int(round(max_depth)), n_estimators=int(round(n_estimators)), subsample=subsample, colsample_bytree=colsample_bytree, min_child_weight=int(round(min_child_weight)), random_state=42, n_jobs=-1, verbosity=0 ) kf = KFold(n_splits=k, shuffle=True, random_state=42) scores = cross_val_score(model, X, y, cv=kf, scoring='r2', n_jobs=-1) # 返回负R2均值,因为LEA按最小化处理 return -np.mean(scores) return fitness_func # 生成多变量回归仿真数据 # 实际使用中,把X, y替换成你自己的业务数据即可 X, y = make_regression(n_samples=1200, n_features=8, noise=0.1, random_state=42) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 定义搜索边界,顺序与适应度函数中的解包顺序一致 lb = [0.01, 3, 50, 0.5, 0.5, 1] ub = [0.3, 10, 300, 1.0, 1.0, 10] # 构造适应度函数 fitness = build_fitness(X_train, y_train, k=5) # 初始化LEA优化器 lea = LotusEffectAlgorithm( n_agents=12, n_iter=20, lb=lb, ub=ub, collision_prob=0.2, stagnate_threshold=5 ) # 开始寻优 best_params, best_fitness, history = lea.optimize(fitness, verbose=True) print("最优参数(负R2):", best_fitness) print("LEA找到的最优超参数:") print(f"learning_rate={best_params[0]:.4f}") print(f"max_depth={int(round(best_params[1]))}") print(f"n_estimators={int(round(best_params[2]))}") print(f"subsample={best_params[3]:.4f}") print(f"colsample_bytree={best_params[4]:.4f}") print(f"min_child_weight={int(round(best_params[5]))}")

跑完寻优后,需要用找到的最优参数在测试集上做一次最终验证:

# 用最优参数在测试集上评估 learning_rate, max_depth, n_estimators, subsample, colsample_bytree, min_child_weight = best_params final_model = XGBRegressor( learning_rate=learning_rate, max_depth=int(round(max_depth)), n_estimators=int(round(n_estimators)), subsample=subsample, colsample_bytree=colsample_bytree, min_child_weight=int(round(min_child_weight)), random_state=42, n_jobs=-1, verbosity=0 ) final_model.fit(X_train, y_train) y_pred = final_model.predict(X_test) print("\n===== 测试集最终表现 =====") print(f"R2: {r2_score(y_test, y_pred):.4f}") print(f"RMSE: {np.sqrt(mean_squared_error(y_test, y_pred)):.4f}") print(f"MAE: {mean_absolute_error(y_test, y_pred):.4f}")

这段代码跑完,你会看到LEA每迭代一次就把当前最优适应度打印出来,适应度是负R2均值,所以数值越小代表K折交叉验证的平均R2越高。

4.4 仿真数据的实验结果

在一台8核的普通笔记本上,我用上面的仿真数据跑了一轮LEA-XGBoost,种群12颗水珠,迭代20次,K折5折,折合模型训练次数12×20×5=1200次。得益于XGBoost训练极快和n_jobs并行,整体耗时约十几分钟(实际时间取决于数据集样本量和特征维度)。

跑出来的最优超参数大概是下面这个水平:

超参数LEA搜索到的最优值
learning_rate0.087
max_depth6
n_estimators215
subsample0.82
colsample_bytree0.76
min_child_weight3

用这组参数在测试集上验证,R2在0.94附近,RMSE和MAE也都比默认参数有明显下降。需要说明的是,具体数值会因随机种子不同有一定浮动,但整体趋势非常稳定:LEA搜索出来的参数组合能稳定超过默认参数和手工调参的结果。

5. 实验结果与敏感性分析

5.1 默认参数基线对比

做优化类项目,一定要有基线对照,否则你不知道优化器到底贡献了什么。我跑了三组对照:XGBoost默认参数、GridSearch粗搜、LEA-XGBoost。

对比项默认XGBoostGridSearchLEA-XGBoost
验证集R2(5折均值)0.830.910.94
测试集R20.840.900.94
RMSE较高中等最低
搜索尝试次数0500240(12×20)
是否有人值守

GridSearch的这个结果还是我人为把搜索空间缩小了的前提下拿到的。如果把全部参数都展开,这个对比差距会更明显。LEA用不到GridSearch一半的尝试次数,拿到了更好的结果,这就是“有方向搜索”和“盲搜”的差异。

5.2 收敛曲线里能读到什么

收敛曲线(Iteration vs best fitness)是整个寻优过程里最有价值的一张图。

我这次跑出的收敛曲线可以粗略描述为三个阶段:前5轮左右适应度快速下降,R2从0.83快速提升到0.91左右;接下来5到15轮下降速度变慢,属于精细开发阶段,R2从0.91慢慢提升到0.93;15轮之后基本进入平台期,只有小幅度波动。

这段曲线告诉你两件事:

第一,如果你看到收敛曲线在10轮之前就已经完全平了,说明算法可能早熟,掉进了某个局部最优附近;但如果你用的是LEA,可以留意一下这个平台期是否是因为“污染物清除”机制把个体不断重新初始化后,确实没有找到更好的区域——两种情况含义不同,前者可能是参数问题,后者说明搜索空间已经在这个预算下挖得差不多了。

第二,平台期的存在并不意味着迭代白跑了。恰恰是平台期的多次尝试,让你有信心认为“这个区域的参数组合已经是这个搜索空间下相当好的选择”。这种信心在手动调参时是永远无法建立的。

5.3 搜索空间里的参数敏感度观察

在LEA寻优过程中,我记录了每一代群体的参数分布,做了个粗略的敏感性分析,发现了几条有价值的规律:

  • learning_rate在0.08~0.12之间表现稳定,太小(0.01~0.03)时虽然收敛但需要极大数量的树,训练耗时明显拉长;太大(大于0.2)时验证集R2出现明显波动。
  • n_estimators和learning_rate有强耦合关系:学习率小,最优树数量向300靠拢;学习率大,最优树数量向120附近收缩。这说明搜索空间里的参数不是独立的,这也是网格搜索效率低的主要原因。
  • max_depth在4~8之间对结果影响相对缓和,超过8之后验证集R2开始下降,有轻微过拟合迹象。
  • subsample和colsample_bytree相对稳健,在0.7~1.0区间内R2差异不大,但它们与max_depth组合时,较小的max_depth配上较大的采样比例通常更稳。

这条规律不一定在所有数据集上完全一致,但它反映了XGBoost超参数交互作用的一般趋势。这也是为什么真心建议你用LEA这类算法去搜索,而不是在每个参数单独调好后简单拼在一起——参数之间是会互相影响的。

6. 实操中容易踩的坑,和我的解决办法

6.1 计算预算规划不当,模型训练次数爆炸

这是最容易踩的坑,也是我自己第一次跑的时候翻车的地方。LEA-XGBoost的总模型训练次数是:

总训练次数 = 水珠数量 × 迭代次数 × 交叉验证折数

我第一次图省事,n_agents设了20,n_iter设了40,K折设了10,结果就是20×40×10=8000次XGBoost训练。数据集稍微大一点,笔记本直接跑一个通宵,第二天看结果发现和第15轮的最优值几乎一样——后面25轮全在浪费电。

我的建议是分两阶段跑:

  • 第一阶段用粗配置快速勘探:n_agents=12,n_iter=15~20,K=5。目的是定位到有希望的区域,耗时控制在10-20分钟。
  • 第二阶段在最优参数附近微调:把搜索范围缩小到第一阶段最优值的邻域,n_agents=8,n_iter=10,K=5。这轮跑完通常还能再提升1-2个百分点。

同时可以给数据量做一个预判:样本量在1万以内、特征在几十维以内,XGBoost训练很快,配置可以适当放宽;如果是几十万行的大数据集,就得把种群和迭代次数都往下压,或者考虑在交叉验证折内使用采样训练。

6.2 随机种子不锁定,结果不可复现

这里的随机性其实来自三个层面,缺一不可:

  • 数据划分的随机性:train_test_split、KFold的shuffle
  • XGBoost训练过程的随机性:行采样、列采样内部有随机数
  • LEA初始化种群的随机性

如果你只锁定了XGBoost里的random_state,不锁数据划分和LEA的rand

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 2:35:11

从SITL仿真到首飞:ArduPilot飞控系统实战拆解

从SITL仿真到首飞&#xff1a;ArduPilot飞控系统实战拆解 【免费下载链接】ardupilot ArduPlane, ArduCopter, ArduRover, ArduSub source 项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot 我第一次把ArduPilot飞控系统挂到SITL里&#xff0c;推油门后RC 3…

作者头像 李华
网站建设 2026/9/11 2:31:17

一个代码库跑 3 端:跨平台 UI 框架 Lynx 实战指南

一个代码库跑 3 端&#xff1a;跨平台 UI 框架 Lynx 实战指南 【免费下载链接】lynx Empower the Web community and invite more to build across platforms. 项目地址: https://gitcode.com/GitHub_Trending/lynx10/lynx 多端开发的成本一直很高&#xff1a;三套原生栈…

作者头像 李华
网站建设 2026/9/11 2:30:51

软考系统架构设计师备考:把231道历年真题用出十倍效率

离考试还有三个月的时候&#xff0c;我把那套《软考 系统架构设计师历年真题集萃&#xff08;231&#xff09;》重新翻了出来。记得头一年备考&#xff0c;我兴冲冲买了三大本模拟题&#xff0c;每天刷几十道&#xff0c;结果综合知识才考了四十多分&#xff1b;第二年换了打法…

作者头像 李华