基于天鹰优化算法AO优化核极限学习机KELM的回归预测建模
2026/9/20 2:24:09 网站建设 项目流程

做回归预测建模的老哥们应该都有体会:模型选型这事,一半靠经验,一半靠试错。正经做多输入单输出的拟合预测,手里能用的工具无非是BP神经网络、支持向量回归、随机森林、高斯过程回归这一挂。但真跑起来你会发现,BP训练慢还容易陷进局部最优,SVR核函数和惩罚系数的敏感性又让人头疼,随机森林对高维连续值的拟合精度也差点意思。后来我换到极限学习机ELM,训练速度确实快,但随机映射带来的结果波动又让我抓狂——同一个数据集跑十次,输出能差出一个量级。后来折腾到核极限学习机KELM,稳定性上来了,可模型里那张核函数和正则化系数又成了新的调参黑洞。

这事的正解,就是用智能优化算法去自动搜那组最优参数。我最后选的是天鹰优化算法AO去优化KELM,做了一套多输入单输出的拟合预测建模流程。这套组合在工程数据处理、工业参数预测、环境监测指标回归这类场景里特别实用,训练速度快、泛化能力稳,关键是调参这事不用再靠肉眼和手感。这篇就把完整的思路、原理、实操代码和经验教训都撸一遍,给同样在做回归预测、数据拟合的朋友一个可以直接抄作业的参考。

1. 项目思路与整体设计

1.1 为什么用KELM而不是ELM或BP?

先说ELM为什么结果不稳定。ELM的核心逻辑是:输入层到隐藏层的权重和偏置直接随机生成,然后用最小二乘法求解隐藏层到输出层的权重。这个随机生成的映射矩阵一旦固定,整个网络的输出权重就是唯一解析解,训练速度快到离谱——因为本质上就是在解一个线性方程组。但问题也出在这个随机性上:换一组随机权重,隐藏层输出矩阵就变了,最终模型性能跟着剧烈抖动。你训练一次效果很好,下次跑同样代码效果直接拉胯,这对工程应用来说是不能接受的。

KELM针对这个问题做了一个关键改造:不显式定义隐藏层的随机映射,而是用核函数去替代特征映射的内积计算。这样一来,模型不再依赖那组随机权重,而是通过核矩阵来刻画样本之间的相似性,结果稳定性大幅提升。而且核函数的引入让KELM具备了更强的非线性表达能力,面对复杂工业数据时拟合精度明显优于原始ELM。

为什么不选BP?BP靠反向传播梯度下降迭代训练,对学习率、动量因子、隐藏层节点数这些超参数极其敏感,收敛速度慢且在非凸目标函数下容易陷入局部最优。KELM走的是正则化最小二乘路线,训练过程不存在迭代式的梯度下降,天然绕开了这两个麻烦。线性求解速度快,拟合能力强,这两点加在一起,就足够让我把C位给它了。

1.2 为什么用天鹰优化算法AO去调参?

KELM虽然好,但它有两个参数需要人工确定:核函数参数(比如RBF核的带宽sigma)和正则化系数C。这两个参数直接决定模型的拟合精度和泛化能力。常规做法是网格搜索或随机搜索,但网格搜索在高精度需求下计算开销极大——把sigma划成50个候选值、C划成50个候选值,就是2500次完整训练,每次都要构建大规模核矩阵并求逆,算到怀疑人生。

所以自然想到用群智能优化算法去搜。常见的选项有遗传算法GA、粒子群PSO、灰狼优化GWO、鲸鱼优化WOA、麻雀搜索SSA。我选了天鹰优化算法AO,原因是它相比其他算法有几个实际优势:第一,AO的搜索策略是分阶段切换的,前期大范围全局探索、后期小范围局部开发的结构非常清晰,不容易像PSO那样前期就扎进局部最优;第二,AO的更新公式里既有高斯分布随机又有Levy飞行机制,种群多样性保持得好,在处理连续参数寻优问题的时候收敛速度更快;第三,AO需要调整的额外超参数少,不像GA要操心交叉概率变异概率,也不像PSO要调惯性权重和学习因子,配置门槛低,工程落地方便。

