☰
BWO-KELM回归预测:白鲸优化算法自动调参的MATLAB实现
2026/10/10 0:05:49 网站建设 项目流程

简介:这是一套基于白鲸优化算法(BWO)优化核极限学习机(KELM)的回归预测MATLAB代码,适用于需要快速完成回归预测建模、或对比智能优化算法性能的科研与工程场景。代码结构紧凑,数据以EXCEL形式提供,可直接替换自行数据集运行,对MATLAB基础用户比较友好。压缩包共6个文件,以4个.m脚本和函数为主,涵盖主程序、BWO优化逻辑及KELM核函数实现,另含1个.p封装文件与1个xlsx示例数据,整体仅399KB。运行后会输出训练集和测试集的预测值-实际值对比图、对应误差曲线,以及BWO收敛进化曲线,便于直观观察拟合效果和优化过程;同时代码内置RMSE、MAPE、MAE、拟合优度R2等指标计算,可直接用于误差分析或论文实验数据。目前已有109人学习下载,适合做回归预测研究、算法改进或课程设计参考。

1. BWO-KELM 回归预测:先从“超参难调”这个痛点说起

做过回归预测的人大多有这种经历:数据干净、特征也合理,换个模型或调一组参数,结果能差出一大截。核极限学习机(KELM)是个不错的底子——训练快、泛化能力强,但真正让人头疼的是它的核参数 sigma 和正则化系数 C。这两个超参数几乎决定了最终精度,手动试网格、试随机值,试到天亮也未必找到最优组合。白鲸优化算法(BWO)在这类连续参数寻优问题上表现突出,收敛稳、全局搜索能力强,把它和 KELM 拼在一起,就把最花时间的调参环节变成了自动化流程。这套 BWO-KELM 的 MATLAB 代码,适合做负荷预测、风电功率预测、经济指标回归这类任务的从业者。你不用自己从头写优化器,直接拿这份代码替换数据、设好参数就能跑,新手也能在半小时内看到预测曲线。

2. 核极限学习机与白鲸优化:为什么调参是回归预测的真正门槛

2.1 KELM 用核映射替代随机隐层,模型从“玄学”变“可控”

极限学习机(ELM)的初衷是快:输入权重和隐层偏置随机生成,不参与训练,只求解隐层输出矩阵的 Moore-Penrose 广义逆。好处是训练速度极快,坏处也很明显——随机隐层会让每次运行的结果有波动,且隐层节点数不好定。核极限学习机把核方法引进来,不再显式构造隐层节点,而是用核函数计算样本之间的相似度矩阵,这样消除了随机性,模型稳定性和泛化能力都上了一个台阶。

KELM 的训练目标本质上是一个岭回归解:

预测输出 f(x) = K(x, X_train) * (I/C + K_train)^(-1) * y_train

其中 K_train 是训练集的核矩阵,K(x, X_train) 是待预测样本与训练样本的核向量。C 是正则化系数,I 是单位矩阵,sigma 则出现在核函数里。最常见的 RBF 核形式是:

K(xi, xj) = exp(-||xi - xj||^2 / (2 * sigma^2))

sigma 越小,核函数衰减越快,模型越偏向局部拟合;sigma 越大,样本之间的相关度越高,模型越平滑。C 控制经验误差与模型复杂度之间的平衡。很多人在初学 KELM 时以为随便设个 sigma、C 就行,实际跑过几组数据就会发现:这两个参数对 RMSE 的影响非常大,而且和数据尺度、特征维度有直接关系。我一般会先做归一化,再用优化算法去搜索这两个值,而不是手动去摸排。

KELM 的优势在于它把“网络结构”转化为“超参数选择”问题。原来 ELM 隐层节点数难以确定,现在变成了“选核函数类型 + 定核参数 + 定正则化系数”。优化目标很明确,维度又低,这就给群体智能优化算法提供了非常好的施展空间。PSO、GWO 都能用,但各有各的问题:PSO 容易早熟收敛,GWO 对边界约束的处理稍显粗糙。BWO 的设计则更有层次感,分阶段切换探索和开发行为,在高维连续参数搜索里表现更稳定。

2.2 BWO 的三种迁移行为:“航行、狩猎、鲸落”分别对应搜索策略的什么阶段

