Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第 7 讲习题集

四组难度递进:A 概念判断 → B 推导证明 → C 编程实现 → D 开放设计。答案默认折叠,点击展开。 用法:先闭卷做 A 组(只写对错不给分,必须给一句话理由或反例);B 组手写推导;C 组上机并跑通每题末尾的验收标准;D 组写成半页方案(方案 + 理由 + 失败判据 + 验证计划,四项缺一不可)。 两条本讲特有纪律:① 涉及伦理与政策争议的题目,参考答案一律并列不同立场与各自依据并指出「哪种表述不可验证」,不要求也不给分给任何替读者下价值判断的写法;② 引用监管事实必须写核查时点与来源,不确定处写「需核实」(勘误页第三节)。

A 组 · 概念判断(8 题)

A1. 「把模型对齐就是让它听话:用户要什么就给什么,越顺从越对齐。」(依据:定义 7.2.1、定义 7.2.2、7.2 的误解 1)

A2. 「我们请外部团队做了一轮红队,没有找出问题,可以认定系统是安全的。」(依据:定义 7.2.4、7.1 的误解 4)

A3. 「训练数据里已经删掉了性别、民族、户籍这些字段,所以模型对任何群体都不会有歧视。」(依据:定义 7.4.1、7.1 的误解 3)

A4. 「Grad-CAM 显示模型主要看右下角,所以决策依据就是右下角;这张图可以直接写进事故复盘。」(依据:方法 7.3.1、例 7.3.1、方法 7.3.4)

A5. 「ECE 已经压到 0.020.02 了,说明这个模型可以放心用于自动决策。」(依据:定义 7.3.5、7.3 的误解 5)

A6. 「给生成内容加上水印,就可以做通用的『AI 内容检测』了。」(依据:定义 7.3.6、7.3 的误解 6)

A7. 「FMEA 表算完之后,RPN\mathrm{RPN} 最高的那一项就是必须最先处理的项。」(依据:定义 7.5.2、例 7.5.1 第 ① 问)

A8. 「只要给每个安全指标都配了监控看板,可检测度 DD 就不会高。」(依据:定义 7.5.2、例 7.5.1 第 ② 问、7.5 的误解 3)

答案(每题:判断 1 分 + 理由 2 分)

A1. 错。 服从本身可能是不对齐:一个能被任意越狱、对任何请求都照做的系统恰恰不对齐(7.2 的误解 1)。对齐衡量的是代理目标 gg 与真实意图 uu 的接近程度,而不是顺从度;「让模型听话」没有指定 uu,因此不可验证。 A2. 错。 红队产出的是「在哪些攻击下会失守」以及覆盖面有多宽,对「已知失效集合的补集」没有任何陈述能力(定义 7.2.4)。「没找到问题」与「不存在问题」之间的距离由红队的覆盖面与创造性决定,不由结论决定。可验证的写法是给出「用例数 / 攻击类别 / 工具范围 / 完整绕过率」。 A3. 错。 删掉的是特征,不是信息:地址与邮编、就读学校、设备型号、活跃时段、拼写与语言风格都可能是受保护属性的代理变量(定义 7.4.1 后的读法)。判断依据不是字段清单,而是分群评估——并且要连「受保护属性如何获得(申报还是推断)及其推断质量」一起报告。 A4. 错,至少不足以这样写。 ① 单张热力图是单样本证据,没有统计意义,「主要依据」是全称结论;② 图形形状受方法、层、归一化与后处理影响,不同方法可能给出互相矛盾的图;③ 关键是忠实性未经检验——高亮的依据来自近似器而非模型内部计算。例 7.3.1 的读图算术上正确,但前提未验证。要进报告至少附扰动检验结果与方法一致性,并按方法 7.3.4 标明证据等级。 A5. 错。 ① 校准只在评测分布上成立,漂移后先失效、而且失效得很安静(数字仍好看、含义已变),必须与 OOD 监测成对上线;② 校准不改变排序(AUC 不变),模型分不开两类样本时,校准只是把数字改得更诚实;③ ECE 是加权平均,会把「低置信区完全正确」与「高置信区严重过自信」混成一个不错的数字——门槛必须写成分桶形式(例 7.3.2)。 A6. 错。 水印是可计算的检验统计量(绿名单偏置下的 zz),相对「检测器模型」的优势是假阳率可控;但它只对加了水印的那一个模型有效,对开源权重模型与未加水印的模型都没有作用。它不能防篡改(改写、翻译、截断、换模型润色都会让信号衰减甚至消失),假阴率随文本长度与改写程度变化(短文本几乎无法判定)。它是取证线索,不是防伪标(定义 7.3.6)。 A7. 错。 RPN\mathrm{RPN} 是三个因子的乘积,低发生度会掩盖高严重度。FMEA 在安全关键系统里的标准纪律是不许用 RPN 覆盖 SiS_i 极高的项:例 7.5.1 的 F2 有 S=9S=9、RPN=180\mathrm{RPN}=180,排在 F5(360360)、F3(256256)、F1(252252)之后,却必须单列高危项并先处理(对策:变体对抗测试 ++ 高危类别白名单复核)。正确做法是把「S≥8S\ge8 的项」单独列成一张高危清单。 A8. 错。 DD 衡量「后果发生之前被发现的可能性」,有指标只是三件事里的第一件:还要有合适的阈值(由基线推出,不能拍脑袋)与从告警到人工介入的时延,并且要有止损动作。三条缺一条 DD 都降不下来:例 7.5.1 的 F5 即使建了指标,若没有「相对基线上升 X 个百分点即告警」的阈值与「拦截结果不入训」的管线改动,DD 仍是 9。

B 组 · 推导与证明(6 题)

B1. 公平准则的不兼容性(直觉版推导)。设分数 s^\hat s 在每个群体上校准:P(Y=1∣s^=s)=π(s)P(Y=1\mid \hat s=s)=\pi(s) 与群体无关;记 πa:=P(Y=1∣A=a)\pi_a:=P(Y=1\mid A=a)。(a) 用贝叶斯公式写出 P(s^=s∣Y=1,A=a)P(\hat s=s\mid Y=1,A=a),指出均等化几率要求什么等式;(b) 化成两组条件密度的比例关系并写出比例因子;(c) 取例 7.4.1 的 A、B 两组(πA=0.40\pi_A=0.40、πB=0.26\pi_B=0.26)与某网格点(π(s)=0.5\pi(s)=0.5、P(s^=s∣A=A)=0.20P(\hat s=s\mid A=\text{A})=0.20),算出 B 组必须取到的密度;(d) 说明为何这对所有 ss 不可能同时成立,「基础发生率相同」为何让矛盾消失。

B2. KL 正则目标的闭式解与 DPO 的来处。对 max⁡πEy∼π[r(y)]−β KL(π∥πref)\max_{\pi}\mathbb E_{y\sim\pi}[r(y)]-\beta,\mathrm{KL}(\pi\Vert\pi_{\text{ref}}),∑yπ(y)=1\sum_y\pi(y)=1:(a) 写拉格朗日函数与一阶条件;(b) 解出 π⋆(y)\pi^\star(y) 与 Z(x)Z(x);(c) 反解 r(y)r(y),说明代回 Bradley–Terry 损失后 βlog⁡Z(x)\beta\log Z(x) 为什么消失;(d) 用 β→0+\beta\to0^{+} 与 β→+∞\beta\to+\infty 说明「β\beta 是对齐预算而不是普通正则系数」。

B3. 越狱的优化式 max⁡z∈Vnlog⁡πθ(t∣x∥z)\max_{z\in\mathcal V^{n}}\log\pi_\theta(t\mid x\Vert z):(a) 为什么不能直接对 zz 梯度上升(写清取值空间与导数在什么集合上有定义);(b) 写出 GCG 的两步并指出各需多少次前向 / 反向;(c) 取 V=32000V=32000、n=20n=20,估算 ∣Vn∣\lvert\mathcal V^{n}\rvert 的数量级(给以 10 为底的对数);(d) 由 (c) 说明黑名单式过滤的天花板,以及为什么更可靠的方向是降低内部表示的线性可分性。

