阳明轨迹 · 第 3

断点检测:不预设事件年份的转折点定位

第 1 章用 ITS 估计了"1506 廷杖触发了什么"。前提是事件年份已知。但若反过来问"数据本身告诉我们最大转折发生在哪一年",不预设任何事件,答案会不会和史学公认的 1521 年致良知重合?

这一章用断点检测回答这个问题。断点检测的关键性在于它完全不依赖任何史学假设,仅凭时间序列内部结构判断"哪一年最像分水岭"。如果算法自动找出的位置恰好和史学事件吻合,这是 ITS 论证之外的独立强证据。

断点检测的算法原理

定义最优单断点
def:single-breakpoint

设时间序列 {y1,y2,,yT}\{y_1, y_2, \ldots, y_T\}。一个候选断点 τ{2,3,,T1}\tau \in \{2, 3, \ldots, T-1\} 把序列切成前段 {y1,,yτ}\{y_1, \ldots, y_{\tau}\} 与后段 {yτ+1,,yT}\{y_{\tau+1}, \ldots, y_T\}。最优单断点 τ\tau^* 是使两段内部残差平方和最小的位置:

τ=argminτ[t=1τ(ytyˉ[1,τ])2+t=τ+1T(ytyˉ[τ+1,T])2].\tau^* = \arg\min_{\tau} \left[ \sum_{t=1}^{\tau}(y_t - \bar y_{[1,\tau]})^2 + \sum_{t=\tau+1}^{T}(y_t - \bar y_{[\tau+1,T]})^2 \right].

其中 yˉ[a,b]\bar y_{[a,b]} 是序列在 [a,b][a, b] 区间内的均值。

通俗讲,算法扫所有可能的切分位置,每个位置算"两段内部偏差有多大",选让两段内部偏差最小的那个位置。这个位置就是序列里最像"分界"的地方。

Binary Segmentation 与 PELT

实际数据上,断点可能不止一个。Binary Segmentation 是递归地找单断点:先找全序列最优单断点,把序列切成两段;然后递归地在每段内找单断点;直到子段太短或目标函数提升不显著为止。这是最朴素的多断点算法。

PELT(Pruned Exact Linear Time, Killick et al. 2012)用动态规划 + 剪枝把多断点检测优化到线性时间。本章主要用 Binary Segmentation 因为算法直观,PELT 用于对比验证。两者在我们的数据上结果一致。

雷区小样本下断点位置不稳定

当时间序列长度 T<10T < 10 时,单凭 RSS 选断点会有相当大的方差。譬如某序列在 τ=1520\tau = 1520τ=1521\tau = 1521 处 RSS 几乎相等,算法报告的最优位置在小样本下会随随机噪声跳。

诊断方法:同一序列用不同算法(Binary Segmentation, PELT, Bayesian Changepoint)跑出来的位置应一致。

若不一致,说明断点信号弱,不可单凭一种算法报告。

稳健替代:跑 17 个独立时间序列,看断点位置的聚类分布,不依赖单一序列。

17 个时间序列的断点聚类

联合检测的设计

我们对 12 个核心概念加 5 个人格维度共 17 个独立时间序列分别跑 Binary Segmentation。每个序列允许一个最优断点。如果数据中真的有一个共同的转折点,17 个独立序列的断点会聚集在同一年附近。如果没有共同转折点,断点应当均匀分布。

表 3·1 17 个独立时间序列的断点位置分布

断点年份被检为最优断点的序列数
15206
15211
15227
1520–1522 小计14 (82%)
15241
15251
15261

17 个序列里 14 个(82%)落在 1520–1522 这 3 年窗口。

聚类强度的统计意义

17 个独立序列里 14 个的最优断点落在 1520–1522 这 3 年窗口。这是一个非常强的聚类:如果断点是随机的,三年窗口里出现 14 个落点的概率约为 (3/13)14109(3/13)^{14} \approx 10^{-9},这个聚集不可能是巧合。

图 3·1 把这个聚类可视化,同时把每个序列的解释力 R2R^2 作为强度指标列在右下面板。R2>0.3R^2 > 0.3 视为强信号,主要分布在"良知 / 天理 / 人欲 / 教学耐心"这些核心概念上。

断点检测结果
图 3·1 断点检测结果。(a) 17 个序列的时间轨迹与自动检测的断点位置(黑圈)。粗线表示 R² 大于 0.3 的强信号序列。(b) 断点位置聚合直方图,14 个(82%)落在 1520–1522 这 3 年窗口。(c) 各序列 R² 排序,红色表示断点落在 1520–1522 范围。

算法与史学的吻合

1520–1522 三年内的史学事件

1520–1522 是哪一段时间?这三年内阳明经历了几件史学公认的转折期事件。