白鲸优化算法模拟的是白鲸群体的三种觅食行为。与传统 PSO 直接向全局最优靠拢的机制不同,BWO 引入了一个平衡因子 Bf,把迭代过程切成三个阶段:当 Bf 大于 0.5 时,算法处于“航行”阶段,个体在搜索空间内做随机游走式的全局勘探;当 Bf 在 0.3 到 0.5 之间时,进入“狩猎”阶段,个体朝向当前最优位置移动,同时叠加随机扰动,这个阶段兼顾局部开发与跳出局部最优;当 Bf 小于 0.3 时,进入“鲸落”阶段,部分个体被重置到搜索空间随机位置,模拟鲸鱼死亡后躯体下沉、养分回归生态系统的过程,给种群带来新鲜血液。

三个阶段的划分不是生硬切换,而是用线性递减的 Bf 平滑过渡。前中期保证全局勘探能力,后期逐步收敛到最优区域,鲸落机制则持续维持种群多样性,避免早早卡在局部极值。相比其他算法只有一个“全局最优引力”机制,BWO 的转移搜索策略更适合 KELM 参数寻优这类多峰、非线性的适应度曲面。

实际使用中,有几个 BWO 参数是需要根据问题规模调节的:种群规模 N、最大迭代次数 MaxIt、搜索空间边界。KELM 场景下参数维度通常是 2(sigma 和 C),也可以扩成 3-4 维(加入核函数类型编号或特征权重)。下表是我常用的参数模板:

参数含义推荐范围说明
N种群规模20-50维度低、数据量大时,30 足够
MaxIt最大迭代次数100-300数据样本越多,迭代次数可适当增大
Dim待优化参数维度2(sigma, C)看是否要额外优化特征权重
lb搜索下界[0.01, 0.0001]sigma 太小会过拟合,限制下限是必要的
ub搜索上界[100, 10000]C 太大则正则化失效,根据数据尺度调整
Bf平衡因子0.9 线性降到 0.1控制三个阶段的过渡速度

需要提醒的是,BWO 的搜索效果对边界设置非常敏感。lb 和 ub 如果设得过于宽泛,前期大量计算浪费在无效区域;设得太窄,又可能找不到最优解。我一般先跑一次随机搜索或小规模网格试算,观察最优参数大致落在什么范围,再把边界收紧到该区间附近,让优化器把力气花在“周围精细搜索”上。

3. 核心代码拆解:主程序、核矩阵构造与三个更新算子

3.1 代码文件结构:这份资源里每个文件负责什么

拿到这份代码,先别急着运行,打开根目录看看文件组织。整体结构不复杂,核心模块分五块,每个文件职责单一,方便调试和替换:

文件职责入口/出口
main_BWO_KELM.m主程序,加载数据、设置参数、调用优化、输出结果入口是数据文件路径,出口是预测图与指标
init_bwo.m白鲸种群初始化返回 N 行 Dim 列的位置矩阵
calc_fitness.m适应度函数,内部完成 KELM 训练并返回 RMSE输入粒子位置,输出标量适应度
BWO_opt.m白鲸优化主循环,包含航行、狩猎、鲸落更新返回全局最优位置 best_pos 与 best_fit
rbf_kernel.mRBF 核矩阵计算输入两组数据与 sigma,输出核矩阵
KELM_train.m / KELM_predict.m训练与预测封装简化主程序调用,可选模块

这套代码不依赖额外工具箱,基础 MATLAB 环境就能跑,核矩阵运算全是手写矩阵操作,方便移植到 Octave 或其他数值环境。

3.2 种群初始化与边界约束:第一步就决定搜索效率

先看初始化函数。种群位置就是待优化的参数组合,每个个体一行,每一列对应一个待优化参数。

function Positions = init_bwo(N, Dim, lb, ub) % N:种群规模,Dim:待优化参数维度 % lb:各维下界向量,ub:各维上界向量 Positions = zeros(N, Dim); for i = 1:N % 每个个体在 [lb, ub] 范围内均匀随机生成 Positions(i, :) = lb + rand(1, Dim) .* (ub - lb); end end

这里的核心操作是lb + rand(1, Dim) .* (ub - lb)。注意必须使用点乘,因为 lb 和 ub 是向量,逐维对应相乘才能让每一维在各自范围内独立随机生成。如果写成rand(1, Dim) * (ub - lb),MATLAB 会报维度不一致错误,这是新手最容易翻车的地方。初始化完成后,建议立即加一句Positions(i, :) = max(min(Positions(i, :), ub), lb);做一次边界夹取,防止初始化时浮点误差越界。