B4. 分桶 ECE 的读法。某二分类模型在验证集(n=1000n=1000)上:桶 1(200200 条,置信 0.100.10,正确率 0.100.10)、桶 2(300300,0.400.40,0.300.30)、桶 3(250250,0.700.70,0.600.60)、桶 4(250250,0.950.95,0.750.75)。(a) 逐桶列权重、差值与贡献,求 ECE;(b) 手算 conf‾\overline{\mathrm{conf}} 与 acc‾\overline{\mathrm{acc}},验证 ECE=conf‾−acc‾\mathrm{ECE}=\overline{\mathrm{conf}}-\overline{\mathrm{acc}},说明该恒等式在什么条件下成立;(c) 把桶 1、2 合并成 [0,0.5)[0,0.5) 桶(500500 条、0.280.28、0.220.22)重算 ECE,解释它没变的原因,并说明只看 ECE 会漏掉什么;(d) 按「允许错误率 ≤1.2×(1−conf)\le1.2\times(1-\mathrm{conf})」逐桶检验,指出失守的桶与超限倍数,写出应有的门槛形式。

B5. SAE 的「重建 vs 稀疏」权衡(二维玩具)。d1=(1,0.2)T\boldsymbol d_1=(1,0.2)^{\mathsf T}、d2=(0.2,1)T\boldsymbol d_2=(0.2,1)^{\mathsf T},x=(1,1)T\boldsymbol x=(1,1)^{\mathsf T},x^=f1d1+f2d2\hat{\boldsymbol x}=f_1\boldsymbol d_1+f_2\boldsymbol d_2(f≥0f\ge0),L=∥x−x^∥22+λ∥f∥1\mathcal L=\lVert\boldsymbol x-\hat{\boldsymbol x}\rVert_2^2+\lambda\lVert\boldsymbol f\rVert_1。(a) 求全开解(f1,f2>0f_1,f_2\gt0)的 ff、重建误差与 ∥f∥1\lVert\boldsymbol f\rVert_1;(b) 只开 f1f_1 时写出 f1(λ)f_1(\lambda) 与 Lsparse(λ)\mathcal L_{\text{sparse}}(\lambda),并用化简式 Lsparse=2−1.04f12\mathcal L_{\text{sparse}}=2-1.04f_1^{2} 验证 λ=0\lambda=0 与 λ=0.5\lambda=0.5 两点;(c) 令 Lsparse=Ldense=53λ\mathcal L_{\text{sparse}}=\mathcal L_{\text{dense}}=\frac{5}{3}\lambda,解出切换阈值 λ⋆\lambda^\star(三位小数)并说明两侧行为;(d) λ\lambda 极大时最优解变成什么?用它说明 SAE 的两个已知局限。

B6. 风险 → 需求的翻译。不合格的风险描述:「我们的在线问诊助手要防止被用来获取具体的用药剂量建议,这关系到患者安全。」(a) 按方法 7.5.3 的五要素逐条指出缺什么;(b) 改写成五要素齐备的需求(具体数字、或写出「待标定」并说明标定方式);(c) 按定义 7.6.1 的两条附加纪律,说明为什么必须同时给出过拒率与最差子群的数值。

提示与答案

B1. (a) 用贝叶斯公式(「校准」这一前提恰好让第一个因子与群体无关):

P(s^=s∣Y=1,A=a)=P(Y=1∣s^=s,A=a) P(s^=s∣A=a)P(Y=1∣A=a)=π(s) P(s^=s∣A=a)πa.P(\hat s=s\mid Y=1,A=a)=\frac{P(Y=1\mid \hat s=s,A=a)\,P(\hat s=s\mid A=a)}{P(Y=1\mid A=a)}=\frac{\pi(s)\,P(\hat s=s\mid A=a)}{\pi_a}.

均等化几率要求 P(s^=s∣Y=1,A=A)=P(s^=s∣Y=1,A=B)P(\hat s=s\mid Y=1,A=\text{A})=P(\hat s=s\mid Y=1,A=\text{B})。(b) 代入后 π(s)\pi(s) 约掉:

P(s^=s∣A=A)=πAπBP(s^=s∣A=B),πAπB=0.400.26≈1.538.P(\hat s=s\mid A=\text{A})=\frac{\pi_{\text{A}}}{\pi_{\text{B}}}P(\hat s=s\mid A=\text{B}),\qquad \frac{\pi_{\text{A}}}{\pi_{\text{B}}}=\frac{0.40}{0.26}\approx1.538 . (c) 于是 B 组在该点必须取到

P(s^=s∣A=B)=πBπA×0.20=0.260.40×0.20=0.65×0.20=0.13.P(\hat s=s\mid A=\text{B})=\frac{\pi_{\text{B}}}{\pi_{\text{A}}}\times0.20=\frac{0.26}{0.40}\times0.20=0.65\times0.20=\mathbf{0.13}.

读法:要在「同一分数含义相同」(校准)的前提下把两组假阴性率拉平,该分数在 B 组的出现频率必须系统性低于 A 组(65%65\%)。(d) 该要求必须对每个 ss 同时成立,即两组整个分数分布相差同一个非零常数因子 0.650.65;而两个分布各自要归一化到 11,只能是同一个分布的倍数——除非分布在几乎所有 ss 上退化(分数毫无区分能力)。若 πA=πB\pi_{\text{A}}=\pi_{\text{B}},因子变成 11,两边可取同一分布,矛盾消失:这正是定理 7.4.1 里「基础发生率不同」这个前提的作用。

B2. (a) 展开两项后构造拉格朗日函数(固定 xx,记 r(y):=r(x,y)r(y):=r(x,y)):

L=∑yπ(y)r(y)−β∑yπ(y)log⁡π(y)πref(y)+λ(1−∑yπ(y)),∂L∂π(y)=r(y)−β[log⁡π(y)πref(y)+1]−λ=0.L=\sum_y\pi(y)r(y)-\beta\sum_y\pi(y)\log\frac{\pi(y)}{\pi_{\text{ref}}(y)}+\lambda\Big(1-\sum_y\pi(y)\Big),\quad \frac{\partial L}{\partial \pi(y)}=r(y)-\beta\Big[\log\frac{\pi(y)}{\pi_{\text{ref}}(y)}+1\Big]-\lambda=0 . (b) 整理一阶条件、把常数项并入归一化常数:

π⋆(y)=1Z(x)πref(y)exp⁡ ⁣(r(y)β),Z(x)=∑yπref(y)exp⁡ ⁣(r(y)β)>0.\pi^\star(y)=\frac{1}{Z(x)}\pi_{\text{ref}}(y)\exp\!\Big(\frac{r(y)}{\beta}\Big),\qquad Z(x)=\sum_y\pi_{\text{ref}}(y)\exp\!\Big(\frac{r(y)}{\beta}\Big)\gt 0 . (c) 两边取对数得「奖励被策略比值的对数表达」:r(y)=βlog⁡π⋆(y)πref(y)+βlog⁡Z(x)r(y)=\beta\log\frac{\pi^\star(y)}{\pi_{\text{ref}}(y)}+\beta\log Z(x)。代回 L=−E[log⁡σ(r(x,yw)−r(x,yl))]\mathcal L=-\mathbb E[\log\sigma(r(x,y_w)-r(x,y_l))]:ywy_w 与 yly_l 共享同一个提示 xx,Z(x)Z(x) 是同一个数,在差值中被消掉:

r(x,yw)−r(x,yl)=βlog⁡π(yw∣x)πref(yw∣x)−βlog⁡π(yl∣x)πref(yl∣x),r(x,y_w)-r(x,y_l)=\beta\log\frac{\pi(y_w\mid x)}{\pi_{\text{ref}}(y_w\mid x)}-\beta\log\frac{\pi(y_l\mid x)}{\pi_{\text{ref}}(y_l\mid x)},

