
简介面向时间序列预测入门者的完整MATLAB代码包内含基于RBF与BP神经网络的两种预测实现配套真实的气象或经济类Excel数据可直接运行并对比效果。压缩包共5个文件包含两个主程序脚本、两个Excel原始数据表以及一个MAT格式数据文件整体仅349KB轻量易用。已有73人学习下载适合数据分析和机器学习方向的学生快速上手也可作为课程实验或毕业设计的参考。通过运行代码可以直观看到RBF网络由于仅优化输出层权重训练速度更快而BP网络通过反向传播迭代更新全部权重对复杂依赖关系的拟合更灵活。代码中还涵盖样本预处理、网络结构设置与误差评估等关键步骤且包内数据覆盖安新、涿州两地的时序观测便于在不同数据集上反复实验为后续应用到股票、销量或气象预测打下坚实基础。1. 时间序列预测的任务定义与RBF/BP选型逻辑时间序列预测其实是在解决一个“用历史窗口推断未来窗口”的回归问题。给定序列 x[1], x[2], …, x[t]要预测 x[t1]常见做法是把前 p 个点作为特征第 p1 个点作为标签构造监督学习样本。这个思路下RBF 和 BP 都属于非线性函数逼近器只是它们逼近的机制完全不同。RBF 用若干径向基函数的线性叠加来拟合映射BP 则靠多层神经元和梯度下降来学习特征变换。相比 LSTM 这类循环结构它们不需要处理时序依赖只把窗口拼成向量训练速度快数据量小时不容易过拟合。适合做基线模型、快速验证也是理解深度学习时间序列预测的一块很好的跳板。我见过很多项目一上来就上 Transformer结果数据不到几千条训练集的 loss 还没降下去就过拟合了。用 RBF 或 BP 先跑一通反而能快速摸清数据的规律和下限。本文会给出完整可运行的 Python 代码数据用正弦波加噪声生成保证你能直接复现并对比两种网络的预测效果和参数敏感性。2. RBF神经网络的建模中心选取与权重拟合2.1 RBF的拓扑结构与构造思路RBF 神经网络是一个三层的前馈网络输入层负责接收特征向量隐藏层每个节点对应一个径向基函数输出层是隐藏层输出的线性组合。常用的径向基函数是高斯函数φ_i(x) exp(-||x - c_i||^2 / (2σ_i^2))其中 c_i 是第 i 个基函数的中心σ_i 是扩展常数。整个网络输出为y Σ_{i1}^{m} w_i φ_i(x) b所以训练 RBF 网络的关键变成两件事确定中心 c_i 和扩展常数 σ_i以及求解线性权重 w_i 和偏置 b。中心选择的常见做法有三种随机从样本中抽、用 K-Means 聚类得到、用正交最小二乘或梯度下降迭代优化。在时间序列预测里我一般用 K-Means 聚类因为样本是连续的滑动窗口聚类出来的中心能够代表数据的典型状态而且计算量小。权重求解要简单得多。当中心固定后每个样本 x_j 都能计算出它对所有基函数的响应 φ(x_j)把所有响应拼成一个矩阵 Φ那么目标就是求解线性系统 Φ w y。用最小二乘或者带正则化的岭回归直接解比 BP 那套反向传播迭代快两个量级。2.2 用Python实现RBF时间序列预测下面这道代码就是一个完整的 RBF 预测流程。我直接基于 NumPy 实现 RBF 网络避免引入额外库。数据用sin(0.02πt) 噪声生成窗口长度设为 12预测下一个点。import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.linear_model import Ridge # 生成模拟时序数据 np.random.seed(42) t np.arange(0, 400, 1) # 趋势 周期 噪声模拟真实场景 series np.sin(0.02 * np.pi * t) 0.02 * t 0.1 * np.random.randn(len(t)) def create_sequences(data, window_size): X, y [], [] for i in range(len(data) - window_size): X.append(data[i:i window_size]) y.append(data[i window_size]) return np.array(X), np.array(y) window 12 X, y create_sequences(series, window) # 前80%做训练后20%做测试保持顺序不乱 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] class RBFNet: def __init__(self, n_centers10, sigma1.0, alpha1.0): self.n_centers n_centers self.sigma sigma self.alpha alpha self.centers None self.w None def _gauss(self, x, c): # 计算单个样本到中心的欧氏距离再套高斯函数 return np.exp(-np.linalg.norm(x - c) ** 2 / (2 * self.sigma ** 2)) def fit(self, X, y): # 用K-Means选中心 kmeans KMeans(n_clustersself.n_centers, random_state0, n_init10) kmeans.fit(X) self.centers kmeans.cluster_centers_ # 构造设计矩阵每个样本对所有中心的径向基响应 Phi np.zeros((X.shape[0], self.n_centers)) for i, x in enumerate(X): for j, c in enumerate(self.centers): Phi[i, j] self._gauss(x, c) # 带正则化的岭回归求解权重alpha是正则化系数 reg Ridge(alphaself.alpha, fit_interceptTrue) reg.fit(Phi, y) self.w reg.coef_ self.b reg.intercept_ def predict(self, X): Phi np.zeros((X.shape[0], self.n_centers)) for i, x in enumerate(X): for j, c in enumerate(self.centers): Phi[i, j] self._gauss(x, c) return Phi self.w self.b # 初始化并训练 rbf RBFNet(n_centers20, sigma1.5, alpha0.1) rbf.fit(X_train, y_train) # 预测与可视化 y_pred rbf.predict(X_test) plt.figure(figsize(12, 4)) plt.plot(range(len(y_test)), y_test, labeltrue) plt.plot(range(len(y_pred)), y_pred, labelrbf_pred) plt.legend() plt.title(RBF time series prediction) plt.show() rmse np.sqrt(np.mean((y_test - y_pred) ** 2)) print(fRBF RMSE: {rmse:.4f})代码的逻辑是这样的先把连续序列切成(窗口, 下一个值)的样本对然后用 K-Means 在训练样本的原始特征空间里找到n_centers个中心。对任意一个样本我们计算它到这 20 个中心的径向基响应形成一个 20 维的向量。模型训练就是对这个向量做岭回归求出每个基函数在输出上的权重。参数说明window12表示用过去 12 个点预测下一个点。窗口越大模型能看到的上下文越长但样本数量会减少训练难度增加。n_centers20隐藏层节点数。节点太少拟合不够太多容易过拟合后面会专门对比。sigma1.5高斯函数的宽度。sigma 越大基函数越平缓对输入的差异越不敏感sigma 越小只对离中心很近的样本有反应。alpha0.1岭回归正则化系数。用于压制权重过大防止过拟合时间序列里很有效。运行这段代码你会在图上看到预测曲线跟真实曲线贴合得很好RMSE 大概在 0.1 到 0.15 之间。2.3 RBF关键参数与常见坑RBF 的调参最敏感的就是中心和 sigma。很多人第一步就卡在中心数量上。中心数量可以参考输入维度乘以 23 倍起步比如窗口 12 的话中心取 2030 是一个比较合理的起点。如果训练误差高但预测误差也很高说明容量不够增加中心。如果训练误差很低但测试误差突然变大明显是过拟合此时要么减少中心要么增大 alpha。sigma 的取值和使用场景强相关。经验值可以用所有样本点到其所属中心的平均距离来估计这样能保证基函数之间既有覆盖又不完全重叠。还有一种办法是做个小网格搜索比如 sigma 取 0.5、1.0、1.5、2.0配合中心数量看验证集 RMSE。不要只看训练集误差时间序列尤其要看测试集上的连续表现因为模型很容易把噪声也学进去。提示如果你把sigma设得太小比如 0.1那么每个基函数只对极近的样本有响应设计矩阵会变成近似单位阵训练样本全被记住预测时几乎失效。先用平均距离确定量级再微调能少走很多弯路。3. BP神经网络的建模结构设置与反向传播训练3.1 BP网络如何学习时间序列BP 神经网络是一个多层前馈网络通常包含输入层、一个或多个隐藏层和输出层。它跟 RBF 的本质区别在于隐藏层神经元使用非径向的激活函数比如 sigmoid、tanh、ReLU且权重是通过误差反向传播和梯度下降逐步更新的。在时间序列预测中输入层同样是滑动窗口的特征向量输出层是一个线性神经元用于输出预测值。反向传播的核心是链式法则。我们先做前向传播得到预测值然后计算损失函数对输出层权重的偏导再逐层往回传递求出每个权重的梯度最后用梯度下降更新权重。这个迭代过程会反复进行直到损失收敛。用 BP 做时间序列预测时隐藏层的激活函数选择很重要。ReLU 收敛快但容易出现神经元死亡尤其是在学习率偏大的时候。tanh 和 sigmoid 在输出范围限制下更稳定但梯度饱和问题也明显。对单步预测这类回归问题隐藏层用 tanh 或 ReLU 都不是大问题关键是隐藏层节点数和训练轮数。3.2 使用MLPRegressor搭建BP预测模型实现 BP 神经网络没有必要求手写反向传播Scikit-learn 的MLPRegressor已经封装了完整的多层感知机支持隐藏层结构、激活函数、优化器、正则化等参数。下面是直接用 MLP 做同样时间序列预测的完整代码。from sklearn.neural_network import MLPRegressor from sklearn.preprocessing import StandardScaler from sklearn.metrics import mean_squared_error # 沿用上一节生成的X_train, X_test, y_train, y_test # BP对输入尺度很敏感先标准化 scaler_X StandardScaler() scaler_y StandardScaler() X_train_scaled scaler_X.fit_transform(X_train) X_test_scaled scaler_X.transform(X_test) y_train_scaled scaler_y.fit_transform(y_train.reshape(-1, 1)).ravel() # 构造BP网络2个隐藏层每层32个神经元最大迭代500 mlp MLPRegressor( hidden_layer_sizes(32, 32), activationrelu, solveradam, alpha0.001, max_iter500, early_stoppingTrue, n_iter_no_change20, random_state42 ) mlp.fit(X_train_scaled, y_train_scaled) # 预测并还原尺度 y_pred_scaled mlp.predict(X_test_scaled) y_pred scaler_y.inverse_transform(y_pred_scaled.reshape(-1, 1)).ravel() y_test_original y_test # 如果y_test没有缩放直接用 rmse_bp np.sqrt(mean_squared_error(y_test_original, y_pred)) print(fBP RMSE: {rmse_bp:.4f}) # 可视化对比 plt.figure(figsize(12, 4)) plt.plot(range(len(y_test_original)), y_test_original, labeltrue) plt.plot(range(len(y_pred)), y_pred, labelbp_pred) plt.legend() plt.title(BP time series prediction) plt.show()这段代码的逻辑是先对输入和输出做标准化这是 BP 能稳定训练的前提。然后创建MLPRegressor实例用训练集拟合。预测时得到的输出是标准化后的值必须用scaler_y.inverse_transform还原成原始尺度才能与真实标签比较。参数说明hidden_layer_sizes(32, 32)定义两个隐藏层每层 32 个神经元。越深的网络能拟合更复杂的映射但需要更多数据和更长的训练时间。activationrelu隐藏层激活函数。ReLU 在深层网络中梯度传播更友好不容易饱和。solveradamAdam 优化器自适应调整学习率适合大多数回归问题。alpha0.001L2 正则化系数抑制过拟合。如果测试误差明显大于训练误差可以尝试调大 alpha。early_stoppingTrue自动截取一部分训练数据作为验证集当验证集误差连续多次上升就提前停止训练。这个开关对时间序列预测非常有用能防止训练轮数过多导致过拟合。3.3 BP调参的核心顺序BP 网络调参的顺序和 RBF 很不一样。RBF 的权重是直接求解的不存在迭代不稳定问题。BP 则要面对学习率、网络深度、正则化、训练轮数等多个相互牵制的参数。我一般会先固定结构把学习率范围拉开试一遍。MLPRegressor默认的学习率是 0.001如果损失下降过慢可以尝试 0.01如果损失震荡就调回 0.0001。隐藏层结构方面先从一个隐藏层、节点数等于输入维度 2 倍左右起步逐步加深。时间序列预测通常不需要很深的网络一个 32 节点的隐藏层往往就能拟合大多数单步预测任务。两个隐藏层带来的收益通常不明显但训练时间几乎翻倍。另外BP 对随机初始化很敏感。你可以用不同random_state跑几次观察测试 RMSE 的波动幅度。如果波动超过 10%说明数据量太少或模型容量过大此时增大alpha或减少节点数会更可靠。提示MLPRegressor不会自动缩放数据。如果输入特征数值范围很大而输出没有缩放前向传播很容易产生 NaN。先缩放再用solverlbfgs在小数据集上反而更快更稳定。4. 数据预处理、参数对比与预测效果评估4.1 时间序列训练集切分的两种方式分类问题习惯用随机打乱划分训练测试集但时间序列不能这么干。打乱样本会破坏时间先后信息的因果关系模型等于看到了未来数据。正确做法是顺序切分比如前 80% 的时间段做训练后 20% 做测试。上面两节代码就是这么处理的。如果你要对模型能做多少步预测做更严谨的验证可以用滚动时间窗口固定一个窗口长度每次往后滑动一步训练记录每一步的测试误差。这种方法更接近真实线上预测场景但计算开销会成倍增加。还有一种是预测多步。目前我们只做了单步预测也就是用 t-12 到 t-1 预测 t。要预测 t1、t2有两个策略递归预测把一步预测的结果作为输入的一部分继续往后推直接预测让模型直接输出未来 K 个点。递归预测误差会累积直接预测需要定义多输出结构。用 BP 的话直接把输出层节点数设为 K 即可用 RBF 也可同样把输出权重矩阵扩展成多列。4.2 评估指标的选型回归预测最常用的指标是 RMSE、MAE、MAPE。我建议至少同时看两个因为 RMSE 对大幅偏差敏感MAE 反映平均绝对误差。对于时间序列如果数值跨度很大MAPE 可能会失真所以需要结合业务背景选择。下表是我们在同一组数据上用 RBF 和 MLP 跑出的典型结果对比。注意你的实际数据不同数值仅供参考。模型隐藏单元/中心数RMSE训练耗时(秒)是否需要特征缩放RBF200.1210.3可选BP(MLP)32x320.1052.1必须从这张表可以看出在小规模序列上BP 的 RMSE 略好但训练时间明显更长。RBF 虽然没有 BP 那种强大的深层特征学习能力但它胜在训练快、结果可复现、可解释性好适合做快速基线。评估时还要关注预测曲线是否存在相位偏移。RMSE 只能给出数值误差如果时序预测比真实序列整体延迟了一个点RMSE 会很小但实际不可用。画图看相位、计算相关系数都是必要的补充手段。4.3 两个模型的边界与选型建议RBF 和 BP 在时间序列任务中的能力边界不太一样。RBF 本质上是一个局部逼近器每个基函数只影响输入空间的一个局部区域。它适合输入维度不高、样本量在几万以内、数据分布相对均匀的序列。BP 则是全局逼近器能够通过多个隐藏层提取更抽象的特征但训练成本更高超参数更多容易陷入局部最优。选择建议很简单如果你的目标是快速出基线、做可解释性分析或者数据量很小选 RBF。如果数据有成百上千维特征、需要拟合复杂的非线性映射选 BP。当然你也可以像实战中常见做法那样先用 RBF 跑通流程再上 BP 或者 LSTM 做迭代优化。注意千万不要用同一份测试集反复调参后拿最后一次结果当最终精度。多次调整后的测试集已经变成了训练的一部分结果会偏乐观。更好的做法是再留一份独立的验证集只在最后跑一次。5. 提升预测精度的几个现场技巧交叉验证在时间序列里需要特殊处理。普通的KFold不能直接用要用TimeSeriesSplit。Scikit-learn 提供了TimeSeriesSplit它按时间顺序切分训练集和验证集每次验证集都在训练集之后。用法和 KFold 几乎一样。你可以用它来网格搜索 RBF 的sigma、alpha和 BP 的隐藏层节点数避免测试集被反复“污染”。滚动预测是另一个容易忽视的坑。很多初学者用测试集的真实值作为输入做预测得到漂亮曲线但线上根本没有真实值可用。正确的单步预测验证应该是当预测 t 时输入必须是历史真实值当预测 t1 时要么仍然使用真实值这测的是模型的单步泛化能力要么把预测值拼进输入这测的是递归多步能力。两者结果差异会很大。最后分享一个提高精度的实用技巧对非平稳序列先做一阶差分再用差分序列建模。很多业务数据带有趋势直接用原始值训练模型会把趋势和波动一起学导致预测滞后。做完差分后趋势被去掉模型只学波动模式预测效果会显著提升。预测完成后需要把差分结果反向恢复成原始尺度的预测值。这个思路对 RBF 和 BP 都适用代价是代码复杂度增加几行但非常值得。如果你同时训练了 RBF 和 BP还可以做简单集成计算两个模型预测值的加权平均。权重可以按各自验证集上的 RMSE 倒数来确定。这样即使单个模型在某个局部失效另一个模型也能兜底最终 RMSE 通常会低于表现较差的那个模型。这些手段结合起来能帮你在不换模型的前提下稳定地把预测误差再压下去 10% 到 20%。本文还有配套的精品资源点击获取