量化交易中文教材

第 22b 章 分类误差评估:交叉验证与 VC 界

本章与第 22a 章共同对应 Wasserman 原书第 22 章,重点是原书 22.8 节《Assessing Error Rates and Choosing a Good Classifier》及相关习题。第 22a 章的实验已经显示:不限深度的树训练误差为 0,测试误差却比线性模型还差。训练误差会系统地低估真实误差,而且模型越灵活、被比较的模型越多,低估越严重。这正是量化研究中"回测过拟合"的数学本质。本章给出两类工具:一是交叉验证,用没参与训练的数据估计误差;二是概率不等式(Hoeffding、VC 不等式),给出对整族分类器同时成立的误差界,从而量化"挑选"本身带来的乐观偏差。最后讨论时间序列中交叉验证的正确用法。

学习目标

  1. 理解训练误差为什么低估真实误差,能画出"训练误差单调下降、验证误差 U 形"的典型图像并解释它。
  2. 会用留出验证和 K 折交叉验证估计错误率、选择模型复杂度。
  3. 会用 Hoeffding 不等式与并集界推导有限分类器族的一致收敛界,并据此解释"从 \(m\) 个策略中挑最好的"的乐观偏差。
  4. 理解粉碎系数、VC 维的定义,会计算简单集合类的 VC 维,知道 VC 界的意义和局限。
  5. 理解分类问题中偏差–方差权衡与回归的不同(Friedman 分解)。
  6. 能识别时间序列数据中随机 K 折造成的信息泄露,会使用前推验证与剔除重叠样本。

读前导读

这一章在解决什么问题

结论:本章回答"回测里看到的胜率,有多少是真本事、有多少是挑出来的运气",并给出定量的修正方法。

你在 CFA 的回测与数据挖掘偏差(data-snooping bias)部分见过这个问题的定性描述:试了足够多的策略,总有一个看起来很好。本章把它变成数学:如果你从 \(m\) 个策略里挑出样本内最好的那个,它的真实胜率与样本内胜率之间的差距,最多会有多大?答案只随 \(\log m\) 增长,这就是 Hoeffding 不等式加并集界。对线性分类器、树这类有无穷多个参数取值的"策略族",用 VC 维代替 \(m\) 来度量"挑选空间有多大"。

实务上更常用的是交叉验证:把数据切开,在没参与训练的部分上打分。但金融时间序列有自相关和标签重叠,随机切分会让模型"偷看"到测试期的信息,导致严重高估。本章最后专门讲怎么正确地在时间序列上做验证,这在量化研究中可能比本章任何定理都更直接有用。

需要先想起来的数学

1. 二项分布与样本比例的置信区间。 正确次数 \(\sim\text{Binomial}(n,p)\),比例 \(\hat p\) 的标准误 \(\sqrt{p(1-p)/n}\)。例:500 天、胜率 52%,标准误约 \(\sqrt{0.25/500}\approx0.022\),52% 离 50% 还不到一个标准误。

2. 指数与对数的反解。 从 \(2me^{-2n\epsilon^2}=\alpha\) 解出 \(\epsilon\):两边取自然对数 \(\log(2m)-2n\epsilon^2=\log\alpha\),于是 \(\epsilon^2=\frac{1}{2n}\log\frac{2m}{\alpha}\)。参见 第 00 册第 04 章 级数与收敛 中指数对数部分。

3. 概率不等式与并集界。 并集界:\(\mathbb P(A_1\cup\cdots\cup A_m)\le\sum_j\mathbb P(A_j)\),即"至少一件坏事发生"的概率不超过各件坏事概率之和(重叠部分被重复计算,所以是上界)。Hoeffding 不等式给出样本均值偏离真值的概率上界,比切比雪夫不等式紧得多。参见 第 00 册第 07 章 概率中的分析工具。

4. 记号 \(\sup\) 与 \(\max\)。 \(\sup\)(上确界)可以先当作"最大值"理解;区别只在于无穷多个对象时最大值可能取不到,但上确界总存在。例:\(\{0.9,0.99,0.999,\dots\}\) 没有最大值,上确界是 1。参见 第 00 册第 01 章 函数极限与连续。

5. 标准正态分布函数 \(\Phi\)。 \(\Phi(z)=\mathbb P(Z\le z)\),\(1-\Phi(z)\) 是右尾概率。例:\(1-\Phi(1)\approx0.16\),\(1-\Phi(-1)\approx0.84\)。

怎么读这一章

核心必读:22b.1、22b.2(交叉验证与"使用纪律")、22b.3(有限族界,最贴近"挑策略"问题)、22b.7(时间序列交叉验证)、22b.8 实战。22b.4 的 VC 理论第一次只需理解"粉碎"的定义、例 22.22–22.23 和"VC 维是容量度量"这一结论,VC 不等式的常数可以略过。22b.5 Friedman 分解与 22b.6 维数灾难几何直观可在第二遍阅读。建议顺序:22b.1 → 22b.2 → 22b.7 → 22b.8 实验 (1)(2) → 22b.3 → 实验 (3) → 22b.4 → 22b.5–22b.6。