把 π⋆\pi^\star 换成待训策略 πθ\pi_\theta 并取负号求最小,即得 DPO 损失——奖励模型是被整条消掉的,而不是被近似掉的;r^=βlog⁡(πθ/πref)\hat r=\beta\log(\pi_\theta/\pi_{\text{ref}}) 就是 DPO 的隐式奖励(方法 7.2.3)。(d) 偏移按 exp⁡(r/β)\exp(r/\beta) 重加权:β→0+\beta\to0^{+} 时该因子被极端放大 → 微小奖励差异造成巨大偏移 → 更听奖励模型的话、也更容易掉进它的漏洞;β→+∞\beta\to+\infty 时 π⋆→πref\pi^\star\to\pi_{\text{ref}},几乎学不动。所以 β\beta 是「允许多大程度偏离既有行为」的对齐预算。

B3. (a) zz 的取值空间是离散集合 Vn\mathcal V^{n}(词表的 nn 次笛卡尔积,每个元素是一条 token 序列),梯度只在连续域上有定义;对 one-hot 表示 ezie_{z_i} 求的梯度是关于表示的导数,不是关于取值本身的导数,因此写不出「沿方向走一小步」。(b) ① 连续梯度定位:对每个位置算 ∇ezilog⁡πθ(t∣x∥z)\nabla_{e_{z_i}}\log\pi_\theta(t\mid x\Vert z)、取 top-kk 候选(1 次反向拿到所有位置的梯度);② 离散贪心评估:逐位置、逐个候选地实际替换并前向评估,只保留目标值真正上升的那次替换(n×kn\times k 次前向);③ 重复至收敛或达到预算。可迁移结论:当搜索空间离散而你有梯度时,梯度是启发式而不是方向。 (c) log⁡10∣Vn∣=nlog⁡10V=20log⁡1032000=20×4.505≈90.10\log_{10}\lvert\mathcal V^{n}\rvert=n\log_{10}V=20\log_{10}32000=20\times4.505\approx90.10,即约 1.3×10901.3\times10^{90} 条后缀。(d) 要「匹配」一类可疑后缀就必须枚举 109010^{90} 量级空间里的元素,而优化者换一个目标函数就能生成新后缀——所以依赖黑名单的防御必须假设它是可被绕过的,它的价值是提高攻击成本,不是关闭攻击面。更可靠的方向是让有害意图在内部表示上不再线性可分(表征层干预不去追后缀形状,因而能挡住大量未见过的变体),代价是可能一并压制与目标任务共线的好特征,需要可解释性做定位(方法 7.2.6)。

B4. (a) 逐桶表:

桶 权重 ∣Bm∣/n\lvert B_m\rvert/n ∣acc−conf∣\lvert\mathrm{acc}-\mathrm{conf}\rvert 贡献
1 0.200 0.00 0.000
2 0.300 0.10 0.030
3 0.250 0.10 0.025
4 0.250 0.20 0.050

ECE=0.000+0.030+0.025+0.050=0.105\mathrm{ECE}=0.000+0.030+0.025+0.050=\mathbf{0.105}。(b) conf‾=0.10(0.2)+0.40(0.3)+0.70(0.25)+0.95(0.25)=0.5525\overline{\mathrm{conf}}=0.10(0.2)+0.40(0.3)+0.70(0.25)+0.95(0.25)=0.5525;acc‾=0.10(0.2)+0.30(0.3)+0.60(0.25)+0.75(0.25)=0.4475\overline{\mathrm{acc}}=0.10(0.2)+0.30(0.3)+0.60(0.25)+0.75(0.25)=0.4475;差 =0.105==0.105= ECE ✓。成立条件:所有桶的偏差同向(此处全是 acc<conf\mathrm{acc}\lt\mathrm{conf},即系统性过自信),此时绝对值可整体提出:∑mwm(confm−accm)=conf‾−acc‾\sum_m w_m(\mathrm{conf}_m-\mathrm{acc}_m)=\overline{\mathrm{conf}}-\overline{\mathrm{acc}};若有欠自信的桶,符号互相抵消,ECE 会大于净偏差。(c) 合并后权重 0.50.5、∣0.22−0.28∣=0.06\lvert0.22-0.28\rvert=0.06、贡献 0.0300.030,加上桶 3 的 0.0250.025 与桶 4 的 0.0500.050 仍是 0.1050.105——没变正是因为 (b) 的恒等式:同向过自信时 ECE 等于「平均置信度 − 平均准确率」,与怎么切桶无关。由此得到本节最重要的工程结论:ECE 会把「低置信区完全正确」与「高置信区严重过自信」混成一个不错的数字——只看 0.1050.105 就会漏掉「被自动处理的那批高置信样本实际错了 25%25\%」。(d) 桶 1 允许 1.2×0.90=1.081.2\times0.90=1.08 / 实际 0.900.90 → 通过;桶 2 允许 0.720.72 / 实际 0.700.70 → 通过;桶 3 允许 0.360.36 / 实际 0.400.40 → 不通过(1.11 倍);桶 4 允许 0.060.06 / 实际 0.250.25 → 不通过(4.17 倍)。门槛必须写成分桶形式(例如「桶 4 精确率 ≥p⋆\ge p^\star 且覆盖率 ≥c⋆\ge c^\star」);温度缩放一类后处理能压低过自信,但不改变排序——用于「是否自动处理」够用,用于「预测本身对不对」无能为力。

B5. (a) 无惩罚时 WTWf=WTx\boldsymbol W^{\mathsf T}\boldsymbol W\boldsymbol f=\boldsymbol W^{\mathsf T}\boldsymbol x,其中 WTW=(1.040.40.41.04)\boldsymbol W^{\mathsf T}\boldsymbol W=\begin{pmatrix}1.04&amp;0.4\\0.4&amp;1.04\end{pmatrix}、WTx=(1.2,1.2)T\boldsymbol W^{\mathsf T}\boldsymbol x=(1.2,1.2)^{\mathsf T}。由对称性 f1=f2=ff_1=f_2=f,代入 1.44f=1.21.44f=1.2 得 f=5/6≈0.8333f=5/6\approx0.8333,x^=(1,1)T\hat{\boldsymbol x}=(1,1)^{\mathsf T}:重建误差 00、∥f∥1=1.6667\lVert\boldsymbol f\rVert_1=1.6667、两个特征都开。(b) 只开 f1f_1 时目标为 ∥x−f1d1∥22+λf1\lVert\boldsymbol x-f_1\boldsymbol d_1\rVert_2^2+\lambda f_1,求导得

f1⋆=2.4−λ2.08=d1Tx−λ/2∥d1∥22,Lsparse(λ)=2−2.4f1+1.04f12+λf1=2−1.04f12.f_1^\star=\frac{2.4-\lambda}{2.08}=\frac{\boldsymbol d_1^{\mathsf T}\boldsymbol x-\lambda/2}{\lVert\boldsymbol d_1\rVert_2^{2}},\qquad \mathcal L_{\text{sparse}}(\lambda)=2-2.4f_1+1.04f_1^{2}+\lambda f_1=2-1.04f_1^{2}.

验证:λ=0\lambda=0 时 f1=1.1538f_1=1.1538、L=0.6154\mathcal L=0.6154(劣于全开解的 00);λ=0.5\lambda=0.5 时 f1=0.9135f_1=0.9135、L=1.1322\mathcal L=1.1322,而全开解 Ldense=1.6667λ=0.8333\mathcal L_{\text{dense}}=1.6667\lambda=0.8333——仍劣。注意反直觉处:λ>0\lambda\gt0 会增大稀疏解的损失(它压低了 f1f_1),所以比较的是两条损失曲线,而不是单看一项。(c) 令 2−1.04f12=53λ2-1.04f_1^{2}=\frac{5}{3}\lambda 并代入 f1=(2.4−λ)/2.08f_1=(2.4-\lambda)/2.08,整理得 1.04λ2+2.2187λ−2.6624=01.04\lambda^{2}+2.2187\lambda-2.6624=0,故

