MATLAB实现基于MOE-SVR 专家混合(MoE)结合支持向量回归(SVR)进行股票价格预测的详细项目实例

请注意此篇内容只是一个项目介绍 更多详细内容可直接联系博主本人 

 或者访问对应标题的完整博客或者文档下载页面(含完整的程序,GUI设计和代码详解)

现代金融市场中,股票价格序列呈现出高噪声、高非线性、强非平稳、多尺度波动等复杂特征,传统的线性时间序列模型在面对这些特点时往往表现乏力。回归类机器学习方法,尤其是支持向量回归(SVR),由于具备良好的泛化能力和对小样本、高维输入的适应能力,在金融预测场景中得到了广泛关注。在利用SVR预测股票价格的实践过程中,常见做法是针对单一数据集训练一个统一的SVR模型,或者通过简单的模型集成方式(如平均、加权平均)融合多个回归模型的输出,但这类策略对数据分布的非均匀性与结构性差异往往缺乏针对性的刻画能力,难以从根本上提高预测精度和稳定性。

专家混合模型(Mixture of Experts, MoE)是一类重要的分而治之模型结构,其思想是将输入空间划分为多个区域,由不同的“专家”子模型分别建模不同区域的数据,同时利用一个门控网络(Gating Network)根据输入特征为各个专家分配权重。MoE框架非常适合处理金融时间序列这种“片段间规律不同”的情形:例如在趋势上涨、震荡盘整、急跌回调等不同市场阶段,价格行为模式、成交活跃度和波动结构都存在显著差异,单一模型难以在所有阶段保持一致表现,而MoE可以通过门控网络对不同阶段选择更擅长刻画该阶段特征的专家,从而提升整体预测性能。

支持向量回归作为一种核方法,能够通过核函数将输入非线性映射到高维特征空间,在该空间中学习近似线性的回归函数,从而强化对复杂非线性关系的拟合能力,并通过间隔最大化与结构风险最小化的原则增强模型的泛化能力。将MoE框架与SVR结合,形成基于MOE-SVR的混合专家回归模型,在股票价格预测任务中具有非常明显的吸引力:每个专家采用SVR结构负责不同的数据子区域,门控网络则根据输入特征在多个SVR专家之间进行软选择,通过加权融合输出构建整体预测。这样既保留了SVR对非线性关系的刻画能力,又利用MoE的结构分解优势,将复杂任务拆解为多个相对简单的子任务。

在MATLAB平台上构建MOE-SVR股票预测项目,一方面可以充分利用MATLAB在数值计算、矩阵运算、可视化以及回归建模方面的成熟工具箱支持;另一方面,也能够构建一套相对完整、可复现实验流程:从原始行情数据读取、预处理、特征构造、训练集与测试集划分,到MoE门控网络训练、各SVR专家参数选择、模型融合输出、预测性能评价与结果可视化分析,形成一个完整的工程化案例。特别是在MATLAB R2025b版本下,回归建模函数接口、可视化组件和一些机器学习函数的参数规则有所调整,需要在项目实现时进行适配,以确保代码在最新版本环境中稳定运行。

在股票数据层面,除收盘价外,开盘价、最高价、最低价、成交量、换手率等指标,以及技术指标(如移动平均线、相对强弱指数RSI、MACD等)都能作为特征输入MoE-SVR模型,从而让门控网络和各个SVR专家学会在不同市场状态下提取更有效的信息。通过对历史时间窗口构建特征向量,再用后一时刻的价格或收益率作为预测目标,可以搭建基于滑动窗口的监督学习框架,让模型在训练阶段充分捕捉时间依赖关系与状态转移模式。

在项目工程实现中,MoE-SVR的训练过程可以分两条主线:一条主线针对门控网络的参数优化,使其输出在不同样本点上对各专家的权重分布合理;另一条主线针对各SVR专家的参数学习,使其在被赋予较高权重的样本子集上达到更优拟合效果。在MATLAB环境中,门控网络可以采用带Softmax输出层的多层感知机(MLP),使用fmincon或自定义梯度下降方式进行优化;SVR部分可以利用fitrsvm等函数对每个专家单独训练,注意R2025b中与核函数、标准化和超参数优化相关的规则,结合交叉验证或网格搜索选择核参数与惩罚系数。

股票价格预测的目标不仅是给出数值上的未来价格估计,更重要的是在实际策略开发中衡量预测误差对收益及风险控制的影响。通过项目中的MOE-SVR模型,有助于探索在不同市场阶段的预测误差特征,分析门控网络在多大程度上学习到了“牛市”、“震荡”、“熊市”等状态间的隐含划分。进一步配合误差分析图、残差分布图以及各专家权重随时间变化的可视化,可以从模型结构层面理解各模块在不同阶段的作用,提高金融建模的可解释性与可信度。

本项目通过MATLAB R2025b中的矩阵运算能力和回归算法接口,构建一个可重复、可扩展的MOE-SVR股票预测案例,既可以作为机器学习方法在金融时序任务中的工程实践模板,也可以作为研究“分而治之+核方法”在复杂系统预测中的有效组合策略的实验平台。通过系统地设计数据管线、模型结构、训练流程与评估指标,为后续拓展到多资产组合预测、风险因子建模、量化选股因子构造等工作打下技术基础。

项目目标与意义

提升股票价格预测的精度和稳定性

项目的首要目标是利用MOE-SVR架构在股票价格预测任务中取得比传统单模型回归更高的预测精度和更好的稳定性。单一SVR模型在面对不同市场阶段时往往受到参数折衷的限制:参数设置适合趋势行情时,在震荡行情中会出现过拟合或欠拟合;而适合震荡行情的参数组合,在剧烈波动时又无法很好地捕捉大幅价格变动。MOE-SVR通过多个SVR专家并行建模,门控网络根据当前特征自适应分配权重,从而形成针对不同数据子结构的专门模型。项目在目标设计上会关注多种误差指标,如均方误差(MSE)、平均绝对误差(MAE)、最大绝对误差以及R平方等,从而多角度衡量预测效果。通过在训练集和测试集上的系统评估,对比单SVR模型、传统多模型平均策略和随机游走基准模型,验证MOE-SVR在实际股票预测场景中的收益。稳定性方面,则重点分析在不同市场阶段和不同波动水平下误差的稳定程度,期望在较长时间区间内保持相对平滑的预测性能,而非仅在短期样本内呈现偶然性提升。

