量化交易中文教材

第 27 章 案例:预测与金融时间序列

本章对应原书第 27 章(案例研究 5:预测),并附原书附录 A–C 的简要说明。原书案例是为磁悬浮系统建立 NARX 动态模型:用过去的位置和电流预测下一时刻的位置。这是全书唯一一个输入为时间序列、并明确按时间顺序划分测试集的案例,与量化中的收益预测在形式上完全相同。但两者有一个根本差别:磁悬浮是确定性的物理系统,金融收益的信噪比极低且不平稳。本章先把原书案例讲透,再用一节完整的量化实战,说明把 NARX 搬到金融时间序列上时,数据处理、划分、评估、多步预测各要改什么。

学习目标

读完本章,你应当能够:

  1. 写出 NARX 模型 \(y(t)=f(y(t-1),\dots,y(t-n_y),u(t-1),\dots,u(t-n_u))\),说明它与线性 ARX 的关系。
  2. 解释系统辨识中激励信号(skyline 函数)的设计原则,以及"测试集取末尾连续一段"的理由。
  3. 区分 NARX 的并联形式与串并联形式,说明为什么串并联形式可以用静态反向传播训练,以及为什么它只保证一步预测好。
  4. 用误差自相关和误差–输入互相关检验预测模型,并据此调整延迟阶数;用并联形式的多步迭代预测做更严格的检验。
  5. 把这套流程用到金融收益预测:无前视的波动标准化、按时间的 walk-forward 与间隔、线性基准、样本外 \(R^2\)/IC/夏普、残差 Ljung–Box 检验、多步预测的衰减。
  6. 判断一个"神经网络收益预测"结果是否可信。

读前导读

这一章在解决什么问题

一句话:怎样用一个变量自己的过去和其他变量的过去来预测它的下一期,以及怎样判断这个预测"已经把能用的信息用完了"。

你在 CFA 二级的时间序列部分见过 AR(1)、AR(p):\(x_t=b_0+b_1x_{t-1}+\varepsilon_t\),并且学过一条检验规则——残差的自相关系数要用 \(t=\hat\rho/(1/\sqrt T)\) 检验,显著就说明模型还要加滞后项。本章做的是同一件事的两个推广:第一,把右边的线性函数换成神经网络 \(f(\cdot)\),并加入外生变量(ARX → NARX);第二,残差检验从"自己和自己"扩展到"残差和输入之间"。式 (27.7) 的置信界 \(\pm2R_e(0)/\sqrt Q\),本质上就是你熟悉的 \(\pm 2/\sqrt T\) 乘上了残差方差。

前半章是原书的工程案例(磁悬浮),它的作用是让你在一个"答案已知、噪声很小"的系统上看清整套流程。后半章把流程搬到金融收益上,核心结论和你做投资研究的经验一致:信号很弱、关系会漂移、线性模型往往已经够用、多步预测几天后就退化成均值。

需要先想起来的数学

  • 导数与微分方程。\(\frac{dy}{dt}\) 是位置对时间的变化率,即速度;\(\frac{d^2y}{dt^2}\) 是速度的变化率,即加速度。式 (27.1) 就是牛顿第二定律"加速度 = 合力 / 质量"写成的方程,含二阶导数,所以叫"二阶"微分方程。离散化时,速度近似为 \(\frac{y(t)-y(t-1)}{\Delta t}\)。例:0.01 秒内位置从 2.000 变到 2.003,速度约 0.3。见 第 00 册第 02 章 导数与泰勒展开。
  • 自协方差与求和记号。\(\frac{1}{Q-\tau}\sum_{t=1}^{Q-\tau}e(t)e(t+\tau)\) 就是"把序列错开 \(\tau\) 期,对齐后逐项相乘再取平均",即滞后 \(\tau\) 的样本自协方差(假设均值为零)。\(\tau=0\) 时就是方差。例:\(e=(1,-1,1,-1)\),\(\tau=1\) 时三对乘积都是 \(-1\),\(R_e(1)=-1\),强烈负相关。见 第 00 册第 07 章 概率中的分析工具。
  • 样本相关系数的抽样分布。若真实相关为零,\(Q\) 个样本算出的相关系数近似服从均值 0、标准差 \(1/\sqrt Q\) 的正态分布,所以 95% 置信界约为 \(\pm2/\sqrt Q\)。\(Q=1000\) 时界为 \(\pm0.063\)。这是本章所有"超界"判断的来源。
  • 几何级数。EWMA 波动 \(\hat\sigma^2_t=\lambda\hat\sigma^2_{t-1}+(1-\lambda)r^2_{t-1}\) 反复展开后,权重是 \((1-\lambda),(1-\lambda)\lambda,(1-\lambda)\lambda^2,\dots\),总和为 \((1-\lambda)\cdot\frac{1}{1-\lambda}=1\),和你算永续年金用的是同一个公式。见 第 00 册第 04 章 级数与收敛。
  • tanh 函数。\(\tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}\),取值在 \((-1,1)\),在 0 附近近似 \(x\),绝对值大时饱和到 \(\pm1\)。网络的隐层用它,27.7.6 节的模拟信号 \(0.12\tanh(1.5x)\) 也用它,含义是"外生变量越大收益越高,但效果有上限"。见 第 00 册第 01 章 函数极限与连续。

怎么读这一章

核心必读:27.3(NARX 与两种形式)、27.5.2(误差两条性质与置信界)、27.5.4 和 27.6 末尾的"一步与多步的差别"、整个 27.7。27.1 的物理方程和 27.2 的 skyline 激励第一次可以只看结论;27.4 的有效参数个数如果你没读过第 23 章,先记住"它类似 Ridge 回归的有效自由度"即可。两段代码第一次阅读只看"关键输出"及其后的解读,理解流程后再回头看代码。最后用 27.7.7 的检查清单回顾全章。


27.1 问题:预测与系统辨识

预测是一种动态滤波:用一个或多个时间序列的过去值预测未来值,使用第 10、14 章的动态网络。原书列举的应用包括:金融分析师预测股票、债券等金融工具的未来价值;工程师预测喷气发动机即将失效;以及系统辨识(system identification),即用数据建立物理系统的动态模型,用于制造系统、化工过程、机器人、航空航天等领域的分析、仿真、监控与控制。

本案例的对象是磁悬浮系统:一块磁铁悬浮在电磁铁上方,只能竖直运动,目标是控制它的位置。运动方程为

\[\frac{d^2y(t)}{dt^2}=-g+\frac{\alpha}{M}\frac{i^2(t)\,\mathrm{sgn}[i(t)]}{y(t)}-\frac{\beta}{M}\frac{dy(t)}{dt},\qquad(27.1)\]
\(y(t)\) 为磁铁到电磁铁的距离,\(i(t)\) 为电磁铁电流,\(M\) 为磁铁质量,\(g\) 为重力加速度,\(\beta\) 为黏性摩擦系数,\(\alpha\) 为场强常数。取 \(\beta=12\),\(\alpha=15\),\(g=9.8\),\(M=3\)。三项分别是重力、电磁力(与电流平方成正比、与距离成反比,电流反向时力也反向)、阻尼。