22b.1 训练误差的乐观偏差

训练误差 \(\hat L_n(h)\) 在固定 \(h\) 时是 \(L(h)\) 的无偏估计。但实际中 \(\hat h\) 是用同一份数据挑出来的——在所有候选中,它恰好让训练误差最小。被挑中的那个,往往是"在这份数据上运气好"的那个,所以 \(\hat L_n(\hat h)\) 向下有偏。

白话解释:用期望的语言说,对每个固定的 \(h\),\(\mathbb E\hat L_n(h)=L(h)\);但"先取最小值再求期望"不等于"先求期望再取最小值":\(\mathbb E\big[\min_h\hat L_n(h)\big]\le\min_h\mathbb E\hat L_n(h)\)。最小值这个操作会主动挑出向下偏离的那个。

金融直觉:这就是基金业的"冠军诅咒"。1000 只基金都没有选股能力,去年排名第一的那只业绩依然会很亮眼;拿它的去年业绩估计明年业绩,必然高估。22b.8 实验 (3) 用数字演示了这一点:1 万个纯随机策略中最好的那个,样本内方向准确率平均达 58.6%。

例 22.14(CORIS)。 依次拟合含 1、2、…、9 个协变量的 logistic 模型,再逐个加入平方项,得到 18 个复杂度递增的分类器。训练误差单调下降(继续加项可以降到零);10 折交叉验证估计的误差先降后升。这与第 20 章的偏差–方差权衡是同一件事:复杂度低时偏差主导,复杂度高时方差主导。

22b.2 交叉验证

22b.2.1 留出验证

最简单的做法:把数据随机分成训练集 \(\mathcal T\) 与验证集 \(\mathcal V\)(常留约 10%–30% 做验证)。只用 \(\mathcal T\) 构造 \(\hat h\),然后在 \(\mathcal V\) 上计算

\[\hat L(\hat h)=\frac1m\sum_{X_i\in\mathcal V}I(\hat h(X_i)\ne Y_i),\tag{22.32}\]
\(m\) 是验证集大小。由于 \(\hat h\) 与 \(\mathcal V\) 独立,\(\hat L(\hat h)\) 是 \(L(\hat h)\) 的无偏估计,且 \(m\hat L\sim\text{Binomial}(m,L(\hat h))\),可以直接构造置信区间。缺点是浪费数据:训练只用了一部分,验证也只用了一部分。

22b.2.2 K 折交叉验证

  1. 把数据随机分成大小近似相等的 \(K\) 块(常取 \(K=5\) 或 \(10\));
  2. 对 \(k=1,\dots,K\):删去第 \(k\) 块,用其余数据训练得 \(\hat h_{(k)}\),在第 \(k\) 块上计算错误率 \(\hat L_{(k)}\);
  3. \(\hat L(h)=\frac1K\sum_{k=1}^K\hat L_{(k)}\)。(22.33)

每个观测恰好被验证一次,所有数据都参与了训练和验证。

补充:\(K\) 的选择。 每次训练只用 \((K-1)/K\) 的数据,所以 CV 估计的是"样本量略小时"的误差,略偏悲观;\(K\) 越大这一偏差越小,但各折训练集高度重叠,估计的方差和计算量都增加。\(K=5\) 或 \(10\) 是常用的折中。留一法(\(K=n\))在第 20 章的平滑问题中有捷径公式,在分类中一般没有。

例 22.15(CORIS 分类树)。 10 折 CV 误差在 6 个叶时最小,选出的树规则简单且可解释(见第 22a 章)。

重要的使用纪律。 用 CV 选出复杂度(例如叶子数)后,CV 误差的最小值本身又是一个"挑出来的最小值",同样偏乐观。需要无偏的最终误差估计时,应在一开始就留出一份从不参与任何选择的测试集,或使用嵌套交叉验证(外层估计误差、内层选参数)。

22b.3 概率不等式:有限分类器族

交叉验证给出点估计;概率不等式则给出对整族分类器同时成立的置信区间,从而量化"挑选"的代价。设 \(\mathcal H\) 是一族分类器,**经验风险最小化(ERM)**选出

\[\hat h=\arg\min_{h\in\mathcal H}\hat L_n(h).\tag{22.34}\]

工具:Hoeffding 不等式(第 01 章)。\(X_i\sim\text{Bernoulli}(p)\) IID 时

\[\mathbb P(|\hat p-p|>\epsilon)\le2e^{-2n\epsilon^2}.\tag{22.35}\]
对固定的 \(h\),\(I(h(X_i)\ne Y_i)\) 就是 Bernoulli\((L(h))\),所以 \(\mathbb P(|\hat L_n(h)-L(h)|>\epsilon)\le2e^{-2n\epsilon^2}\)。

定理 22.16(一致收敛)。 若 \(\mathcal H\) 有限,含 \(m\) 个分类器,则

