尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

极限学习机(ELM)回归预测:原理、MATLAB实现与调参优化

极限学习机(ELM)回归预测:原理、MATLAB实现与调参优化 简介这是一份基于MATLAB的ELM极限学习机多输入单输出回归预测完整实现适合需要快速搭建单隐含层前馈神经网络预测模型的科研人员、竞赛选手或算法初学者。资源以7个输入特征、1个输出变量的回归数据为例提供从数据读取、极限学习机训练到预测评估的整套流程代码并配套说明文档与注意事项可帮助理解ELM的随机权重思想与回归建模步骤。压缩包共11个文件涵盖3个.m源码文件、5张结果展示图、1份Excel示例数据、1份docx说明文档和1份txt注意事项整体大小约363KB结构简单清晰。运行环境需为MATLAB2018b及以上版本描述中提到程序乱码可通过记事本打开复制解决。目前该资源已有1198人学习代码和数据集配合使用适合快速移植到自己的多输入单输出回归任务中。1. ELM 极限学习机的回归优势7 个特征直接映射到 1 个输出同样是 7 个特征预测 1 个连续变量BP 网络要反复调学习率、动量、初始权重稍不小心就落在局部最优ELM 极限学习机换了一条路隐藏层的输入权重随机生成之后只解一个最小二乘问题输出权重用伪逆直接算出来整个过程没有反向传播迭代。训练速度比 BP 快一个量级对中小规模回归数据尤其合适。这份资源包含 elmtrain.m、elmpredict.m、MainELMR.m、data.xlsx 和 5 张运行结果图输入 7 列特征、输出 1 列变量运行环境 MATLAB2018b 及以上。我会按“原理—源码—实战—调参”的顺序拆重点说明哪些参数真正影响结果、哪些报错属于格式问题而不是逻辑问题。2. ELM 工作原理随机权重、sigmoid 映射与广义逆求解2.1 单隐层网络的随机投影思想经典单隐层网络先计算隐层输出 h g(w^T x b)再通过输出层线性组合得到预测值。如果所有权重都走 BP学习率、动量项和初始值之间相互影响训练行为非常敏感。ELM 的视角是既然隐层只是把原始 7 维输入映射到高维特征空间而输出层本身是线性的那么输入权重 w 与偏置 b 就不一定需要通过梯度来学习。只要 g 是无限可微的激活函数比如 sigmoid随机生成的 w 和 b 就能让隐层输出矩阵以大概率满足逼近条件。这看起来反直觉实际相当于把输入做了一次随机投影高维空间下回归关系更容易被线性层抓住。对 N 个训练样本输入矩阵 X 的大小为 N×7隐层节点数为 L随机权重 IW 的大小是 7×L偏置 B 是 1×L。隐层输出矩阵 H g(X IW B)维度为 N×L。ELM 的训练任务变成求解线性系统 Hβ ≈ Y其中 Y 为 N×1 输出向量。与 BP 不同这里唯一未知的只有 β并且目标函数是凸的所以不会撞上局部最优。2.2 输出权重 β 的闭式解Moore-Penrose 广义逆2.2.1 最小二乘解的矩阵实现elmtrain.m 内部最核心的计算逻辑如下% ELM 训练核心计算随机映射 广义逆 X Xtrn; % 输入的7个特征N×7已由主脚本归一化 Y Ytrn; % 输出1个变量N×1已归一化 nNode 30; % 隐藏层节点数 rng(1); % 固定随机种子保证可复现 IW rand(7, nNode) * 2 - 1; % 输入层到隐层权重范围[-1,1] B rand(1, nNode) * 2 - 1; % 隐层偏置范围[-1,1] H 1 ./ (1 exp(-(X * IW repmat(B, size(X, 1), 1)))); % sigmoid beta pinv(H) * Y; % 广义逆求解输出权重逻辑说明X 与 IW 相乘得到 N×nNode 的线性组合值repmat 把偏置 B 复制成相同维度矩阵保证每个样本、每个隐层节点都有对应偏置1./(1exp(-z)) 是 sigmoid 激活pinv(H) 返回 H 的 Moore-Penrose 伪逆beta 的维度是 nNode×1。如果换成 inv(H*H)*H*Y会在 H*H 不可逆时报错用 pinv 则能处理 H 列不满秩或样本数小于节点数的情形这也是 ELM 工程实现中普遍采用这种写法的原因。参数说明nNode 是 ELM 的模型容量控制量。太小隐层无法提供足够特征维度欠拟合太大H 的列之间可能出现较强共线性训练误差很低但测试误差反弹。在数据量不大的回归任务里常见做法是从 10 扫到 100 或 150每个节点跑多次再取测试集 RMSE 最低的位置。2.2.2 与 BP 在训练机制上的差异BP 每一轮都要前向计算、反向传播、更新所有层权重ELM 只解一次线性最小二乘训练时间主要花在构造 H 和求伪逆上。实际对比中特征数不变时假设数据量几百条、隐层节点数几十ELM 通常几十毫秒就能完成训练而 BP 即使小规模也要迭代数百轮。两者差异见下表对比项BP 神经网络ELM 极限学习机训练方式反向传播迭代更新所有权重随机映射 广义逆闭式解主要调节参数学习率、动量、初始化、隐层节点隐层节点数、随机种子、激活函数主要风险局部最优、收敛慢、对初始值敏感节点过多时共线性与过拟合适用场景数据量大、需要精细调优的模型快速基线、回归/分类初步验证这张表解释了为什么回归预测场景里很多人先跑 ELM先用极限学习机确认 7 个输入特征确实能预测输出变量再往上加复杂度比一上来就用 BP 排错更容易定位问题。3. elmtrain.m / elmpredict.m / MainELMR.m 的源码结构与参数约束3.1 资源文件清单与运行顺序拿到 ELM.zip 之后先区分核心文件与展示文件。文件作用使用者需要改动吗elmtrain.m训练函数接收输入、输出、隐层节点数返回模型参数一般不改elmpredict.m预测函数接收测试输入和训练结果返回预测值一般不改MainELMR.m主脚本负责读 data.xlsx、划分数据、归一化、训练、预测、画图换数据时改这里data.xlsx示例数据前 7 列输入第 8 列输出替换成自己的数据ELMR1.png ~ ELMR5.png训练/测试结果图运行后覆盖不需要ELM极限学习机回归.docx项目说明文档参考注意事项.txt运行前必读包含乱码处理说明参考执行顺序是 MainELMR.m 从上往下读入 data.xlsx划分为训练集和测试集归一化调用 elmtrain 训练调用 elmpredict 预测最后画图。两个 .m 函数只是被调用不在主脚本里展开。换数据时最省事的做法是保持 data.xlsx 的列顺序前 7 列特征、第 8 列输出然后只改 MainELMR.m 里的节点数和随机种子。3.2 MainELMR.m 的数据导入与训练测试划分主脚本打开后一般会看到类似下面的骨架% MainELMR.m 主流程常见封装方式 clear; clc; close all; data xlsread(data.xlsx); % 读取 Excel 数据 X data(:, 1:7); % 前 7 列为输入特征 Y data(:, 8); % 第 8 列为输出变量 n size(X, 1); % 样本总数 idx randperm(n); % 随机打乱索引 numTrain round(0.7 * n); % 70% 样本训练 Xtr X(idx(1:numTrain), :); Ytr Y(idx(1:numTrain), :); Xte X(idx(numTrain1:end), :); Yte Y(idx(numTrain1:end), :);逻辑说明xlsread 在 MATLAB2018b 及以上可以直接读 xlsx。randperm(n) 产生一个 n 长的随机排列用它切分训练集和测试集避免按原顺序划分时因为数据分布偏移影响评估。round(0.7*n) 保证训练集数量为整数Xtr 与 Ytr 的行数一一对应Xte 与 Yte 同理。参数说明0.7 是训练比例样本量更小的时候建议改成 0.8或者直接做 K 折交叉验证。这里有一个容易忽略的点切分之后无论用不用归一化都要保证 elmtrain 收到的输入矩阵是 N×7输出矩阵是 N×1。如果读出来的 Y 恰好是行向量建议在调用前显式执行 Ytr Ytr(:)避免维度匹配报错。3.3 elmtrain.m 与 elmpredict.m 的输入输出约定常见版本的 elmtrain.m 接口如下function [IW, B, beta] elmtrain(X, Y, numberHiddenNeurons, activationType) % X: N×features % Y: N×1 % numberHiddenNeurons: 隐藏层节点数 % activationType: sig、sin、hardlim 之一函数内部先检查 size(X,1) 和 size(Y,1) 是否相等再检查节点数是否大于样本数。这两个检查是 ELM 源码最容易暴露的边界约束。如果 numberHiddenNeurons 超过样本数H 的列数大于行数pinv 虽然仍能给出一个解但这个解只是满足最小训练误差的最小范数解泛化性没有保证。因此常见做法是在源码里直接加入判断if size(X, 1) numberHiddenNeurons error(隐藏层节点数不能超过训练样本数); endelmpredict.m 的接口与之对应function Y_hat elmpredict(X, IW, B, beta, activationType)它接收输入权重 IW、偏置 B、输出权重 beta用与训练时完全相同的激活函数重新计算 H然后乘 beta 得到预测值。这里需要注意训练时如果对数据做了归一化预测前必须用训练集得到的归一化参数处理测试集不能拿测试集重新做一次归一化否则数据泄漏会让评估结果虚高。激活函数参数是另一个容易踩的坑。elmtrain 用 sigelmpredict 里也必须用 sig训练时用 sin预测时写回 sig输出权重对应的是另一组隐层特征预测结果会完全错乱。换用自己数据时最关键的是列顺序和归一化参数传递隐藏层节点数后面再扫。4. 用 data.xlsx 复现多输入单输出回归归一化、训练与绘图4.1 为什么要对 7 个输入特征做归一化data.xlsx 里的 7 个特征如果有量纲差异比如一列在 0.1 量级、另一列在几千量级sigmoid 的输入区间会被大数值特征主导H 很容易饱和到接近 0 或 1矩阵条件数变大最后 beta 的数值稳定性变差。虽然 ELM 不依赖梯度下降但矩阵求解阶段对输入尺度仍然敏感所以先归一化再训练是标准操作。常见归一化方式见下表方法公式 / MATLAB 函数输出范围适用场景mapminmaxmapminmax(x, 0, 1)[0,1]量纲差异大、值无界特征mapminmax 对称版mapminmax(x, -1, 1)[-1,1]激活函数输出带正负时更稳zscore(x - mean(x)) / std(x)均值为0、方差1特征方差差异大、希望保留分布形状在 ELM 场景里我一般选 mapminmax 到 [0,1]因为 sigmoid 的输出范围正好是 [0,1]输入和隐层输出处于同一量级数值表现最直观。注意 mapminmax 默认按行处理矩阵输入 Xtr 是 N×7要先转置成 7×N得到归一化结果后再转回 N×7否则会把每一列当作一个样本结果面目全非。4.2 完整流程归一化、训练、预测、反归一化下面这段代码是 MainELMR.m 里最值得逐行看的片段% 1. 训练数据归一化记录参数 [Xtrn, ps_in] mapminmax(Xtr, 0, 1); % 训练输入转置后归一化得到 7×N [Ytrn, ps_out] mapminmax(Ytr, 0, 1); % 训练输出转置后归一化得到 1×N % 2. 用训练集的归一化参数处理测试集避免数据泄漏 Xten mapminmax(apply, Xte, ps_in); % 测试输入7×M Yten mapminmax(apply, Yte, ps_out); % 测试输出1×M % 3. 训练与预测 rng(1); % 固定随机种子 [IW, B, beta] elmtrain(Xtrn, Ytrn, 50, sig); % 训练 ELM pred_norm elmpredict(Xten, IW, B, beta, sig); % 预测归一化输出M×1 % 4. 反归一化回原始尺度 pred mapminmax(reverse, pred_norm, ps_out); % 得到 M×1逻辑说明第一步把 Xtr 转置成 7×Nmapminmax 才能按每个特征一行做归一化返回的 ps_in 是结构体记录每行的 min 和 range。第二步用 apply 让测试集使用训练集统计出的 min 和 range保证两个集合落进同一个线性变换否则预测会失真。第三步中 elmtrain 的输入 Xtrn 又转回 N×7与函数接口保持一致。第四步把 elmpredict 输出的 M×1 先转置成 1×M用 reverse 恢复原始输出量纲再转置回来。这里有个非常典型的报错mapminmax(reverse, pred_norm, ps_out) 直接传 M×1 矩阵MATLAB 会报维度错误因为 reverse 期望的行数与 ps_out 保存的行数一致。记住在 ELM 这类回归流程里归一化和反归一化的操作对象始终以“每个变量一行”为准样本维度永远放在列方向。新手在这里卡住时先检查矩阵是 N×k 还是 k×N。4.3 训练/测试对比图与评估指标项目里的 ELMR1.png 到 ELMR5.png常见内容包括训练集真实值与预测值对比、测试集对比、误差曲线、散点回归图和误差直方图。主脚本中测试集对比图通常是这样% 测试集真实值与预测值对比 figure; plot(1:length(Yte), Yte, o-, LineWidth, 1.2); hold on; plot(1:length(pred), pred, x-, LineWidth, 1.2); legend(真实值, 预测值); xlabel(样本序号); ylabel(输出变量); title(ELM 测试集回归预测对比);说明这条曲线最直观地反映模型是否跟住了输出变量的变化趋势。如果真实值波动剧烈预测曲线只是近似均值说明隐藏层节点数不够或者输入特征与输出之间的非线性关系没有被充分表达如果训练集贴合良好但测试集完全走平则优先怀疑过拟合。除了画图建议再用三个指标评估R2 1 - sum((Yte - pred).^2) / sum((Yte - mean(Yte)).^2); RMSE sqrt(mean((Yte - pred).^2)); MAE mean(abs(Yte - pred)); fprintf(R2%.4f RMSE%.4f MAE%.4f\n, R2, RMSE, MAE);R2 接近 1 表示模型解释了绝大部分方差RMSE 对较大误差敏感用于判断极端预测是否离谱MAE 反映平均偏离幅度。这三个指标同时看比只盯着 R2 更稳。4.4 乱码与运行环境问题注意事项.txt 里一般会提到程序打开乱码是 MATLAB 版本不一致导致的编码问题不是源码损坏。常见做法是右键 .m 文件用记事本打开全选复制到 MATLAB 新建脚本中或者在记事本里另存为 UTF-8 编码再让 MATLAB2018b 及以上版本打开。这样做不影响 elmtrain.m、elmpredict.m 的计算逻辑只是中文注释显示恢复正常。如果直接双击打开后看到一串不认识的乱码字符先不要改源码按上面方式重新保存编码再试。运行环境按摘要要求选择 MATLAB2018b 及以上旧版本在 xlsread 读取 xlsx 和图形 handle 的兼容性上会更差一些。5. 隐藏层节点数与随机种子的 ELM 调参技巧5.1 扫描节点数并固定随机种子ELM 的随机权重让每次运行结果不同所以调参第一步不是找最优学习率而是固定随机种子再用循环扫隐藏层节点数。常见做法如下nodeList 10:10:120; for i 1:length(nodeList) rng(1); % 每个节点都用同一随机序列 [IW, B, beta] elmtrain(Xtrn, Ytrn, nodeList(i), sig); pred_norm elmpredict(Xten, IW, B, beta, sig); pred mapminmax(reverse, pred_norm, ps_out); rmse(i) sqrt(mean((Yte - pred).^2)); end逻辑说明rng(1) 放在循环里确保不同节点数使用的是同一组随机权重序列这样测试 RMSE 的差异主要来自节点数变化而不是随机种子。扫描结果的常见规律是 RMSE 先下降、进入平台、再上升上升段就是节点过多开始过拟合的区域。5.2 多随机种子平均更可靠固定 rng(1) 适合复现但单个种子有可能撞上一个特别差或特别好的随机投影。做对比实验时可以对每个节点数跑多次取平均for i 1:length(nodeList) tmp zeros(1, 10); for rep 1:10 rng(rep); % 不同种子 [IW, B, beta] elmtrain(Xtrn, Ytrn, nodeList(i), sig); pred_norm elmpredict(Xten, IW, B, beta, sig); pred mapminmax(reverse, pred_norm, ps_out); tmp(rep) sqrt(mean((Yte - pred).^2)); end rmse_avg(i) mean(tmp); rmse_std(i) std(tmp); end这样不仅能选节点数还能看到 ELM 在该数据上的稳定性。若 std 很大说明随机投影波动明显此时可以通过增加节点数降低偏差或者考虑用集成版本把多个 ELM 的预测平均。5.3 验证过拟合的快速方法选完节点数后用同一模型计算训练集 RMSE 和测试集 RMSE。训练集远低于测试集说明隐层节点过多两者都高说明节点不足。最直接的验证是把节点数增加到最优值的 1.5 倍和 2 倍看测试 RMSE 是否反弹。反弹说明当前数据量承载不了更大的隐层应回到最低点附近再固定随机种子重新训练得到可用于后续预测的最终模型。本文还有配套的精品资源点击获取
返回列表