白话解释:左边 \(\frac{d^2y}{dt^2}\) 是加速度,右边是"每单位质量受的合力",整个式子就是牛顿第二定律 \(a=F/M\)。\(\mathrm{sgn}[i]\) 是符号函数(\(i>0\) 取 1,\(i<0\) 取 \(-1\)),配合 \(i^2\) 使得 \(i^2\,\mathrm{sgn}(i)=i|i|\):大小随电流平方增长,方向随电流方向翻转。\(\frac{dy}{dt}\) 是速度,阻尼项与速度成正比、方向相反,相当于"摩擦"。你不需要会解这个方程,只要知道两点:它是非线性的(\(i^2/y\)),所以需要神经网络而不是线性 ARX;它是二阶的,所以系统的"状态"由位置和速度两个量决定,这直接决定了下面延迟阶数的初值。

案例的目标是建立一个动态神经网络模型,由过去的位置和电流预测下一时刻的位置。模型建好后可以用来设计控制器(确定使磁铁到达期望位置的电流),控制设计不在本章范围。


27.2 数据收集与预处理

27.2.1 激励信号:skyline 函数

原书没有搭建实物,而是用 Simulink 仿真式 (27.1):电流在 \(-1\) 到 4 安之间,每 0.01 秒采样一次,共 4000 个数据点。

要得到准确的模型,系统的输入和输出必须覆盖将来使用的整个工作范围。系统辨识中常用的输入是由随机幅度、随机宽度的脉冲组成的序列,形似城市天际线,称为 skyline 函数。脉冲的宽度和幅度都要仔细选择:

  • 长脉冲末端系统接近稳态,用来学稳态特性;短脉冲用来学暂态特性。
  • 稳态性能差,可以加长脉冲;但稳态数据过多,训练集就不能代表典型工况,暂态性能反而会变差。
  • 所以应当使用宽度和幅度都有一定范围的输入,兼顾暂态与稳态。

这条原则在量化里的对应物是:训练数据应当覆盖不同的市场状态(牛市、熊市、高波动、低波动、流动性危机),否则模型只在单一状态下有效。区别在于,物理系统的激励可以由工程师设计,而市场的"激励"只能等它自己发生。

27.2.2 划分与归一化

用贝叶斯正则化训练,不需要验证集;留 15% 作测试。原书特别指出:输入是时间序列时,测试序列宜取原数据中的连续一段,这里取最后 15%。理由很直接:时间序列相邻样本高度相关,随机抽取的测试点会被训练点"包围",测出来的性能不能代表对未来的预测能力。

输入和目标用式 (22.1) 缩放到 \([-1,1]\)。


27.3 结构选择:NARX 网络

27.3.1 NARX 模型

NARX(nonlinear autoregressive with exogenous inputs,带外生输入的非线性自回归)模型是时间序列建模中线性 ARX 模型的非线性推广:

\[y(t)=f\big(y(t-1),y(t-2),\dots,y(t-n_y),\ u(t-1),u(t-2),\dots,u(t-n_u)\big).\qquad(27.2)\]
因变量的下一个值对它自己的过去值和外生输入的过去值回归。本例中 \(y\) 是磁铁位置,\(u\) 是电流。若 \(f\) 是线性函数,这就是 ARX 模型;NARX 用一个两层前馈网络(tansig 隐层 + 线性输出层)来逼近 \(f\),隐层神经元数 \(S^1\) 取决于系统的复杂度。

还要确定两条抽头延迟线的长度 \(n_u\) 和 \(n_y\)。式 (27.1) 是二阶微分方程,所以先取 \(n_y=n_u=2\),之后再检验其他取值。物理直觉是:二阶系统的状态是位置和速度,用 \(y(t-1)\) 和 \(y(t-2)\) 恰好能表示这两者。

推导拆解:为什么两个滞后够用?离散化后,位置就是 \(y(t-1)\),速度可以用差分近似:\(\dot y(t-1)\approx\frac{y(t-1)-y(t-2)}{\Delta t}\)(这里用的是导数的定义,把极限换成有限的 \(\Delta t=0.01\))。知道了"当前位置 + 当前速度 + 当前受力(由电流 \(u\) 决定)",牛顿定律就能推出下一时刻的位置。所以 \(\{y(t-1),y(t-2),u(t-1),u(t-2)\}\) 在原理上包含了预测 \(y(t)\) 所需的全部状态信息。实际中差分近似和采样会带来误差,所以 27.5.3 节最终把阶数加到 4。

金融直觉:金融收益没有"物理阶数"可依,延迟阶数只能靠数据选,通常用信息准则(AIC/BIC)或残差检验,这就是 CFA 里"残差自相关显著就加 AR 阶数"的做法。

27.3.2 并联形式与串并联形式

NARX 有两种形式(原书图 27.5):

  • 并联形式(parallel):标准 NARX 把网络自己输出的估计值 \(\hat y\) 反馈到输入端。这是模型实际使用时的形式,也是做多步预测的形式。
  • 串并联形式(series-parallel):训练时真实输出是已知的,可以用真实的 \(y(t-1),\dots\) 代替反馈的估计值。

串并联形式有两个好处:一是前馈网络的输入更准确;二是整个网络变成纯前馈结构,可以用静态反向传播训练。此时直接用一个标准多层网络实现 NARX,输入向量由过去的输入和输出组成:

\[\mathbf p(t)=[u(t-1),\ u(t-2),\ y(t-1),\ y(t-2)]^T,\qquad t=y(t).\qquad(27.3,27.4)\]

在机器学习中,串并联训练又叫 teacher forcing。它的代价是:训练只优化了一步预测误差,模型在自己的预测被反馈回来时(并联形式)表现如何,训练过程完全没有约束。这一点在验证环节要单独检查。

白话解释:式 (27.4) 里的 "\(t=y(t)\)" 容易看糊涂:左边的 \(t\) 是原书记号里的目标(target,原书用粗体 \(\mathbf t\)),右边括号里的 \(t\) 才是时间。意思是"第 \(t\) 个样本的输入是 \(\mathbf p(t)\),目标是 \(y(t)\)"。这样一来,每个时间点就变成一行普通的回归数据,和你用 Excel 做"\(y\) 对四个滞后变量回归"没有区别。

金融直觉:串并联与并联的区别,相当于回测一个日度模型时"每天都用真实的昨日数据重新预测"与"只给第一天的真实数据,之后用自己的预测值往前滚"。前者检验的是一步预测能力;后者检验的是模型能否独立模拟一条路径,类似用模型做多期情景模拟,误差会层层叠加。


27.4 训练

  • Nguyen–Widrow 初始化,贝叶斯正则化训练。预测问题与第 23 章的函数逼近类似,该方法对两者都有效。
  • 有 4000 个数据点,而权值和偏置不到 100 个,其实不太可能过拟合,并不需要贝叶斯正则化或提前停止;但贝叶斯正则化能给出有效参数个数,所以作者只要适用就喜欢用。
  • \(S^1=10\),训练 1000 次迭代后性能变化很小;多个不同初值训练的最终误差平方和相近,可以确信没有陷入局部极小。
  • 有效参数个数收敛到 39。4-10-1 网络共有 \(4\times10+10+10+1=61\) 个参数,有效使用了不到 2/3。若有效参数接近总参数,应当增加隐层神经元重训,这里不需要;也无需减少神经元:计算时间不关键,而就防止过拟合而言,39 个有效参数等价于网络总共只有 39 个参数。这正是贝叶斯正则化的好处:只要网络里潜在的参数足够多,它会为每个问题选出合适的参数数。