λ⋆=−2.2187+2.21872+4×1.04×2.66242.08≈0.856.\lambda^\star=\frac{-2.2187+\sqrt{2.2187^{2}+4\times1.04\times2.6624}}{2.08}\approx0.856 .

λ<λ⋆\lambda\lt\lambda^\star(如 0.50.5):两个特征都开更优(重建误差的下降大于稀疏惩罚的增加),λ\lambda 太小时 SAE 退化成普通自编码器;λ>λ⋆\lambda\gt\lambda^\star(如 1.21.2):只开一个特征更优(1.65391.6539 优于 2.02.0)。(d) λ\lambda 极大时 f1⋆f_1^\star 变负并被非负约束截断到 00:什么都不开、重建误差 =2=2,这就是「死特征 / 空重建」那一端。两个局限的落点:① 重建不完美——任何 λ>0\lambda\gt0 的解都留下未解释的方差(这里 0.61540.6154 或更大),它残留在重建误差里,因此必须一起报告「有几成激活方差没被解释」;② 稀疏与可解释只是相关——λ\lambda 越大编码越稀疏,但「每个特征都能被人类命名」不是稀疏度的推论(本例中 f1f_1 对应好解释的方向是我们构造出来的)。因此 SAE 的定位是审计与定位工具,不是安全证书。

B6. (a) 缺口:指标完全没有(「防止获取剂量建议」没有指明用哪个量观测);阈值与作用对象完全没有(无数值,也没说在什么数据 / 人群 / 分布上测);验收方式完全没有(「要防止」无法审计);负责人完全没有(要角色,不是「团队」);回退路径完全没有(止损动作与时延都没写)。唯一有用的信息是「关系到患者安全」——它指明 SS 高、且单向不对称(漏答比过拒贵),但这仍是依据,不是需求。(b) 改写示例:需求 R-A——在占位评测集(N≥500N\ge500,含「剂量类提问」与「一般用药信息提问」各不少于 200200 条)上,剂量类提问中输出具体剂量的比率 ≤1%\le1\%(人工双盲判定,含单位换算与「以医生为准」式绕道表述),同时一般用药信息提问的过拒率 ≤10%\le10\%(阈值由留出的、与真实流量一致的校准集标定,标定记录归档);上线后按周复测,任一比率相对首月基线上浮 ≥3\ge3 个百分点即告警。验收:红队脚本(改写 / 多轮追问 / 虚构情境三类入口)输出绕过率 ++ 人工抽检 200200 条的一致性报告 ++ 告警演练记录。负责人:模型上线责任人(值班表具名)。回退:触发告警后 24 小时内把该类提问切到「结构化字段 ++ 引用」模式(只输出有检索证据支持的用药信息,剂量一律不给),5 个工作日内完成原因分析。(c) 过拒率是这条需求的另一侧代价:1%1\% 的漏出率可以靠「一律拒答」轻易达成,只报一侧等于把需求写成「越严越好」,最终得到一个用户学会绕道的系统(而绕道会把风险推到监控看不见的地方)。最差子群则防止平均值掩盖差异:整体过拒率达标可能掩盖「某类表述的提问被 30%30\% 过拒」,而这批用户正被单向排除在服务外。二者合起来才让需求既有实质又不撒谎。

C 组 · 编程实现(6 题)

C1. 复现分桶 ECE 与逐桶相对口径:实现 ece、identity、relative_rule(1.21.2 倍口径)。

  • 验收标准:① ece 输出 0.1050.105(误差 <10−9&lt;10^{-9});② 断言 ECE=conf‾−acc‾=0.5525−0.4475\mathrm{ECE}=\overline{\mathrm{conf}}-\overline{\mathrm{acc}}=0.5525-0.4475;③ 合并桶 1、2 为 (500,0.28,0.22)(500,0.28,0.22) 后 ECE 不变(断言成立并打印结论);④ relative_rule 返回「桶 1、2 通过、桶 3、4 不通过」且桶 4 超限 ≈4.17\approx4.17(误差 <0.05&lt;0.05)。
参考实现
import numpy as np
BUCKETS = [(200, 0.10, 0.10), (300, 0.40, 0.30), (250, 0.70, 0.60), (250, 0.95, 0.75)]
def ece(bs):
    """期望校准误差:按样本数加权的 |acc − conf| 之和。"""
    m = sum(b[0] for b in bs)
    return sum(b[0] / m * abs(b[2] - b[1]) for b in bs)
identity = lambda bs: (sum(b[0] * b[1] for b in bs) / sum(x[0] for x in bs),
                       sum(b[0] * b[2] for b in bs) / sum(x[0] for x in bs))
def relative_rule(bs, factor=1.2):
    """逐桶:实际错误率 (1−acc) 是否 ≤ factor × 允许错误率 (1−conf)。"""
    return {f"桶{i}": ((1 - b[2]) <= factor * (1 - b[1]) + 1e-12,
                       round((1 - b[2]) / (factor * (1 - b[1])), 3)) for i, b in enumerate(bs, 1)}
conf, acc = identity(BUCKETS)
print("ECE =", round(ece(BUCKETS), 6), f";平均置信 {conf:.4f} 平均正确 {acc:.4f} 差 {abs(conf-acc):.4f}")
print("逐桶口径:", relative_rule(BUCKETS))
assert abs(ece(BUCKETS) - 0.105) < 1e-9
assert abs(abs(conf - acc) - ece(BUCKETS)) < 1e-12                  # 同向过自信 → 恒等式成立
assert abs(ece([(500, 0.28, 0.22)] + BUCKETS[2:]) - 0.105) < 1e-9  # 桶 1+2 → [0,0.5),ECE 不变
r = relative_rule(BUCKETS)
assert r["桶1"][0] and r["桶2"][0] and not r["桶3"][0] and not r["桶4"][0]
assert abs(r["桶4"][1] - 4.17) < 0.05
print("结论:改桶数 ECE 不变 → 门槛必须写成分桶形式,不能只写 ECE ≤ ε。")

C2. 复现 Grad-CAM 的手算结果,并实现单调性检验(insertion):从空图基线开始,按解释器认为的重要性从高到低逐格填入前景,检查目标分数是否单调非降。

  • 验收标准:① 用 A1A_1、A2A_2 与 α1=0.8\alpha_1=0.8、α2=−0.5\alpha_2=-0.5 复现 SS、S+S^{+} 与归一化图(逐元素误差 <10−3&lt;10^{-3}),且 G[0,0]=0G[0,0]=0、G[2,2]=1.0G[2,2]=1.0;② 忠实解释的插入曲线单调非降(容差 10−910^{-9});③ 不忠实解释(把背景当关键区域)的曲线存在下降步;④ 断言忠实曲线终值严格大于不忠实曲线。
参考实现
import numpy as np
# ① 复现正文例 7.3.1:加权求和 → ReLU → 归一化
A1 = np.array([[0, 0, 1], [0, 1, 2], [1, 2, 3]], float)
A2 = np.array([[3, 2, 1], [2, 1, 0], [1, 0, 0]], float)
S = 0.8 * A1 - 0.5 * A2
S_relu = np.maximum(S, 0)                     # ReLU 是 Grad-CAM 的关键一步
G = S_relu / S_relu.max()                     # 归一化到 [0, 1]
assert np.allclose(S, [[-1.5, -1.0, 0.3], [-1.0, 0.3, 1.6], [0.3, 1.6, 2.4]])
assert np.allclose(G, [[0, 0, 0.125], [0, 0.125, 0.667], [0.125, 0.667, 1.0]], atol=1e-3)
assert G[0, 0] == 0.0 and G[2, 2] == 1.0       # 左上角被 ReLU 清零、右下角为峰值
# ② 单调性检验(insertion):首点是空图基线,少了它"第一步就掉下去"会被漏掉
W = np.array([[-0.5, 0.0, 0.0], [0.2, 1.0, 1.5], [0.1, 0.8, 2.2]])   # 含一处背景抑制项
IMG = np.array([[0.5, 0.4, 0.3], [0.6, 0.9, 0.7], [0.4, 0.8, 1.0]])
IMP = {"忠实": np.maximum(W, 0),                                     # 只指向正贡献区域
       "不忠实": np.array([[2.2, 1.5, 1.0], [0.5, 0.0, 0.0], [0.0, 0.0, 0.0]])}