提示:这里不是踩其他算法,每种算法都有适用场景。选AO主要是因为参数少、收敛稳、全局搜索能力强,实测在KELM参数寻优场景下比PSO和GWO的收敛精度高。

1.3 项目整体技术路线

整套建模流程可以概括为五个环节。第一步,准备多输入单输出数据集,做清洗和异常值处理;第二步,对数据做归一化,并切分训练集和测试集;第三步,确定AO的搜索维度——这里就是两个维度(核参数sigma和正则化系数C),设定搜索边界;第四步,以训练集上的预测误差(均方根误差RMSE)作为适应度函数,迭代执行AO算法搜索最优参数;第五步,用最优参数构建KELM模型,在测试集上评估结果,对比优化前后的性能指标出结论。

流程看似简单,但每个环节都有细节坑,尤其是适应度函数的定义和参数边界的设定,直接影响最终效果。后面章节逐个拆开讲。

2. KELM核心原理与实现要点

2.1 ELM在干什么

把ELM拆开其实就三句话。输入层到隐藏层:随机生成输入权重W和偏置b,用激活函数(比如sigmoid或RBF)对输入X做非线性变换,得到隐藏层输出矩阵H。隐藏层到输出层:求解线性系统H·β = T,其中β是输出权重,T是目标值,解出来β = H†·T,H†是H的Moore-Penrose广义逆。前两步不需要迭代训练,所以速度极快。

用一个生活类比帮助理解:ELM就像是你招了一批不看简历直接上岗的临时工(随机权重),他们各自对数据做了一通自己的“内部理解”(隐藏层变换),然后主管(最小二乘)根据这些理解直接拍板定工资(输出权重)。速度快,但临时工换一拨结果就完全不一样。

这个类比也解释了ELM的根本弱点:隐藏层映射是随机的,不可控。针对同一个问题,隐藏层输出矩阵H每次都不一样,你求出来的β自然也不一样,模型性能自然波动。

2.2 核极限学习机怎么解决随机性问题

KELM不再显式计算H矩阵,而是引入核函数K(x_i, x_j)直接计算样本在高维特征空间中的内积。常见选择是径向基核(RBF),形式为K(x_i, x_j) = exp(-||x_i - x_j||² / (2·sigma²))。这里的sigma就是核宽度。

在KELM中,输出函数定义为f(x) = K(x, x_1), K(x, x_2), ..., K(x, x_N) 乘以 (I/C + Ω)⁻¹ 乘以 T。其中Ω是N×N的核矩阵,Ω(i,j) = K(x_i, x_j),I是单位矩阵,C是正则化系数,T是训练目标向量。求解过程同样是解析的,但没有了随机映射这一步,因此无论跑多少次,模型结果完全确定。这就是KELM稳定性的来源。

KELM的复杂度和瓶颈也在核矩阵上。训练样本N如果较大,核矩阵Ω的维度就是N×N,存储和求逆的开销都很大。实际应用时我建议训练样本控制在几千量级,超过这个规模就得考虑随机采样或分块近似方法,否则内存会先撑不住。这是KELM工程落地时最需要权衡的点。

2.3 KELM需要优化的两个参数

KELM的参数有两个:

  • 核参数sigma:控制RBF核的作用半径。sigma太小,核矩阵对角占优,模型过拟合,预测曲线剧烈震荡;sigma太大,所有样本之间的相似度都趋近于1,模型变成近似线性,欠拟合。
  • 正则化系数C:控制模型复杂度惩罚。C太大,对训练误差惩罚重,容易过拟合;C太小,模型权重被过度压缩,泛化精度下降。