1519 年 7 月平宁王朱宸濠之乱,阳明孤军 43 天平定。1521 年正德皇帝崩,新皇即位(嘉靖元年),阳明的政治处境彻底改变。1521 年阳明本人正式提出"致良知"三字纲领。1522 年父亲王华卒。

数据自报与史学共识的相互验证

也就是说,算法在不告诉它任何史实的情况下,把最大断点定位到了史学共识的转折期。这是断点检测的力量:数据本身能告诉你哪一年最关键,不需要你预设答案。

鲁棒性:只用语录体的检验

为什么需要语录体子样本

第二章(ITS)的方法学边界提到一个真实顾虑:阳明全集 6 种体裁混在一起,T3 → T4 过渡正好对应着"学生记录的语录体"切换到"阳明亲笔写的书信体"。会不会断点聚集在 1520–1522 仅仅是因为体裁切换,不是阳明思想真的变了?

子样本检测的设计与结果

为了排除这个解释,我们用只包含语录体的子样本重做断点检测。语录体涵盖 8 个学生(徐爱、陆澄、薛侃、陈九川、黄直、黄修易、黄省曾、黄以方)的记录,共 273 条,排除了卷中所有亲笔书信。

表 3·2 语录体子样本断点位置 vs 全样本

概念全样本断点语录体子样本断点
致良知1524(R2R^2=0.50)1524(R2R^2=0.92)
良知1522(R2R^2=0.68)1524(R2R^2=0.77)
人欲1520(R2R^2=0.53)1520(R2R^2=0.56)
天理1522(R2R^2=0.55)1520(R2R^2=0.40)
朱子1526(R2R^2=0.08)1520(R2R^2=0.26)

语录体子样本上,关键概念的断点位置稳定在 1520–1524,与全样本基本一致。"致良知"的 R2R^2 反而从 0.50 升到 0.92,信号变强。这说明体裁切换不是断点聚集的原因,阳明思想的真实变化才是

T4 内部分裂:1521 作为子时段切点

第 2 章把传习录划分成 6 时段,其中 T4 涵盖 1518–1527 共 10 年。这个跨度其实偏长,而且正好横跨 1521 致良知。如果断点检测的结论是真的,T4 内部应当还能再切出一个分界。

图 3·2 在 T4 内部独立跑一次断点检测,结果把 T4 切成 1518–1520(T4-早,致良知尚未提出)与 1521–1527(T4-晚,致良知已成纲领)两段,切点正好在 1521。这是一个相对独立的次级证据,在不依赖 17 序列联合的前提下,单独从 T4 内部就能找出和外部一致的转折点。

T4 (1518–1527) 内部断点检测
图 3·2 T4(1518–1527)内部断点检测。算法在 T4 内独立跑,把 70 条文档切成 T4-早(1518–1520,6 条 / 1209 字,致良知尚未提出)与 T4-晚(1521–1527,64 条 / 25,350 字,致良知已成纲领)两段,切点 1521 与外部 17 序列断点检测的结论一致。

方法卡片

方法卡片断点检测在思想史时间序列上的应用

使用场景:需要回答"这段历史的最大转折在哪一年"而不预设答案时,断点检测比 ITS 更适用。ITS 假设你已知道答案要量化效应;断点检测假设你不知道答案。

Python 实现ruptures 库的 PeltBinseg 类。代码见 code/probe06_breakpoint_detection.py

核心假设:(1) 序列内部有清晰的两阶段结构。

(2) 噪声为独立同分布的高斯白噪声(实际很少严格成立,但 PELT 对偏离稳健)。(3) 多序列联合聚类作为辅助证据,单序列断点不足以下结论。

典型失效场景:序列太短(T<10T < 10)时断点位置会随机抖动。序列带趋势时,算法可能把趋势变化误检为断点。只跑一个序列,单点估计不可靠,必须跑多个独立序列看聚类。

本章知识地图

表 3·3 第 3 章核心概念与常见误解

核心概念核心内容常见误解为什么错
最优单断点让两段内部 RSS 最小的位置以为算法能"自动找出真因果"断点只是描述性最佳分界,因果解释需结合史学
Binary Segmentation递归地找单断点直到收敛以为多断点算法一定比单断点好小样本下多断点容易过拟合,单断点更稳健
断点聚类多序列独立断点都落在同一年附近以为单个序列断点信号就够单序列断点方差大,必须多序列联合判断
数据自报不预设答案让算法找分界以为它能否定史学叙事自报结果与史学吻合是支持证据,不吻合也只是提示需要重读
鲁棒性子样本用更窄的子集重做检测以为子样本结果应该一致子样本可能信噪比不同,关键是方向一致而非数值精确一致