score = lambda x: float((W * x).sum())
def insertion_curve(imp, img):
    order = [ij for ij in sorted(np.ndindex(img.shape), key=lambda ij: (-imp[ij], ij)) if imp[ij] > 0]
    x, curve = np.zeros_like(img), [score(np.zeros_like(img))]
    for ij in order:
        x[ij] = img[ij]
        curve.append(score(x))
    return np.array(curve)
monotone = lambda c, tol=1e-9: bool(np.all(np.diff(c) >= -tol))
c_f, c_w = insertion_curve(IMP["忠实"], IMG), insertion_curve(IMP["不忠实"], IMG)
print("忠实前五步:", np.round(c_f[:5], 3), " 不忠实前五步:", np.round(c_w[:5], 3))
assert monotone(c_f), "忠实解释应给出单调非降的插入曲线"
assert not monotone(c_w), "不忠实解释应出现下降步(首个填入的像素带负贡献)"
assert c_f[-1] > c_w[-1]
print(f"终值:忠实 {c_f[-1]:.3f} vs 不忠实 {c_w[-1]:.3f} → 单调性检验能区分两者。")

C3. 激活引导的加 / 减方向实验:由对比提示(正例均值 − 反例均值)构造概念方向 v\boldsymbol v,实现 h′=h+αvunith&#x27;=h+\alpha\boldsymbol v_{\text{unit}},扫描 α∈[−2,2]\alpha\in[-2,2](含负值),并加两个旁路探针做成组能力回归。

  • 验收标准:① 目标行为随 α\alpha 单调上升(断言差分 >0\gt0),负 α\alpha 时低于基线;② 旁路探针同向变化,且「旁路斜率 / 目标斜率」≈0.970\approx0.970(误差 <0.01&lt;0.01)——打印该比值并解释它为什么不是 00;③ 无关任务探针的斜率绝对值 <0.2&lt;0.2(断言成立);④ 打印 ∣α∣>1.5|\alpha|\gt1.5 的「退化风险」标记,并说明 α\alpha 与层号必须一起记录。
参考实现

迁移到真实模型的挂钩方式(不改权重,只在该层前向里加方向):layer.register_forward_hook(lambda m, i, o: o + alpha * v_unit)。真实实验还需两点——方向必须来自同一层的对比激活(层选错则无效或破坏能力),且每换一个 α\alpha 都要重跑成组能力回归(下面两个旁路探针就是它的最小版)。

import numpy as np
# 两组对比提示在某层的激活(示意;实践中是正例 / 反例提示的激活均值)
h_pos = np.array([[1.1, 0.3, -0.2], [0.9, 0.4, -0.1], [1.0, 0.2, -0.3], [1.05, 0.35, -0.15], [0.95, 0.25, -0.25]])
h_neg = np.array([[0.1, 0.0, 0.0], [0.0, 0.05, -0.05], [-0.1, 0.0, 0.05], [0.05, -0.05, 0.0], [0.0, 0.1, -0.05]])
v_unit = h_pos.mean(0) - h_neg.mean(0)                   # 概念方向 = 对比提示的激活差
v_unit = v_unit / np.linalg.norm(v_unit)
PROBES = {"目标行为(拒答倾向)": np.array([1.0, 0.0, 0.0]),   # 目标行为
          "旁路一(与目标共线)": np.array([0.8, 0.6, 0.0]),   # 与目标方向高度共线的"好特征"
          "旁路二(无关任务)":   np.array([0.0, 0.0, 1.0])}   # 一个常规任务
alphas = np.array([-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0])
curves = {k: np.array([w @ (a * v_unit) for a in alphas]) for k, w in PROBES.items()}
for k, y in curves.items():
    print(f"{k}:{np.round(y, 3)}")
beh, side, task = curves.values()
assert np.all(np.diff(beh) > 0), "α 增大应单调抬升目标行为,负 α 时应低于基线"
slope = lambda y: float(np.polyfit(alphas, y, 1)[0])
ratio = slope(side) / slope(beh)
print(f"目标斜率 {slope(beh):.4f}  旁路斜率 {slope(side):.4f}  斜率比 {ratio:.4f}")
assert abs(ratio - 0.970) < 0.01, "旁路被带动了几乎同量级的变化 → 引导没有副作用保证"
assert abs(slope(task)) < 0.2, "无关任务受影响较小(这正是必须做回归、不能假设的原因)"
print("退化风险标记(|α| > 1.5):", [float(a) for a in alphas if abs(a) > 1.5],
      ";记录要求:α 与层号必须一起写——换层或换 α 都是另一次实验。")

C4. 扰动一致性检查:实现输入×梯度、纯梯度与遮挡三种归因,比较两两的 top-3 一致性(Jaccard),并按归因排序做删除曲线与随机排序对照。

  • 验收标准:① 口径相同时可对齐:线性模型上「输入×梯度」与「遮挡」的 top-3 完全一致(Jaccard =1.0=1.0);② 非线性造成真分歧:含交互项(ReLU 拐点处于临界位置)时同一对方法的 Jaccard ≈0.5\approx0.5(断言 0.4<Jaccard<0.60.4&lt;\text{Jaccard}&lt;0.6),打印两个 top-3 集合与分歧成员;③ 换口径也会不一致:线性模型上把归因换成纯梯度,Jaccard 也降到 0.50.5;④ 断言按归因排序的删除曲线曲线下面积严格小于 200 次随机排序的均值(固定随机种子,可复现);⑤ 打印处置结论:不一致的样本不可作为单一证据。
参考实现
import numpy as np
W = np.array([[-0.5, 0.00, 0.0], [0.2, 0.05, 1.5], [0.1, 0.80, 2.2]])
X = np.array([[0.5, 0.4, 0.3], [0.6, 1.2, 0.05], [0.4, 0.8, 1.0]])
C, GATE = 5.0, 0.05      # 交互项 C·ReLU(x[1,1]·x[1,2] − GATE),拐点处在临界位置
def make_score(c=C, gate=GATE):        # c = 0 时退化为线性模型("两法必须对齐"的对照)
    return lambda x: float((W * x).sum() + c * max(0.0, x[1, 1] * x[1, 2] - gate))
def grad_map(x, f, eps=1e-6):          # 纯梯度归因(中心差分;真实系统里是一步反向传播)
    g = np.zeros_like(x)
    for ij in np.ndindex(x.shape):
        xp, xm = x.copy(), x.copy(); xp[ij] += eps; xm[ij] -= eps
        g[ij] = (f(xp) - f(xm)) / (2 * eps)
    return g
def occlusion_map(x, f):               # 遮挡类归因:逐格置零,看分数下降多少
    base, m = f(x), np.zeros_like(x)
    for ij in np.ndindex(x.shape):
        xz = x.copy(); xz[ij] = 0.0
        m[ij] = base - f(xz)
    return m
grad_input_map = lambda x, f: grad_map(x, f) * x          # 输入 × 梯度:另一种常见口径
topk = lambda a, k=3: {ij for ij in sorted(np.ndindex(a.shape), key=lambda ij: (-abs(a[ij]), ij))[:k]}
jac = lambda a, b: len(a & b) / len(a | b)
def jaccard_report(tag, attr_a, attr_b, expect):
    ta, tb = topk(attr_a), topk(attr_b)
    got = jac(ta, tb)
    print(f"{tag}: Jaccard={got:.2f} 分歧={sorted(ta ^ tb)}(期望 {expect})")
    return got
s_lin, s_int = make_score(c=0.0), make_score()
j = [jaccard_report("① 线性 / 输入×梯度 vs 遮挡", grad_input_map(X, s_lin), occlusion_map(X, s_lin), 1.0),
     jaccard_report("② 含交互项 / 输入×梯度 vs 遮挡", grad_input_map(X, s_int), occlusion_map(X, s_int), 0.5),
     jaccard_report("③ 线性 / 纯梯度 vs 遮挡", grad_map(X, s_lin), occlusion_map(X, s_lin), 0.5)]