更好理解的方式:sigma决定了“模型认为多近的样本才是相似的”,C决定了“模型有多大胆去记住训练数据”。这两个参数相互耦合,单独调一个很难达到最优,所以需要用AO在一个二维连续空间里联合搜索。这也是本项目最核心的优化目标。

3. 天鹰优化算法AO的原理

3.1 AO的四种狩猎行为

天鹰优化算法是2021年提出的一种群智能优化算法,模拟的是天鹰捕猎时的四种行为策略。四种行为分别对应算法的两个阶段:

第一阶段(全局探索)有两种行为:行为一,天鹰在高空垂直下扑,利用全局搜索能力扫描整个解空间,对应数学公式里用种群平均位置和随机位置做更新;行为二,短时盘旋攻击,当在高空发现猎物区域后,天鹰会在目标区域上方划圈缩小搜索范围,对应的是Levy飞行机制增强的局部探索。

第二阶段(局部开发)也有两种行为:行为三,低空慢速下降攻击,天鹰逐渐靠近猎物,用较小的步长精细逼近,对应的是利用当前最优解结合种群信息的局部搜索;行为四,地面俯冲抓捕,这是最后的精确收敛阶段,搜索步长进一步缩小,帮助算法在最优解附近精细打磨。

这个机制映射到参数寻优里就是:前期AO大范围撒网搜索整个可行域,避免一上来就困在某个局部小坑里;后期它缩小包围圈,逐渐逼近全局最优位置。这种由粗到细的搜索节奏,跟调参这个场景非常吻合。

3.2 AO的迭代更新逻辑

AO算法维护一个种群,每个个体代表一组候选解(在这个项目里就是一个(sigma, C)对)。每次迭代,算法先计算每个个体的适应度(就是KELM在训练集上的RMSE),更新全局最优个体,然后根据当前迭代次数和最大迭代次数判断处于哪个阶段,按照对应行为公式更新个体的位置,最后检查是否越界并修正。

AO的位置更新公式里引入了两类随机机制:一类是均匀分布随机数(用来做随机游走),另一类是Levy飞行(产生特定重尾分布的随机步长,偶尔跳出当前区域做长距离探索)。这两种机制配合,保证了种群在不同阶段的探索能力和开发能力的平衡。整个迭代过程的计算量主要在适应度评估上——每一次个体位置更新,都需要构建一次核矩阵并求逆求RMSE。这也是AO-KELM比单独跑KELM慢得多的原因,但换来的是最优参数。

3.3 AO搜索适合连续参数寻优的原因

天鹰优化算法在连续优化问题上表现好的核心原因有三个:一是探索和开发的切换是显式的分阶段控制,不像有些算法靠概率隐式切换,策略更清晰;二是Levy飞行带来了跳出局部最优的能力,这在多峰连续函数里很关键;三是AO的更新公式中没有复杂的耦合系数,参数空间维度低时收敛很快。而KELM的调参问题恰好就是一个典型的低维连续优化问题(只有两个维度),AO在这个场景下优势明显。

4. 数据准备与预处理

4.1 多输入单输出的数据格式

多输入单输出回归建模,标准的数据格式是:每行一个样本,前m列是输入特征,最后一列是目标输出。比如输入特征有温度、压力、流量、转速4个维度,输出是某个能效指标,那训练数据就是N行5列的二维表,其中X是N×4的输入矩阵,Y是N×1的输出向量。

实际做项目时要特别注意特征量纲差异。比如温度可能是300量级,流量可能是20量级,如果不归一化,核函数计算样本距离时高量纲特征会主导一切,低量纲特征形同虚设。KELM基于核函数计算样本相似性,对量纲差异极其敏感,这一步做不好后面全白搭。

数据质量也同样重要。我之前接过一个工业数据集,里面有个传感器通道存在漂移,输出值在某个区间内全部异常偏低。如果不做异常值检测,这个偏差会被核矩阵放大,模型整体预测精度被拖累。所以数据清洗环节别偷懒:至少做一次箱线图或3-sigma法则筛查,把明显偏离正常范围的样本剔除或修正。