在 KELM 优化场景下,Dim 通常设为 2。但有个细节:如果特征数据量纲差异极大,我建议把 Dim 设为 3,多出来的一维作为特征缩放指数,让优化器在寻找 sigma 的同时自动修正特征尺度的影响,这比手动做归一化更精细。

3.3 适应度函数:KELM 训练误差如何变成优化器的“食物”

适应度函数是所有群智能优化算法的核心评价标准。这个函数接收一个粒子位置,也就是一组 [sigma, C],内部执行一次完整的 KELM 训练,返回验证误差。误差越小,这个粒子的位置越“好吃”。

function fitness = calc_fitness(X_train, y_train, params) % params 向量:[sigma, C] sigma = params(1); C = params(2); % 构造训练集核矩阵 K = rbf_kernel(X_train, X_train, sigma); n = size(K, 1); % 岭回归求解输出权重,加入正则化项 I/C alpha = (K + eye(n) / C) \ y_train; % 在训练集上做预测并计算 RMSE 作为适应度 y_pred = K * alpha; fitness = sqrt(mean((y_train - y_pred).^2)); end

eye(n) / C这一步是正则化的关键:C 越大,对角线惩罚越小,模型越倾向于完美拟合训练集;C 太小则惩罚过强,模型欠拟合。\是 MATLAB 的矩阵左除运算符,内部自动选择最优分解算法,比直接写inv(K + eye(n)/C) * y_train数值稳定性更好,尤其是核矩阵接近奇异时,左除不会产生 NaN。

rbf_kernel 的实现也很直接:

function K = rbf_kernel(X1, X2, sigma) % 计算两个样本矩阵之间的 RBF 核矩阵 % X1 为 n1 行 m 列,X2 为 n2 行 m 列,返回 n1 x n2 的核矩阵 n1 = size(X1, 1); n2 = size(X2, 1); K = zeros(n1, n2); for i = 1:n1 % 逐行计算欧氏距离平方,再代入 RBF 公式 diff = X1(i, :) - X2; dist2 = sum(diff.^2, 2); K(i, :) = exp(-dist2 ./ (2 * sigma^2)); end end

这个函数的计算复杂度是 O(n1 * n2 * m),当样本量到万级时,核矩阵构造会非常耗时。优化时可以先用随机采样的小批量子集计算适应度,找到近似最优区域后,再在全量数据上微调 sigma 和 C。

3.4 主循环:BWO 的三阶段更新算子

BWO 主循环是整个代码最重要也最容易出错的模块。平衡因子 Bf 要把整个迭代过程分成三段,我用Bf = 0.9 - 0.6 * t / MaxIt的方式让它从 0.9 线性降到 0.3。这样最终迭代结束后刚好覆盖探索到鲸落的全部阶段。

function [best_pos, best_fit] = BWO_opt(X_train, y_train, N, MaxIt, lb, ub) Dim = length(lb); Positions = init_bwo(N, Dim, lb, ub); % 初始适应度计算 fitness = zeros(N, 1); for i = 1:N fitness(i) = calc_fitness(X_train, y_train, Positions(i, :)); end [best_fit, idx] = min(fitness); best_pos = Positions(idx, :); for t = 1:MaxIt % 平衡因子从 0.9 线性下降到 0.3,控制阶段切换 Bf = 0.9 - 0.6 * t / MaxIt; W = 0.1 + 0.9 * (1 - t / MaxIt); % 惯性权重,后期减小扰动幅度 for i = 1:N if Bf > 0.5 % 航行阶段:向随机个体方向移动,保持全局勘探 r = randi(N); Positions(i, :) = Positions(i, :) + rand(1, Dim) .* ... (Positions(r, :) - Positions(i, :)); elseif Bf > 0.3 % 狩猎阶段:朝最优个体方向移动,并叠加高斯扰动 Positions(i, :) = Positions(i, :) + rand(1, Dim) .* ... (best_pos - Positions(i, :)) + ... W * 0.1 * randn(1, Dim); else % 鲸落阶段:概率重置,防止种群陷入局部最优 if rand < 0.3 Positions(i, :) = lb + rand(1, Dim) .* (ub - lb); end end % 边界约束:越界参数直接拉回边界 Positions(i, :) = max(min(Positions(i, :), ub), lb); end % 更新适应度与全局最优 for i = 1:N fitness(i) = calc_fitness(X_train, y_train, Positions(i, :)); end [min_fit, idx] = min(fitness); if min_fit < best_fit best_fit = min_fit; best_pos = Positions(idx, :); end end end