在非线性和非平稳时间序列建模中验证MoE+SVR的有效性

股票价格序列往往表现为非线性、非平稳、带有突变和结构断点的复杂动态过程。传统的统计模型大多基于平稳性和线性结构的前提,对“结构变换”和“状态切换”的刻画能力有限。本项目将MoE的“局部专家+门控”机制与SVR的核回归能力结合,在股票预测任务中系统验证这一结构对非线性和非平稳序列的适配性和有效性。从模型设计角度,门控网络的输入不仅包括价格本身,还可以包括技术指标和波动性特征,使得门控网络在不同波动 regimes 之间形成软划分;而各个SVR专家在被分配到的样本子集上,专注于局部规律的拟合,从而在局部区域内实现更高的精度。本项目在实验部分会设计多组对比:如固定专家数量与改变门控网络结构的对比、固定门控结构与改变核函数类型的对比等,观察对预测性能的影响。通过系统实验,将MoE+SVR结构置于金融时间序列的背景下进行评估,为后续将其应用到更广泛的非线性时间序列预测问题提供参考。

构建一套可复现、可扩展的MATLAB MOE-SVR工程示例

项目的另一重要目标是提供一个在MATLAB R2025b环境下可直接运行、可复现的MOE-SVR股票预测工程示例。该示例覆盖从数据读取、特征工程、训练测试划分、模型训练、性能评估到可视化展示的完整流程,并严格遵循R2025b的语法与函数使用规范,避免版本不兼容问题。工程结构上,将不同功能模块进行清晰划分,如数据预处理模块、门控网络训练模块、SVR专家训练模块、预测与误差分析模块等,便于扩展和重用。为方便实际使用,项目中的代码示例会采用清晰的变量命名和逐行注释方式,确保在读取真实行情数据后只需做少量修改即可应用在新的标的或新的时间区间上。通过这样的工程模板,不仅能够加快研究者对MOE-SVR结构的理解,也为后续加入更多专家类型(如神经网络专家、树模型专家)打下基础,增强整个预测系统的可扩展性和可维护性。

为量化投资策略研发和风险管理提供技术支撑

项目的最终目标不是停留在纯粹的模型层面,而是服务于量化投资策略研发与风险管理实践。股票价格预测结果可以直接嵌入到多种策略框架中,例如趋势跟随、均值回归、波段交易、择时调仓等。通过对未来一个或多个交易日价格的预测,可以构建基于预测信号的多空仓位调整规则,并在回测环境中评估其收益、回撤和风险暴露水平。本项目通过在MATLAB中构建MOE-SVR预测模块,为后续策略层的搭建提供输入信号,并为风险管理模块(如VaR估计、压力测试)提供更细致的价格路径预测。此外,通过门控网络在各个时间段对不同专家的权重,可以间接反映市场状态变化,为风险管理人员提供关于“当前处于何种市场环境”的定性和定量参考。项目从技术层面推动了机器学习预测模型与实务量化策略的融合,为在实盘中引入结构更复杂、解释更丰富的预测模型提供了参考实现。

项目挑战及解决方案

股票价格序列的高噪声和非平稳性处理

股票价格序列具有显著的噪声成分和非平稳性,在短时间尺度上经常受到突发信息、情绪交易、流动性变化等因素影响,导致价格波动中包含大量随机成分。直接用原始价格做监督回归,会导致模型在训练阶段过度拟合高频噪声,在测试阶段表现严重劣化。项目面临的首个挑战就是如何在MoE-SVR架构中处理这一高噪声、非平稳的数据来源。为此,在解决方案设计时,从三个方面着手:一是数据预处理层面,通过差分、对数收益率转换或局部平滑等方式,减少趋势和尺度变化对模型学习的干扰。例如使用对数收益率代替原始价格作为预测目标,可以一定程度上减弱非平稳性;使用滚动均值或中值滤波构造特征,缓和极端价格波动的影响。二是特征构造层面,利用技术指标、多尺度移动平均、波动率估计等特征,引导模型把注意力集中在更具有经济意义的结构性信息上,而不是纯噪声部分;也可以加入部分滞后特征,帮助模型捕捉短期自相关结构。三是在MoE-SVR模型结构中,通过门控网络实现对不同“波动状态”的软划分,使得高波动阶段的数据更多地交由专门处理剧烈波动的SVR专家进行拟合,而低波动阶段则由更加平滑的专家进行建模。通过这种“状态划分+专家专门化”的策略,有助于缓解非平稳性带来的建模困难。实验证明,在引入合理的预处理及特征工程后,MoE-SVR在测试集上的误差指标更为稳定,尤其是在波动较大的区间内,预测精度相较基线模型有明显改善。

门控网络与多个SVR专家联合训练的复杂性

MoE-SVR的结构虽然带来更强的表达能力,但也增加了训练过程的复杂性。门控网络的参数与各个SVR专家的参数相互作用:门控网络根据输入分配不同专家的权重,而SVR专家的拟合效果又会反作用于门控网络的权重学习,整体训练具有一定的耦合性。若简单采用“先训练SVR,再训练门控网络”的分离式流程,容易出现门控网络对专家分工不合理、部分专家长期处于“闲置”状态的问题,导致模型整体能力未被充分发挥。针对这一挑战,项目在训练策略上采用一种分阶段迭代优化思路,使得门控网络和专家参数在若干轮迭代中逐步协调:初始阶段,通过对全部样本训练一个粗略的SVR模型,作为各专家的初始参数;然后训练一个简单的门控网络,使其按输入特征将样本大致分成若干簇;在此基础上,每一轮迭代中,先根据当前门控网络为每个样本计算专家权重,按权重为各专家构造“软样本集”(即样本对专家的影响按权重缩放),再分别利用fitrsvm对每个专家进行再训练;随后固定专家参数,对门控网络进行若干轮梯度更新,以最小化整体预测误差。这种分阶段迭代方法虽然不是最严格的联合优化,但在工程上更易实现,也更符合MATLAB R2025b环境中对回归函数调用和优化例程的使用习惯。为了防止训练过程中出现数值不稳定和过拟合,还在门控网络中加入L2正则化与早停策略,在SVR专家中通过交叉验证和网格搜索选择合适的惩罚参数与核函数参数,同时限制专家数量防止模型过于庞大。通过反复实验调整,可以在训练复杂度与预测性能之间取得良好平衡。