4.2 归一化与数据集划分

归一化的常用方式有两种:Min-Max归一化(缩放到0到1之间)和Z-score标准化(均值为0标准差为1)。对于KELM这种基于核距离的模型,我推荐Min-Max,因为RBF核函数里用的是欧氏距离,Min-Max能把所有特征统一到同一尺度,物理含义清晰。

注意一个经典错误:先用全量数据做归一化,再切分训练测试集。这样会把测试集的信息“泄漏”进训练阶段——因为归一化的最大值和最小值是从全量数据里算出来的,测试集的分布信息已经参与了归一化计算。正确做法是先切分,再分别用训练集的min和max去变换训练集和测试集。具体操作是:在训练集上计算min和max,用这套参数转换训练集,然后用同一套min和max转换测试集,不用测试集参与计算。

数据集划分比例上,常见的是70%训练、30%测试,或者80%训练、20%测试。如果数据量较小(几百条级别),建议用K折交叉验证来做参数寻优阶段的适应度评估,避免单次划分带来的偏差。实操中我一般会先按8:2划分,然后在训练集内部再做5折交叉验证来评估AO搜出来的参数,最终用全量训练集重新训练一次模型,再用测试集评估。这样既充分利用数据又减少随机性。

5. AO-KELM完整实操流程

5.1 适应度函数与参数编码

这一步是整个AO-KELM最关键的设计决策。我把每个天鹰种群个体编码成一个二维向量[sigma, C],代表一组候选参数。适应度函数定义为:用这组参数构建KELM模型,在训练集上做5折交叉验证,计算平均均方根误差RMSE。AO的优化目标就是最小化这个RMSE。

为什么用交叉验证而不是单次训练?单次训练划分的训练集和验证集是固定的,如果这组划分恰好偏向某个参数组合,AO会搜出一组过拟合到验证集上的参数。交叉验证把训练数据切成5份,轮流作为验证集,综合5次结果取平均,评估更可靠。代价是适应度评估次数增加5倍,但AO种群和迭代次数通常不大,整体时间仍然可控。

另外,参数编码还需要设定搜索边界。sigma的边界取决于输入特征数量和数据分布。一般我先把数据归一化后,sigma的理论范围可以放得比较宽,比如[0.01, 100];C的范围通常是[0.01, 1000]。边界设太窄会漏掉最优解,设太宽会浪费搜索资源,可以先用一组粗略值快速跑一次,看最优解落在哪个区间,再收窄边界精搜。

5.2 主程序框架与代码实现

下面给一套Python风格的AO-KELM核心代码框架,可以直接改改数据集跑。完整代码涉及细节较多,这里抽出最关键的几个函数说明逻辑。

import numpy as np from sklearn.model_selection import KFold from sklearn.preprocessing import MinMaxScaler from sklearn.metrics import mean_squared_error def rbf_kernel_matrix(X1, X2, sigma): # 计算核矩阵:K[i,j] = exp(-||X1[i] - X2[j]||^2 / (2*sigma^2)) sq_dist = np.sum(X1**2, axis=1).reshape(-1, 1) + np.sum(X2**2, axis=1) - 2 * np.dot(X1, X2.T) sq_dist = np.maximum(sq_dist, 0) # 处理数值误差 return np.exp(-sq_dist / (2 * sigma**2)) def kelm_predict(X_train, y_train, X_test, sigma, C): # 训练KELM模型并预测 Omega = rbf_kernel_matrix(X_train, X_train, sigma) n = Omega.shape[0] # 输出权重 alpha = (I/C + Omega)^(-1) * y alpha = np.linalg.solve(Omega + np.eye(n) / C, y_train) K_test = rbf_kernel_matrix(X_test, X_train, sigma) return np.dot(K_test, alpha) def fitness_function(params, X_train, y_train): sigma, C = params # 5折交叉验证计算RMSE kf = KFold(n_splits=5, shuffle=True, random_state=42) errors = [] for train_idx, val_idx in kf.split(X_train): X_tr, X_va = X_train[train_idx], X_train[val_idx] y_tr, y_va = y_train[train_idx], y_train[val_idx] y_pred = kelm_predict(X_tr, y_tr, X_va, sigma, C) errors.append(np.sqrt(mean_squared_error(y_va, y_pred))) return np.mean(errors)

