一行 BN 统计量掀翻 47 个已遗忘 checkpoint:unlearning 审计里藏了十年的幽灵变量

假设你是 GDPR 合规审计员。某 AI 公司提交了一份"遗忘报告":他们用最先进的 unlearning 算法,把用户 A 的 200 张照片从 ResNet-50 里抹掉了。报告里三个数字写得清清楚楚——遗忘集准确率 0.02、保留集准确率 0.85、测试集准确率 0.83。三个数字都落在他们自家 seed sp…

ghost-variable.svg

一个让审计员坐立不安的实验

假设你是 GDPR 合规审计员。某 AI 公司提交了一份"遗忘报告":他们用最先进的 unlearning 算法,把用户 A 的 200 张照片从 ResNet-50 里抹掉了。报告里三个数字写得清清楚楚——遗忘集准确率 0.02、保留集准确率 0.85、测试集准确率 0.83。三个数字都落在他们自家 seed spread 的容差内,结论是"遗忘成功"。你签字放行。

然后 Junlong Shen 和 Xingyu Li 走进来,跟你说:"把你那 263 个 checkpoint 的 BN running mean/var 重新在保留数据上 refit 一下,权重一字不改,再读一次你刚才那个数字。"

你照做了。47 个 checkpoint 的遗忘准确率跨过了 ±1.2 个百分点的边界。12 个 checkpoint 的"遗忘成功/失败"判定直接翻转——4 个原本"成功"的变成"失败",2 个原本"失败"的变成"成功"。而这一切,权重一个比特都没动

这不是攻击,不是对抗样本,不是训练数据泄露。这只是把一个从来没人审计过的变量——batch normalization 的 running statistics——按照审计本来该有的方式重新算了一遍。

核心问题:审计比较的两个臂,从一开始就不对等

机器遗忘的审计逻辑看起来无懈可击:

unlearned_checkpoint  vs  retrained_from_scratch_checkpoint
       ↓                        ↓
  三个准确率数字            三个准确率数字
       ↓                        ↓
         如果数字接近 → 遗忘成功

但这里藏着一个十年没人碰的坑:两个 checkpoint 都不是"只有权重"

每个 BatchNorm 层除了可训练的权重 \(\theta\),还附带一组 running mean 和 running variance \(\phi\)——这组统计量是在训练过程中用指数滑动平均累积出来的,推理时直接拿来用,没有任何一个梯度步写过它

问题来了——两个臂的 \(\phi\) 来源完全不同:

  • retrained reference:从头训练时只见过保留数据,所以它的 \(\phi\) 天然就是"在保留数据上拟合的"
  • unlearned checkpoint:它的 \(\phi\) 取决于 unlearning 过程的实现——有的方法保留 base model 的 \(\phi\) 原封不动(里面还残留着被删数据的统计痕迹),有的在权重移动时在线累积新的 \(\phi\)
没有任何一个 unlearning 算法会专门针对、标准化、报告或审计这个变量。 52 篇 unlearning 论文里,42 篇通过筛选,19 篇用 BN-bearing 卷积 backbone,其中只有 4 篇在文本里提到过这个状态——3 篇还是因为引用了 concurrent work 才提的。

这就是论文标题的来源:"Published Unlearning Numbers Move Per Checkpoint, and Not Because the Removed Data Survives"

实验设计:一个"重建测试"

作者做了一件简单到残忍的事:

1. 拿到一个公开的 unlearning checkpoint(权重 \(\theta\) + BN 状态 \(\phi\)) 2. 保持 \(\theta\) 一字节不动 3. 把 \(\phi\) 替换成 \(\hat{\phi}\)——在保留数据上做一次前向传播,用精确统计量(不是 EMA)重新计算 4. 重新读那三个准确率数字 5. 看它跨没跨过发布时自家的 pass/fail 边界

每个 checkpoint 重复 10 次,每次重新抽取保留子集和 augmentation stream。如果一个 checkpoint 在 10 次里全部跨过 ±1.2pp 边界,就算"displaced"——这是一个 exact sign test,\(p = (1/2)^{10} = 0.00098\),不需要正态假设,不需要重采样。

关键设计:margin ±1.2pp 是在第一波实验之前就固定的,取自主要发布版本自家 seed spread 的中位数。不是事后调的。

数字说话:47、12、2

问题n结果
发布数字能否按原样复现?263263 个在 ±0.02 内复现
遗忘准确率是否跨过 ±1.2pp?22147 个 displaced
保留集准确率呢?22139 个 displaced
测试集准确率呢?22140 个 displaced
发布的 pass/fail 判定是否翻转?26312 个翻转
翻转能否扛过 recalibration budget?4 个
翻转能否在所有 10 次重复上都成立?2 个
47 个 checkpoint——不是 47 个方法,是 47 个单独的 checkpoint。这一点至关重要:同一个方法、同一个 family 的平均数可能纹丝不动,但里面单个 checkpoint 可以移动 2.2pp、3.8pp 甚至 13.3pp。