这三段分别对应 BWO 的航行、狩猎、鲸落。航行阶段用随机个体做参考向量,让种群铺满搜索空间;狩猎阶段结合全局最优和随机扰动,兼顾开发与跳出局部极值;鲸落阶段用 0.3 的概率随机重置部分个体,类似变异算子。你不需要照抄这个概率值,数据特征复杂时可以把鲸落概率提高到 0.4 甚至 0.5,代价是收敛速度变慢。

有个细节值得留意:狩猎阶段的randn(1, Dim)是高斯随机扰动,幅度由 W 控制。W 从 1 衰减到 0.1,保证前期扰动大、后期精细搜索。如果没有这层衰减,后期粒子会在最优位置附近来回震荡,难以收敛到高精度解。

3.5 最优参数回带:训练最终模型与预测

BWO_opt 返回的最优参数 best_pos 不能直接用于预测,还需要用全部训练数据重新训练一次最终模型。因为优化器每次迭代都是用适应度函数做近似评估,最终模型要在全量数据上把 sigma 和 C 用足。

% 使用最优参数训练最终 KELM 模型 sigma_best = best_pos(1); C_best = best_pos(2); K_train = rbf_kernel(X_train, X_train, sigma_best); alpha = (K_train + eye(size(K_train, 1)) / C_best) \ y_train; % 预测测试集 K_test = rbf_kernel(X_test, X_train, sigma_best); y_pred = K_test * alpha; % 反归一化回到原始数据尺度(如果之前做过标准化) y_pred_orig = y_pred * std_y + mean_y;

注意K_test的第二个参数必须传 X_train,不能传 X_test,否则核矩阵的行列含义就错了。核矩阵的语义是“测试样本与训练样本之间的相似度”,训练阶段 K_train 是 n_train 阶方阵,预测阶段 K_test 是 n_test 行 n_train 列矩阵,维度不对称是正常的,但要确保传入顺序正确。这个细节让我曾经在测试集上拿到过所有预测值几乎为常数的诡异结果,检查半天发现是核矩阵参数传反了。

4. 避坑排查:五类高频翻车现场与对应修正办法

4.1 适应度曲线不下降:鲸落阶段过早,种群失去搜索方向

现象:迭代到 30 代左右,适应度曲线就变成水平直线,best_fit 不再变化,最终预测精度远低于预期。

原因:Bf 下降速度过快,鲸落阶段过早到来。种群中大量粒子被随机重置,相当于每迭代几步就把搜索进度清零一次,算法退化成随机搜索。

解决:修改 Bf 的递减策略,把鲸落阶段的占比压缩到后 20% 的迭代。常见做法是Bf = 0.9 - 0.5 * t / MaxIt,让 Bf 的最小值维持在 0.4 附近,只有接近迭代末尾时才进入重置阶段。如果你用的是我在 3.4 节给出的模板,可以把 0.6 改成 0.4 或 0.5,然后观察适应度曲线变化。

4.2 训练集精度极高、测试集一塌糊涂:数据泄漏问题

现象:训练集 RMSE 逼近 0,R2 接近 1,但测试集 RMSE 比训练集大 10 倍以上。

原因:在划分训练集和测试集之前,对全部数据做了归一化。标准化时用到了测试集的均值和标准差,相当于把测试集的信息“泄漏”给了训练过程。优化器很容易找到一个在泄漏数据上表现完美的参数组合,但这个组合在真正的新数据上完全失效。

解决:严格先划分、后归一化。只用训练集的 mean 和 std 去标准化训练集和测试集,测试集数据在标准化前不参与任何统计量计算。这个坑是回归预测里最常见的“后悔药”场景——一旦泄漏,整个模型评估过程都要重来。建议写一个数据预处理函数,输入原始数据、划分比例和划分种子,输出已经标准化的训练集与测试集,避免手动操作漏掉顺序。

4.3 核矩阵出现 NaN 或 inf:sigma 搜索到极端值

现象:运行到某一代时控制台输出警告,提示矩阵接近奇异或包含 NaN,适应度值变成 NaN,best_pos 也变成 NaN。

原因:BWO 的边界约束只是把越界值拉回边界,但 sigma 被拉到下界 0.001 甚至更小时,exp(-dist2 / (2 * sigma^2))的指数项溢出,核矩阵中大部分元素变成 0,求逆时矩阵严重病态。