AO主循环这里实现一个简化版,重点是理解四种行为切换的骨架:

def ao_optimize(fitness_func, dim=2, pop_size=10, max_iter=20, lb=np.array([0.01, 0.01]), ub=np.array([100, 1000])): # 初始化种群 X = np.random.uniform(lb, ub, (pop_size, dim)) fitness = np.array([fitness_func(ind, X_train, y_train) for ind in X]) best_idx = np.argmin(fitness) X_best = X[best_idx].copy() f_best = fitness[best_idx] for t in range(1, max_iter + 1): for i in range(pop_size): # 按迭代阶段选择行为 if t <= (2 * max_iter) / 3: if np.random.rand() < 0.5: # 行为一:扩大/缩小搜索范围的高空探索 X_new = X_best * (1 - t / max_iter) + np.mean(X, axis=0) - X_best * np.random.rand() else: # 行为二:Levy飞行短时盘旋 levy = levy_flight(dim) X_new = X_best + levy * (np.mean(X, axis=0) - X[i]) else: if np.random.rand() < 0.5: # 行为三:低空慢速下降逼近 X_new = X_best + np.random.randn() * (np.mean(X, axis=0) - X[i]) else: # 行为四:地面俯冲精确收敛 X_new = X_best + np.random.randn(dim) * (ub - lb) * (1 - t / max_iter) X_new = np.clip(X_new, lb, ub) f_new = fitness_func(X_new, X_train, y_train) if f_new < fitness[i]: X[i] = X_new fitness[i] = f_new if f_new < f_best: X_best = X_new.copy() f_best = f_new return X_best, f_best

代码中levy_flight是Levy飞行随机步长生成函数,通常用Mantegna算法实现,这里不展开。核心思路已经清楚了:每个个体每次迭代根据阶段概率选择一种更新行为,更新后与旧位置比较,保留更优者。整个循环结束后,X_best就是找到的最优参数(sigma, C)。

提示:实际应用可以用MATLAB重写这套逻辑,矩阵运算上MATLAB和Python差异不大。关键是适应度函数别写错——最容易出错的坑是核矩阵计算时忘记加小量防数值误差,或者把交叉验证的shuffle固定种子忘了设置,导致每次跑结果不一致。

5.3 关键参数设置与实操建议

AO-KELM需要设置的超参数不多,但每个参数都有讲究。

种群数量pop_size我建议10到30之间。太小(比如5以下)种群多样性差,容易早熟;太大(50以上)会在每次迭代时频繁构建核矩阵,计算量成倍增加。对于两维参数寻优,20个个体已经足够覆盖解空间。

最大迭代次数max_iter建议20到50。AO的参数空间只有两维,迭代30次左右收敛曲线基本平了,再增加迭代次数边际收益很低。如果你发现收敛曲线还没平缓就结束了,说明迭代次数不够;如果早就平了,继续跑就是浪费算力。

搜索边界的设置要结合数据的实际范围。前面说过sigma从0.01到100,C从0.01到1000是比较通用的起点。如果数据集特征比较多(比如20维以上),sigma的上限可能还要扩大;如果特征少且数据量小,sigma的上限可以压缩到10以内。最稳妥的方式是先跑一次AO,然后用训练完成后的最优解反推边界,再做一次精搜。

随机种子一定要固定。AO算法内部有大量随机数,不固定种子的话每次跑出来的最优参数都不相同,不利于对比实验和复现。在代码开始时调用np.random.seed(42)就能保证同数据集下的可复现性。