白话解释:"有效参数个数"不是数出来的,而是衡量"正则化之后参数实际上还有多少自由度"。最熟悉的类比是 Ridge 回归:惩罚为 \(\lambda\) 时,有效自由度为 \(\sum_j\frac{d_j^2}{d_j^2+\lambda}\)(\(d_j\) 是设计矩阵的奇异值)。每一项在 0 和 1 之间:数据强烈支持的方向(\(d_j^2\gg\lambda\))几乎算一个完整参数,数据不支持的方向(\(d_j^2\ll\lambda\))几乎被压成零、不算参数。贝叶斯正则化的 \(\gamma\) 是同样的思路(第 23 章)。61 个参数里有效 39 个,意味着约 22 个"方向"被正则化压住了,网络大小留有余量。


27.5 验证

27.5.1 散点图

测试集的散点图与训练集一样贴近 45° 线,没有过拟合。但对预测问题,这还远远不够。

27.5.2 预测误差的两条基本性质

预测误差

\[e(t)=y(t)-\hat y(t)=y(t)-a^2(t)\qquad(27.5)\]
应当满足(Box–Jenkins):

  1. 相邻时间步的误差互不相关;
  2. 误差与输入序列 \(u(t)\) 不相关。

否则就能利用这种相关性改进预测。例如,如果相隔一步的误差正相关,那么当前一个大的正误差就预示下一步误差也为正,把下一步的预测调高就能减小误差。输入与误差相关时同理。

自相关检验:

\[R_e(\tau)=\frac{1}{Q-\tau}\sum_{t=1}^{Q-\tau}e(t)e(t+\tau),\qquad -\frac{2R_e(0)}{\sqrt Q}<R_e(\tau)<\frac{2R_e(0)}{\sqrt Q}.\qquad(27.6,27.7)\]
白噪声误差的自相关函数应是 \(\tau=0\) 处的一个脉冲,其余接近零。

互相关检验:

\[R_{ue}(\tau)=\frac{1}{Q-\tau}\sum_{t=1}^{Q-\tau}u(t)e(t+\tau),\qquad |R_{ue}(\tau)|<\frac{2\sqrt{R_e(0)}\sqrt{R_u(0)}}{\sqrt Q}.\qquad(27.8,27.9)\]

推导拆解:两个置信界其实是同一条规则换了单位。 第一步,把自协方差除以方差,得到自相关系数:\(\hat\rho_e(\tau)=R_e(\tau)/R_e(0)\)。 第二步,若误差是白噪声(各期独立),样本自相关系数近似服从 \(N(0,1/Q)\),所以 95% 置信区间约为 \(|\hat\rho_e(\tau)|<1.96/\sqrt Q\approx2/\sqrt Q\)。这就是 CFA 里残差自相关 \(t\) 检验 \(t=\hat\rho/(1/\sqrt T)\) 的同一个结论。 第三步,两边乘回 \(R_e(0)\),得到式 (27.7):\(|R_e(\tau)|<2R_e(0)/\sqrt Q\)。 互相关同理:相关系数是 \(R_{ue}(\tau)/\sqrt{R_e(0)R_u(0)}\)(协方差除以两个标准差),在"误差是白噪声且与 \(u\) 独立"的原假设下标准差也约为 \(1/\sqrt Q\),乘回分母就是式 (27.9)。 注意:同时检验 20 个滞后时,即使模型完美,平均也会有约 1 个滞后"偶然超界"(20×5%),所以看到 1–2 个超界不必紧张,要看超界的数量和幅度。这也是 Ljung–Box 联合检验存在的原因。

27.5.3 用检验结果调整延迟阶数

  • \(n_y=n_u=2\)、\(S^1=10\) 时,误差自相关在若干点超出置信界,提示需要增大 \(n_y\)、\(n_u\);互相关都在界内。
  • 把 \(n_y\)、\(n_u\) 增到 4 重训后,自相关除 \(\tau=0\) 外都在界内,互相关也都远在界内。此时预测误差是白噪声且与输入不相关,模型是准确的。

这体现了第 22 章的迭代精神:不是看误差小就满意,而是看误差里还有没有可以被利用的结构。

27.5.4 一步预测与多步迭代预测

最终模型的一步预测误差非常小(归一化单位下约 \(10^{-4}\) 量级),但因为是串并联形式,这只是一步预测误差:每一步都用真实的过去位置作输入。更严格的检验是把网络改回并联形式,做多步迭代预测:只给初始几个真实位置,之后每一步都把自己的预测反馈回去。原书图 27.14 显示,即使提前 600 个时间步(6 秒)预测,NARX 仍然非常准确。


27.6 复现:磁悬浮系统的 NARX 辨识

下面用 Python 复现整个案例:按式 (27.1) 仿真 4000 点 skyline 激励数据,缩放到 \([-1,1]\)(统计量只用训练段),用串并联形式训练 \(n=2\) 与 \(n=4\) 两个 NARX 网络,做自相关、互相关检验,然后改回并联形式做 600 步迭代预测,比较 5 个随机初值及其委员会。

与原书有两处实现差异,先说明:一是仿真里电流为负时磁铁会被拉到电磁铁上,我们在 \(y=0.05\) 处加了一个"接触"边界;二是让网络学习标准化的增量 \(y(t)-y(t-1)\),再加回 \(y(t-1)\) 得到 \(y(t)\)。后者只是目标的重新参数化,模型仍是式 (27.2) 的 NARX;这样做是因为 0.01 秒内位置变化极小,直接拟合 \(y(t)\) 时损失函数数值太小,lbfgs 会过早触发停止条件。这也是金融里直接预测收益(增量)而不是价格的原因之一。

import numpy as np, warnings
from sklearn.neural_network import MLPRegressor
warnings.filterwarnings("ignore")
rng = np.random.default_rng(0)

# ---------- 磁悬浮系统式(27.1)的仿真, skyline 随机脉冲输入 ----------
alpha, beta, g, M = 15.0, 12.0, 9.8, 3.0
N, dt, sub = 4000, 0.01, 50                           # 4000 点, 每 0.01 秒采样, 内部 50 个欧拉子步
u = np.empty(N); k = 0
while k < N:                                          # 随机幅度 [-1,4] A、随机宽度 0.05~1.5 s
    w = rng.integers(5, 150); u[k:k + w] = rng.uniform(-1, 4); k += w
y = np.empty(N); pos, vel, h = 2.0, 0.0, dt / sub
for t in range(N):
    y[t] = pos
    for _ in range(sub):
        acc = -g + alpha / M * u[t] ** 2 * np.sign(u[t]) / pos - beta / M * vel
        vel += h * acc; pos += h * vel
        if pos < 0.05: pos, vel = 0.05, 0.0           # 磁铁落到电磁铁上