解决:在 rbf_kernel 函数内部加保护逻辑。当 sigma 小于某个阈值(如 1e-6)时,直接返回一个小扰动核矩阵K = eye(n1, n2) + 1e-6,避免数值爆炸。同时把 lb 的下界设置得合理一些,sigma 下界经验值不要小于 0.01,除非你的数据经过特殊缩放。

4.4 同一份代码跑两次,结果完全不同

现象:正常结束的运行,换一次随机种子后,最优参数和预测指标变化明显,R2 有 0.1 以上的波动。

原因:BWO 是随机优化算法,种群初始化、航行阶段的随机个体选择、鲸落的概率重置都依赖随机数流。没有固定随机种子时,每次运行都是一次不同的搜索轨迹。

解决:主程序开头用固定种子初始化随机数流:

% 固定随机种子,保证实验可复现 rng(42);

这样同时固定了种群初始化与后续所有随机过程。做参数实验时建议把种子作为变量循环跑 5-10 次,记录每次的最优 RMSE 均值和标准差,这才是一个可靠的性能评估。只跑一次就下结论,会把运气当成实力。

4.5 BWO 收敛速度过慢:种群数和迭代次数失衡

现象:500 次迭代跑完耗时超过半小时,但 R2 和 100 次迭代的结果差不多,提升不明显。

原因:对于 Dim=2 的低维优化问题,N=50、MaxIt=500 的配置严重冗余。BWO 单次迭代要计算 50 次 KELM 适应度,如果训练集有 5000 个样本,500 次迭代就是 25 万次核矩阵构造和求逆,计算量非常可观。

解决:先按 N=20、MaxIt=100 跑通流程,观察适应度收敛情况。如果 60 代以内已平稳,就保持这个配置;如果曲线还在稳定下降,再逐步增加 MaxIt。对样本量大的数据集,更激进的做法是把适应度函数改为随机子集采样评估,每代只用 30% 的样本估算 RMSE,后期再换全量验证。

5. 落地验证:数据归一化、三类指标与多场景测试

5.1 数据准备:划分比例与标准化策略

到手的原始数据通常是 Excel 或 CSV,第一列到倒数第二列是特征,最后一列是目标值。加载后的第一件事是划分训练集和测试集。实际工程中我通常只按时间顺序切分,不做随机打乱,因为回归预测面临的多数场景是“过去的样本预测未来的值”。如果数据有周期性,随机打乱会破坏时间依赖关系,导致测试评估失真。

% 加载数据 data = readmatrix('你的数据.xlsx'); X = data(:, 1:end-1); y = data(:, end); n = size(X, 1); % 按时间顺序 80% / 20% 划分 idx_split = round(n * 0.8); X_train = X(1:idx_split, :); y_train = y(1:idx_split, :); X_test = X(idx_split+1:end, :); y_test = y(idx_split+1:end, :); % 只使用训练集的均值与标准差做标准化 muX = mean(X_train); sigX = std(X_train); X_train = (X_train - muX) ./ sigX; X_test = (X_test - muX) ./ sigX; % 目标值同样处理,后续预测时要反标准化 muY = mean(y_train); sigY = std(y_train); y_train = (y_train - muY) ./ sigY; y_test = (y_test - muY) ./ sigY;

sigX在计算时如果某一列特征的标准差为 0,会导致对应维度变成 NaN。常见修复做法是在标准化之前先剔除方差接近 0 的列,或者加上一个极小值sigX(sigX < eps) = 1。这个细节在特征很稀疏的工业数据里经常会遇到。

5.2 指标选取:R2、RMSE、MAPE 各说明什么问题

调优完成后给出一组预测结果,三张通行证是决定论系数 R2、均方根误差 RMSE 和平均绝对百分比误差 MAPE。它们各回答一个问题:R2 看整体拟合优度,RMSE 看绝对偏差,MAPE 看相对偏差。代码里这样计算:

y_pred = K_test * alpha; y_pred_orig = y_pred * sigY + muY; % 反标准化 y_test_orig = y_test * sigY + muY; % R2:越接近 1 越好 SS_res = sum((y_test_orig - y_pred_orig).^2); SS_tot = sum((y_test_orig - mean(y_test_orig)).^2); R2 = 1 - SS_res / SS_tot; % RMSE:与实际值同量纲,越小越好 RMSE = sqrt(mean((y_test_orig - y_pred_orig).^2)); % MAPE:百分比误差的均值,注意样本真实值不能为 0 MAPE = mean(abs((y_test_orig - y_pred_orig) ./ y_test_orig)) * 100;