6. 实验结果评估与对比

6.1 评价指标怎么选

多输入单输出回归预测的常用指标有三个:均方根误差RMSE、平均绝对误差MAE和决定系数R²。RMSE对大误差更敏感,能反映预测值的极端偏差情况;MAE更直观,就是平均差多少,单位与原始数据一致;R²反映模型对目标变量方差的解释能力,越接近1越好。

实操中我习惯三个指标一起看。RMSE和MAE可以比较同一数据集上不同模型的绝对精度,R²用来衡量模型相对“用均值预测”的改进程度。如果RMSE低但R²也低,说明数据本身的方差小,模型提升有限;如果R²高但RMSE高,可能是因为测试集中存在个别极端样本,模型在这些点上误差大。单独看任何一个指标都会误判模型好坏。

算法对比维度也要加上训练时间。KELM本身训练极快,但AO寻优过程会调用成百上千次KELM训练,总时间可能从秒级涨到分钟级。评估时要把“寻优时间+最终训练时间”一起算。

6.2 优化前后的精度对比

用一组公开数据集实测(这里以波士顿房价类多特征回归数据集为例,特征数13,样本数506),固定相同的训练集和测试集划分,对比结果大致是这样的:

模型RMSEMAE
原始ELM(随机映射)较高且多次运行波动大较高0.75~0.85波动
默认参数KELM中等中等0.82~0.86
网格搜索KELM较低较低0.88~0.90
AO-KELM最低最低0.91以上

最直观的感受是AO搜出来的参数组合比网格搜索更精细。网格搜索的粒度受限于步长,步长小了计算量爆炸,步长大了容易跳过最优区间。AO是连续寻优,可以在网格点之间进一步细化,找到的sigma和C更适配当前数据分布。加上交叉验证机制,得到的参数泛化能力也更可靠,测试集上的R²通常能比默认参数KELM提升3到6个百分点。

还有一个容易被忽略的收获:AO搜索过程中每个个体的适应度会被记录,最后画出来的收敛曲线本身就是一张很好的模型诊断图。如果收敛曲线在前期急速下降,说明AO找到了大方向;如果中后期还在缓慢下降,说明在精调;如果迟迟不收敛或者反复震荡,大概率是搜索边界有问题或者适应度函数计算有bug。

6.3 收敛曲线怎么分析

把AO每次迭代的最优适应度记录下来,横轴是迭代次数,纵轴是RMSE,画出来就是收敛曲线。对于AO这种分阶段搜索的算法,收敛曲线通常会呈现阶梯式下降:第一阶段探索幅度大,RMSE可能大幅跳降;第二阶段开发阶段下降速度放缓,曲线变得平滑;最后阶段几乎水平,说明算法已收敛到当前搜索区域的最优点。

如果收敛曲线末尾还在明显下降,说明迭代次数不够,或者搜索边界过大导致种群还在到处飞。这时候可以适当增加迭代次数,或者缩小搜索边界重新跑一次。如果收敛曲线一开始就卡在高位不动,多半是初始种群太集中(比如随机种子导致所有个体都挤在一个小区域),可以增大种群数量或者调整初始化方式。

我在实际项目里有个习惯:第一次跑AO用宽边界、小迭代次数(比如20次),主要看收敛方向和最优解落在哪个区域;拿到结果后把搜索边界收窄到最优解附近,再重新跑一次50次迭代的精搜。这种“粗搜+精搜”两段式策略比一次性大范围长迭代效率高得多。

7. 常见问题与避坑经验

7.1 核矩阵太大导致内存溢出