MATLAB R2025b环境与MOE-SVR实现细节的适配

MATLAB R2025b在一些机器学习函数和可视化接口上与旧版本存在差异,项目需要在实现过程中充分考虑这些变化,避免出现参数不兼容或函数调用错误。例如,对于回归模型,fitrlinear在当前版本对Regularization、Standardize、KernelScale等参数有新的限制条件,fitrnet在正则化参数使用上也有所调整;此外,在可视化和UI组件方面,R2025b不再推荐使用某些旧组件组合方式,需要用更基础的figure和uicontrol构建简单界面。项目的解决方案是在模型实现中优先选用fitrsvm作为SVR专家的训练函数,结合R2025b的参数规则,只使用当前版本稳定支持的选项,如合适的核函数名称、BoxConstraint、Epsilon等。同时,在必要的超参数搜索中,避免使用不再推荐或不兼容的优化选项,而是采用手工网格搜索配合交叉验证的方式,确保兼容性。门控网络部分则采用MATLAB基础矩阵运算和自定义MSE损失函数,利用fmincon或自编梯度下降实现参数更新,不依赖深度学习工具箱中的高层接口,以适应R2025b在dlnetwork和相关工具上的限制。在可视化分析中,所有颜色映射采用colormap(fig, turbo)的形式,不对不支持的对象调用colormap;在构建简单交互界面时使用figure和uicontrol,避免R2025b中不推荐的UI组件组合。通过对版本细节的仔细适配,使整个MOE-SVR项目在R2025b中运行稳定,避免因版本差异导致的训练中断或可视化错误。

项目模型架构

输入特征与目标变量设计

MOE-SVR股票预测模型的输入特征设计直接影响门控网络和SVR专家的学习效果。模型采用多维输入向量形式,将时间序列在一个固定长度的历史窗口内的信息压缩为一个特征向量,用于预测下一个时间点的价格或收益。典型做法是选取过去N天的收盘价、最高价、最低价、成交量等原始行情数据,并计算相关技术指标,如N日移动平均、N日移动标准差、RSI、MACD等,将这些数值统一构成特征向量x。比如窗口长度为10天时,可以将这10天的收盘价标准化后串联在一起,再加上技术指标值,从而形成维度较高的输入。当特征维数较高时,SVR的核方法能够在高维空间中构建非线性回归面,适应复杂的输入模式。

目标变量可选择未来一天的收盘价、未来一天的对数收益率或未来多天价格的某种函数。为了减弱非平稳性,本项目中更倾向于采用对数收益率作为目标变量y,使得序列的均值和方差相对稳定,有利于回归模型的拟合。针对训练和测试数据的划分,一般按照时间顺序划分成训练集和测试集,而不是随机打乱,以保持时间依赖关系。输入特征在进入模型前,还可以进行标准化处理,如对每一维特征减去训练集均值再除以标准差,以保证各维度尺度相近,避免某些尺度较大的特征在训练中主导损失函数。

特征设计中还可以考虑加入一些反映市场状态的指标,如短期波动率、成交量均值与标准差、价量相关系数等,这些特征直接影响门控网络对“市场状态”的判断,使其在高波动时期更多激活相关专家,而在平稳时期选择另一类专家。整个输入特征向量既为门控网络提供分段依据,又同时馈入各个SVR专家,使得专家在同一输入空间上学习,但对不同区域的拟合侧重点各不相同。通过合理的输入特征设计,MOE-SVR能够在金融时序预测中实现更细致的模式区分。

门控网络结构与原理

门控网络是MoE架构的核心组件,其作用是根据当前输入特征x为每个SVR专家分配一个非负权重,所有权重之和为1。门控网络可视为一个多类概率输出模型,其输出向量g(x) = [g1(x), g2(x), …, gK(x)],K为专家数量,gi(x)表示在输入x下第i个专家的权重或“责任度”。最常用的门控结构是前馈神经网络(MLP)加Softmax输出层:输入层接收特征向量x,经过一到两层隐藏层的非线性变换,最后通过线性层映射到K维向量,再经Softmax函数规范化成概率分布。Softmax函数形式为gi(x) = exp(zi)/∑j exp(zj),其中zi为第i个专家的线性激活值。这样的设计可以保证输出权重介于0和1之间且总和为1,便于解释和后续加权计算。

从原理上看,门控网络试图学习一种“软划分”规则,将输入空间划分为K个重叠子区域,每个专家主要服务于自己负责的区域。与传统聚类不同,门控网络的划分是输入相关的、带监督信息的:划分的目标是让整体预测误差最小,而不是仅仅基于输入空间密度。门控网络参数通过最小化MoE整体损失函数进行训练,损失函数通常采用加权误差形式:L = ∑n ∑k gk(xn) * (yk - fk(xn))^2,其中fk为第k个SVR专家的输出。通过对门控网络参数进行梯度下降更新,可以促使其将更多权重分配给在当前样本点上表现更好的专家,从而逐步形成“输入模式到专家组合”的映射。

在MATLAB R2025b环境中,门控网络可以通过自编函数实现:使用矩阵乘法和非线性激活函数(如tanh或ReLU)进行前向计算,在训练时手写梯度或利用数值优化工具(如fmincon)进行参数调整。由于门控网络规模相对较小,一般不需要深度学习工具箱的高级接口。通过调节隐藏层节点数与正则化系数,可以控制门控网络复杂度,避免过拟合训练数据。门控网络的输出不仅影响预测结果,还可以用于分析模型在不同时间段主要依赖哪些专家,从而为市场状态识别提供有价值的辅助信息。

SVR专家模型结构与核函数选择

每个专家采用SVR作为基本回归模型。SVR源自支持向量机思想,通过在特征空间中寻找一个平衡拟合误差与模型复杂度的回归函数。给定输入x和目标y,SVR的目标是找到函数f(x) = w^T φ(x) + b,使得预测误差在一个ε-不敏感带内尽可能小,同时保持w的范数较小。通过引入松弛变量和惩罚系数C,得到的优化问题可用对偶形式求解,支持不同核函数的选择。核函数的作用是隐式地将输入映射到高维特征空间,常用核函数包括线性核、多项式核和径向基函数(RBF)核。其中RBF核在股票价格等非线性任务中应用广泛,其形式为K(x,x′) = exp(-γ||x - x′||^2),γ决定高维空间中映射的“宽度”。