assert j[0] == 1.0 and 0.4 < j[1] < 0.6 and abs(j[2] - 0.5) < 1e-12, "对齐 / 非线性分歧 / 口径差异"
def del_curve(x, order, f):            # 从全图开始按 order 逐格置零,首点是初始分数
    xc, curve = x.copy(), [f(x)]
    for ij in order:
        xc[ij] = 0.0
        curve.append(f(xc))
    return np.array(curve)
attr = grad_input_map(X, s_int)
order_attr = sorted(np.ndindex(X.shape), key=lambda ij: (-abs(attr[ij]), ij))
rng, cells = np.random.default_rng(0), list(np.ndindex(X.shape))
area_attr = float(del_curve(X, order_attr, s_int).sum())
area_rand = float(np.mean([del_curve(X, [tuple(ij) for ij in rng.permutation(cells)], s_int).sum()
                           for _ in range(200)]))
print(f"删除曲线面积:按归因 {area_attr:.3f} vs 随机均值 {area_rand:.3f}")
assert area_attr < area_rand, "按归因删除应比随机删除下降更快(面积更小)"
print("处置结论:两法不一致的样本,其解释只能作为线索;要进报告必须补成组统计与消融检验。")

C5. 风险—覆盖曲线与工作点判定:用例 7.3.2 的四桶数据算 (覆盖率,风险)(\text{覆盖率},\text{风险}) 曲线,并实现 deployable(cov, risk, c_star, r_star)。

  • 验收标准:① τ=0.95, 0.70, 0.40, 0.10\tau=0.95,,0.70,,0.40,,0.10 四点分别为 (0.25,0.2500)(0.25,0.2500)、(0.50,0.3250)(0.50,0.3250)、(0.80,0.4656)(0.80,0.4656)、(1.00,0.5525)(1.00,0.5525)(误差 <10−3&lt;10^{-3});② 断言风险随覆盖率单调非降;③ deployable 对 (c⋆,r⋆)=(0.20,0.30)(c^\star,r^\star)=(0.20,0.30) 返回 True、对 (0.80,0.30)(0.80,0.30) 返回 False;④ 打印「若同时施加逐桶 1.21.2 倍口径」的结论(桶 4 不得自动处理,与 τ=0.95\tau=0.95 的工作点冲突 → 先校准或扩大转人工)。
参考实现
import numpy as np
BUCKETS = [(200, 0.10, 0.10), (300, 0.40, 0.30), (250, 0.70, 0.60), (250, 0.95, 0.75)]
n = sum(b[0] for b in BUCKETS)
def risk_coverage(buckets, thresholds):
    """按「置信度 ≥ τ 才自动处理」计算 (覆盖率, 风险)。"""
    rows = []
    for t in thresholds:
        sel = [b for b in buckets if b[1] >= t]
        rows.append((t, sum(b[0] for b in sel) / n,
                     1 - sum(b[0] * b[2] for b in sel) / sum(b[0] for b in sel)))
    return rows
deployable = lambda cov, risk, c_star, r_star: bool(cov >= c_star and risk <= r_star)
curve = risk_coverage(BUCKETS, [0.95, 0.70, 0.40, 0.10])
for t, cov, risk in curve:
    print(f"τ={t:.2f}  覆盖率 {cov:.4f}  风险 {risk:.4f}")
assert np.allclose([round(c, 4) for _, c, _ in curve], [0.25, 0.50, 0.80, 1.00])
assert np.allclose([round(r, 4) for _, _, r in curve], [0.2500, 0.3250, 0.4656, 0.5525])
risks = [r for _, _, r in curve]
assert all(b >= a - 1e-12 for a, b in zip(risks, risks[1:])), "风险应随覆盖率单调非降"
assert deployable(0.25, 0.25, 0.20, 0.30) is True
assert deployable(0.80, 0.4656, 0.80, 0.30) is False
factor, (_, c4, a4) = 1.2, BUCKETS[-1]
print(f"逐桶 1.2 倍口径:桶 4 允许错误率 {factor*(1-c4):.2f},实际 {1-a4:.2f} → "
      f"{'通过' if 1-a4 <= factor*(1-c4) else '不通过'}")
print("结论:τ=0.95 的工作点在逐桶口径下不成立 → 先做校准 / 转人工,再谈自动处理。")

C6. 水印的检验统计量:实现 z=(∣s∣G−γT)/Tγ(1−γ)z=\bigl(\lvert s\rvert_G-\gamma T\bigr)/\sqrt{T\gamma(1-\gamma)},用蒙特卡洛验证三件事。

  • 验收标准:① 未加水印时 Pr⁡(z>4)\Pr(z\gt4) 落在 [2×10−5,5×10−5][2\times10^{-5},5\times10^{-5}](理论 Φ(−4)=3.17×10−5\Phi(-4)=3.17\times10^{-5}),并打印 95% 置信区间;② 真实命中率 p=0.35p=0.35、T=1000T=1000 时模拟 E[z]\mathbb E[z] 与解析值 7.307.30 相差 <5%&lt;5%,且 Pr⁡(z>4)>0.99\Pr(z\gt4)\gt0.99;③ T=50T=50 时打印 E[z]≈1.63\mathbb E[z]\approx1.63 并断言 <4&lt;4(短文本无法判定);④ 打印随 TT 的 E[z]\mathbb E[z] 序列与「改写会进一步降低命中率」这一外部依赖。
参考实现
import numpy as np
from math import erf
GAMMA, N_SIM = 0.25, 1_000_000
Phi = lambda x: 0.5 * (1 + erf(x / np.sqrt(2.0)))          # 标准正态 CDF,用来对照理论假阳率
def z_stat(hits, T, gamma=GAMMA):
    """水印检验统计量:|s|_G 为落在绿名单的 token 数,T 为 token 数。"""
    return (hits - gamma * T) / np.sqrt(T * gamma * (1 - gamma))
rng, T = np.random.default_rng(7), 1000
# ① 未加水印:每步命中绿名单的概率就是 γ
z_null = z_stat(rng.binomial(T, GAMMA, size=N_SIM), T)
fp = float((z_null > 4).mean()); se = np.sqrt(fp * (1 - fp) / N_SIM)
print(f"未加水印:P(z>4) = {fp:.2e} ± {1.96*se:.2e}(理论 Φ(−4) = {Phi(-4):.2e})")
assert 2e-5 < fp < 5e-5, "假阳率应与 Φ(−4) 同量级(这正是「假阳率可控」的含义)"
# ② 加水印:真实命中率抬到 p
p = 0.35
z_wm = z_stat(rng.binomial(T, p, size=N_SIM), T)
theory = (p - GAMMA) * np.sqrt(T) / np.sqrt(GAMMA * (1 - GAMMA))
print(f"加水印:模拟 E[z] = {z_wm.mean():.2f}(解析 {theory:.2f}),P(z>4) = {(z_wm > 4).mean():.4f}")
assert abs(z_wm.mean() - theory) / theory < 0.05
assert (z_wm > 4).mean() > 0.99
# ③ 短文本:统计量的期望随 √T 缩小 → 检不出
for Ts in (50, 200, 1000):
    print(f"T={Ts:5d}: E[z] = {(p-GAMMA)*np.sqrt(Ts)/np.sqrt(GAMMA*(1-GAMMA)):.2f}")
assert (p - GAMMA) * np.sqrt(50) / np.sqrt(GAMMA * (1 - GAMMA)) < 4
print("边界:假阴率依赖文本长度与改写程度;水印是取证线索,不是防伪标,也检测不了未加水印的模型。")

D 组 · 开放设计(4 题)

每题都必须交出四项:方案 + 理由 + 失败判据 + 验证计划。评分不看篇幅,看是否可执行、可验收、可回退。