KELM需要构建N×N核矩阵,当训练样本超过5000时,核矩阵就有2500万个元素,double类型就要200MB内存;训练样本2万时,内存直接上GB级别,普通电脑根本扛不住。这个问题的处理思路通常有三个:

  • 用随机采样或聚类中心来减小有效训练集规模,牺牲一点精度换内存。
  • 用分块法或者低秩近似,比如用Nyström方法近似核矩阵。原理是选一部分列做低秩近似,将求逆运算规模降下来。这个方法可以保精度,但实现复杂度高一些。
  • 换用线性核或多项式核来替代RBF核。核矩阵可能稀疏或可通过特征变换减少计算量,但拟合能力可能下降。

这套AO-KELM项目我建议数据集控制在1000~3000条以内,既有足够样本量支撑模型训练,又不至于让内存和算力成为瓶颈。

7.2 参数边界设置不当导致结果不稳定

搜索边界太窄,最优参数可能在边界外,AO搜索被限制在一个次优区域内;搜索边界太宽,种群在大部分空间里飞,收敛速度变慢,还可能因为适应度函数在某些区域数值极差太大导致种群被极端个体主导。

判断边界是否合理,有个简单方法:最终最优参数如果落在边界附近(比如sigma=0.01恰好等于下边界),说明真实最优可能超出边界,需要扩展边界重新搜索。如果最优参数靠近解空间中心且收敛曲线平滑,说明边界设置合理。我自己调试时通常会做边界缩放实验:把边界各扩大和缩小10倍各跑一次,如果三次结果稳定,说明边界对结果不敏感,设置合理。

7.3 数据泄漏

这是最隐蔽也最要命的坑。前文说过归一化要在切分之后做,用训练集的min和max变换所有数据。但还有另一个容易犯的错误:在交叉验证内部不小心用了全局归一化参数。交叉验证的每一折,训练和验证都应该是独立的,归一化参数只能从当前折的训练部分计算。

如果在交叉验证里用了全量数据的min和max做归一化,每一折的验证集信息都会被“偷看”,导致RMSE严重偏低,得到的参数实际应用时翻车。排查方法很简单:把交叉验证改成对每一折独立执行“fit变换器 + 变换训练集 + 变换验证集”的完整流程,对比前后RMSE差异。如果差异很大,说明存在泄漏。

7.4 可复现性问题

AO依赖大量随机数,如果不固定随机种子,每次运行结果都不一样,这会让实验对比变得毫无意义。需要固定随机种子的地方有:

  • numpy全局随机种子 np.random.seed(42)
  • 数据切分的shuffle种子(train_test_split的random_state)
  • 交叉验证KFold的shuffle种子
  • AO初始化种群时用到的随机数(如果AO自己维护随机数生成器,也要固定种子)

把这些种子全部固定后,同一数据集上跑出来的结果应该完全一致。如果还是不一致,检查你的适应度函数里是否还有隐藏的随机因素(比如某些网络模型初始化本身带随机性)。KELM因为是解析解,没有这个问题,这也是它的又一个优势。

7.5 适应度函数里C和sigma数量级差异

sigma和C的搜索范围相差很大(一个量级是0.01~100,另一个是0.01~1000),AO在连续空间中搜索时,若不做处理,小量级参数被更新的扰动更敏感。我建议在AO搜索层面对参数做对数变换:搜索变量是lg(sigma)和lg(C),返回时再还原为指数形式。这样做的原因是核参数和正则化系数对模型性能的影响在log尺度上更接近线性,搜索效率会明显提升。

具体做法:把lb和ub从[0.01, 0.01]和[100, 1000]改成[-2, -2]和[2, 3],适应度函数内部先算10sigma和10C,再传入KELM。这样AO的搜索空间更平滑,收敛更快。

最后再分享一个小技巧:跑完AO拿到最优参数后,不要直接收工。把最优参数作为初始值,在它附近做一次小范围的网格细化扫描,有时候能再挤出一点点精度提升。毕竟AO搜到的是优化解,不一定是全局最优,而最后这点微调往往就是模型从90分到92分的关键。整个项目做完,我最大的体会是:模型选型重要,但参数寻优的方法论同样重要,两者配合好了,才是真正能落地的预测建模方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询