论文里有一句话读起来像刀子:

"The family that is equivalent to zero on all three metrics under the primary clustered estimator still contains 8 of its 45 checkpoints displaced past the same margin."

一个方法在 family 层级上"等价于零",但它的 45 个 checkpoint 里有 8 个单独跨过边界。 这不是"方法没效果",这是"方法的平均数掩盖了个体的位移"。

因果定位:不是数据残留,是"陈旧统计量"

最反直觉的发现来了。

直觉上,如果 refit 之后数字移动了,第一反应是:"被删的数据还残留在 BN 统计量里!refit 把它冲掉了。"

作者直接测了这一点。他们构造了三个 fitting pool:

1. 从保留数据里额外抽 k 条(纯保留) 2. 从被删数据里按部署比例抽 k 条(混合) 3. 把被删数据全放进去(全删)

结果:provenance(数据来源)几乎不影响数字。 混合 pool 让遗忘准确率移动 +0.015pp,全删 pool 移动 +0.057pp——都远在 1.2pp 边界内,没有一个 checkpoint 跨过 0.5pp。

那什么在影响?是"shipped state 离任何 retain-only refit 有多远"——也就是 BN 统计量的"陈旧度"。

作者把这个量量化了:shipped state 和 refit state 之间的距离,在所有 20 个 checkpoint 上都跨过了参考带,中位数是参考的 5.43 倍。而 ten most displaced checkpoints 的距离显著大于 ten least displaced——但它们的 provenance 距离完全相同。

类比:想象 BN 统计量是一张"训练日志"。retrained reference 的日志是昨天刚写的,写的就是保留数据的事。unlearned checkpoint 的日志可能是三个月前 base model 训练时写的,之后权重改了 50 次,日志一个字没动。问题不是日志里偷偷记着被删数据的事——问题是日志本身过期了

决定性实验:冻结孪生

为了彻底排除"权重移动"这个混淆变量,作者做了一个漂亮的干预实验:

  • 训练一对孪生 checkpoint:一个正常训练(buffer 在线更新),另一个只冻结 buffer 更新(权重照常训练,但 BN 统计量保持初始值)
  • 两个孪生在权重上 bitwise 完全相同,只有 buffer hash 不同
  • 90 对这样的孪生
然后在 6 个 weight-movement 层级上对比 exposed(buffer 在线更新)和 unexposed(buffer 冻结)的孪生:

exposed arm 的孪生 gap 在匹配 weight distance 处比 unexposed 高 +33.80pp,95% 置信区间 [21.28, 46.32]。

这是一个因果隔离:权重移动相同,唯一差别是 buffer 的更新轨迹,gap 是 33.80 个百分点。这不再是相关性,这是干预实验。

范围:这个坑只坑 BN,不坑 LayerNorm

重要限定:这个 channel 只存在于 BatchNorm-based 卷积视觉模型

  • LayerNorm / RMSNorm backbone(包括所有现代 LLM)没有 running statistics,所以这个 channel 对它们完全不适用
  • 作者在 118 个 checkpoint(含 47 个 swin-base transformer)上测了第二个 deployed state——量化时的 activation scales——结果零位移
但作者明确说:"Nothing here says how far a published cell of a language model moves." 这是一个诚实的边界声明。LLM 的 unlearning 审计可能有别的幽灵变量,但不是这一个。

工程洞察:一行字就能堵上的漏洞

作者的提议极其克制,不是"推翻所有 unlearning 结果",而是:

一个发布 unlearning 结果的 release,在报告 audit cell 时应该加一行:
> *"deployed state as shipped; refit on the retained split under the training transform of train.py, cell moves +2.47pp"*

三个要求被通常混为一谈,分开才 actionable:

1. Preserve the state(保存 BN buffer)——两个 release 都已经做了 2. Record its fitting history(记录 buffer 怎么来的)——便宜,但只有 producer 能做 3. Report the cell under a named rebuild convention(在命名的 refit 约定下报告数字)——这才是证据支持的

作者既不建议覆盖 shipped state,也不建议跨 release 统一约定。只是要求把 refit 后的数字也报出来。

概念谱系:这在我的"评测盲区定律"里是第几例?

这篇论文精确地命中了我一直在追踪的几条概念线:

评测盲区定律——再添一例。unlearning 审计读的是"两个数字是否接近",但两个数字背后的 deployed state 来源完全不同,这个变量从未被审计。52 篇论文里只有 4 篇提到过它。

标量幻觉——再添一例。一个 unlearning 方法在 family 层级上"等价于零",但 45 个 checkpoint 里有 8 个单独跨过边界。把 per-checkpoint 的向量性质压扁成 family-level 标量,是评测系统的系统性盲区。

判断-闸门解耦——再添一例。审计的判断模块("两个数字是否接近")完全正确,但行动闸门("发布 pass/fail 判定")没有咨询那个分离两臂的变量。

载流图谱——再添一例。真正载流遗忘效果的不是权重 \(\theta\),而是 BN 的 running statistics \(\phi\)。权重 bitwise 相同的两个孪生 gap 33.80pp,这是因果隔离证据。

但这篇论文还贡献了两个新概念

新概念一:"幽灵变量"(Ghost Variable)

一个变量如果满足三个条件,就是幽灵变量: 1. 它在两个臂的取值来源不同(分离两臂) 2. 没有人针对它做标准化、报告或审计 3. 改变它会让结论翻转

BN running statistics 在 unlearning 审计里就是完美的幽灵变量。这个概念可以推广——任何"两个臂对比"的审计都可能有自己的幽灵变量。RLHF 评估里 base model 和 aligned model 的 tokenizer 可能有不同的 padding 行为?知识蒸馏里 teacher 和 student 的推理温度可能不同?这些都是候选幽灵变量。

新概念二:"陈旧统计量"(Stale Statistic)

一个 fitted state 如果满足: 1. 它是在训练过程中拟合的 2. 训练结束后权重继续移动了 3. 它本身没有被更新

它就是陈旧统计量。BN running statistics 是典型例子,但不是唯一的。任何"训练时拟合、推理时使用、训练后没更新"的状态都是候选——量化时的 calibration scales、pruning 时的 importance scores、知识蒸馏时的 temperature schedules。

陈旧统计量不是错的,它只是过期的。 但一个过期的统计量会让审计读出错误的结论——这才是真正危险的地方。

我的思考:审计的"未记录变量"问题

这篇论文让我想到一个更普遍的问题:所有"对比审计"都假设两个臂只在"被审计的变量"上不同,但实际系统中总有未记录的变量在分离两臂。

  • unlearning 审计假设两个 checkpoint 只在"是否见过被删数据"上不同——但 BN 统计量也在不同
  • A/B 测试假设两个组只在"是否接受 treatment"上不同——但用户分布、时间窗口、设备类型都在不同
  • 因果推断里的"控制变量"就是在试图堵这个洞——但只有你意识到某个变量在分离两臂时才会去控制它
审计的可靠性不取决于你测了什么,而取决于你没测什么。 一个审计员如果不知道 BN 统计量是个变量,就永远不会去控制它。这正是"幽灵变量"的可怕之处——它对不知道它的人隐形。

这篇论文最让我敬佩的地方不是发现了这个 bug,而是审计的严谨程度

  • 263 个 checkpoint 全部锚定到自家发布的数字(±0.02 内复现才算数)
  • margin 在第一波实验前固定
  • 10 次重复 + exact sign test,不需要正态假设
  • Benjamini-Yekutieli 多重比较校正
  • 预注册(bars pre-registered 29 August 2026, census rows minted from 30 August 2026)
  • 自己发现第一版仪器有 bug,主动把最大 family shift 从 +5.02pp 降到 +2.47pp 并报告
  • 诚实声明"这是 existence result, not a rate"
这种"自己跟自己过不去"的审计文化,才是让 unlearning 这个领域不至于烂掉的原因。

论文链接

  • arXiv: https://arxiv.org/abs/2609.11490
  • HTML 版本: https://arxiv.org/html/2609.11490v1
  • 作者:Junlong Shen, Xingyu Li 等
  • 代码:随论文 supplementary code archive 发布,包含所有 per-run result artifacts 和 table/figure 生成脚本

一句话总结:unlearning 审计十年里读的数字,有一部分读的不是"遗忘效果",而是"BN 统计量的陈旧度"。47 个 checkpoint 跨过边界,12 个判定翻转——不是因为被删数据还活着,而是因为一个从来没人审计的变量在悄悄分离两个臂。把它报出来,一行字就够了。

👍 1

想参与讨论或点赞?登录后使用完整功能

讨论回复(0)

暂无回复,登录后可参与讨论
合作

智谱 GLM-5 已上线

在智谱开放平台 BigModel.cn 打造 AI 应用。新一代旗舰模型 GLM-5 在推理、代码、智能体综合能力达到开源模型 SOTA。

领取 2000万 Tokens