# 式(22.1) 缩放到 [-1,1]; 统计量只用前 85%(训练段)
ntr = int(0.85 * N)
sc = lambda x: 2 * (x - x[:ntr].min()) / (x[:ntr].max() - x[:ntr].min()) - 1
un, yn = sc(u), sc(y)

def design(n):            # 串并联 NARX 输入 p(t) = [u(t-1..t-n), y(t-1..t-n)], 目标 y(t)
    P = np.column_stack([un[n - i:N - i] for i in range(1, n + 1)] + [yn[n - i:N - i] for i in range(1, n + 1)])
    return P, yn[n:]

def corr_check(e, x, maxlag=20):
    Q = len(e); Re0, Rx0 = e @ e / Q, x @ x / Q
    Re = np.array([e[:Q - k] @ e[k:] / (Q - k) for k in range(1, maxlag + 1)])
    Rxe = np.array([x[:Q - k] @ e[k:] / (Q - k) for k in range(0, maxlag + 1)])
    return (np.sum(np.abs(Re) > 2 * Re0 / np.sqrt(Q)), np.abs(Re).max() / (2 * Re0 / np.sqrt(Q)),
            np.sum(np.abs(Rxe) > 2 * np.sqrt(Re0 * Rx0) / np.sqrt(Q)))

class NARX:   # 网络学习增量 y(t)-y(t-1)(标准化后), 输出仍是 y(t); 只是目标的重新参数化
    def __init__(self, n, seed=0): self.n, self.seed = n, seed
    def fit(self, P, T):
        D = T - P[:, self.n]; self.s = D.std()
        self.net = MLPRegressor(hidden_layer_sizes=(10,), activation="tanh", solver="lbfgs", alpha=1e-6,
                                max_iter=20000, max_fun=50000, tol=1e-12, random_state=self.seed).fit(P, D / self.s)
        return self
    def predict(self, P): return P[:, self.n] + self.s * self.net.predict(P)

for n in (2, 4):
    P, T = design(n); tr, te = np.arange(ntr - n), np.arange(ntr - n, len(T))   # 测试 = 末尾连续 15%
    net = NARX(n).fit(P[tr], T[tr])
    e = T - net.predict(P)
    a, ratio, b = corr_check(e[tr], un[n:][tr])
    print(f"n_u=n_y={n}: 一步预测 RMSE(归一化单位) 训练 {np.sqrt(np.mean(e[tr]**2)):.2e} 测试 {np.sqrt(np.mean(e[te]**2)):.2e}"
          f" | 自相关超界 {a}/20 (最大值为界的 {ratio:.1f} 倍) | 互相关超界 {b}/21")

# ---------- 改回并联形式: 用自己的预测反馈, 从测试段起点迭代预测 600 步 ----------
n, start, H = 4, ntr, 600
to_raw = lambda z: (z + 1) * (y[:ntr].max() - y[:ntr].min()) / 2 + y[:ntr].min()
P, T = design(n); tr = np.arange(ntr - n)
nets = [NARX(n, seed).fit(P[tr], T[tr]) for seed in range(5)]

def iterate(members):
    yhat = list(yn[start - n:start])                   # 只用起点之前的真实输出初始化
    for t in range(start, start + H):
        p = np.r_[un[t - n:t][::-1], np.array(yhat[-n:])[::-1]]   # [u(t-1..t-n), ŷ(t-1..t-n)]
        yhat.append(np.mean([m.predict(p[None])[0] for m in members]))
    return to_raw(np.array(yhat[n:]))

truth = y[start:start + H]
for k, m in enumerate(nets):
    one = np.sqrt(np.mean((to_raw(m.predict(P[ntr - n:ntr - n + H])) - truth) ** 2))
    par = np.sqrt(np.mean((iterate([m]) - truth) ** 2))
    print(f"种子 {k}: 原始单位 RMSE: 一步预测 {one:.1e}   并联迭代 {H} 步 {par:.4f}")
yc = iterate(nets)
print(f"5 网络委员会: 并联迭代 RMSE {np.sqrt(np.mean((yc - truth) ** 2)):.4f}   (测试段位置标准差 {truth.std():.4f})")
for step in (1, 10, 100, 300, 600):
    print(f"  第 {step:>3} 步: 真实 {truth[step - 1]:.3f}  委员会预测 {yc[step - 1]:.3f}")

关键输出:

n_u=n_y=2: 一步预测 RMSE(归一化单位) 训练 3.73e-04 测试 1.60e-04 | 自相关超界 19/20 (最大值为界的 8.7 倍) | 互相关超界 0/21
n_u=n_y=4: 一步预测 RMSE(归一化单位) 训练 3.05e-04 测试 9.83e-05 | 自相关超界 3/20 (最大值为界的 8.5 倍) | 互相关超界 0/21
种子 0: 原始单位 RMSE: 一步预测 2.9e-04   并联迭代 600 步 0.5769
种子 1: 原始单位 RMSE: 一步预测 3.1e-04   并联迭代 600 步 0.1868
种子 2: 原始单位 RMSE: 一步预测 2.4e-04   并联迭代 600 步 0.1289
种子 3: 原始单位 RMSE: 一步预测 1.8e-04   并联迭代 600 步 0.1201
种子 4: 原始单位 RMSE: 一步预测 2.7e-04   并联迭代 600 步 0.2397
5 网络委员会: 并联迭代 RMSE 0.1037   (测试段位置标准差 0.6024)
  第   1 步: 真实 2.620  委员会预测 2.621
  第  10 步: 真实 2.814  委员会预测 2.817
  第 100 步: 真实 4.151  委员会预测 4.016
  第 300 步: 真实 3.968  委员会预测 3.974
  第 600 步: 真实 4.312  委员会预测 4.095

延迟阶数。 \(n=2\) 时 20 个滞后中有 19 个自相关超界;\(n=4\) 时降到 3 个,与原书"把 2 增到 4 后误差变白"的结论方向一致。我们的 \(n=4\) 模型在一阶滞后上仍超界较多,主要来自仿真中的接触边界(磁铁撞到电磁铁时动态不光滑),按第 22 章的流程,下一步可以再加神经元或延迟,或者为接触状态单独建模。互相关始终在界内。

一步与多步的差别。 这是本节最值得记住的结果。5 个随机初值的一步预测误差都在 \(2\times10^{-4}\) 左右,几乎无法区分;改成并联形式迭代 600 步后,误差却从 0.12 到 0.58 不等,种子 0 的误差几乎和位置本身的标准差一样大。原因是串并联训练只约束了一步映射,而多步迭代时,小的模型误差会沿着反馈回路累积,结果取决于模型在"自己造成的、训练中没见过的状态"附近的行为,不同初值在这些区域差别很大。5 个网络组成委员会后,600 步迭代误差降到 0.104,约为位置标准差的六分之一,比任何单个网络都好,这是第 22 章委员会方法在动态模型上的价值。结论是:对动态模型,必须在并联形式下验证,并且要看多个初值,而不是挑一个一步误差最小的就交差。