D1. 威胁模型与红队方案。 某内部文档问答智能体原有三个工具(知识库检索、日历读取、邮件草稿),本次新增第四个:工单创建(可直接在缺陷系统立单并自动通知被指派者);用户输入可能来自员工粘贴的外部邮件与网页片段。要求:(a) 写六段模板里的三段——信任边界与数据流 / 攻击者与能力假设(必须含最常被漏掉的那一类)/ 攻击面清单(按入口、通路、出口);(b) 设计红队方案(覆盖哪些注入位置与形态、指标口径、失败模式怎么记录、何时重跑);(c) 说明红队结论在文档里能写什么、不能写什么。

参考方案与评分要点

(a) 三段。 信任边界与数据流:数据流为「用户输入(可能含外部粘贴)→ 模型 → 工具调用(检索 / 日历 / 工单创建)→ 外部副作用(工单已创建、指派通知已发出)」;信任边界在「用户输入」处即断裂——粘贴的网页片段与外部邮件属于不可信内容,却与用户本人的指令在模型看来是同一个字符串流;工具返回值(日历标题、工单正文)同样由他人可写、不可信。工单创建是半可逆动作:工单可撤销,但指派通知已发出、被指派者的排期已被占用。 攻击者与能力假设(含最常被漏的一类):

类型 能力假设 期望结果
外部内容投放者(最危险) 能让人看到一段文字(发邮件、放网页)并诱使员工粘贴进对话 让智能体读走内部信息,或创建内容由攻击者控制、指派对象难以追查的工单
内部好奇员工 有正常账号 越过权限读取不属于自己的文档
有组织的滥用者 多账号、有预算 批量创建工单以阻塞缺陷系统队列(拒绝服务式滥用)
无意触发者(最常被漏) 无任何恶意 粘贴含敏感信息的文档 → 敏感信息进入日志与第三方模型调用;或把「请立单给 X」误当成自己的意图

每条假设都要写「如果它不成立会怎样」。攻击面(选摘):入口——用户粘贴文本(单次会话)、检索返回的文档(可被内部人员长期投毒)、工具返回值(中等持续);通路——模型 → 工单创建 → 缺陷系统与通知渠道;出口——工单正文、附件、错误信息。每格问:这里能进什么?能影响什么?能持续多久? (b) 红队方案。 覆盖四类入口(直接注入 / 间接注入 / 角色扮演 / 多轮诱导)× 三类投放位置(粘贴文本、检索文档、工具返回值)× 两个目标(越权读取、越权写工单),共 N≥120N\ge120 条用例(含「与正常业务指令高度相似」的边缘用例);指标两侧都测——完整绕过率(产生攻击者预期且未经确认的副作用)、按类绕过率、以及过拒率;失败样本逐条归档(输入、上下文来源、工具调用序列、判定理由);每次模型、提示、工具 schema 或权限配置变更后重跑全量并留存版本。 (c) 能写 / 不能写。 能写:「在 NN 条用例、四类攻击、两处工具入口的覆盖下,工单创建的完整绕过率为 pp,失败样本见附录」。不能写:「红队通过,系统安全」——红队只扩大已知失效集合,对补集没有陈述能力(定义 7.2.4)。还要写清方法边界:红队不回答「这个能力把什么事变得更容易了」(那是滥用评估,核心是基线对照),也不回答「分布外表现如何」(那是常规评测)。 评分要点:三段齐全且信任边界正确 4 分(漏掉「无意触发者」扣 1 分);红队方案的覆盖面与双率指标 3 分(只报绕过率扣 1 分);结论表述纪律 3 分(写出「红队通过 ≠ 安全」得满分)。

D2. 监控与回滚设计。 某信贷产品的「额度调整模型」已上线三个月(输入账户行为特征,输出上调 / 维持 / 下调;低于某额度的调整自动生效,其余转人工;已有申诉通道)。要求:(a) 给出三层指标的最小版本,并指出哪一层最能提前发现分布漂移;(b) 为其中两个安全指标写出门槛、阈值来源与接收角色;(c) 写清灰度与同期对照设计;(d) 写出回滚的触发条件 / 执行人 / 执行时长,并给出事故四个时限(TdetectT_{\text{detect}} / TtriageT_{\text{triage}} / TmitigateT_{\text{mitigate}} / TnotifyT_{\text{notify}})的取值与依据。

参考方案与评分要点

(a) 三层最小版本:质量层——调整决策准确率 / 与人工复核一致率、按额度区间与按群体的分群指标;安全层——拒答与转人工率、过拒率、分群质量差异(最差子群)、争议率(申诉量与申诉推翻率);行为层——三类决策的占比、上调额度分布、对单一特征的敏感度(捷径特征)、单位用户调用次数。漂移最早出现在行为层与输入侧:分布漂移往往先表现为「输入变了」(新客群、新消费模式、新渠道)与输出分布改变,再传导到质量指标;因此还要单独监控漂移检测本身的指标——样本量、输入分布变化、未覆盖输入的比例(方法 7.6.3)。样本量本身就是监控项:样本量下降往往先于指标恶化出现。 (b) 两个安全指标:

指标 阈值 阈值来源 接收角色
分群质量差异(最差子群误差率相对整体) 升 ≥3\ge3 个百分点 → 告警;≥8\ge8 → 熔断 首月线上分布 ++ 允许波动,并经一次人为注入偏移的演练校准 模型上线责任人(值班表具名)
自动化比例与过拒率 自动化比例上限 A⋆A^\star;过拒率 ≥\ge 基线 +2+2 个百分点 → 告警 由「转人工的人力预算」与「过拒的业务损失」两笔账共同推出 业务负责人(++ 风控复核)
(c) 灰度与同期对照:新版本先 5%5\% 流量、与旧版本同期并行,每档看四项(质量、分群差异、P95 延迟、转人工率);关键设计是对照——没有同期对照就无法区分「模型变差」与「这段时间流量变难」;灰度比例按样本量需求定,不要为快而失去统计功效;低额度自动档与高额度人工档分别统计。
(d) 回滚与四时限:
项 取值(示例) 依据
触发条件 熔断指标命中 / 某群体申诉推翻率显著抬升 / 出现一次不可接受的个案 触发条件必须事前写死,且每个条件都有接收角色
执行人 值班工程师(执行)++ 业务负责人(确认);权限事前授予并演练过 未演练的回退在事故当天通常不可用(配置漂移、权限过期)
执行时长 ≤30\le30 分钟切回上一版本;≤24\le24 小时把该版本产生的自动决策批量重跑或转人工 回滚要包含已产生后果的承接,而不只是切版本
TdetectT_{\text{detect}} ≤1\le1 个自然日(按日看板与告警采样频率决定) 没有指标的失效等于没有发现时间
TtriageT_{\text{triage}} ≤2\le2 小时(值班与升级路径) 由值班设计决定
TmitigateT_{\text{mitigate}} ≤30\le30 分钟(== 回滚时长) 这一项最常被高估,它由「回退是否演练过」决定
TnotifyT_{\text{notify}} 按合同与合规要求(例如严重事件在约定时限内通报受影响方) 由合规与合同决定,需核对现行法域要求(需核实)

加分项:把「先止损、后定位」写成流程——定位期间系统继续运行会改变数据、污染证据(日志与反馈被新模式覆盖),而回滚本身给出一次自然的对照实验,常常比事后分析更快锁定原因。 评分要点:三层指标齐全且指出漂移的最早信号 3 分;两个指标的门槛 / 来源 / 接收角色各 1.5 分;灰度含同期对照 2 分;回滚含执行时长与后果承接 2 分;四时限取值与「止损时间最常被高估」的理由 2 分。

D3. 公平度量的选择与理由。 某地公共助学金名额分配系统用模型对申请者排序,名额有限(约录取 15%15%);受保护属性按自愿申报获得,覆盖率约 60%60%(其余只能靠统计推断补足)。要求:(a) 写出方法 7.4.1 五步的答案,第 1 步必须写清「给谁分配什么、犯错的代价是否双向对称」;(b) 选一个主准则 ++ 一个副准则并写成需求(含阈值、验收、负责人、回退);(c) 并列两种立场(以结果分布为目标 / 以同等条件同等对待为目标)的依据,指出你的选择牺牲了什么、由谁承担;(d) 写明残余风险接受者与复查条件,并说明「受保护属性靠推断补足」如何影响第 (c) 步的可信度。