在本项目中,每个SVR专家在结构上基本一致,但参数上可能有所区别。通过选择不同的核参数γ和惩罚系数C,可以让某些专家更擅长拟合平滑变化的区间,而另一些专家更擅长捕捉剧烈波动。训练时采用MATLAB的fitrsvm函数,设定核函数为'gaussian',调整BoxConstraint(对应C)和Epsilon参数。由于R2025b对部分回归函数参数有所限制,fitrsvm依然是稳定选择。对于每个专家,可以单独进行小规模网格搜索或使用交叉验证,在训练集上选取性能较优的参数组合,或者在MoE训练的迭代过程中逐步微调。

SVR专家主导的是局部回归行为:当某一类输入样本在特征空间里具有相似性时,其对应的门控输出会偏向某个专家,该专家的SVR核函数在该局部区域达到更好的拟合效果。通过K个专家的组合,整体模型实现了“多核、多参数”的多样性,增强了对复杂模式的表达能力。每个专家的SVR模型既是独立训练的,也通过门控网络的权重在整体损失中耦合,因此在训练设计上需要平衡专家数量、参数多样性与训练时间成本。

MOE-SVR整体前向传播与预测机制

MOE-SVR的整体前向传播过程可概括为“门控权重计算+专家输出计算+加权融合”三步。给定一个新的输入样本x,首先送入门控网络进行前向运算:经过若干层矩阵乘法和非线性激活,得到一个K维的未归一化输出向量z,再通过Softmax函数转换为权重向量g(x)。这一步确定了在当前输入下各个专家的相对重要程度。然后,输入x同样送入每个SVR专家,利用其核函数和支持向量计算各自的回归输出fk(x)。在MATLAB中,fitrsvm训练得到的回归模型可以直接调用predict函数对新样本进行预测。完成所有专家输出计算后,整体预测结果为f(x) = ∑k gk(x) fk(x),即各专家输出的加权平均。

这种加权预测机制的优势在于,可以灵活组合多个专家的能力,而不是在所有输入上强迫某一个专家承担全部预测任务。当某个专家在当前输入附近样本中表现良好时,门控网络会自动为其分配较高权重,使其贡献主导;当输入处于另一个模式区间时,门控网络则激活另一组专家。由此形成的整体模型相当于一个输入依赖的加权回归系统,其内部是多核、多参数、多区域联合运作的结构。对于股票价格预测任务,这意味着模型可以根据当前市场状态自适应调整“预测策略”:如在趋势明显时更多依赖擅长趋势拟合的专家,在震荡或高噪声区间则由擅长平滑预测的专家主导。

前向传播机制在实现上相对简单,却是整个MoE结构的核心运行方式。对于时间序列,可对每个时间点构造输入特征向量后进行前向预测,得到一条随时间变化的预测曲线。结合真实价格序列,便可以计算误差曲线和误差统计量,并通过可视化观察门控权重随时间的动态变化,分析模型在不同阶段主要依赖哪些专家,为理解模型决策提供直观依据。

训练流程、损失函数与优化策略

MOE-SVR的训练本质上是一个同时包含门控网络参数和多个SVR专家参数的联合优化问题。从系统角度,目标是最小化数据集上整体预测误差,同时通过正则化控制模型复杂度。损失函数可以采用加权平方误差形式:L = ∑n (yn - ∑k gk(xn) fk(xn))^2 + λ||θg||^2 + ∑k λk||θk||^2,其中yn为真实目标值,gk(xn)为门控网络输出权重,fk(xn)为第k个SVR专家输出,θg和θk分别为门控和专家参数,λ和λk为正则化系数。直接对所有参数进行联合优化在工程上较为复杂,尤其是在MATLAB环境下对SVR部分使用fitrsvm的情形。因此项目采用分阶段迭代的近似优化策略:在每一轮迭代中,先固定门控网络,根据当前权重用加权样本训练SVR专家;然后固定专家,对门控网络进行若干步梯度更新,使其更好地分配权重。

具体流程可以设计为:首先使用全部训练样本训练K个初始SVR专家,获得基础回归能力;然后初始化门控网络参数为小随机值,通过若干轮迭代进行以下操作:1)前向计算所有样本的门控权重;2)构造每个专家的样本权重向量(如wnk = gk(xn)),利用fitrsvm中的'Weights'参数对每个专家进行再训练,使得其在获得高权重的样本上拟合得更好;3)计算在当前专家输出下的整体预测误差,对门控网络参数执行梯度下降或利用fmincon最小化误差。通过多轮迭代,门控网络与专家模型逐步协调,门控在不同输入区域选择最能降低误差的专家组合。

在MATLAB R2025b中,为避免对不再推荐的自动超参数优化机制的依赖,专家训练中的参数调节采用手工网格或简单搜索策略,例如为C和γ设定若干候选值,在少量验证样本上评估表现。为了防止过拟合,训练过程中可使用早停策略,当在验证集上的误差不再降低时停止迭代;同时适当限制门控网络大小和专家数量,控制整体参数规模。通过这一训练与优化策略,MOE-SVR模型能够在合理时间内收敛到较优解,兼顾预测精度与模型复杂度。

项目模型描述及代码示例