推导拆解:为什么一步误差几乎一样,多步误差却差几倍?用最简单的线性情形看。设真实系统 \(y(t)=a\,y(t-1)\),模型估出 \(\hat a=a+\delta\),\(\delta\) 很小。 一步预测:\(\hat y(t)-y(t)=\delta\,y(t-1)\),误差与 \(\delta\) 同阶,很小。 迭代 \(h\) 步:\(\hat y(t+h)=\hat a^{h}y(t)\),误差为 \((\hat a^h-a^h)y(t)\)。对 \(a^h\) 求导(幂函数求导 \(\frac{d}{da}a^h=h\,a^{h-1}\))作一阶泰勒近似,得 \(\hat a^h-a^h\approx h\,a^{h-1}\delta\)。 当 \(|a|\) 接近 1(系统"记忆长",如磁悬浮的位置),\(a^{h-1}\) 衰减很慢,误差约以 \(h\) 倍放大;600 步就是几百倍。非线性系统里还要加上"轨迹进入训练中没见过的区域"这个因素,放大得更不规则。所以一步误差相差 1.7 倍的几个模型,多步误差可以相差近 5 倍。 委员会平均之所以有效,是因为各网络的 \(\delta\) 方向不同,平均后部分抵消,类似组合分散化降低了非系统性误差。


27.7 量化实战:用 NARX 预测金融收益

27.7.1 磁悬浮与金融序列的根本差别

形式上,用收益和外生变量(资金流、情绪、利差、成交量、期货基差等)的滞后项预测下一期收益,就是式 (27.2) 的 NARX,线性版本就是 ARX/ARDL。但两类问题在四个方面截然不同:

方面 磁悬浮(原书案例) 金融收益
噪声 确定性系统,误差可以压到 \(10^{-4}\) 信噪比极低,日度可预测部分的 \(R^2\) 通常只有百分之一的量级
平稳性 物理规律不变 波动率聚集、关系随时间衰减或反转
外生输入 电流是控制量,未来值已知 外生变量的未来值未知,多步预测还要预测它们
激励设计 可以设计 skyline 输入覆盖工况 只能被动接受历史上发生过的状态

这些差别决定了下面每一条改动。

27.7.2 数据处理

预测收益而不是价格。 价格非平稳且高度自相关,预测"明天价格 ≈ 今天价格"就能得到极高的 \(R^2\) 和漂亮的散点图,但毫无价值。目标应是收益(增量),评估也要针对收益。

无前视的波动标准化。 收益的方差随时间剧烈变化(GARCH 效应,第 06 册第 03a 章),直接用原始收益训练,损失会被高波动时期主导。常用做法是除以只用 \(t-1\) 及以前信息估计的波动,例如 EWMA:

\[\hat\sigma^2_t=\lambda\hat\sigma^2_{t-1}+(1-\lambda)r^2_{t-1},\qquad z_t=r_t/\hat\sigma_t.\]
这既是第 22 章的"归一化",也是"非线性变换融入先验知识"。注意 \(\hat\sigma_t\) 里绝不能含 \(r_t\)。

金融直觉:这就是 RiskMetrics 的 EWMA 波动模型,日度常用 \(\lambda=0.94\),也是你在 VaR 计算里见过的那个。把递推式反复代入展开:\(\hat\sigma^2_t=(1-\lambda)\sum_{k\ge1}\lambda^{k-1}r^2_{t-k}\),权重按几何级数衰减、总和为 1,平均"回看期"约 \(1/(1-\lambda)\approx17\) 天。除以 \(\hat\sigma_t\) 后,\(z_t\) 大致变成单位方差的序列,2008 年和 2017 年的一天在损失函数中的分量才可比。 前视的典型错误是用全样本标准差,或用包含当天的滚动窗口(如 rolling(20).std() 后忘了滞后一期):这样 \(z_t\) 里暗含了 \(|r_t|\) 的信息,回测会虚高。

时间对齐。 输入里的每个变量都必须在决策时刻已经可得:收盘后才公布的数据只能用于下一个交易日;财务数据要按公告日而不是报告期对齐;宏观数据要用当时的初值而不是事后修订值。

归一化统计量只来自训练窗。 每次重训都重新计算均值、标准差,然后原样用于该窗口之后的测试期。

27.7.3 划分与训练

扩展窗口 walk-forward。 原书"测试集取末尾连续一段"推广为:在 \([0,s)\) 训练、在 \([s,s+\Delta)\) 测试,然后 \(s\leftarrow s+\Delta\) 重训。这样能得到一整段连续的样本外预测,并模拟真实的定期重训。

间隔(purge/embargo)。 标签是 1 日收益时,训练窗末尾与测试窗之间隔 1 天即可;标签是 \(H\) 日累计收益时,要删去训练窗末尾 \(H\) 个样本(第 22 章)。

提前停止的验证集取训练窗末尾,同样隔开,不能随机抽取。

先建线性基准。 原书第 22 章的第一条建议:线性方法够用就不用神经网络。在收益预测中,NARX 必须在同样的 walk-forward 下击败 ARX(如 Ridge),才值得用。

委员会。 低信噪比下单个网络方差很大,5–10 个随机种子的平均几乎总是值得的。

27.7.4 评估

  • 样本外 \(R^2\):以训练期均值(或零)为基准,\(R^2_{oos}=1-\sum(y-\hat y)^2/\sum(y-\bar y_{train})^2\)。日度收益上 \(R^2_{oos}\) 为正、哪怕只有 0.5%,在经济上就可能有意义。
  • IC:预测值与实现收益的相关系数。
  • 策略表现:把预测转成仓位后的收益、夏普比率,扣除交易成本后再看。
  • 残差白噪声检验:式 (27.6)–(27.7) 的逐滞后检验,加上 Ljung–Box 联合检验(第 06 册第 02a 章)。在金融里,收益本身就接近白噪声,所以"残差是白噪声"几乎总能通过,它是必要条件而不是模型好的证据。
  • 残差与外生变量的互相关:式 (27.8)–(27.9) 的思想。若残差与某个变量(或其非线性变换)的滞后项相关,说明还有信息没用上。
  • 分时段评估:非平稳意味着性能会随时间变化,要分段报告,并持续监控。

白话解释:几个指标之间的关系。 样本外 \(R^2\) 与普通 \(R^2\) 不同,它的分母用的是训练期均值,所以可以为负:负值意味着模型还不如"永远预测历史均值"。 \(R^2\) 与 IC 的关系:如果预测值经过最优线性缩放,\(R^2_{oos}\approx\mathrm{IC}^2\)。下文前段 Ridge 的 IC 为 0.089,\(0.089^2\approx0.0079\),与报告的 \(R^2_{oos}=0.0075\) 很接近。这说明 \(R^2\) 小得"吓人"其实只是 IC 平方后的结果;IC 为 0.05–0.1 在实务中已经算可用的信号。 IC 与夏普的联系可以用 Grinold 的主动管理基本定律粗略估计:\(\mathrm{IR}\approx\mathrm{IC}\times\sqrt{\text{每年独立下注次数}}\)。单资产日度择时一年约 252 次下注,\(0.089\times\sqrt{252}\approx1.4\),与下文约 1.1 的夏普同一量级(仓位截断、波动变化会使实际值偏低)。 Ljung–Box 检验把多个滞后的自相关合成一个统计量:\(Q_{LB}=n(n+2)\sum_{k=1}^{m}\frac{\hat\rho_k^2}{n-k}\),原假设"前 \(m\) 阶自相关全为零"下近似服从自由度为 \(m\) 的 \(\chi^2\) 分布。\(p\) 值大表示没发现自相关。