\[\mathbb P\Big(\max_{h\in\mathcal H}|\hat L_n(h)-L(h)|>\epsilon\Big)\le2me^{-2n\epsilon^2}.\]
证明。 "存在某个 \(h\) 偏离超过 \(\epsilon\)"是 \(m\) 个事件的并,由并集界 \(\mathbb P(\cup A_j)\le\sum\mathbb P(A_j)\) 加 Hoeffding 即得。\(\square\)

定理 22.17。 令

\[\epsilon=\sqrt{\frac1{2n}\log\frac{2m}\alpha},\]
则 \(\hat L_n(\hat h)\pm\epsilon\) 是 \(L(\hat h)\) 的 \(1-\alpha\) 置信区间。 证明。 无论 \(\hat h\) 是怎样从 \(\mathcal H\) 中选出的,都有 \(\mathbb P(|\hat L_n(\hat h)-L(\hat h)|>\epsilon)\le\mathbb P(\max_h|\hat L_n(h)-L(h)|>\epsilon)\le\alpha\)。\(\square\)

这个结论的关键在于"无论怎样选出"。对单个固定的分类器,区间半宽是 \(\sqrt{\log(2/\alpha)/(2n)}\);要对从 \(m\) 个中挑出的那个负责,半宽要放大到 \(\sqrt{\log(2m/\alpha)/(2n)}\)。\(\mathcal H\) 越大,区间越宽——候选越多,越可能挑中一个靠运气胜出的,宽区间正是对此的补偿。 好消息是代价只随 \(\log m\) 增长。

推导拆解:定理 22.17 的 \(\epsilon\) 是这样定出来的:要求定理 22.16 右边 \(2me^{-2n\epsilon^2}\) 恰好等于 \(\alpha\),取对数解出 \(\epsilon\)(见读前导读第 2 条)。

证明里的关键是第一个不等号:\(\hat h\) 是 \(\mathcal H\) 中的某一个,所以"\(\hat h\) 偏离超过 \(\epsilon\)"这个事件包含在"族中至少有一个偏离超过 \(\epsilon\)"这个事件里,前者概率不会更大。由于后者对所有成员同时控制,不管你用什么方法(甚至偷看数据)选出 \(\hat h\),界都成立。

数值感受(\(n=500\),\(\alpha=0.05\)):\(m=1\) 时半宽 0.061;\(m=10000\) 时 0.114。候选数扩大 1 万倍,半宽不到翻倍。但反过来看,即便只测了一个策略,500 天的数据也只能把胜率确定到 ±6% 左右。

22b.4 VC 理论:无限分类器族

线性分类器有无穷多个,\(\log m=\infty\),定理 22.17 失效。Vapnik 与 Chervonenkis 的想法是:在 \(n\) 个数据点上,无穷多个分类器能产生的不同标注方式其实是有限的。

22b.4.1 粉碎系数与 VC 不等式

设 \(\mathcal A\) 是一族集合。对有限点集 \(F=\{x_1,\dots,x_n\}\),令