stockFile = 'stock_data.csv'; % 指定包含股票历史数据的CSV文件名称,文件需事先准备在当前工作目录或指定路径
rawTable = readtable(stockFile,'PreserveVariableNames',true); % 读取CSV数据为表格形式,保留原始列名便于后续按列名索引
dateVec = rawTable.Date; % 提取日期列,便于后续按时间顺序分析与可视化
closePrice = rawTable.Close; % 提取收盘价列,用作构造收益率与部分技术指标的基础
highPrice = rawTable.High; % 提取最高价列,用于衡量当日价格波动区间
lowPrice = rawTable.Low; % 提取最低价列,同样用于波动区间及技术指标计算
volume = rawTable.Volume; % 提取成交量列,作为量能特征反映市场活跃度
closePrice = fillmissing(closePrice,'linear'); % 对收盘价中的缺失值采用线性插值填补,减少缺失数据对建模的不利影响
openPrice = fillmissing(openPrice,'linear'); % 对开盘价缺失值做线性插值,保持时间序列完整性
highPrice = fillmissing(highPrice,'linear'); % 对最高价缺失值做线性插值,避免极端缺口
lowPrice = fillmissing(lowPrice,'linear'); % 对最低价缺失值做线性插值,保证价格区间连续
volume = fillmissing(volume,'nearest'); % 对成交量缺失值采用最近邻填充,保持交易量水平平稳
ret1 = diff(logClose); % 计算相邻两个交易日的对数收益率,作为相对稳定的预测目标候选
ret1 = [NaN; ret1]; % 在首位补NaN以对齐原始时间索引,保证长度与价格序列一致
maLong = movmean(closePrice,20); % 计算20日移动平均价,反映中期趋势特征
volStd = movstd(ret1,20); % 计算20日收益率滚动标准差,近似度量短期波动率
priceRange = (highPrice - lowPrice) ./ closePrice; % 用最高价与最低价差占收盘价比例刻画当日相对振幅
volNorm = (volume - movmean(volume,20)) ./ (movstd(volume,20) + 1e-6); % 以20日均值和标准差对成交量做标准化,突出异常放量或缩量
validIdx = ~isnan(ret1) & ~isnan(maShort) & ~isnan(maLong) & ~isnan(volStd); % 构造逻辑索引,筛选所有关键特征均非NaN的有效样本
dateVec = dateVec(validIdx); % 用有效索引筛选日期,确保后续样本与特征对应
ret1 = ret1(validIdx); % 筛选有效对数收益率,排除前期不可用数据
closePrice = closePrice(validIdx); % 筛选有效收盘价序列,与特征保持同步
volStd = volStd(validIdx); % 筛选有效波动率估计值,用于反映市场状态
volNorm = volNorm(validIdx); % 筛选有效标准化成交量,体现量能变化
windowLen = 10; % 设置时间窗口长度为10天,用于构造滞后特征描述近期价格行为
numSamples = numel(closePrice); % 计算有效数据点总数,便于后续循环与索引控制
numFeatPerDay = 5; % 设置单日基础特征数量,这里准备使用5个日度特征组合成窗口输入
X_list = {}; % 初始化特征单元格列表,用于逐步将每个样本的窗口特征存入
y_list = []; % 初始化目标向量列表,存放每个样本对应的预测目标
for t = windowLen+1:numSamples % 从第windowLen+1个样本开始循环,确保向前有完整窗口长度
    feat_vec = feat_mat(:)'; % 将窗口特征矩阵按列展开为行向量,形成单个样本的高维特征输入
    X_list{end+1,1} = feat_vec; % 将构造好的特征向量存入单元格列表末尾,用于后续转为矩阵
X = cell2mat(X_list); % 将所有样本的特征单元格拼接为数值矩阵,每行对应一个样本
y = y_list; % 将目标列表转换为列向量形式,方便回归训练调用
[muX, sigmaX] = deal(mean(X,1), std(X,[],1)); % 分别计算各特征维度的均值和标准差,用于标准化处理
sigmaX(sigmaX==0) = 1; % 对标准差为零的维度置为1,避免后续除零错误
numTotal = size(X_norm,1); % 获取样本总数,便于按比例划分训练集与测试集
numTrain = floor(numTotal * trainRatio); % 按比例取整得到训练样本数量
X_test = X_norm(numTrain+1:end,:); % 剩余样本作为测试特征矩阵,用于检验泛化性能
y_test = y(numTrain+1:end); % 对应的测试目标向量,评估预测效果
date_train = dateVec(windowLen+1:windowLen+numTrain); % 为训练样本记录对应日期,便于可视化预测时对齐时间
date_test = dateVec(windowLen+numTrain+1:windowLen+numTotal); % 为测试样本记录对应日期,方便画图展示预测与真实
门控网络结构定义与前向计算示例
hiddenDim = 16; % 设置门控网络隐藏层神经元数量,控制网络表达能力
rng(1); % 固定随机数种子,确保参数初始化与实验结果具有可重复性
W1 = 0.01 * randn(inputDim, hiddenDim); % 初始化输入到隐藏层权重矩阵,采用小随机值避免初始输出过大
b1 = zeros(1, hiddenDim); % 初始化隐藏层偏置为零向量,简化起始状态
W2 = 0.01 * randn(hiddenDim, numExperts); % 初始化隐藏层到输出层权重矩阵,小随机值保证输出初始平衡
b2 = zeros(1, numExperts); % 初始化输出层偏置为零,避免某个专家在初始阶段被偏置强化
    x_n = X_train(n,:); % 取出第n个样本的特征行向量,用于门控前向运算
    h1 = tanh(z1); % 对隐藏层激活值施加tanh非线性,增加模型表达能力并保持输出在有限区间
    z2 = h1 * W2 + b2; % 计算输出层线性组合,将隐藏表示映射到专家维度
    z2 = z2 - max(z2); % 在Softmax前减去最大值,提升数值稳定性避免指数溢出
    g_n = exp_z / sum(exp_z); % 将指数值归一化为概率分布,得到各专家权重之和为1
    g_train(n,:) = g_n; % 将当前样本门控输出存入矩阵,对应后续专家训练时的样本权重参考
end
expertModels = cell(numExperts,1); % 初始化单元格,用于存放训练好的每个SVR专家模型
for k = 1:numExperts % 遍历每一个专家编号,依次训练对应SVR模型
    wk = g_train(:,k); % 提取门控网络对所有训练样本在第k个专家上的权重分布
    C_val = 10; % 设定当前专家的惩罚参数C为10,控制拟合误差与间隔大小的权衡
    eps_val = 0.001; % 设定epsilon不敏感带宽度为0.001,控制对小误差的忽略程度
    svmTemplate = templateSVM('KernelFunction','gaussian','KernelScale',1/sqrt(2*gamma_val), ...
                              'BoxConstraint',C_val,'Epsilon',eps_val, ...
                              'Weights',wk); % 使用fitrsvm训练第k个SVR专家,指定高斯核、惩罚参数和样本权重,让门控权重影响专家拟合