27.7.5 多步预测

磁悬浮可以并联迭代 600 步,是因为系统确定、外生输入已知。金融里做多步预测有两条路:

  • 迭代(并联)预测:把自己的一步预测反馈回去,外生变量的未来值用它自己的预测(如 AR 模型的条件期望)代替。误差会累积,且预测值迅速收缩到均值。
  • 直接预测:为每个步长 \(h\) 单独训练一个预测 \(y(t+h)\) 的模型,不需要反馈,但要处理重叠标签。

无论哪条路,都要预期预测能力随步长迅速衰减。不要拿原书 600 步的精度去类比收益预测。

推导拆解:为什么迭代预测会"收缩到均值"?以 27.7.6 节的外生变量 \(x_t=0.7x_{t-1}+\varepsilon_t\) 为例。站在 \(t\) 时刻,下一期的条件期望是 \(\mathbb E_t[x_{t+1}]=0.7x_t\)(\(\mathbb E_t\) 表示用 \(t\) 时刻已知信息求的条件期望;\(\varepsilon\) 的期望为 0)。再往后一步,用期望的线性性:\(\mathbb E_t[x_{t+2}]=0.7\,\mathbb E_t[x_{t+1}]=0.7^2x_t\),依此类推 \(\mathbb E_t[x_{t+h}]=0.7^hx_t\)。\(0.7^{9}\approx0.04\),所以 10 步后 \(x\) 能提供的信息只剩约 4%。收益的信号又由 \(x\) 驱动,预测值自然随步长几何衰减到零(均值)。这和债券久期里"远期现金流贴现后权重很小"是同一种几何衰减。

27.7.6 代码:walk-forward NARX 与线性基准

下面模拟 5000 个交易日:收益有 GARCH(1,1) 波动;标准化收益的条件均值由外生变量 \(x\)(AR(1))的非线性函数 \(0.12\tanh(1.5x_{t-1})\) 和一个"大幅波动后反转"项组成,第 3500 天之后信号强度减半(模拟非平稳的信号衰减)。流程:EWMA 无前视波动标准化;NARX 输入为 \(z\) 和 \(x\) 各 5 个滞后;从第 1500 天开始扩展窗口 walk-forward,每 250 天重训;对照 Ridge(ARX)和 5 个 MLP 的委员会(提前停止的验证集取训练窗末尾 15%);分段报告样本外 \(R^2\)、IC、简单策略夏普、Ljung–Box;检验残差与 \(\tanh(1.5x_{t-1})\) 的相关;最后做 1–10 步的并联迭代预测。

import numpy as np, warnings, copy
from sklearn.neural_network import MLPRegressor
from sklearn.linear_model import Ridge
from statsmodels.stats.diagnostic import acorr_ljungbox
warnings.filterwarnings("ignore")
rng = np.random.default_rng(2026)

# ---------- 模拟日频数据: GARCH 波动 + 弱的非线性可预测性 + 外生变量 ----------
T = 5000
x = np.zeros(T); r = np.zeros(T); sig2 = np.full(T, 1e-4); z = np.zeros(T)
for t in range(1, T):
    x[t] = 0.7 * x[t - 1] + np.sqrt(1 - 0.49) * rng.normal()          # 外生变量(如资金流/情绪), AR(1)
    sig2[t] = 1e-6 + 0.08 * r[t - 1] ** 2 + 0.90 * sig2[t - 1]         # GARCH(1,1)
    k = 1.0 if t < 3500 else 0.5                                       # 第 3500 天后信号衰减一半(非平稳)
    mean = k * (0.12 * np.tanh(1.5 * x[t - 1]) - 0.06 * z[t - 1] * min(abs(z[t - 1]), 2))
    z[t] = mean + rng.normal()                                         # 标准化收益
    r[t] = np.sqrt(sig2[t]) * z[t]

# 只用 t-1 及以前的信息估计波动(EWMA), 得到无前视的波动标准化收益
ew = np.zeros(T); ew[0] = r[:50].var()
for t in range(1, T): ew[t] = 0.94 * ew[t - 1] + 0.06 * r[t - 1] ** 2
zs = r / np.sqrt(ew)

L = 5          # NARX: 输入 [zs(t-1..t-5), x(t-1..t-5)], 目标 zs(t)
P = np.column_stack([zs[L - i:T - i] for i in range(1, L + 1)] + [x[L - i:T - i] for i in range(1, L + 1)])
Y, idx = zs[L:], np.arange(L, T)

def fit_mlp(Ptr, Ytr, seed):
    nv = int(0.85 * len(Ytr)); a, b = np.arange(nv), np.arange(nv + 1, len(Ytr))   # 验证 = 训练窗末尾, 隔 1 天
    mu, sd = Ptr[a].mean(0), Ptr[a].std(0)
    net = MLPRegressor(hidden_layer_sizes=(8,), activation="tanh", solver="lbfgs", alpha=1.0,
                       max_iter=5, warm_start=True, random_state=seed)
    best, be, wait = None, np.inf, 0
    for _ in range(200):
        net.fit((Ptr[a] - mu) / sd, Ytr[a])
        err = np.mean((net.predict((Ptr[b] - mu) / sd) - Ytr[b]) ** 2)
        if err < be: best, be, wait = copy.deepcopy(net), err, 0
        else:
            wait += 1
            if wait >= 10: break
    return lambda Q: best.predict((Q - mu) / sd)

# ---------- 扩展窗口 walk-forward: 每 250 天重训, 训练窗与测试窗之间隔 1 天 ----------
pred = {"ridge": np.full(len(Y), np.nan), "mlp": np.full(len(Y), np.nan)}
members = None
for s in range(1500, len(Y), 250):
    tr, te = np.arange(0, s - 1), np.arange(s, min(s + 250, len(Y)))
    mu, sd = P[tr].mean(0), P[tr].std(0)
    lin = Ridge(10.0).fit((P[tr] - mu) / sd, Y[tr])
    pred["ridge"][te] = lin.predict((P[te] - mu) / sd)
    members = [fit_mlp(P[tr], Y[tr], seed) for seed in range(5)]       # 5 网络委员会
    pred["mlp"][te] = np.mean([m(P[te]) for m in members], 0)