\[N_{\mathcal A}(F)=\#\{F\cap A:A\in\mathcal A\}\tag{22.36}\]
为 \(\mathcal A\) 能从 \(F\) 中"挑出"的不同子集个数。**粉碎系数(shatter coefficient)**是所有 \(n\) 点集上的最大值:
\[s(\mathcal A,n)=\max_{|F|=n}N_{\mathcal A}(F)\le2^n.\tag{22.37}\]
若 \(N_{\mathcal A}(F)=2^n\),即 \(F\) 的每个子集都能被某个 \(A\) 挑出,称 \(\mathcal A\) **粉碎(shatter)**了 \(F\)。

白话解释:把"集合 \(A\)"理解为一条交易规则"在 \(A\) 里就做多"。在 \(n\) 个历史日子上,一条规则的全部行为就是"哪些天做多",即 \(F\) 的一个子集。规则有无穷多条,但它们在这 \(n\) 天上产生的不同"做多日组合"最多 \(2^n\) 种;真正影响过拟合程度的是实际能产生多少种,这就是 \(N_{\mathcal A}(F)\)。

小例子:规则族为"信号值 ≤ 阈值 \(a\) 时做多"(半直线)。三天的信号值为 1、2、3,阈值从左到右移动,只能产生 \(\varnothing\)、\(\{1\}\)、\(\{1,2\}\)、\(\{1,2,3\}\) 四种组合,而不是 \(2^3=8\) 种。所以这族规则虽然有无穷多个阈值,"有效个数"只有 \(n+1\) 个,挑选它的代价很小。

"粉碎"就是"任何做多日组合都能实现"——容量大到可以拟合任何标签,这正是过拟合的危险信号。

定理 22.18(Vapnik–Chervonenkis 1971)。 对任意分布 \(\mathbb P\)、任意 \(n\) 和 \(\epsilon>0\),

\[\mathbb P\Big\{\sup_{A\in\mathcal A}|\mathbb P_n(A)-\mathbb P(A)|>\epsilon\Big\}\le8s(\mathcal A,n)e^{-n\epsilon^2/32},\tag{22.38}\]
其中 \(\mathbb P_n(A)=\frac1n\sum_iI(X_i\in A)\) 是经验概率。(证明优雅但较长,原书略去。)

对分类器族 \(\mathcal H\),令 \(\mathcal A=\{\{x:h(x)=1\}:h\in\mathcal H\}\),定义 \(s(\mathcal H,n)=s(\mathcal A,n)\)。

定理 22.19。

\[\mathbb P\Big\{\sup_{h\in\mathcal H}|\hat L_n(h)-L(h)|>\epsilon\Big\}\le8s(\mathcal H,n)e^{-n\epsilon^2/32},\]
因此 \(L(\hat h)\) 的 \(1-\alpha\) 置信区间为 \(\hat L_n(\hat h)\pm\epsilon_n\),\(\epsilon_n^2=\frac{32}n\log\frac{8s(\mathcal H,n)}\alpha\)。

它与定理 22.17 结构完全相同,只是把"分类器个数 \(m\)"换成了"在 \(n\) 个点上能产生的不同标注数 \(s(\mathcal H,n)\)"。只有当 \(s(\mathcal H,n)\) 增长得不太快(多项式而非指数)时,\(\epsilon_n\to0\),这个界才有用。

22b.4.2 VC 维

定义 22.20。 \(\mathcal A\) 的 VC 维 \(VC(\mathcal A)\) 是 \(\mathcal A\) 能粉碎的最大点集的大小,即使 \(s(\mathcal A,k)=2^k\) 的最大 \(k\);若对所有 \(n\) 都有 \(s(\mathcal A,n)=2^n\),则 \(VC(\mathcal A)=\infty\)。

定理 22.21(Sauer 引理的推论)。 若 \(VC(\mathcal A)=v<\infty\),则 \(s(\mathcal A,n)\le n^v+1\)。

这是一个"相变":粉碎系数要么在所有 \(n\) 上等于 \(2^n\)(指数增长,界无用),要么一旦超过 VC 维就只能多项式增长。VC 维有限,\(\log s(\mathcal H,n)\approx v\log n\),于是 \(\epsilon_n\approx\sqrt{32v\log n/n}\to0\)。VC 维是分类器族"容量"的度量。

推导拆解:为什么多项式增长就够、指数增长就不行?把 \(s\) 代入 \(\epsilon_n^2=\frac{32}{n}\log\frac{8s}{\alpha}\)。

若 \(s=2^n\):\(\log s=n\log2\),\(\epsilon_n^2\approx32\log2\approx22\),不随 \(n\) 减小,界没用。直观上,族能拟合任意标签,数据再多也无法排除"纯靠拟合噪声"。

若 \(s\le n^v+1\):\(\log s\approx v\log n\),\(\epsilon_n^2\approx\frac{32v\log n}{n}\)。分子是对数增长,分母是线性增长,比值趋于 0(例如 \(n=10^6\) 时 \(\log n/n\approx1.4\times10^{-5}\))。

实务上的读法:要让误差界维持不变,样本量大致要与 \(v\)(乘一个对数因子)成比例增加。

例题。 计算 VC 维要做两件事:找一个大小为 \(v\) 的点集能被粉碎,再证明任何 \(v+1\) 个点都不能被粉碎。

  • 例 22.22:半直线 \(\{(-\infty,a]\}\)。任何单点能被粉碎(\(a\) 取在点的左边或右边)。两点 \(x<y\) 时,挑不出只含 \(y\) 的子集(包含 \(y\) 的半直线必然包含 \(x\))。\(VC=1\)。
  • 例 22.23:实轴上的闭区间。两点能被粉碎;三点 \(x<y<z\) 时挑不出 \(\{x,z\}\)(包含 \(x,z\) 的区间必然包含 \(y\))。\(VC=2\)。
  • 例 22.24:平面上的线性半空间。任意不共线的三点能被粉碎;四点时,若构成凸四边形,对角的两点无法被单独挑出;若一点在另三点的凸包内,该点无法被单独排除。\(VC=3\)。一般地,\(\mathbb R^d\) 中半空间的 VC 维是 \(d+1\)。
  • 例 22.25:平面上边平行于坐标轴的矩形。菱形排列的 4 点能被粉碎;任意 5 点中,取最左、最右、最上、最下的点(至多 4 个),包含它们的最小矩形必然包含剩下的点,所以去掉那个点的子集无法挑出。\(VC=4\)。

定理 22.26。 \(d\) 维线性分类器的 VC 维是 \(d+1\),所以真实错误率的 \(1-\alpha\) 置信区间为 \(\hat L_n(\hat h)\pm\epsilon_n\),

\[\epsilon_n^2=\frac{32}n\log\Big(\frac{8(n^{d+1}+1)}\alpha\Big).\]

VC 界的实际意义与局限。 VC 界对任何分布都成立,代价是常数极其保守。下一节的计算会显示,5 维线性分类器、3000 个样本时 \(\epsilon_n\approx0.75\)——比 0–1 区间的一半还宽,毫无实用价值。它的价值在于定性结论:(1) 只要 VC 维有限,ERM 就能一致地逼近族内最优;(2) 误差界随 \(\sqrt{v\log n/n}\) 变化,所需样本量与模型容量成正比;(3) 不同族的比较应看容量而不是参数个数(例如 \(\sin(\omega x)\) 只有一个参数但 VC 维无穷)。实践中误差估计还是要靠交叉验证。

22b.5 分类中的偏差–方差:与回归不同

原书习题 13(Friedman 1997)揭示了分类与回归的一个重要差别。固定 \(x\),设估计的回归函数近似正态 \(\hat r(x)\approx N(\bar r(x),\sigma^2(x))\),\(\hat h(x)=I(\hat r(x)>\frac12)\)。由第 22a 章定理 22.5 的证明,

\[\mathbb P(Y\ne\hat h(x))=\mathbb P(Y\ne h^*(x))+|2r(x)-1|\cdot\mathbb P(\hat h(x)\ne h^*(x)).\]
若 \(r(x)>\frac12\),\(\mathbb P(\hat h\ne h^*)=\mathbb P(\hat r<\frac12)=1-\Phi\big(\frac{\bar r-1/2}\sigma\big)\);\(r(x)<\frac12\) 时对称。合起来
\[\mathbb P(Y\ne\hat h(x))\approx\mathbb P(Y\ne h^*(x))+|2r(x)-1|\Big[1-\Phi\Big(\frac{\text{sign}(r(x)-\frac12)\,(\bar r(x)-\frac12)}{\sigma(x)}\Big)\Big].\]

推导拆解:第一个等式就是第 22a 章证明中"错分概率之差 \(=(2r-1)(h^*-h)\)"在随机的 \(\hat h\) 上取期望:\(\hat h\ne h^*\) 时多付 \(|2r-1|\),否则不多付。第二步:设 \(r(x)>\frac12\),\(h^*=1\),于是 \(\hat h\ne h^*\) 等价于 \(\hat r<\frac12\);\(\hat r\) 近似 \(N(\bar r,\sigma^2)\),标准化得 \(\mathbb P\big(Z<\frac{1/2-\bar r}{\sigma}\big)=1-\Phi\big(\frac{\bar r-1/2}{\sigma}\big)\)(用了 \(\Phi(-z)=1-\Phi(z)\))。

数值例子:设真实 \(r(x)=0.6\)。 模型 A:\(\bar r=0.55\)(低估了 0.05,但方向对),\(\sigma=0.05\)。\(\Phi\) 的自变量 \(=1\),误判概率 \(1-\Phi(1)\approx0.16\);把 \(\sigma\) 降到 0.01,自变量 \(=5\),误判概率几乎为 0。降方差有益。 模型 B:\(\bar r=0.45\)(偏差把方向弄反),\(\sigma=0.05\)。自变量 \(=-1\),误判概率 \(1-\Phi(-1)\approx0.84\);把 \(\sigma\) 降到 0.01,误判概率接近 1。降方差反而更糟。

解读:分类中偏差的作用是非线性的,只有符号重要。

  • 若偏差不改变 \(\bar r\) 落在 1/2 的哪一侧(\(\Phi\) 的自变量为正),偏差再大也无妨,减小方差 \(\sigma\) 就能降低错误率;
  • 若偏差把 \(\bar r\) 推到了错误的一侧(自变量为负),减小方差反而提高错误率——估计越"自信",错得越稳定。

所以分类对偏差的容忍度高于回归:一个概率估计得很不准(偏差大)但方向正确的模型,可以是很好的分类器。这也解释了为什么朴素 Bayes 这类概率严重失真的方法分类效果不差,以及为什么 bagging(降方差)在分类中特别有效。对交易而言,它提醒我们区分两个目标:预测方向(分类)和预测幅度或概率(回归、概率校准)。仓位大小依赖于后者,只做好前者是不够的。

22b.6 维数灾难的几何直观

原书习题 10(Hastie et al. 2001):\(X\) 在 \([-\frac12,\frac12]^d\) 上均匀分布,\(n\) 个样本,\(R\) 是原点到最近样本点的距离。对 \(r\le\frac12\),半径 \(r\) 的球在立方体内,\(\mathbb P(R>r)=(1-v_d(r))^n\),\(v_d(r)=r^d\frac{\pi^{d/2}}{\Gamma(d/2+1)}\)。令其为 1/2,得 \(R\) 的中位数

\[\text{median}(R)=\Big(\frac{1-(1/2)^{1/n}}{v_d(1)}\Big)^{1/d}.\]
数值计算表明,最近邻距离的中位数超过 1/2(即超出立方体中心到表面的距离)的维数:\(n=100\) 时 \(d=9\),\(n=1000\) 时 \(d=12\),\(n=10000\) 时 \(d=14\)。也就是说,十几维时"最近的邻居"已经在立方体的边缘之外,局部方法(kNN、核方法)赖以成立的"附近有数据"不再成立。样本量每扩大 10 倍,可承受的维数只增加两三维。

推导拆解:\(\mathbb P(R>r)=(1-v_d(r))^n\) 的含义是"\(n\) 个点全都落在半径 \(r\) 的球外":每个点落在球内的概率等于球的体积 \(v_d(r)\)(立方体体积为 1,均匀分布下概率 = 体积),各点独立,所以概率相乘。\(v_d(r)\) 是 \(d\) 维球体积公式,\(\Gamma\) 是阶乘的推广(\(\Gamma(k+1)=k!\)),\(d=2\) 时退化为 \(\pi r^2\),\(d=3\) 时为 \(\frac43\pi r^3\)。令 \((1-v_d(R))^n=\frac12\) 解出 \(R\) 就是中位数。

关键在于高维球的体积极小:半径 \(\frac12\) 的球在 \(d=10\) 时只占单位立方体体积的约 0.25%,大部分体积都在"角落"里,所以中心附近几乎没有样本。


22b.7 时间序列中的交叉验证(本教材补充)

原书的交叉验证假设数据 IID。金融数据违反这一假设的方式有两种,都会让随机 K 折严重高估预测能力。

  1. 特征的持续性。 估值、长期动量、波动率等特征高度自相关,相邻两天的特征几乎相同。随机分折时,测试样本的"邻居"几乎必然在训练集中。
  2. 标签重叠。 用"未来 \(H\) 天收益的方向"作标签时,相邻样本的标签共享 \(H-1\) 天的收益,几乎相同。

两者叠加:灵活的模型只要"记住"训练集中时间相邻的样本,就能在测试集上猜对,哪怕特征对未来毫无预测力。正确的做法:

  • 前推验证(walk-forward):只用测试期之前的数据训练,模拟真实的信息结构;
  • 剔除(purging):从训练集中删去标签区间与测试期重叠的样本(训练集末尾的 \(H\) 天);
  • 禁区(embargo):在测试期之后再空出一段,防止测试期信息通过序列相关渗入随后的训练样本(在"组合 K 折"等非前推的方案中需要)。

这些做法系统地见于 López de Prado(2018)《Advances in Financial Machine Learning》。

22b.8 量化实战

场景。 三个实验。(1) 用不同大小的分类树重现例 22.14 的图像:训练误差、10 折 CV 误差、真实测试误差。(2) 构造一个标签完全不可预测的数据集——日收益是纯噪声,特征是高度持续的 AR(1) 过程,标签是未来 20 日收益的方向——比较随机 5 折 CV 与前推验证。(3) \(m\) 个纯随机的"择时策略"在 500 个交易日上比较方向准确率,看最优者的样本内表现,以及 Hoeffding + 并集界与 VC 界给出的修正量。

import numpy as np, warnings
warnings.filterwarnings("ignore")
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import KFold, cross_val_score

rng = np.random.default_rng(222)
# ---------- (1) 复杂度与误差:训练误差单调降,CV 误差 U 形 ----------
def make(n):
    X = rng.standard_normal((n, 5))
    logit = 0.6 * X[:, 0] - 0.5 * (X[:, 1] ** 2 - 1) + 0.4 * X[:, 0] * X[:, 1]
    return X, rng.binomial(1, 1 / (1 + np.exp(-logit)))
X, y = make(2000); Xte, yte = make(100000)
print("叶子数  训练误差  10折CV误差  测试误差")
for leaves in [2, 4, 8, 16, 32, 64, 128, 256, 512]:
    m = DecisionTreeClassifier(max_leaf_nodes=leaves, random_state=0)
    cv = 1 - cross_val_score(m, X, y, cv=KFold(10, shuffle=True, random_state=0)).mean()
    m.fit(X, y)
    print("%5d %9.3f %10.3f %9.3f" % (leaves, 1 - m.score(X, y), cv, 1 - m.score(Xte, yte)))

# ---------- (2) 时间序列:随机 K 折的信息泄露 ----------
T, H = 3000, 20
ret = 0.01 * rng.standard_normal(T + H)                       # 日收益:纯噪声,不可预测
feat = np.zeros((T, 3))
for k, phi in enumerate([0.98, 0.95, 0.9]):                   # 高度持续的特征(如估值、长期均线偏离)
    e = rng.standard_normal(T)
    for t in range(1, T):
        feat[t, k] = phi * feat[t - 1, k] + e[t]
fwd = np.array([ret[t + 1:t + 1 + H].sum() for t in range(T)])  # 未来 20 日收益(标签相互重叠)
lab = (fwd > 0).astype(int)
rf = RandomForestClassifier(n_estimators=200, min_samples_leaf=5, random_state=0, n_jobs=-1)
acc_random = cross_val_score(rf, feat, lab, cv=KFold(5, shuffle=True, random_state=0)).mean()
acc_block, acc_purged = [], []
folds = np.array_split(np.arange(T), 5)
for k in range(1, 5):                                          # 前推:只用过去训练
    te = folds[k]
    tr_all = np.arange(te[0])
    tr_pur = np.arange(max(te[0] - H, 0))                      # 剔除与测试期标签重叠的最后 H 天
    acc_block.append(rf.fit(feat[tr_all], lab[tr_all]).score(feat[te], lab[te]))
    acc_purged.append(rf.fit(feat[tr_pur], lab[tr_pur]).score(feat[te], lab[te]))
print("标签不可预测(真实准确率 50%%)时:随机5折 CV 准确率 = %.3f" % acc_random)
print("                         前推验证 = %.3f   前推+剔除重叠 = %.3f" % (np.mean(acc_block), np.mean(acc_purged)))

# ---------- (3) 有限类的一致收敛界:从 m 个“策略”中挑最好的 ----------
n, alpha = 500, 0.05
for m in [1, 10, 100, 1000, 10000]:
    best = []
    for _ in range(200):
        acc = rng.binomial(n, 0.5, size=m) / n                 # m 个纯随机策略的样本内方向准确率
        best.append(acc.max())
    eps = np.sqrt(np.log(2 * m / alpha) / (2 * n))
    print("m=%5d  最优策略样本内准确率均值=%.3f   Hoeffding+并集界 ε=%.3f" % (m, np.mean(best), eps))
# VC 界:d 维线性分类器
for d, nn in [(5, 3000), (5, 100000), (50, 100000)]:
    eps = np.sqrt(32 / nn * np.log(8 * (nn ** (d + 1) + 1) / alpha))
    print("VC 界: d=%2d, n=%6d -> ε=%.3f" % (d, nn, eps))

关键输出:

叶子数  训练误差  10折CV误差  测试误差
    2     0.393      0.408     0.415
    4     0.353      0.377     0.378
    8     0.331      0.365     0.357
   16     0.312      0.369     0.366
   32     0.280      0.376     0.381
   64     0.236      0.379     0.375
  128     0.174      0.394     0.398
  256     0.084      0.403     0.409
  512     0.000      0.415     0.427
标签不可预测(真实准确率 50%)时:随机5折 CV 准确率 = 0.584
                         前推验证 = 0.491   前推+剔除重叠 = 0.495
m=    1  最优策略样本内准确率均值=0.500   Hoeffding+并集界 ε=0.061
m=   10  最优策略样本内准确率均值=0.535   Hoeffding+并集界 ε=0.077
m=  100  最优策略样本内准确率均值=0.555   Hoeffding+并集界 ε=0.091
m= 1000  最优策略样本内准确率均值=0.572   Hoeffding+并集界 ε=0.103
m=10000  最优策略样本内准确率均值=0.586   Hoeffding+并集界 ε=0.114
VC 界: d= 5, n=  3000 -> ε=0.753
VC 界: d= 5, n=100000 -> ε=0.154
VC 界: d=50, n=100000 -> ε=0.435

解读。

  1. 例 22.14 的图像。 训练误差从 0.393 单调降到 0;CV 误差在 8 个叶子处最低(0.365),之后回升;真实测试误差与 CV 误差走势一致,最低点也在 8 个叶子。CV 正确地选出了复杂度。
  2. 随机 K 折的泄露非常严重。 标签由纯噪声决定,任何方法的真实准确率都是 50%。随机 5 折 CV 却报告 58.4%——在日频方向预测中,这已经是"非常强"的信号。前推验证给出 49.1%,剔除重叠后 49.5%,都与真实情况相符。若在回测报告中看到用随机 K 折得到的准确率,应该首先怀疑这一点。
  3. 挑选的代价。 1 万个毫无预测力的策略,最好的那个在 500 天上平均有 58.6% 的方向准确率。Hoeffding + 并集界给出的半宽 \(\epsilon=0.114\) 足以覆盖这一乐观偏差(\(0.586-0.5=0.086<0.114\)),而且只随 \(\sqrt{\log m}\) 增长。这正是第 10b 章多重检验在分类语言中的表述:报告最优策略的表现时,必须同时报告一共试了多少个。
  4. VC 界过于保守。 5 维线性分类器、3000 个样本时 \(\epsilon=0.75\),没有任何实用意义;10 万样本时也有 0.15。50 维时更差。VC 界的价值在于说明"容量与样本量之比"决定泛化能力,而不是给出可用的数字。

本章小结

用同一份数据选出的分类器,其训练误差会低估真实误差,模型越灵活、候选越多,低估越严重。交叉验证用未参与训练的数据估计误差,K 折 CV 是标准做法;CV 的最小值本身也偏乐观,最终评估需要独立的测试集或嵌套 CV。概率不等式给出对整族分类器同时成立的误差界:有限族用 Hoeffding 加并集界,半宽 \(\sqrt{\log(2m/\alpha)/(2n)}\) 随候选数的对数增长;无限族用粉碎系数和 VC 维代替候选数,VC 维有限时粉碎系数多项式增长、ERM 一致。VC 界常数过于保守,主要提供定性理解。分类中的偏差只在改变决策方向时才有害,因此分类比回归更能容忍偏差,降方差的方法更有效。时间序列中随机 K 折会因特征持续性和标签重叠而泄露信息,必须使用前推验证和剔除。

概念 公式 / 要点
训练误差 \(\hat L_n(h)=\frac1n\sum_iI(h(X_i)\ne Y_i)\),对 \(\hat h\) 向下有偏
K 折 CV \(\hat L=\frac1K\sum_k\hat L_{(k)}\)
Hoeffding \(\mathbb P(\vert \hat p-p\vert >\epsilon)\le2e^{-2n\epsilon^2}\)
有限族一致界 \(\mathbb P(\max_h\vert \hat L_n-L\vert >\epsilon)\le2me^{-2n\epsilon^2}\)
有限族置信区间 \(\hat L_n(\hat h)\pm\sqrt{\frac1{2n}\log\frac{2m}\alpha}\)
VC 不等式 \(\mathbb P(\sup_A\vert \mathbb P_n(A)-\mathbb P(A)\vert >\epsilon)\le8s(\mathcal A,n)e^{-n\epsilon^2/32}\)
VC 维 能被粉碎的最大点集大小;\(s(\mathcal A,n)\le n^v+1\)
常见 VC 维 半直线 1,区间 2,\(\mathbb R^d\) 半空间 \(d+1\),轴平行矩形 4
线性分类器区间 \(\epsilon_n^2=\frac{32}n\log\frac{8(n^{d+1}+1)}\alpha\)
Friedman 分解 \(P(Y\ne\hat h)=P(Y\ne h^*)+\vert 2r-1\vert \big[1-\Phi\big(\frac{\text{sign}(r-\frac12)(\bar r-\frac12)}\sigma\big)\big]\)
时间序列 CV 前推验证 + 剔除重叠标签 + 禁区

练习

基础

  1. 证明定理 22.16 与 22.17。若 \(n=250\)(一年交易日),\(\alpha=0.05\),要使半宽 \(\epsilon\le0.05\),最多能比较多少个策略?(提示:\(\log(2m/0.05)\le2\cdot250\cdot0.0025=1.25\),\(m\le0.087\),即连一个都不够;说明一年数据不足以在 5% 精度上确认方向准确率。)
  2. 证明例 22.22、22.23 中的 VC 维结论。
  3. 原书习题 4:求平面上圆盘族 \(\{(x,y):(x-a)^2+(y-b)^2\le c^2\}\) 的 VC 维。(答案:3。三个不共线点可被粉碎;四点时,若构成凸四边形,两对对角点不能同时被分别挑出——两圆之差的几何论证;若一点在另三点凸包内,则无法排除该点。)
  4. 解释为什么 \(\sin(\omega x)\) 型分类器族 \(\{x:\sin(\omega x)>0\}\) 只有一个参数,VC 维却是无穷。这对"用参数个数衡量模型复杂度"有什么启示?
  5. 留出验证集大小为 \(m=500\),测得错误率 0.46。给出真实错误率的 95% 置信区间,并判断能否在 5% 水平上声称分类器优于瞎猜。(提示:\(0.46\pm1.96\sqrt{0.46\cdot0.54/500}=0.46\pm0.044\),上界 0.504,不能。)

进阶

  1. 原书习题 13:推导 22b.5 节的 Friedman 公式,并构造一个数值例子说明"减小方差反而提高错误率"。
  2. 原书习题 10:推导最近邻距离中位数公式,并编程验证 \(n=100,1000,10000\) 时中位数超过 1/2 的维数分别为 9、12、14。
  3. 原书习题 6:用 VC 理论给 iris 数据(或任一 4 维、150 样本的数据集)上的 LDA 分类器构造真实错误率的置信区间。结果有用吗?与 10 折 CV 比较。
  4. 在 22b.8 节实验 (2) 中把标签期限 \(H\) 从 20 改为 1,随机 5 折的乐观偏差如何变化?把特征持续性 \(\phi\) 改为 0.5 呢?分别解释"特征持续性"与"标签重叠"各自的贡献。
  5. 设计一个嵌套交叉验证:外层 5 折前推估计误差,内层在训练期内用前推验证选择树的叶子数。与"在全样本上用 CV 选叶子数、再报告该 CV 误差"的做法比较,后者偏乐观多少?

原书推荐习题:第 22 章习题 4、6、10、13。

原书对照

本章内容 原书章节 PDF 页码
训练误差的偏差,例 22.14 22.8 p.366–372
留出验证、K 折交叉验证,例 22.15 22.8 p.366–372
Hoeffding 不等式,定理 22.16–22.17 22.8 p.366–372
粉碎系数、VC 不等式、VC 维,定理 22.18–22.26,例 22.22–22.25 22.8 p.366–372
习题(圆盘 VC 维、iris VC 区间、维数灾难、Friedman 分解) 22.13 p.381–383
时间序列交叉验证、嵌套 CV(本教材补充) — —