第 8 天日志:模型窃取与隐私泄露(一)成员推断攻击
| 项目 | 内容 |
|---|---|
| 模块 | 模块三 模型窃取与隐私泄露 |
| 进度 | 第 8 天 / 共 10 天 |
| 数据集 | MNIST |
| 模型 | MNISTCNN(目标 / 影子 / 攻击模型) |
一、任务目标
- 理解成员推断攻击(Membership Inference Attack, MIA)的概念与威胁模型;
- 掌握训练数据隐私泄露的形成机制(过拟合)及影子模型训练方法;
- 训练攻击模型判断样本是否属于训练集,报告准确率/精确率/召回率;
- 分析模型架构、训练策略(过拟合程度、正则化)对攻击成功率的影响;
- 实施差分隐私训练(DP-SGD)与置信度截断防御并验证。
二、实验原理
2.1 成员推断攻击
攻击者通过模型返回的置信度向量,判断某个样本是否在训练集中出现过
(成员=在训练集,非成员=不在)。威胁模型:攻击者只能查询模型输出,不能
访问模型参数或训练数据。
2.2 隐私泄露的形成机制:过拟合
模型对训练样本"记忆"得越多,成员样本的输出置信度/预测正确率系统性地高于
非成员样本------这个差异就是攻击信号。过拟合差距(train-test accuracy gap)
越大,成员与非成员的行为差异越大,攻击越容易成功。
2.3 影子模型(Shadow Model)
攻击者无法直接获取目标模型的训练/非训练样本标签,因此:
- 用与目标分布相似的影子训练集训练影子模型(模拟目标模型行为);
- 收集影子模型在"其训练集(成员)"与"其测试集(非成员)"上的输出特征;
- 用这些特征训练攻击模型(二分类:成员/非成员);
- 将攻击模型应用到目标模型的输出上。
2.4 攻击特征(有序统计量)
本实验使用有序置信度特征(而非按类别排列的原始向量):
- top-1 / top-2 / top-3 置信度
- softmax 熵
- 预测是否正确(correct 标志)
- top-1 与 top-2 的差值(margin)
有序统计量保证特征跨样本可比(例如"最大置信度"对所有样本都有意义,而
"类别 7 的置信度"对一张数字 3 的图无意义)。
2.5 隐私保护
- DP-SGD :逐样本梯度裁剪(L2 范数 ≤ C)+ 高斯噪声,提供 ε-差分隐私
保证;代价是模型效用下降; - 置信度截断:只返回 top-2 且四舍五入的置信度,破坏攻击特征的精度。
2.6 威胁模型的形式化与攻击者知识分级
成员推断攻击可形式化为一个假设检验问题:给定模型 fθf_\thetafθ 与样本 xxx,
判断 x∈Dtrainx \in \mathcal{D}{train}x∈Dtrain 还是 x∉Dtrainx \notin \mathcal{D}{train}x∈/Dtrain。
攻击者的"最优"决策依据是后验:
P(x∈Dtrain∣fθ(x)) P\big(x \in \mathcal{D}{train} \mid f\theta(x)\big) P(x∈Dtrain∣fθ(x))
由于模型对成员的输出(高置信度、低损失)系统性不同于非成员,该后验偏离
1/2,攻击得以成功。攻击者知识分为三个层级(Shokri et al., 2017):
| 层级 | 攻击者可访问信息 | 典型攻击 |
|---|---|---|
| 黑盒-仅标签 | 预测类别 | 阈值攻击(正确与否) |
| 黑盒-置信度 | softmax 向量 | 影子模型 + 攻击模型(本实验) |
| 白盒 | 参数/梯度/中间层 | 损失阈值、梯度范数攻击 |
本实验属于第二层级:只利用置信度向量,符合多数真实 API 场景。
2.7 过拟合与隐私泄露的理论联系
模型在训练样本上的记忆程度可用泛化差距刻画:
Gap(f)=Ex∼DtrainL(f(x),y)⏟训练损失−Ex∼DtestL(f(x),y)⏟测试损失 \mathrm{Gap}(f) = \underbrace{\mathbb{E}{x \sim \mathcal{D}{train}}\\mathcal{L}(f(x), y)}{\text{训练损失}} - \underbrace{\mathbb{E}{x \sim \mathcal{D}{test}}\\mathcal{L}(f(x), y)}{\text{测试损失}} Gap(f)=训练损失 Ex∼DtrainL(f(x),y)−测试损失 Ex∼DtestL(f(x),y)
泛化差距越大,意味着模型对训练样本的"记忆痕迹"越深------成员样本的损失
系统性低于非成员样本,形成可检测信号。直觉解释:
- 训练目标本质是压缩"训练集信息"到参数中;当数据量小、模型容量大、
训练轮数多时,模型把训练样本"逐条记住"(甚至可达到 100% 训练准确率),
而非只学习可迁移的模式; - 记忆的样本在输出上表现为异常高的置信度、异常低的损失 ------这就是
攻击模型要学习的特征模式。
本实验定量验证:全量训练时泛化差距 < 1.2%,MIA ≈ 50%(无信号);300
样本强过拟合时差距达 11.3%,MIA 升至 63.5%、召回率 85.3%。
2.8 攻击模型:迁移学习的视角
影子模型攻击的本质是迁移学习 :攻击模型在影子模型的输出特征上训练,
再应用于目标模型。其成立依赖一个假设:
Pshadow(输出特征∣成员)≈Ptarget(输出特征∣成员) P_{shadow}\big(\text{输出特征} \mid \text{成员}\big) \approx P_{target}\big(\text{输出特征} \mid \text{成员}\big) Pshadow(输出特征∣成员)≈Ptarget(输出特征∣成员)
即"成员身份在输出上留下的统计痕迹"在相似训练条件下跨模型一致。影子模型
与目标模型训练数据越接近、结构越相似,迁移越有效。攻击模型本身是一个
二分类器:
h:Rdfeat→{0,1},h(特征)=I成员 h: \mathbb{R}^{d_{feat}} \to \{0, 1\}, \quad h(\text{特征}) = \mathbb{I}\\text{成员} h:Rdfeat→{0,1},h(特征)=I成员
特征工程(有序统计量而非原始类别向量)保证 PshadowP_{shadow}Pshadow 与 PtargetP_{target}Ptarget
的特征分布"对齐"------这是本实验从 ~50% 提升到 65.8% 的关键。
2.9 差分隐私原理
差分隐私(Dwork et al., 2006)提供可证明 的隐私保证。算法 A\mathcal{A}A
满足 (ε,δ)(\varepsilon, \delta)(ε,δ)-差分隐私,若对任意相邻数据集 D,D′D, D'D,D′
(差一个样本)与任意输出集合 SSS:
PA(D)∈S≤eε⋅PA(D′)∈S+δ P\\mathcal{A}(D) \\in S \le e^{\varepsilon} \cdot P\\mathcal{A}(D') \\in S + \delta PA(D)∈S≤eε⋅PA(D′)∈S+δ
直观含义:删除或篡改任意一个训练样本,模型输出的分布几乎不变 ------
因此攻击者无法从输出判断某个样本是否在训练集里。ε 越小隐私越强。
DP-SGD 是实现差分隐私训练的机制:
- 逐样本梯度裁剪 :把每个样本的梯度限制在范数 C 内
g~i=gi/max(1,∥gi∥2/C)\tilde{g}_i = g_i / \max(1, \|g_i\|_2 / C)g~i=gi/max(1,∥gi∥2/C)------限制"单个样本的影响力"; - 高斯噪声注入 :g^=1B(∑ig~i+N(0,σ2C2I))\hat{g} = \frac{1}{B}\big(\sum_i \tilde{g}_i + \mathcal{N}(0, \sigma^2 C^2 I)\big)g^=B1(∑ig~i+N(0,σ2C2I)),用噪声掩盖任何单样本的贡献;
- 组合定理 :T 轮训练后隐私预算按轮次累积,最终保证
(ε,δ)(\varepsilon, \delta)(ε,δ)-DP(常用矩会计法精确计算)。
DP 的代价是模型效用下降(本实验强隐私配置下验证准确率崩到 11.7%):
噪声直接污染了梯度,等于用"信息量"换"隐私"。实际部署需要在
隐私预算 ε、模型效用、训练样本量三者之间权衡。
2.10 输出混淆的信息论视角
隐私防御可以统一看作降低输出与训练集之间的互信息:
I(fθ(x);Dtrain) I\big(f_\theta(x); \mathcal{D}_{train}\big) I(fθ(x);Dtrain)
置信度截断/加噪让攻击者可获得的特征 y′=Ψ(fθ(x))y' = \Psi(f_\theta(x))y′=Ψ(fθ(x)) 变成原输出的
有损版本,从而 I(y′;Dtrain)<I(fθ(x);Dtrain)I(y'; \mathcal{D}{train}) < I(f\theta(x); \mathcal{D}_{train})I(y′;Dtrain)<I(fθ(x);Dtrain):
- top-2 截断:把多数类别的置信度置零,删除"长尾"中携带的成员痕迹;
- 量化(四舍五入) :把连续置信度离散化,使成员/非成员的精细差异被
舍入抹平(本实验中成员与非成员 top-1 仅差 ~0.1,量化后难以区分)。
本实验截断后 MIA 从 63.5% 降到 48.3%(低于随机猜测),而模型效用不变
(90.07%)------说明输出层混淆是"低代价高收益"的隐私防御。
2.11 实现要点与可复用代码
python
# ① 攻击特征:★ 必须用"有序统计量",不能用按类别排列的原始 softmax
conf = model(x).softmax(1)
top3, _ = conf.topk(3, dim=1) # 前三大置信度
entropy = -(conf * conf.clamp_min(1e-9).log()).sum(1, keepdim=True)
correct = (conf.argmax(1) == y).float().unsqueeze(1) # 是否预测正确
margin = (top3[:, 0] - top3[:, 1]).unsqueeze(1) # top1-top2 差
features = torch.cat([top3, entropy, correct, margin], dim=1) # 6 维,跨样本可比
# ② 影子模型流程:用"影子训练集/非训练集"构造成员/非成员样本
shadow = train(cnn, shadow_train_x, shadow_train_y)
feats_s, labels_s = collect_features(shadow, shadow_train_x, shadow_train_y, # 成员=1
shadow_holdout_x, shadow_holdout_y) # 非成员=0
attack_model, _ = train_binary_mlp(feats_s, labels_s) # 攻击模型
feats_t, labels_t = collect_features(target, target_train_x, ..., target_test_x, ...)
mia_acc = (attack_model(feats_t).argmax(1) == labels_t).float().mean()
# ③ DP-SGD 三步(★ 噪声尺度与裁剪粒度最容易写错)
# ① 逐样本裁剪
g_i = flatten(grad(loss_i)) # 单样本梯度
scale = min(1.0, C / (g_i.norm() + 1e-9)); g_i_clip = g_i * scale
# ② 批量平均
g_avg = torch.stack(g_list).mean(0)
# ③ 加噪:标准差 = clip × noise_mult / batch_size
g_noisy = g_avg + torch.randn_like(g_avg) * (C * sigma / B)
params -= lr * g_noisy
# ④ 输出混淆:只返回 top-2 置信度并四舍五入(破坏精细特征)
top2 = conf.topk(2, dim=1)
conf_out = torch.zeros_like(conf)
conf_out.scatter_(1, top2.indices, top2.values.round(decimals=2))
2.12 常见误解、纠正与自测题
常见误解
- "MIA 成功率高说明模型不安全" → 需结合场景:本实验全量训练时 MIA
仅 50%(无信号),强过拟合才到 63.5%。风险由过拟合程度决定。 - "用原始 softmax 向量做特征就行" → 类别排列的方式使特征跨样本不可比,
实测逻辑回归 5 折仅 49.3%;改有序统计量后升到 65.8%。 - "攻击模型越复杂越好" → 特征工程比模型复杂度更关键(6 维特征 + 小型
MLP 即达 65.8%)。 - "DP-SGD 免费获得隐私" → 强隐私配置下模型效用崩到 11.7%;
必须报告"隐私-效用"两端。 - "置信度截断会损害业务" → 实测模型效用完全不变(90.07%)而 MIA 从
63.5% 降到 48.3%,是性价比最高的隐私防御。 - "影子模型必须与目标同结构" → 关键是行为分布相似;同结构更稳妥,
但攻击模型本身对结构差异有一定容忍度。
自测题(附答案要点)
- MIA 的攻击信号来自哪里?
要点 :模型对训练样本的"记忆"------成员样本系统性表现为高置信度、
低损失、预测更可能正确,即泛化差距在样本级的表现。 - 为什么要用有序统计量而不是原始 softmax?
要点 :原始向量按类别排列,同一分量对不同样本含义不同;排序后
(top-k、熵、margin)特征在样本间可比。 - 写出 (ε,δ)(\varepsilon,\delta)(ε,δ)-差分隐私的定义,并解释 ε 的含义。
要点 :PA(D)∈S≤eεPA(D′)∈S+δP\\mathcal{A}(D)\\in S\le e^{\varepsilon}P\\mathcal{A}(D')\\in S +\deltaPA(D)∈S≤eεPA(D′)∈S+δ;ε 越小,单个样本对输出的影响越小。 - DP-SGD 的三个步骤是什么?噪声标准差如何确定?
要点 :逐样本裁剪到 C → 批量平均 → 加高斯噪声;标准差
σC/B\sigma C/BσC/B(σ 为噪声乘子、B 为批大小)。 - 为什么置信度截断能降低 MIA 而不损失效用?
要点 :它降低了输出与训练集之间的互信息(抹掉 top-2/3 的精细差异),
但保留了 top-1 所需的分类信息,因此业务不受影响。 - 若在真实系统中只能做一件事降低隐私风险,你会做什么?
要点 :限制输出信息量(截断/加噪),因为成本最低、对效用影响最小且
直接切断攻击特征;其次才是训练侧手段(正则化、DP-SGD)。
三、实验结果
3.1 全量训练场景(主实验)
目标模型:25 epochs、无 dropout,训练集准确率 100%、测试集 99.34%
(过拟合差距仅 0.66%)。
| 目标模型配置 | 过拟合差距 | MIA 准确率 |
|---|---|---|
| 8 epochs + dropout | 0.94% | 49.55% |
| 25 epochs + dropout | 0.86% | 49.55% |
| 25 epochs 无 dropout | 1.12% | 49.70% |
| 25 epochs 强 L2 | 0.62% | 50.10% |
| 25 epochs 无 dropout(目标) | 0.66% | 50.34% |
结论 :MNIST 全量训练下模型几乎不过拟合,成员与非成员的置信度差异极
小,MIA 成功率接近随机(~50%)。这本身就是一个重要发现:数据量充足、
类别可分性强的场景,成员推断攻击的自然风险很低。
3.2 强过拟合场景(补充实验,隐私泄露演示)
目标模型:300 个训练样本、60 epochs、无 dropout ------ 强制模型记忆训练集
(训练集准确率 100%,非成员准确率 88.67%,差距 11.3%)。
| 指标 | 数值 |
|---|---|
| 影子阶段攻击准确率 | 65.83% |
| 目标 MIA 准确率 | 63.50% |
| 精确率 | 59.40% |
| 召回率 | 85.33% |
攻击成功识别出 85% 的训练成员,证明"过拟合 = 隐私泄露"的机制:模型记住
的样本在输出上留下可检测的痕迹。
3.3 隐私保护效果(强过拟合场景)
| 防御 | MIA 准确率 | 模型效用(验证准确率) |
|---|---|---|
| 无防御 | 63.50% | 90.07% |
| 置信度截断(top-2 + 2 位小数) | 48.33% | 90.07% |
| DP-SGD(裁剪 1.0,噪声 0.1) | 50.00% | 11.67%(效用大幅损失) |
四、结果分析与讨论
4.1 过拟合与隐私泄露的正相关
- 主实验中四种训练配置的过拟合差距都 < 1.2%,MIA 全部 ~50%(随机);
- 强过拟合场景(差距 11.3%)下 MIA 提升到 63.5%、召回率 85.3%;
- 这定量验证了"过拟合程度是成员推断攻击成功率的主要驱动因素"。
4.2 攻击特征工程的重要性
初版实现直接使用 10 维原始 softmax,攻击模型在影子阶段只有 ~50%(类别
顺序不对齐,特征不可比);改为有序统计量(top-3 + 熵 + correct + margin)
后影子阶段达到 65.8%。特征工程是 MIA 成败的关键。
4.3 防御效果
- 置信度截断 是最"便宜"的有效防御:把 MIA 从 63.5% 压到 48.3%(低于
随机),且模型效用完全不变(90.07%)------输出混淆破坏了攻击特征中
top-2/top-3 的精细信息; - DP-SGD 也能把 MIA 压到 50%,但代价是模型效用崩到 11.67%------隐私与
效用存在根本性权衡,需要谨慎选择噪声强度与训练预算(本实验的噪声/裁剪
配置偏保守)。
4.4 隐私风险评估
对本课程场景(MNIST + CNN):
- 若模型正常训练(充分数据 + 正则化),成员推断风险低(~50%);
- 若模型在少量数据上过拟合(如小团队、小样本领域),隐私泄露风险显著
(63.5%,召回率 85%); - 生产系统应:限制置信度输出精度(截断/扰动)、监控过拟合程度、必要时
采用 DP-SGD(并接受其效用成本)。
4.5 与实验结果的对应
| 原理 | 实验对应 |
|---|---|
| 泛化差距驱动攻击 | 差距 0.7--1.1% → MIA ~50%;差距 11.3% → MIA 63.5% |
| 特征坐标系对齐 | 原始 softmax ~50% → 有序特征 65.8% |
| DP 隐私-效用权衡 | MIA 50% 但模型效用 11.7% |
| 输出混淆降互信息 | MIA 48.3%,效用保持 90.07% |
4.6 理论预测 vs 实测数据
| 理论预测 | 实测结果 | 是否吻合 |
|---|---|---|
| 泛化差距越大,MIA 越容易 | 差距 0.7%/1.1% → MIA 50.1%/50.3%;差距 11.3% → MIA 63.5% | ✅ |
| 足够过拟合时攻击应显著优于随机 | 强过拟合场景:MIA 63.5%、精确率 59.4%、召回率 85.3% | ✅ |
| 有序特征比原始 softmax 更有效 | 原始 softmax(逻辑回归 5 折)49.3% → 有序特征影子阶段 65.8% | ✅ |
| 置信度截断应降低 MIA 且不损效用 | MIA 63.5% → 48.3%(低于随机),模型效用不变(90.07%) | ✅ |
| DP-SGD 降低 MIA 但损失效用 | MIA → 50.0%,但模型验证准确率仅 11.7%(强隐私配置) | ✅ |
隐私风险三档实测(可直接引用)
| 场景 | 泛化差距 | MIA 准确率 | 风险判断 |
|---|---|---|---|
| 全量数据 + 正则化 | 0.7%--1.2% | ~50%(随机) | 低 |
| 2000 样本 + 40 轮 | 3.0% | 53.6% | 中 |
| 300 样本 + 60 轮(无正则) | 11.3% | 63.5% | 高 |
五、试错与调试记录
5.1 问题速览
| # | 问题 | 类型 | 影响 | 解决方式 |
|---|---|---|---|---|
| 1 | 原始 softmax 特征不可比 | 特征工程 | 攻击准确率仅 ~50% | 改用有序统计量特征 |
| 2 | 全量训练几乎不过拟合 | 实验设计 | MIA 无信号 | 补充强过拟合场景 |
| 3 | 手写 DP-SGD 噪声/裁剪错误 | 代码 | 模型完全学不会 | 逐样本裁剪 + 正确噪声尺度 |
| 4 | 小样本场景仍无信号(差距 3%) | 实验设计 | 攻击效果弱 | 进一步缩小数据量至 300 |
5.2 问题 1:原始 softmax 特征不可比,攻击模型退化到随机水平
现象
首版成员推断攻击使用 10 维 softmax 向量 + 预测正确标志作为特征,
训练出的攻击模型在影子阶段 (最理想条件)准确率只有
49.2%--52.8%,接近随机猜测;应用于目标模型后 MIA 仅 50.34%。
定位过程
- 先诊断特征是否可分:打印成员/非成员样本的注意力统计量,发现
"最大置信度"成员 0.965 vs 非成员 0.865,信号确实存在; - 但用逻辑回归在原始 softmax 特征上做 5 折交叉验证只有 49.3%;
- 关键发现:原始 softmax 是按类别排列 的向量------对一张"3"的图,
"类别 7 的置信度"是无意义的分量;不同样本的同类分量对应不同含义,
特征空间在样本之间不可比。
根本原因
特征表示与任务不匹配:攻击需要的是"该样本被如何对待"的有序统计量 ,
而原始向量把信息按类别打散了。
解决方案
改用 Shokri 等经典攻击的有序特征(6 维):
| 特征 | 含义 |
|---|---|
| top-1 / top-2 / top-3 置信度 | 排序后的置信度水平 |
| softmax 熵 | 输出分布的不确定度 |
| 预测是否正确 | 硬指标 |
| top1 − top2 差值 | 决策的"自信余量" |
修改后影子阶段攻击准确率升至 65.83% ,目标 MIA 达 63.5% (召回率
85.3%)。
为什么这样解决
有序统计量对所有样本含义一致("最大置信度"永远表示"模型最确信的类别"),
使攻击模型能够在跨样本的特征分布上学习;同时保留了成员身份最有判别力的
信息(置信度水平 + 正确性)。
可积累的经验
- 特征工程是隐私攻击成败的关键,特征必须在样本间可比;
- 排查"分类器学不到东西"时,先做"特征是否可分"的独立验证
(本例用逻辑回归 + 交叉验证快速定位); - 类别相关的向量在使用前应先做"有序化/聚合"处理。
对本项目的作用
这是第 8 天最关键的一次修正:它把"攻击无效"从"数据集太难"区分出来,
证明是特征设计问题而非任务不可行 。该经验也被第 9 天继承(模型提取
用 KL 软标签、反演用 logit 而非 softmax,都是同一思路)。
5.3 问题 2:全量训练几乎不过拟合,成员推断没有信号
现象
主实验中四种训练配置(8 轮/25 轮、有无 Dropout、强弱 L2)的
"训练集-测试集准确率差距"都只有 0.6%--1.2% ,MIA 全部为 49.6%--50.3%
(随机水平),看起来"攻击完全没有效果"。
定位过程
- 确认攻击实现无误(问题 1 修复后影子阶段已有 65.8% 的能力);
- 分析数据:MNIST 类别可分性强、训练样本 57000 张,即使 25 轮无 Dropout,
测试准确率仍有 99.34%------模型"泛化太好,没什么可泄露的"; - 结论:不是攻击失效,而是场景本身没有可观测的隐私泄露信号。
根本原因
成员推断的攻击信号来自"模型对训练样本的记忆",而全量训练下 MNIST 模型
几乎不记忆------泛化差距 <1.2%。
解决方案
增设强过拟合场景 :只用 300 个训练样本、60 轮、无 Dropout,
强制模型记忆训练集(训练准确率 100%,非成员 88.67%,差距 11.3% )。
此时 MIA 达到 63.5%(精确率 59.4%、召回率 85.3%)。
为什么这样解决
- 用一个受控极端场景展示"过拟合 → 隐私泄露"的因果链;
- 同时保留主实验结果,形成对照:"泛化好 → 风险低",两者共同构成完整的
隐私风险评估,而不是只给出"攻击失败"。
可积累的经验
- 攻击"无效"时,先区分"实现错误"与"场景无信号";
- 用受控极端场景展示机制,用真实场景评估风险,二者互补;
- 泛化差距(train-test gap)是隐私风险的直接量化指标。
对本项目的作用
该设计使第 8 天同时给出"低风险(正常训练)"与"高风险(强过拟合)"两种
结论,并与第 9 天的模型提取(查询即泄露)形成互补,构成了第 9--10 天
"隐私风险评估"的完整证据链。
5.4 问题 3:手写 DP-SGD 噪声与裁剪错误,模型完全学不会
现象
首版手写 DP-SGD 训练 12 轮后验证准确率仅 21%--30% ,远低于正常训练的
99%;且不同随机种子下结果在 11%--40% 间大幅波动,说明训练基本失败。
定位过程
-
检查噪声尺度:
pythonstd = clip * noise_mult / (len(grads) / 8) # ≈ 1.0当噪声标准差与梯度本身量级相当时,梯度信号被完全掩盖;
-
检查裁剪对象:代码把一组 8 个样本的平均梯度 裁剪到范数 1,
而不是对每个样本 分别裁剪------这既不符合 DP-SGD 定义(灵敏度按
单样本计算),也无法控制单样本影响;
-
对照标准算法:DP-SGD 应为"逐样本裁剪 → 批量平均 → 加
N(0,σ2C2/B2)\mathcal{N}(0, \sigma^2C^2/B^2)N(0,σ2C2/B2) 噪声"。
根本原因
两处实现偏差:噪声尺度公式错误(分母含义搞错)、裁剪粒度错误
(组平均 vs 单样本)。
解决方案
重写为标准的逐样本 DP-SGD:
- 对 batch 内每个样本单独计算梯度,裁剪到 ∥gi∥2≤C\|g_i\|_2 \le C∥gi∥2≤C;
- 对裁剪后的梯度求平均;
- 加入标准差为 σC/B\sigma C / BσC/B 的高斯噪声;
- 用扰动梯度更新参数。
修正后模型恢复学习(准确率曲线正常上升),在强隐私配置下最终准确率
11.67%------虽然效用低,但这是真实的隐私-效用权衡结果(而非实现错误)。
为什么这样解决
- 逐样本裁剪 + 按批次规模缩放噪声,才符合 DP 的形式化定义(灵敏度);
- 保留"效用下降"的真实结果并解释为隐私预算的代价,比把噪声调小以
"让曲线好看"更有价值。
可积累的经验
- 实现差分隐私类算法时,先写清"灵敏度 → 裁剪 → 噪声尺度"三步公式,
再写代码;噪声尺度是最容易写错的地方; - 隐私机制的效果必须成对报告:隐私指标(MIA/ε)与模型效用;
- 训练曲线异常(准确率远低于常规)时,噪声/学习率/裁剪是首要排查对象。
对本项目的作用
修正后第 8 天给出了 DP-SGD 的真实代价(MIA 降到 50% 但效用严重受损),
与"置信度截断"(MIA 48.3% 且效用不变)形成鲜明对比,直接支撑了
"输出层混淆是性价比最高的隐私防御"这一结论。
5.5 问题 4:数据量减少到 2000 仍然信号不足
现象
补充实验先用 2000 个训练样本、40 轮训练,泛化差距仅 3.0%,MIA 仍只有
53.6%,攻击效果不明显。
定位过程
- 计算差距:成员 100% vs 非成员 97%,差距 3%;
- 对照 2D 领域的经验:只有当成员与非成员的输出分布明显分离 时,
攻击才能稳定判别;3% 的准确率差距在 10 类任务上对应的置信度差异有限; - 于是继续缩小数据量并增加轮数,直到差距扩大到 10% 以上。
根本原因
记忆强度不足(数据量仍偏大):2000 张样本对于 MNIST 的 CNN 仍属"够用"。
解决方案
进一步调整到 300 个训练样本 + 60 轮 ,泛化差距扩大到 11.3% ,
MIA 提升到 63.5%,攻击效果稳定可复现。
为什么这样解决
隐私泄露的"水量"由记忆强度决定,需要把实验调到信号可观测 的区间;
该调整同时明确写入了日志,说明这是"为展示机制而设计的极端场景",
不代表正常训练场景的风险水平。
可积累的经验
- 敏感性实验要找到"信号可观测"的参数区间(本例:样本量 300 vs 2000);
- 极端场景的结论要标注适用条件,避免被误读为普遍风险;
- 参数扫描(样本量/轮数)比一次性设定更容易找到有效区间。
对本项目的作用
该参数选择使第 8 天最终得到清晰的正结果,也为第 10 天总结报告中的
"隐私风险随过拟合程度变化"提供了三点数据(差距 0.7%/3.0%/11.3% →
MIA 50%/53.6%/63.5%)。
5.6 复现与验证速查
复现问题 1:先用逻辑回归验证"特征是否可分"
python
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
# ✗ 原始 softmax(按类别排列)+ correct 标志 → 跨样本不可比
X_raw = np.concatenate([softmax_member, softmax_nonmember]) # 11 维
print("原始特征 5 折 CV:", cross_val_score(LogisticRegression(max_iter=1000),
X_raw, y, cv=5).mean()) # → 0.493
# ✓ 有序统计量:top3 + 熵 + correct + margin
top3, _ = conf.topk(3, dim=1)
X_ordered = torch.cat([top3, entropy, correct, margin], dim=1) # 6 维
print("有序特征 5 折 CV:", cross_val_score(LogisticRegression(max_iter=1000),
X_ordered.numpy(), y, cv=5).mean())
判读 :特征不可分(≈0.49)时,不要急着换攻击模型------先修特征。
换有序特征后影子阶段攻击准确率从 49.2% 升到 65.83%。
复现问题 2:过拟合差距与 MIA 的对照扫描
python
for n_samples, epochs in [(57000, 8), (2000, 40), (300, 60)]:
model = train_cnn(train_x[:n_samples], train_y[:n_samples], epochs=epochs,
dropout=(n_samples > 1000))
gap = (acc(model, train_x[:n_samples], train_y[:n_samples])
- acc(model, test_x, test_y))
mia = run_mia(
model,
members=(train_x[:n_samples], train_y[:n_samples]),
nonmembers=(train_x[n_samples:2 * n_samples], train_y[n_samples:2 * n_samples]))
print(f"n={n_samples} epochs={epochs} gap={gap*100:.1f}% MIA={mia*100:.1f}%")
| 数据量 / 轮数 | 泛化差距 | MIA 准确率 | 说明 |
|---|---|---|---|
| 57000 / 8(含正则) | 0.9% | 49.6% | 无信号 |
| 57000 / 25(无 Dropout) | 1.1% | 49.7% | 无信号 |
| 2000 / 40 | 3.0% | 53.6% | 信号弱 |
| 300 / 60(无 Dropout) | 11.3% | 63.5% | 信号显著 |
判读:MIA 的"燃料"是过拟合;数据量足够大时,攻击无法凭空造出信号。
复现问题 3:DP-SGD 的噪声尺度自检
python
# ✗ 错误公式:把"子批次数"当成了批大小
std_wrong = clip * noise_mult / (len(grads) / 8) # 1.0 * 1.0 / 1 = 1.0
# ✓ 正确公式:标准差 = C·σ / B
std_ok = clip * sigma / batch_size # 1.0 * 0.1 / 32 = 0.0031
# 训练时打印"噪声 / 梯度"量级比,判断是否把信号淹没
print(f"噪声std={std_ok:.4f} 梯度范数={g_avg.norm():.4f} 比值={std_ok/g_avg.norm():.2f}")
判读经验 :噪声标准差与梯度同量级(比值 ≈ 1)时训练必然停滞
(本实验错误版本准确率仅 11%--30%);比值在 0.01--0.1 量级时仍可训练。
复现问题 4:样本量扫描找"信号可观测区间"
| 数据量 | 轮数 | 成员准确率 | 非成员准确率 | 差距 | MIA |
|---|---|---|---|---|---|
| 2000 | 40 | 100.0% | 97.0% | 3.0% | 53.6% |
| 300 | 60 | 100.0% | 88.7% | 11.3% | 63.5% |
判读 :差距 <5% 时攻击收益有限;>10% 时攻击稳定有效。做隐私评估时应
报告"差距---MIA"曲线,而不是单点。
本日排错速查
python
cross_val_score(LogisticRegression(), X_feats, y, cv=5).mean() # ① 特征是否可分
gap = acc_train - acc_test # ② 过拟合差距
print(std_noise / g_avg.norm()) # ③ 噪声/梯度量级比
六、经验提炼
6.1 知识收获与心得
- 成员推断攻击的根源是"模型记忆":过拟合差距是隐私泄露的量化指标;
- 攻击成功与否高度依赖特征工程与影子模型对目标行为的模拟质量;
- 置信度截断是性价比最高的隐私防御(MIA 48.3%,效用不变);
- DP-SGD 提供可证明的隐私保证,但隐私-效用权衡是工程上的核心挑战;
- 隐私风险评估必须结合具体场景(数据量、过拟合程度、输出接口)。
6.2 工程与排错经验
- 特征可比性优先:类别相关的原始向量先做有序化,再喂给攻击模型;
- 区分"实现错误"与"场景无信号":前者修代码,后者换场景;
- 受控极端场景用来展示机制,真实场景用来评估风险,二者都要报告;
- DP 三步公式:灵敏度 → 裁剪 → 噪声尺度,写清再写码;
- 隐私与效用必须成对报告,否则结论没有工程意义。