oos = ~np.isnan(pred["mlp"])
for period, mask in [("前段(信号完整)", oos & (idx < 3500)), ("后段(信号衰减)", idx >= 3500)]:
    print(period)
    for name, p in pred.items():
        e = Y[mask] - p[mask]
        r2 = 1 - np.sum(e ** 2) / np.sum((Y[mask] - Y[:1500].mean()) ** 2)
        ic = np.corrcoef(p[mask], Y[mask])[0, 1]
        pnl = np.clip(p[mask] / 0.15, -1, 1) * r[idx[mask]]             # 仓位 = 截断的预测值
        sharpe = pnl.mean() / pnl.std() * np.sqrt(252)
        lb = acorr_ljungbox(e, lags=[10], return_df=True)["lb_pvalue"].iloc[0]
        print(f"  {name:<5} 样本外R^2 {r2:+.4f}  IC {ic:+.3f}  年化夏普 {sharpe:+.2f}  残差Ljung-Box(10) p={lb:.2f}")

# 残差与外生变量的互相关(式 22.19/27.8 的思想): 线性模型漏掉了 tanh 非线性吗?
for name, p in pred.items():
    e = Y[oos] - p[oos]; xx = np.tanh(1.5 * x[idx[oos] - 1])
    c = np.corrcoef(e, xx)[0, 1]
    print(f"{name:<5} 残差与 tanh(1.5 x_(t-1)) 的相关 {c:+.3f}  (95% 界 ±{2/np.sqrt(oos.sum()):.3f})")

# ---------- 多步迭代预测(并联模式): 未来 x 用其 AR(1) 预测代替 ----------
o = np.where(oos)[0][:-12]                         # 预测起点
H = 10
hist_z = [zs[idx[o] - i] for i in range(L, 0, -1)]        # 最近 5 个已知 zs(按时间先后)
hist_x = [x[idx[o] - i] for i in range(L, 0, -1)]
fc = []
for h in range(1, H + 1):
    Q = np.column_stack(hist_z[::-1][:L] + hist_x[::-1][:L])
    f = np.mean([m(Q) for m in members], 0); fc.append(f)
    hist_z.append(f); hist_x.append(0.7 * hist_x[-1])     # 反馈自己的预测; x 的条件期望
print("步长 h:            " + " ".join(f"{h:>6d}" for h in (1, 2, 3, 5, 10)))
print("预测值标准差:      " + " ".join(f"{fc[h - 1].std():6.3f}" for h in (1, 2, 3, 5, 10)))
print("与实现值的 IC:     " + " ".join(f"{np.corrcoef(fc[h - 1], zs[idx[o] + h - 1])[0, 1]:+6.3f}" for h in (1, 2, 3, 5, 10)))

关键输出:

前段(信号完整)
  ridge 样本外R^2 +0.0075  IC +0.089  年化夏普 +1.11  残差Ljung-Box(10) p=0.29
  mlp   样本外R^2 +0.0041  IC +0.085  年化夏普 +1.03  残差Ljung-Box(10) p=0.29
后段(信号衰减)
  ridge 样本外R^2 +0.0022  IC +0.061  年化夏普 +0.83  残差Ljung-Box(10) p=0.16
  mlp   样本外R^2 +0.0016  IC +0.059  年化夏普 +0.85  残差Ljung-Box(10) p=0.19
ridge 残差与 tanh(1.5 x_(t-1)) 的相关 +0.003  (95% 界 ±0.034)
mlp   残差与 tanh(1.5 x_(t-1)) 的相关 +0.004  (95% 界 ±0.034)
步长 h:                 1      2      3      5     10
预测值标准差:       0.116  0.068  0.042  0.046  0.009
与实现值的 IC:     +0.098 +0.064 +0.033 +0.020 +0.002

把这些数字和磁悬浮的结果放在一起看:

  • 量级完全不同。 磁悬浮的一步预测误差是 \(10^{-4}\),这里的样本外 \(R^2\) 只有 0.2%–0.75%,IC 约 0.06–0.09。这就是真实收益预测的量级;如果你在真实数据上看到 \(R^2=30\%\),首先要怀疑的是泄漏(第 22 章实验一)。尽管 \(R^2\) 很小,一个截断的线性仓位在模拟中仍有约 1 的年化夏普(未扣交易成本),说明小的 \(R^2\) 在经济上可以有意义。
  • 神经网络没有胜过线性基准。 真实的条件均值确实是非线性的(\(\tanh\) 和"大波动后反转"),但在这个信噪比下,这点非线性带来的增益小于网络估计误差的代价:MLP 委员会的 \(R^2\) 和 IC 都略低于 Ridge。残差与 \(\tanh(1.5x_{t-1})\) 的相关在两个模型中都远在界内,说明线性模型并没有漏掉多少可利用的非线性信息。这正是原书"先确认线性方法不够"的意义,在金融里它往往是最终答案。
  • 非平稳。 第 3500 天后信号减半,两个模型的 \(R^2\)、IC、夏普都同步下降。扩展窗口仍在用早期较强的关系,会高估后段的信号;实盘中要分段监控,必要时用滚动窗口或给近期样本更大权重。
  • 残差检验只是必要条件。 两个模型的 Ljung–Box \(p\) 值都大于 0.1,残差"是白噪声"。但收益本来就接近白噪声,一个什么都不预测的模型也能通过。所以在金融里,残差检验只能用来发现问题(例如 \(p\) 值很小说明还有自相关结构没用上),不能用来证明模型好。
  • 多步预测迅速衰减。 迭代预测的标准差从 1 步的 0.116 降到 10 步的 0.009,IC 从 0.098 降到 0.002:几步之后预测就退化为均值。与磁悬浮 600 步仍然准确形成鲜明对比。

金融直觉:为什么真实非线性存在,MLP 却输给 Ridge?这是偏差–方差权衡。\(\tanh(1.5x)\) 在 \(x\) 的常见范围(约 \(\pm1.5\))内大部分接近直线,线性模型的偏差很小;而网络多出来的几十个参数,在 \(R^2\) 不到 1% 的数据上,每个都要用噪声来估计,带来的方差远大于它减少的偏差。类比因子投资:一个简单的单因子打分,样本外常常胜过用大量交互项精细拟合的模型,原因相同。

27.7.7 一份检查清单

看到一个"用神经网络预测收益"的结果时,依次问:

  1. 目标是收益还是价格?是否用了重叠标签?
  2. 每个输入在决策时刻是否已经可得?归一化、波动估计、缺失值填补是否只用过去信息?
  3. 训练/验证/测试是否按时间划分,并有 purge/embargo?
  4. 是否与线性基准(ARX/Ridge)在同样的 walk-forward 下比较?
  5. 是否报告了样本外 \(R^2\)、IC,以及扣成本后的策略表现?是否分时段报告?
  6. 是否用多个随机种子或委员会?结果对种子敏感吗?
  7. 做多步预测时,是在并联(迭代)模式还是直接模式下评估的?
  8. 测试期的输入是否落在训练期的分布范围内(新颖性检测)?

这份清单把第 22 章的训练后分析和本章的预测检验合在一起,也是第 11 册综合实战中所有预测模型都要过的一关。


本章小结