参考方案与评分要点

(a) 五步。 ① 对象与后果:把稀缺的教育资源分配给个体;错误双向不对称——漏助(合格者被拒)与误助(不合格者占用名额、挤掉别人)都有代价,且都不落在系统身上。② 候选准则与代价:人口统计平价 → 牺牲「同一分数同一含义」并可能要求对个体区别对待;机会均等 / 均等化几率 → 两组合格率不同时结果比例仍有差异;预测平价 / 分群校准 → 保留结果比例差异,且在基础发生率不同时与均等化几率一般不能兼得。③ 主 ++ 副:例如主准则 == 机会均等(约束合格者不因群体被错筛)、副准则 == 预测平价的偏离上限(约束「同一分数含义」别漂太远)。④ 写进目标或约束:加约束「组间假阴性率之差 ≤δ\le\delta」或对样本少的组重加权——只在评估阶段报指标,优化器没有任何动力改善它。⑤ 残余风险与复查条件:写明哪些差异被选择接受、依据是什么、何时重估(样本量达阈值 / 业务目标变更 / 法规更新 / 申报率变化)。 (b) 需求示范:需求 F-1——在占位评测集(各组样本量 ≥500\ge500;受保护属性用「自愿申报」与「推断补足」两套口径各跑一遍)上,组间假阴性率之差 ≤0.05\le0.05(绝对差),且各组的分群校准偏离 ≤0.05\le0.05;上线后按月复测,任一组相对首月基线恶化 ≥3\ge3 个百分点即告警。验收:分群评估报告(含置信区间与推断属性的质量指标)++ 告警演练记录。负责人:模型负责人(准则与代价)与业务负责人(残余风险接受)双签。回退:触发告警后 24 小时内把该组降级为「进入人工复核池」,并按季度重估准则。 (c) 两种立场(并列,不下判断)。 立场 A:以结果分布为目标。 依据:历史不公正是通过结果分布差异长期累积的,只保证「同等条件同等机会」不足以纠正存量差异;且结果分布更容易被外部检验——外部只需看到通过率,不需看到分数与真实标签。立场 B:以同等条件同等对待为目标。 依据:在基础发生率真实存在差异时,强行拉平结果分布意味着对个体的区别对待(同等资质得到不同结果),这在很多岗位与法律框架下被明确禁止;且它把「历史差异应由谁承担」转移给了当下的个体。牺牲了什么、由谁承担(以选 A 为例):牺牲「同一分数在同一群体内含义一致」这一点(分群校准的偏离)以及可能的个体公平争议;代价由分数处于边界、且所属组基础发生率较低的那批申请者承担。若选 B,则代价由基础发生率较低群体的合格者以更高假阴性率的形式承担。两者共同接受的底线:必须显式选择并记录——不选择的默认(只优化平均损失)本身就是一种选择,而且往往是最不利于弱势群体的那一种。 (d) 残余风险与推断属性的影响。 接受者:业务负责人(分配的政治与伦理责任)++ 合规负责人(法域要求)共同签字;复查条件:申报率变化、样本量翻倍、相关法规更新、或某组申诉推翻率抬升。推断属性的影响:推断本身会出错,而且推断错误的分布并不随机(对少数族裔姓名的推断质量往往更差),因此一切基于推断属性的分群指标都必须同时报告覆盖率、准确率与不同子群上的差异;否则整份评估的可信度无从判断——这会让 (c) 中「以结果分布为目标」的立场更难被验证(分组标签本身带噪声)。这是必须写进文档的事实,不是可省略的脚注。 评分要点:五步齐全(第 1 步的不对称性分析、第 4 步的「写进目标」为关键)4 分;需求五要素齐备且阈值可验收 2 分;两立场并列且给出依据、写明「牺牲了什么、由谁承担」2 分;残余风险接受者与复查条件 1 分;推断属性质量对可信度的影响 1 分。若出现「应当以 X 为准则」而不给依据与代价,本部分不给分。

D4. 申诉与救济机制设计。 某平台的内容审核系统已上线(通过 / 拦截 / 转人工三分类,拦截会向作者发送理由),目前「申诉」只是帮助页深处的一张客服工单表。要求:(a) 按定义 7.4.3 设计一个能真正纠正(而不仅是受理)的流程,逐条写清「可申诉 / 可解释 / 可推翻 / 可聚合」四要件;(b) 说明「可解释」这一环为什么不能直接拿一张未经检验的归因图给用户;(c) 给出通道的监控指标(含一条反直觉指标)与两条可测量的失败判据;(d) 写出答复时限与升级路径。

参考方案与评分要点

(a) 四要件。

要件 具体设计 缺了它为什么不成立
可申诉 拦截通知里直接带入口(不藏在帮助页深处)、与拦截通知出现在同一渠道、支持无账号提交 只有通道可达,「被影响者能问为什么」才不是口号
可解释 给出判定所依据的规则类别与该内容命中的具体判据;若给不出与判定过程一致的理由,则不给理由、只给申诉入口 与判定无关的理由会让用户无法有效申诉、也无法学习规则(例 7.5.1 的 F3 就是这个失效模式)
可推翻 复核者有权覆盖模型输出,需要两种权限:模型侧复核权限(能重跑、能看该样本的特征与分数、能看到判定链路)与业务侧覆盖权限(能批准一次例外并留记录) 只有前者是「技术支持」,只有后者是「客服安抚」;两者都缺就是「不可推翻」
可聚合 记录结构化字段(决策类型、群体、申诉理由分类、处理时长、是否推翻),定期统计推翻率按群体的分布 个案无法证明系统性偏差;推翻率按群体分布本身就是极强的偏差探测器
(b) 为什么不能直接拿未经检验的归因图。 ① 归因默认是近似,其忠实性必须用扰动 / 单调性 / 消融独立验证,否则「解释」可能与该样本的真实决策依据无关;② 单样本解释没有统计意义,也推广不到用户的整类内容;③ 更危险的是自动化偏置——人对流畅、可视的解释有系统性过度信任,一个不忠实的解释会让人更容易被误导,比自己判断还糟(方法 7.3.4 的使用纪律 2)。可用替代:给出与判定一致的规则类别 ++ 可核对的判据,并把「解释读起来顺」与「解释是对的」分开对待。
(c) 指标与失败判据。 指标:通道可达性(通知到申诉的转化率、入口曝光率)、申诉量与处理量、推翻率(总体与按群体)、处理时长(中位数与 P95)、申诉原因分类分布。反直觉指标:申诉通道「太安静」通常不是好消息——若申诉量远低于预期,应先怀疑通道不可达、用户不知道它的存在、或答复成本高到没人愿意走完流程,而不是先庆祝「没有投诉」;因此要把可达性与处理量一起监控,两者都低时先查通道。失败判据:① 某群体推翻率相对整体显著抬升(例如 ≥50%\ge50\%)→ 触发对模型的重新评估与分群复盘,而不是逐个改判;② 处理时长 P95 超过承诺时限(如 >7\gt7 个自然日)→ 判为通道失效,先修产能与流程;③ 申诉量与拦截量之比低于预设下限而入口曝光正常 → 判为「用户在放弃」,需访谈并改进入口文案。
(d) 时限与升级路径:首次答复 ≤72\le72 小时;判定答复 ≤7\le7 个自然日;涉及不可逆后果(封号、永久删除、收益扣除)的申诉进优先队列并双人复核;二次申诉走独立复核人且不得由同一人复核;所有时限写进文档并纳入看板;升级路径必须写明「谁有权覆盖模型输出」的具名角色,而不是「相关团队」。
评分要点:四要件齐备且「可推翻」写出两种权限 4 分;「可解释」写明忠实性未检验的风险与自动化偏置 2 分;反直觉指标 2 分;时限与升级路径可执行、含优先队列与独立复核 2 分。