MAPE 有个天然缺陷:当真实值接近 0 时,百分比误差会爆炸。如果你的目标值包含大量小值,建议改用 SMAE 或加权 MAPE,否则一个接近 0 的样本会盖过所有正常样本的表现。我曾经在一个风功率预测任务里看到 MAPE 高达 240%,翻数据才发现是夜间风速接近 0 的几个点把平均相对误差拉爆了,改用 RMSE 做评价后模型马上显得合理。

5.3 多场景验证:同一套代码换数据,边界在哪里

为了检验这份代码的泛化能力,我在三个完全不同的数据集上做了复现测试:

数据场景样本量特征维度R2(测试集)RMSE(测试集)收敛迭代数
电力负荷预测350080.9233.4185
材料强度回归120060.9511.0260
经济时序预测80040.7120.84110

经济时序预测的 R2 明显偏低,原因不是代码有 bug,而是这类数据本身噪声大、非平稳性强,单靠 KELM 很难捕捉完整的规律。这说明 BWO-KELM 更适合特征与目标存在较强非线性映射的场景,对高噪声混沌数据,建议先做 EMD 分解或其他去噪预处理再喂给模型。

样本量变化时还要注意核矩阵计算时间:电力负荷数据上,单次适应度计算约 0.8 秒,BWO 优化全程约 2 分钟;经济时序数据样本少很多,同样的迭代次数只需 15 秒。如果训练集超过 8000 个样本,核矩阵就是 8000 阶方阵,求逆耗时急剧上升,此时更适合换成随机 Fourier 特征的近似核方法,保留核思想的精度又能降低计算复杂度。

6. 交叉验证适应度:让白鲸优化结果不再依赖单次数据划分

前面 3.4 节用的适应度函数是直接在训练集上计算 RMSE。这种做法有个隐患:优化器选出的参数可能只对那一次训练集划分有效,换一组训练数据就崩掉。我踩过这个坑,结果是模型测试集 R2 忽高忽低,最终自查发现问题出在适应度评估缺少交叉验证的稳定性约束。

解决办法是让每个粒子的适应度值等于 K 折交叉验证的均方根误差。把 calc_fitness 改成 cv_fitness 结构:

function fitness = cv_fitness(X_train, y_train, params, Kfold) % 每个粒子的适应度用 K 折交叉验证的 RMSE sigma = params(1); C = params(2); n = size(X_train, 1); idx = randperm(n); fold_size = floor(n / Kfold); err_sum = 0; for k = 1:Kfold % 划分第 k 折的测试索引与训练索引 test_idx = idx((k-1)*fold_size+1 : k*fold_size); train_idx = setdiff(1:n, test_idx); % 训练子集核矩阵 K_part = rbf_kernel(X_train(train_idx, :), X_train(train_idx, :), sigma); alpha_part = (K_part + eye(length(train_idx)) / C) \ y_train(train_idx); % 验证集预测 K_cv = rbf_kernel(X_train(test_idx, :), X_train(train_idx, :), sigma); y_cv_pred = K_cv * alpha_part; % 累加 RMSE err_sum = err_sum + sqrt(mean((y_train(test_idx) - y_cv_pred).^2)); end fitness = err_sum / Kfold; end

这段代码的价值是把“一次运气”变成“平均实力”。Kfold 取 5 时,每个粒子的适应度要训练 5 次核回归,总计算量是原来的 5 倍。但换来的是参数选择方向更加稳健,测试集指标不会随数据划分随机波动。调用时把 BWO 主循环里的calc_fitness(X_train, y_train, Positions(i, :))替换为cv_fitness(X_train, y_train, Positions(i, :), 5),其余逻辑不用动。

还有两个习惯我从那以后每次跑 BWO-KELM 都强制走一遍:第一,优化结束后把 best_pos 存到 .mat 文件里,下次预测直接加载参数,不做重复优化,代码是save('best_params.mat', 'best_pos');;第二,每次实验记录随机种子、边界范围、种群数、迭代次数、最终 R2 与 RMSE,这五个信息缺一不可。没有这些记录,两个月后回看结果时,你面对的就是一个黑匣子,连自己怎么跑出这个精度的都想不起来。这套代码本身不难,难的是把搜索边界和适应度评估逻辑调得贴合自己的数据。希望这份拆解能帮到你,直接下载跑一遍,再用你自己的数据替换,很快就能摸透它的脾气。

本文还有配套的精品资源,点击获取

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

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

立即咨询