end
g_test = zeros(size(X_test,1), numExperts); % 为测试样本预分配门控输出矩阵,用于预测阶段权重计算
    z1 = x_n * W1 + b1; % 计算隐藏层线性组合,得到中间激活值
    h1 = tanh(z1); % 对隐藏层输出应用tanh激活,形成非线性表示
    z2 = z2 - max(z2); % 减去最大值提高Softmax计算稳定性
    exp_z = exp(z2); % 对调整后的z2取指数,得到未归一化权重
    g_test(n,:) = g_n; % 将该样本的专家权重保存在测试门控矩阵中
end
y_pred_test = zeros(size(y_test)); % 初始化测试集预测向量,之后填入加权预测值
    x_n = X_test(n,:); % 取出当前测试样本特征
    expert_outputs = zeros(1,numExperts); % 初始化当前样本的各专家预测输出数组
    for k = 1:numExperts % 遍历每一个专家,为当前样本计算其回归输出
        expert_outputs(k) = predict(expertModels{k}, x_n); % 调用训练好的第k个SVR专家对当前样本进行预测,得到回归值
    end
    y_pred_test(n) = g_n * expert_outputs'; % 将专家输出按门控权重加权求和,得到MoE整体预测值
mse_test = mean((y_test - y_pred_test).^2); % 计算测试集均方误差,衡量预测偏离程度
R2_test = 1 - sum((y_test - y_pred_test).^2) / sum((y_test - mean(y_test)).^2); % 计算测试集R平方指标,衡量模型解释目标方差的能力
fig1 = figure; % 创建新的图窗对象,用于绘制预测结果对比图
plot(date_test, y_test, 'b','LineWidth',1.0); hold on; % 在图窗中绘制真实收益率曲线,以蓝色实线表示
plot(date_test, y_pred_test, 'r','LineWidth',1.0); % 在同一图中绘制MoE-SVR预测曲线,以红色实线表示
datetick('x','yyyy-mm'); % 将横轴日期刻度格式化为年-月形式,便于观察时间变化
xlabel('Date'); % 设置横轴标签为Date,指示时间维度
title(sprintf('MOE-SVR Test Prediction, MSE=%.4g, MAE=%.4g, R^2=%.3f',mse_test,mae_test,R2_test)); % 设置图表标题并在其中显示主要误差指标,方便快速评估模型效果
grid on; % 打开网格线,提高图像可读性
legend({'True','MOE-SVR'},'Location','best'); % 添加图例,区分真实曲线与模型预测曲线
colormap(fig1, turbo); % 将图窗的颜色映射设置为turbo,以便后续可能的多曲线绘制具有统一色彩风格
简单门控参数更新一轮示例
eta = 1e-3; % 设置门控网络参数更新的学习率,用于控制梯度下降步长
numIter = 1; % 设置演示的迭代轮数为1,这里仅示例一轮更新过程
    db1 = zeros(size(b1)); % 初始化隐藏层偏置的梯度累积向量
    dW2 = zeros(size(W2)); % 初始化隐藏到输出层权重的梯度累积矩阵
    db2 = zeros(size(b2)); % 初始化输出层偏置的梯度累积向量
    for n = 1:size(X_train,1) % 遍历每一个训练样本,累积其对门控参数的梯度贡献
        x_n = X_train(n,:); % 取出当前样本特征向量
        y_n = y_train(n); % 取出当前样本真实目标值
        h1 = tanh(z1); % 隐藏层施加tanh激活,生成非线性表示
        z2 = h1 * W2 + b2; % 计算输出层线性激活值,尚未通过Softmax
        z2s = z2 - max(z2); % 做数值稳定处理,以免Softmax计算中指数溢出
        exp_z = exp(z2s); % 取指数得到未归一化权重
        g_n = exp_z / sum(exp_z); % Softmax归一化得到当前样本门控权重向量
        f_exp = zeros(1,numExperts); % 初始化当前样本各专家预测输出容器
        for k = 1:numExperts % 对每一个专家预测当前样本输出
        y_hat = g_n * f_exp'; % 按门控权重加权专家预测得到当前样本的整体预测值
        err = y_hat - y_n; % 计算预测误差,为正则表示模型输出偏高
        dL_dg = err * df_dg; % 根据链式法则得到损失对门控权重的梯度向量
        S = diag(g_n) - (g_n' * g_n); % Softmax函数的雅可比矩阵,描述权重对未归一化输出的敏感度
        dL_dW2 = h1' * dL_dz2; % 输出层权重的梯度为隐藏表示与dL_dz2的外积
        dh1 = dL_dz2 * W2'; % 根据链式法则将梯度从输出层传到隐藏层激活h1
        dz1 = dh1 .* (1 - h1.^2); % tanh激活函数的导数为1 - tanh^2,得到对z1的梯度
        dL_dW1 = x_n' * dz1; % 输入到隐藏层权重的梯度为输入向量与dz1的外积
        dL_db1 = dz1; % 隐藏层偏置的梯度等于dz1,对每个隐藏单元累加
        db1 = db1 + dL_db1; % 累加当前样本对b1的梯度
        db2 = db2 + dL_db2; % 累加当前样本对b2的梯度
    end
    dW1 = dW1 / size(X_train,1); % 对W1梯度取平均,避免样本数量对梯度大小的影响
    db1 = db1 / size(X_train,1); % 对b1梯度取平均,使更新步长具有稳定尺度
    dW2 = dW2 / size(X_train,1); % 对W2梯度取平均,提高训练稳定性
    db2 = db2 / size(X_train,1); % 对b2梯度取平均,平衡每轮参数更新幅度
    W1 = W1 - eta * dW1; % 按学习率沿负梯度方向更新W1,减小损失函数
b2 = b2 - eta * db2; % 更新输出层偏置b2,为后续样本提供更合理的初始偏移

stockFile = 'stock_data.csv'; % 指定包含股票历史数据的CSV文件名称,文件需事先准备在当前工作目录或指定路径
rawTable = readtable(stockFile,'PreserveVariableNames',true); % 读取CSV数据为表格形式,保留原始列名便于后续按列名索引
dateVec = rawTable.Date; % 提取日期列,便于后续按时间顺序分析与可视化
closePrice = rawTable.Close; % 提取收盘价列,用作构造收益率与部分技术指标的基础
highPrice = rawTable.High; % 提取最高价列,用于衡量当日价格波动区间
lowPrice = rawTable.Low; % 提取最低价列,同样用于波动区间及技术指标计算
volume = rawTable.Volume; % 提取成交量列,作为量能特征反映市场活跃度
closePrice = fillmissing(closePrice,'linear'); % 对收盘价中的缺失值采用线性插值填补,减少缺失数据对建模的不利影响
openPrice = fillmissing(openPrice,'linear'); % 对开盘价缺失值做线性插值,保持时间序列完整性
highPrice = fillmissing(highPrice,'linear'); % 对最高价缺失值做线性插值,避免极端缺口
lowPrice = fillmissing(lowPrice,'linear'); % 对最低价缺失值做线性插值,保证价格区间连续
volume = fillmissing(volume,'nearest'); % 对成交量缺失值采用最近邻填充,保持交易量水平平稳
ret1 = diff(logClose); % 计算相邻两个交易日的对数收益率,作为相对稳定的预测目标候选
ret1 = [NaN; ret1]; % 在首位补NaN以对齐原始时间索引,保证长度与价格序列一致
maLong = movmean(closePrice,20); % 计算20日移动平均价,反映中期趋势特征
volStd = movstd(ret1,20); % 计算20日收益率滚动标准差,近似度量短期波动率
priceRange = (highPrice - lowPrice) ./ closePrice; % 用最高价与最低价差占收盘价比例刻画当日相对振幅
volNorm = (volume - movmean(volume,20)) ./ (movstd(volume,20) + 1e-6); % 以20日均值和标准差对成交量做标准化,突出异常放量或缩量
validIdx = ~isnan(ret1) & ~isnan(maShort) & ~isnan(maLong) & ~isnan(volStd); % 构造逻辑索引,筛选所有关键特征均非NaN的有效样本
dateVec = dateVec(validIdx); % 用有效索引筛选日期,确保后续样本与特征对应
ret1 = ret1(validIdx); % 筛选有效对数收益率,排除前期不可用数据
closePrice = closePrice(validIdx); % 筛选有效收盘价序列,与特征保持同步
volStd = volStd(validIdx); % 筛选有效波动率估计值,用于反映市场状态
volNorm = volNorm(validIdx); % 筛选有效标准化成交量,体现量能变化
windowLen = 10; % 设置时间窗口长度为10天,用于构造滞后特征描述近期价格行为
numSamples = numel(closePrice); % 计算有效数据点总数,便于后续循环与索引控制
numFeatPerDay = 5; % 设置单日基础特征数量,这里准备使用5个日度特征组合成窗口输入
X_list = {}; % 初始化特征单元格列表,用于逐步将每个样本的窗口特征存入
y_list = []; % 初始化目标向量列表,存放每个样本对应的预测目标
for t = windowLen+1:numSamples % 从第windowLen+1个样本开始循环,确保向前有完整窗口长度
    feat_vec = feat_mat(:)'; % 将窗口特征矩阵按列展开为行向量,形成单个样本的高维特征输入
    X_list{end+1,1} = feat_vec; % 将构造好的特征向量存入单元格列表末尾,用于后续转为矩阵
X = cell2mat(X_list); % 将所有样本的特征单元格拼接为数值矩阵,每行对应一个样本
y = y_list; % 将目标列表转换为列向量形式,方便回归训练调用
[muX, sigmaX] = deal(mean(X,1), std(X,[],1)); % 分别计算各特征维度的均值和标准差,用于标准化处理
sigmaX(sigmaX==0) = 1; % 对标准差为零的维度置为1,避免后续除零错误
numTotal = size(X_norm,1); % 获取样本总数,便于按比例划分训练集与测试集
numTrain = floor(numTotal * trainRatio); % 按比例取整得到训练样本数量
X_test = X_norm(numTrain+1:end,:); % 剩余样本作为测试特征矩阵,用于检验泛化性能
y_test = y(numTrain+1:end); % 对应的测试目标向量,评估预测效果
date_train = dateVec(windowLen+1:windowLen+numTrain); % 为训练样本记录对应日期,便于可视化预测时对齐时间
date_test = dateVec(windowLen+numTrain+1:windowLen+numTotal); % 为测试样本记录对应日期,方便画图展示预测与真实

门控网络结构定义与前向计算示例

hiddenDim = 16; % 设置门控网络隐藏层神经元数量,控制网络表达能力
rng(1); % 固定随机数种子,确保参数初始化与实验结果具有可重复性
W1 = 0.01 * randn(inputDim, hiddenDim); % 初始化输入到隐藏层权重矩阵,采用小随机值避免初始输出过大
b1 = zeros(1, hiddenDim); % 初始化隐藏层偏置为零向量,简化起始状态
W2 = 0.01 * randn(hiddenDim, numExperts); % 初始化隐藏层到输出层权重矩阵,小随机值保证输出初始平衡
b2 = zeros(1, numExperts); % 初始化输出层偏置为零,避免某个专家在初始阶段被偏置强化
    x_n = X_train(n,:); % 取出第n个样本的特征行向量,用于门控前向运算
    h1 = tanh(z1); % 对隐藏层激活值施加tanh非线性,增加模型表达能力并保持输出在有限区间
    z2 = h1 * W2 + b2; % 计算输出层线性组合,将隐藏表示映射到专家维度
    z2 = z2 - max(z2); % 在Softmax前减去最大值,提升数值稳定性避免指数溢出
    g_n = exp_z / sum(exp_z); % 将指数值归一化为概率分布,得到各专家权重之和为1
    g_train(n,:) = g_n; % 将当前样本门控输出存入矩阵,对应后续专家训练时的样本权重参考
end
expertModels = cell(numExperts,1); % 初始化单元格,用于存放训练好的每个SVR专家模型
for k = 1:numExperts % 遍历每一个专家编号,依次训练对应SVR模型
    wk = g_train(:,k); % 提取门控网络对所有训练样本在第k个专家上的权重分布
    C_val = 10; % 设定当前专家的惩罚参数C为10,控制拟合误差与间隔大小的权衡
    eps_val = 0.001; % 设定epsilon不敏感带宽度为0.001,控制对小误差的忽略程度
    svmTemplate = templateSVM('KernelFunction','gaussian','KernelScale',1/sqrt(2*gamma_val), ...
                              'BoxConstraint',C_val,'Epsilon',eps_val, ...
                              'Weights',wk); % 使用fitrsvm训练第k个SVR专家,指定高斯核、惩罚参数和样本权重,让门控权重影响专家拟合
end
g_test = zeros(size(X_test,1), numExperts); % 为测试样本预分配门控输出矩阵,用于预测阶段权重计算
    z1 = x_n * W1 + b1; % 计算隐藏层线性组合,得到中间激活值
    h1 = tanh(z1); % 对隐藏层输出应用tanh激活,形成非线性表示
    z2 = z2 - max(z2); % 减去最大值提高Softmax计算稳定性
    exp_z = exp(z2); % 对调整后的z2取指数,得到未归一化权重
    g_test(n,:) = g_n; % 将该样本的专家权重保存在测试门控矩阵中
end
y_pred_test = zeros(size(y_test)); % 初始化测试集预测向量,之后填入加权预测值
    x_n = X_test(n,:); % 取出当前测试样本特征
    expert_outputs = zeros(1,numExperts); % 初始化当前样本的各专家预测输出数组
    for k = 1:numExperts % 遍历每一个专家,为当前样本计算其回归输出
        expert_outputs(k) = predict(expertModels{k}, x_n); % 调用训练好的第k个SVR专家对当前样本进行预测,得到回归值
    end
    y_pred_test(n) = g_n * expert_outputs'; % 将专家输出按门控权重加权求和,得到MoE整体预测值
mse_test = mean((y_test - y_pred_test).^2); % 计算测试集均方误差,衡量预测偏离程度
R2_test = 1 - sum((y_test - y_pred_test).^2) / sum((y_test - mean(y_test)).^2); % 计算测试集R平方指标,衡量模型解释目标方差的能力
fig1 = figure; % 创建新的图窗对象,用于绘制预测结果对比图
plot(date_test, y_test, 'b','LineWidth',1.0); hold on; % 在图窗中绘制真实收益率曲线,以蓝色实线表示
plot(date_test, y_pred_test, 'r','LineWidth',1.0); % 在同一图中绘制MoE-SVR预测曲线,以红色实线表示
datetick('x','yyyy-mm'); % 将横轴日期刻度格式化为年-月形式,便于观察时间变化
xlabel('Date'); % 设置横轴标签为Date,指示时间维度
title(sprintf('MOE-SVR Test Prediction, MSE=%.4g, MAE=%.4g, R^2=%.3f',mse_test,mae_test,R2_test)); % 设置图表标题并在其中显示主要误差指标,方便快速评估模型效果
grid on; % 打开网格线,提高图像可读性
legend({'True','MOE-SVR'},'Location','best'); % 添加图例,区分真实曲线与模型预测曲线
colormap(fig1, turbo); % 将图窗的颜色映射设置为turbo,以便后续可能的多曲线绘制具有统一色彩风格

简单门控参数更新一轮示例

eta = 1e-3; % 设置门控网络参数更新的学习率,用于控制梯度下降步长
numIter = 1; % 设置演示的迭代轮数为1,这里仅示例一轮更新过程
    db1 = zeros(size(b1)); % 初始化隐藏层偏置的梯度累积向量
    dW2 = zeros(size(W2)); % 初始化隐藏到输出层权重的梯度累积矩阵
    db2 = zeros(size(b2)); % 初始化输出层偏置的梯度累积向量
    for n = 1:size(X_train,1) % 遍历每一个训练样本,累积其对门控参数的梯度贡献
        x_n = X_train(n,:); % 取出当前样本特征向量
        y_n = y_train(n); % 取出当前样本真实目标值
        h1 = tanh(z1); % 隐藏层施加tanh激活,生成非线性表示
        z2 = h1 * W2 + b2; % 计算输出层线性激活值,尚未通过Softmax
        z2s = z2 - max(z2); % 做数值稳定处理,以免Softmax计算中指数溢出
        exp_z = exp(z2s); % 取指数得到未归一化权重
        g_n = exp_z / sum(exp_z); % Softmax归一化得到当前样本门控权重向量
        f_exp = zeros(1,numExperts); % 初始化当前样本各专家预测输出容器
        for k = 1:numExperts % 对每一个专家预测当前样本输出
        y_hat = g_n * f_exp'; % 按门控权重加权专家预测得到当前样本的整体预测值
        err = y_hat - y_n; % 计算预测误差,为正则表示模型输出偏高
        dL_dg = err * df_dg; % 根据链式法则得到损失对门控权重的梯度向量
        S = diag(g_n) - (g_n' * g_n); % Softmax函数的雅可比矩阵,描述权重对未归一化输出的敏感度
        dL_dW2 = h1' * dL_dz2; % 输出层权重的梯度为隐藏表示与dL_dz2的外积
        dh1 = dL_dz2 * W2'; % 根据链式法则将梯度从输出层传到隐藏层激活h1
        dz1 = dh1 .* (1 - h1.^2); % tanh激活函数的导数为1 - tanh^2,得到对z1的梯度
        dL_dW1 = x_n' * dz1; % 输入到隐藏层权重的梯度为输入向量与dz1的外积
        dL_db1 = dz1; % 隐藏层偏置的梯度等于dz1,对每个隐藏单元累加
        db1 = db1 + dL_db1; % 累加当前样本对b1的梯度
        db2 = db2 + dL_db2; % 累加当前样本对b2的梯度
    end
    dW1 = dW1 / size(X_train,1); % 对W1梯度取平均,避免样本数量对梯度大小的影响
    db1 = db1 / size(X_train,1); % 对b1梯度取平均,使更新步长具有稳定尺度
    dW2 = dW2 / size(X_train,1); % 对W2梯度取平均,提高训练稳定性
    db2 = db2 / size(X_train,1); % 对b2梯度取平均,平衡每轮参数更新幅度
    W1 = W1 - eta * dW1; % 按学习率沿负梯度方向更新W1,减小损失函数
b2 = b2 - eta * db2; % 更新输出层偏置b2,为后续样本提供更合理的初始偏移

更多详细内容请访问

http://MATLAB实现基于MOE-SVR专家混合(MoE)结合支持向量回归(SVR)进行股票价格预测的详细项目实例(含完整的程序,GUI设计和代码详解)_Matlab时间序列预测模型代码资源-CSDN下载  https://download.csdn.net/download/xiaoxingkongyuxi/90263773

 https://download.csdn.net/download/xiaoxingkongyuxi/90263773

http:// https://download.csdn.net/download/xiaoxingkongyuxi/90263773

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