预测与系统辨识用 NARX 网络:\(y(t)\) 对自身和外生输入的若干滞后值做非线性回归,用 tansig 隐层 + 线性输出的前馈网络逼近。数据要用宽度和幅度都随机的 skyline 激励覆盖暂态和稳态;时间序列的测试集取末尾连续一段;延迟阶数先按系统的物理阶数设定。训练时用串并联形式(用真实的过去输出作输入),可以用静态反向传播,贝叶斯正则化给出有效参数数。验证时检查误差自相关是否落在 \(\pm2R_e(0)/\sqrt Q\) 内、误差与输入的互相关是否落在 \(\pm2\sqrt{R_e(0)R_u(0)}/\sqrt Q\) 内,有相关就加长延迟;最后改回并联形式做多步迭代预测,这一步可能暴露一步误差看不出的差异,多初值委员会能明显改善。搬到金融收益预测时:预测收益而非价格,用无前视的波动标准化,按时间 walk-forward 并留间隔,先建线性基准,用样本外 \(R^2\)、IC、扣成本的策略表现和分段结果评估;残差白噪声只是必要条件;多步预测会迅速退化为均值。

概念 公式 / 要点
NARX \(y(t)=f(y(t-1..n_y),u(t-1..n_u))\);\(f\) 线性时为 ARX
串并联输入 \(\mathbf p(t)=[u(t-1),u(t-2),y(t-1),y(t-2)]^T\),目标 \(y(t)\)
并联形式 反馈 \(\hat y\),用于使用和多步预测
skyline 激励 随机幅度、随机宽度脉冲,兼顾暂态与稳态
预测误差 \(e(t)=y(t)-\hat y(t)\),应白且与输入无关
自相关界 \(\vert R_e(\tau)\vert <2R_e(0)/\sqrt Q\)
互相关界 \(\vert R_{ue}(\tau)\vert <2\sqrt{R_e(0)R_u(0)}/\sqrt Q\)
有效参数 4-10-1 网络 61 个参数,有效 39 个
无前视波动标准化 \(\hat\sigma^2_t=\lambda\hat\sigma^2_{t-1}+(1-\lambda)r^2_{t-1}\),\(z_t=r_t/\hat\sigma_t\)
样本外 \(R^2\) \(1-\sum(y-\hat y)^2/\sum(y-\bar y_{train})^2\)

练习

基础

  1. 式 (27.1) 中,电流恒为 \(i>0\) 时,磁铁的平衡位置是多少?取 \(i=2\) A 计算。 答案:令加速度和速度为零,\(g=\alpha i^2/(My)\),\(y=\alpha i^2/(Mg)=15\times4/(3\times9.8)\approx2.04\)。
  2. 4-10-1 网络有多少个参数?若贝叶斯正则化给出有效参数 58,你会怎么做? 答案:61;有效参数接近总数,说明网络可能不够大,应增加隐层神经元重训。
  3. 为什么串并联形式可以用静态反向传播训练,而并联形式不行? 提示:串并联形式中反馈的是已知的目标值,网络是纯前馈的;并联形式中输入依赖于网络自己过去的输出,梯度要穿过时间(第 14 章的动态反向传播)。
  4. 某预测模型在 \(Q=1000\) 的样本上 \(R_e(0)=4\),\(R_e(1)=0.5\)。是否通过白噪声检验?这提示要怎么改模型? 答案:界为 \(2\times4/\sqrt{1000}=0.253\),0.5 超界;一阶误差正相关,应加长延迟线(或加入误差的移动平均项)。
  5. 为什么"明天价格 = 今天价格"在价格散点图上表现极好,却毫无价值?应当怎样评估? 提示:价格高度持续,散点图和 \(R^2\) 由持续性主导;应评估收益的预测,用样本外 \(R^2\)、IC 等。

进阶

  1. 修改 27.6 节的代码,把 \(n_u=n_y\) 增到 6,并把隐层增到 20,看自相关超界数和 600 步并联预测误差如何变化。一步误差的改进是否总能带来多步误差的改进?
  2. 在 27.6 节代码中,把电流范围改为 \([0.5,4]\)(磁铁不会撞到电磁铁),重做 \(n=2\) 与 \(n=4\) 的检验,与原结果比较,验证"接触边界造成残差自相关"的解释。
  3. 在 27.7.6 节代码中,把条件均值的非线性加强(例如把 \(0.12\tanh(1.5x)\) 换成 \(0.25\,\mathrm{sgn}(x)\,\mathbf 1\{|x|>1\}\)),看 MLP 是否开始胜过 Ridge,并检查 Ridge 残差与该非线性项的相关是否超界。
  4. 把 27.7.6 节的扩展窗口改为 1000 天的滚动窗口,比较前段与后段的样本外表现。滚动窗口在信号衰减后是更好还是更差?为什么?
  5. 为 27.7.6 节实现"直接多步预测":为 \(h=5\) 训练一个预测未来 5 日累计标准化收益的模型(注意 purge),与迭代预测比较 IC。

原书推荐习题:第 27 章为案例章,无习题。建议用原书数据 maglev_u.txt/maglev_y.txt 复现 \(n_y=n_u=2\) 与 4 的残差自相关对比,以及串并联训练后改用并联形式的多步迭代预测;再在一个真实的金融收益序列上做同样的残差检验,比较两类数据的可预测性。

原书对照

本章小节 原书章节 PDF 页码
27.1 问题 27 Objectives;Description of the Magnetic Levitation System(式 27.1) p.965–967
27.2 数据 Data Collection and Preprocessing(skyline 输入,图 27.2–27.3) p.967–968
27.3 结构 Selecting the Architecture(式 27.2–27.4,图 27.4–27.5) p.968–970
27.4 训练 Training the Network(图 27.6–27.7) p.971–972
27.5 验证 Validation(式 27.5–27.9,图 27.8–27.14) p.972–977
— Epilogue、Further Reading p.978–979
27.6、27.7 本册补充的复现与量化实战 —

原书附录(PDF p.980–1012)简要说明。

  • 附录 A 参考文献(p.980–990):全书文献总表,按作者–年份代码排序,每条注明被引用的章节。注意 [Mill93] 与 [Moll93] 实为同一篇标度共轭梯度论文(作者 M. F. Møller),书中出现两种拼写。
  • 附录 B 记号(p.991–998):标量小写斜体、向量小写粗体、矩阵大写粗体;\(w^k_{i,j}\) 为第 \(k\) 层第 \(i\) 行第 \(j\) 列权值,\(\mathbf w_j\) 为列、\({}_i\mathbf w\) 为行;\(M\) 层数、\(S^k\) 第 \(k\) 层神经元数、\(Q\) 样本数、\(R\) 输入维数;动态网络的 \(\mathbf{IW}^{m,l}(d)\)、\(\mathbf{LW}^{m,l}(d)\);ART 与 Hopfield 的专用记号等。读原书公式时可随时查阅。
  • 附录 C 软件(p.999–1003):演示程序需 MATLAB,在 MATLAB 中输入 nnd 打开主菜单,help nndesign 列出全部演示。第 19–21 章正文中引用的演示名沿用第一版编号(nnd16al1、nnd17ds、nnd18hn 等),附录 C 中第二版编号为 nnd19al1、nnd20ds、nnd21hn 等,以附录为准。案例数据文件随演示软件提供。
  • 索引与封底(p.1004–1012)。