第 10 天:设计总结报告
| 项目 | 内容 |
|---|---|
| 模块 | 模块四 综合(设计总结) |
| 进度 | 第 10 天 / 共 10 天 |
| 覆盖范围 | 数据投毒(第 1--3 天)、对抗样本(第 4--7 天)、模型窃取与隐私泄露(第 8--9 天) |
一、设计总览
本次设计以 MNIST 图像分类任务 + CNN 为统一载体,系统完成了信息对抗领域四大攻击面、10 组实验:
| 模块 | 天 | 主题 | 核心成果 |
|---|---|---|---|
| 数据投毒 | 1 | 标签翻转投毒 | 随机/定向翻转、损失检测防御 |
| 2 | 后门攻击 | 触发器设计、Neural Cleanse 检测、微调消除 | |
| 3 | 清洁标签投毒 | 特征碰撞/梯度匹配、影响函数、综合防御 | |
| 对抗样本 | 4 | FGSM/PGD | 白盒攻击、对抗训练 |
| 5 | 黑盒迁移攻击 | 替代模型迁移、NES 查询攻击、集成防御 | |
| 6 | C&W/UAP/贴片 | 优化攻击、通用扰动、物理世界攻击、认证防御 | |
| 7 | 对抗训练 | PGD-AT、TRADES、权衡曲线、自适应攻击 | |
| 模型窃取与隐私 | 8 | 成员推断 | 影子模型、攻击模型、DP-SGD、置信度截断 |
| 9 | 反演与提取 | 模型提取、模型反演、水印、安全服务 | |
| 综合 | 10 | 总结 | 报告 |
二、四大模块核心原理回顾
2.1 数据投毒(第 1--3 天)
共同本质 :攻击发生在训练阶段,通过污染训练数据影响最终模型。三天的
攻击"隐蔽性"递进:
- 标签翻转:改标签不改像素 → 损失统计极易检测(AUC=0.9998);
- 后门攻击:改标签 + 加触发器 → 正常输入性能不变,需触发器反向工程检测;
- 清洁标签投毒:不改标签 + 不可感知扰动 → 损失、影响函数都无法定位。
关键定量结论:
| 攻击 | 效果 | 隐蔽性 | 检测难度 |
|---|---|---|---|
| 随机标签翻转 20% | 准确率 99.15%→98.88% | 低 | 低(损失检测) |
| 定向标签翻转 3→7 | 类别 3 误判率 0.5% | 中 | 中 |
| 后门(固定触发器) | ASR=100%,干净性能不变 | 高 | 中(NC 检测) |
| 清洁标签(FC/GM) | 难目标翻转 75--100% | 很高 | 高(无法定位) |
2.2 对抗样本(第 4--7 天)
共同本质:攻击发生在推理阶段,利用梯度构造微小扰动。攻击强度谱系:
FGSM(单步) < PGD(迭代) < C&W(优化) < 迁移/查询(黑盒)
关键定量结论:
- ε=0.3 时:FGSM 35.6%、PGD 97.7%、C&W 100%(且扰动更小:L2=4.23 vs 7.15);
- 迁移攻击:白盒 98% → 迁移最高 12.4%(MNIST 迁移性弱);
- 查询攻击:6 万次查询仅 8.3%;
- 对抗训练:鲁棒准确率 86.6% → 97.8%,但 C&W 仍可攻破(95--100%),
TRADES β=3 对 C&W 最鲁棒(12%); - 认证防御(去噪+平滑):PGD ASR 95.5% → 37%。
2.3 模型窃取与隐私泄露(第 8--9 天)
共同本质:模型输出即信息泄露。三个层面:
- 成员推断(输出推断训练集成员):过拟合差距驱动,强过拟合下 MIA 63.5%、
召回率 85.3%;置信度截断可压到 48.3%; - 模型提取(输出复制模型):1 万次查询即可复制 99% 行为一致的模型;
- 模型反演(输出恢复训练数据):反演图像与类原型相似度最高 0.64,
泄露类别级特征。
三、攻防对照总表
| 攻击 | 最佳成功率 | 所需资源 | 最有效防御 | 防御后效果 |
|---|---|---|---|---|
| 标签翻转投毒 | 准确率 -0.27% | 篡改数据 | 损失检测 + 清洗 | 恢复至 -0.11% |
| 后门攻击 | ASR=100% | 训练集注入 | 微调/审计清洗 | ASR→9.5--10.8% |
| 清洁标签投毒 | 目标翻转 100% | 特征优化 | 数据来源治理 | 难防 |
| FGSM/PGD | 97.7%(ε=0.3) | 白盒梯度 | 对抗训练 | 鲁棒 97.8% |
| 黑盒迁移 | 12.4% | 代理模型 | 集成/对抗训练 | 1.1% |
| 查询攻击 | 8.3% | 6 万查询 | 查询限制 | 成本不可承受 |
| C&W | 100% | 白盒优化 | TRADES | 12% |
| 成员推断 | 63.5% | 影子模型 | 置信度截断 | 48.3% |
| 模型提取 | 99.06% 一致率 | 1 万查询 | 输出扰动+限流 | -1.6--2.5% |
| 模型反演 | 相似度 0.64 | 白盒/梯度 | 梯度防御 | 中等 |
四、工程实践与可复现性
4.1 工程框架
- 统一实验环境:Python 3.10 + PyTorch 2.13(CPU)+ scikit-learn + Matplotlib;
- 共享工具包
common/:数据加载、模型、训练评估、对抗攻击函数; - 固定随机种子,可复现;脚本支持断点续跑(模型缓存)。
五、综合认识与反思
5.1 对 AI 安全的整体认识
- 攻击面贯穿全生命周期:数据(投毒)→ 模型(对抗/窃取)→ 部署(查询/反演),任何一环都可能被利用;
- 安全与性能存在本质权衡:对抗训练牺牲少量清洁精度换取鲁棒性;DP-SGD 大幅牺牲效用换取隐私;防御设计是"可接受的代价"决策;
- 单一防御必然失效:损失检测防不了清洁标签,PGD-AT 防不了 C&W,输出限制防不了蒸馏------必须分层组合(数据审计、模型鲁棒、运行时限制、事后溯源);
- 评估必须自适应:防御有效性要用"针对该防御设计的攻击"检验,否则会高估安全性(第 7 天 C&W 攻破 PGD-AT 即为明证)。
5.2 数据集依赖的局限
MNIST 类别可分性强、样本充足,导致部分攻击效果弱于真实场景(清洁标签、迁移攻击、成员推断),而模型提取、后门等攻击效果显著。报告中均如实记录
并分析原因;在更复杂数据集(CIFAR-10/ImageNet)上这些攻击通常更强。
5.3 后续研究方向
- 在 CIFAR-10/ImageNet 上复现并对比攻击强度;
- 采用 AutoAttack 等标准化攻击套件做更严格的鲁棒性评估;
- 实现联邦学习场景下的投毒与隐私攻击;
- 研究大语言模型(LLM)的投毒、越狱与隐私泄露;
- 探索可证明的防御(认证鲁棒性、DP 保证)与攻击的对抗演进。
六、试错经验总结(44 条问题 → 方法论与规范)
6.1 问题分布总览
| 类别 | 数量 | 典型例子 | 主要发生日 |
|---|---|---|---|
| 环境与依赖 | 2 | PyTorch 索引源用法、缺 skimage | 第 1、3 天 |
| 工程流程 | 7 | 残留进程抢 CPU、缺续跑、绘图与训练耦合 | 第 1、2、4、5、7 天 |
| 代码语义 | 15 | 广播、索引语义、张量维度、梯度上下文、KL 方向 | 第 1--4、6--8 天 |
| 算法设计 | 3 | Neural Cleanse 超参、UAP 目标函数、反演缺先验 | 第 2、6、9 天 |
| 实验设计 | 14 | 攻击方向、剂量、参数区间、对照组、场景信号 | 第 1--3、5、6、8、9 天 |
| 结论表述 | 3 | 非单调结果、随机波动、防御成本框架 | 第 5、9 天 |
观察 :代码语义类问题最多(15 条),且高度重复(张量维度出现 5 次、
梯度上下文出现 3 次);实验设计类次之(14 条),且往往是"结论是否有
信息量"的决定因素。这两类是本项目最值得沉淀的部分。
6.2 七条可复用方法论
1. 机制优先于调参(第 3 天)
清洁标签攻击连续 6 种配置 0% 成功率,根因是攻击方向理解错误 ,不是
参数不足。修正配方后立刻达到 75%--100%。
方法:连续 3 次以上调参无效 → 停止加预算,回到"方法假设"层面复核。
对本项目的价值 :把"靠算力试错"改为"靠机制定位",第 5、7 天遇到
效果异常时都先做机制复核,避免了多轮无效训练。
2. 先最小验证,再全量运行(第 2、7、8 天)
- Neural Cleanse:先用 2 个类别(约 1 分钟)验证掩码是否收敛,再跑 4 个
模型 × 10 类; - TRADES:先在单模型上暴露 KL 方向错误,避免 6 个模型全部训错;
- DP-SGD:先单次训练观察曲线,再决定参数。
方法 :任何耗时 >10 分钟的批量实验,先用"单个样本/单个类别/单个模型"
验证实现正确性。
3. 计算与呈现解耦 + 增量保存 + 幂等续跑(第 1、2、4、5、7 天)
三件套:
① 结果/权重落盘 torch.save / json.dump
② 增量保存 循环内每完成一个单元就写一次
③ 幂等续跑 存在即加载,不存在才训练(打印 [RESUME])
对本项目的价值 :第 7 天修复配置后仅重跑评估(4.5 分钟)而非重训
(70 分钟);本项目累计 60+ 次模型训练,该机制节省的机时以小时计。
4. 对照组只改变一个变量(第 9 天)
水印验证最初用"随机权重模型"作对照,得到 80.5% 的伪响应;改用"干净训练模型"后为 0.00%,结论才成立。
方法:设计对照时自问"我到底改变了哪个变量?";出现"对照组也异常有效"时,第一个怀疑对象应是自己选的对照组。
5. 区分四类"效果不好"(贯穿第 3、5、6、8 天)
| 现象 | 真实原因 | 处置 |
|---|---|---|
| 实现错误 | 代码语义/梯度/形状问题 | 修代码 |
| 剂量不足 | 攻击强度低于有效区间 | 提高强度或扩大参数区间 |
| 场景无信号 | 数据集/模型本身不具备该脆弱性 | 换受控场景并说明适用条件 |
| 参数不匹配 | 认证半径 < 攻击预算、β 与轮数不匹配 | 调整参数或如实报告限制 |
对本项目的价值:避免把"MNIST 抗性强"误判为"实现错误",也避免把"实现错误"包装成"数据特性"。
6. 结论用趋势与区间表述(第 5、9 天)
- NES 攻击"查询更多反而略差"→ 不隐藏,解释为零阶估计方差 + 小样本波动;
- 水印微调后响应 9.5% 与 36.5% → 表述为"抗微调能力弱(10%--37%)";
- 输出扰动收益小 → 放进"攻击成本"框架,而非宣称"有效阻止提取"。
方法 :区分"方向性结论"(稳健)与"数值点估计"(含随机性),前者用于
结论,后者标注波动来源。
7. 失败也是交付物(第 3、7 天)
- 第 3 天完整记录了 6 种失败配置及其推理过程;
- 第 7 天保留了 TRADES β=6 未收敛的数据点并解释原因。
对本项目的价值 :失败记录把"哪些理解是错的"变成可复用的团队知识,
也使报告更可信(读者能判断结论的边界)。
6.3 工程规范清单(本项目沉淀)
| 规范 | 来源问题 | 具体做法 |
|---|---|---|
| 梯度上下文精确控制 | 第 3、4 天 | 攻击/生成部分保留梯度,评估部分才 no_grad。 |
| 张量形状契约 | 第 2、4、6 天 | 函数注明输入形状;绘图入口统一 squeeze()。 |
| 参数原地更新 | 第 3 天 | 投影/裁剪用 .data,不重新赋值。 |
| 二阶梯度显式声明 | 第 3 天 | 梯度匹配类用 create_graph=True。 |
| 训练模式可恢复 | 第 7 天 | was_training = model.training ... model.train(was_training)。 |
| KL 方向先写公式 | 第 7 天 | 先写清 K L ( p ∣ q ) \mathrm{KL}(p|q) KL(p∣q) 的 p/q 再写代码 |
| 检测逻辑自检 | 第 2 天 | 自问"正常样本会不会也被判为异常?" |
| 数据对象显式命名 | 第 2、3 天 | X_clean / X_poison / X_cleaned 不混用 |
| 结果字段集中定义 | 第 1、4 天 | 写入与读取共用同一套键名 |
共享代码放 common/ |
第 4、5 天 | 跨天复用模块统一放置,避免多份副本 |
| 配置集中 + 启动校验 | 第 7 天 | 模型清单集中定义;缺失产物给出明确告警 |
| 进程卫生 | 第 1 天 | 长任务中断后先检查残留进程再启动新实验 |
6.4 这些经验对本项目的具体作用
1. 保证 10 天任务按期完成
44 条问题中,若不解决"环境安装""进程残留""缺续跑"这三类,项目极可能在第 1--2 天就停滞。工程类经验的直接收益是可计算的时间 :增量保存与
续跑至少节省了数小时机时。
2. 提升结论可信度
- 第 9 天修正对照组后,水印结论才成立;
- 第 5、9 天对非单调结果与波动区间如实表述,避免了"夸大防御效果";
- 第 3、7 天保留失败数据点,使报告的边界条件清晰。
这些做法让报告中每个数字都能追溯到实验设置,结论经得起追问。
3. 提高可复现性
环境固定、脚本幂等、结果落盘、绘图可重放------任何人按 README 与各天脚本即可复现全部图表与数据;日志中记录了参数、随机种子与运行环境。
4. 形成可迁移的能力(对本项目之外同样适用)
本项目的试错经验并不局限于 AI 安全:
- 调试方法论(最小复现、打印形状、二分定位)适用任何数值实验;
- 实验设计(对照组、参数区间、剂量与机制分离)适用任何评测工作;
- 工程规范(幂等、增量保存、计算与呈现解耦)适用任何长跑任务;
- 结论表述(区间、趋势、成本框架)适用任何工程报告。
七、完整实战示例:从"训练莫名变慢"到"清理孤儿进程"
下面以第 1 天的问题 2 为范例,展示一条完整的排错链路。这类"现象 → 数据
→ 假设 → 验证 → 修复 → 复查"的流程,可以直接套用到任何性能异常问题。
7.1 第 1 步:量化现象(不要凭感觉)
text
基线训练:每个 epoch 18.5 → 25.9 秒(正常)
异常训练:每个 epoch 42.3 → 80.1 秒(明显变慢,且不稳定)
7.2 第 2 步:先怀疑"外部资源竞争",再看代码
powershell
Get-Process | Sort-Object CPU -Descending | Select-Object -First 8 Name, Id, CPU, WorkingSet64
text
audiodg 4768 7038.55 72523776
StarRail 22628 2397.25 4606464000
python 11156 2253.33 596529152 ← 高 CPU 的 Python 进程
python 21012 1312.64 614699008 ← 另一个高 CPU 的 Python 进程
判读:有两个 Python 进程在算。如果只启动过一次实验,这就是异常信号。
7.3 第 3 步:取足字段,做"归属判定"
powershell
Get-Process python | Select-Object Id, StartTime, CPU, Path | Format-List
text
Id 11156 | StartTime 10:52:41 | CPU 2308.70 | Path E:\python\python.exe
Id 32712 | StartTime 10:52:41 | CPU 0.00 | Path ...\venv\Scripts\python.exe
Id 21012 | StartTime 10:54:14 | CPU 1371.02 | Path E:\python\python.exe
Id 17956 | StartTime 10:54:14 | CPU 0.03 | Path ...\venv\Scripts\python.exe
| 判据 | 含义 | 本例结论 |
|---|---|---|
| StartTime | 同一次启动的两个进程时间一致 | 10:52:41 与 10:54:14 是两次运行 |
| CPU 累计 | 真正计算的进程 CPU 很高 | E:\python\python.exe 是计算进程,venv 那个是启动器 |
| Path | 区分启动器与真实解释器 | 一次实验 = 一对进程 |
| 日志文件时间戳 | 交叉验证哪次是"当前"的 | 异常日志创建于 10:52:45 → 与 10:52:41 对应 |
7.4 第 4 步:只终止"旧的那一对",再复查
powershell
Stop-Process -Id 11156, 32712 -Force
Get-Process python | Select-Object Id, StartTime, CPU, Path
text
Id 17956 (CPU 0.03) ← 当前实验的启动器
Id 21012 (CPU 1483.6) ← 当前实验的计算进程(保留)
7.5 第 5 步:验证修复效果
text
清理后 epoch 耗时:17.1 / 17.3 / 17.6 / 22.0 秒(恢复正常)
性能恢复 = 假设被证实:瓶颈是 CPU 争抢,不是代码回归。
7.6 这类问题的通用排查顺序
text
1. 量化现象(具体数值,而非"感觉慢")
2. 系统层:Get-Process 按 CPU 排序,看是否有异常进程
3. 归属判定:启动时间 + 累计 CPU + 路径 + 日志时间戳
4. 精确处置:只清理确认无用的进程
5. 复查验证:指标是否恢复正常
八、跨天问题索引(按"我遇到什么现象"检索)
| 你遇到的现象 | 去哪个文件看 | 关键词 |
|---|---|---|
| 依赖装不上 / 找不到包 | day1、day3 | 索引源、--extra-index-url、自研 SSIM |
| 训练莫名变慢 | day1 | 孤儿进程、CPU 争抢、StartTime 判读 |
| 内存爆掉(TB 级分配) | day1 | 广播 (N,1)×(N,) → (N,N) |
| 张量维度/形状报错 | day2、day4、day6 | squeeze/unsqueeze、Invalid shape |
| 攻击效果恒为 0 / 优化变量不动 | day3、day6 | 梯度被切断、变量重新赋值、目标函数抵消 |
| 训练准确率≈随机、损失≈log C | day7 | KL 方向、训练模式未恢复、标签对齐 |
| 报 "tensor 不需要梯度" | day3、day4 | no_grad 包裹攻击循环 |
| 绘图 KeyError / 字段不一致 | day1、day4 | 字段名统一、计算与呈现解耦 |
| 崩溃后结果全丢、要重跑 | day2、day4 | 增量保存、断点续跑 |
| 结论"看不出差别" | day5、day9 | 参数区间、天花板效应、对照组 |
| 检测器把所有样本都判为异常 | day2 | 精确率≈投毒率 = 全量误报 |
| 检测器一个都检不出 | day2、day3 | 审计对象错、特征不可分、影响函数失效 |
| 防御"看起来没用" | day6、day9 | 认证半径 vs 攻击预算、成本不对称 |
九、学习路径与模板库
9.1 学习路径建议
路线 A:按天顺序(理解攻击演进)
day1 → day2 → day3(投毒:越来越隐蔽)→ day4 → day5 → day6 → day7(对抗样本:越来越强、防御越来越深)→ day8 → day9(隐私与窃取)→ day10。
路线 B:按主题横向阅读(理解方法)
- 攻击方法:day1(标签翻转)→ day2(后门)→ day3(清洁标签)→day4/5/6(对抗样本谱系)→ day8/9(隐私攻击);
- 防御方法:day1(清洗/鲁棒损失)→ day2(NC 检测/微调)→ day4/7(对抗训练)→ day6(认证防御)→ day8(DP/输出截断)→day9(水印/限流);
- 评估方法:每天的"理论 vs 实测"表格,重点看"预测与实测是否吻合"。
路线 C:按排错场景阅读(工程速查)
直接使用第八节的索引表:遇到什么现象 → 翻到对应天的"复现与验证速查"→照抄命令/代码 → 对照实测输出判读。
9.2 模板库
模板 1:进程与资源排查
powershell
Get-Process | Sort-Object CPU -Descending | Select-Object -First 8 Name, Id, CPU, WorkingSet64
Get-Process python | Select-Object Id, StartTime, CPU, Path | Format-List
Get-Content <日志文件> -Tail 20 # 交叉验证哪个进程在写日志
Stop-Process -Id <旧进程 PID 列表> -Force
模板 2:结果落盘 + 增量保存 + 幂等续跑
python
ckpt = model_dir / f"{tag}.pt"
result = metric_dir / f"{tag}.json"
if ckpt.exists() and result.exists():
log("[RESUME] 复用已有模型与结果")
model.load_state_dict(torch.load(ckpt, map_location=device))
else:
model = train(...); torch.save(model.state_dict(), ckpt)
for i, item in enumerate(items): # ← 循环内增量保存
res[i] = evaluate(model, item)
save_json(res, result)
模板 3:数值问题的"三连查"
python
print(x.shape, x.requires_grad) # 形状 + 梯度链
print(x.grad.norm() if x.grad is not None else "无梯度")
print((x - x_prev).norm()) # 优化变量是否真的在更新
模板 4:对照实验设计
text
只改变一个变量:
✓ 有水印模型 vs 干净训练模型 → 验证"是否嵌入水印"
✗ 有水印模型 vs 未训练随机模型 → 同时改变了"是否训练"
报告时同时给出:主指标 + 对照指标(如干净准确率、模型效用)
模板 5:结论表述
text
方向性结论(稳健):C&W 可攻破 PGD-AT(95%--100%)
数值型结论(含随机性):水印微调后响应下降到 10%--37%
成本型结论(工程):查询限制使攻击需要数万次调用,性价比崩溃
十、结语与交付清单
十天设计从"改一个标签"到"复制整个模型",完整走过了 AI 安全攻击的主要路径,也验证了对应的检测、防御与治理手段。最重要的收获是攻防一体、纵深防御、自适应评估的安全思维方式------这也是设计的核心目标。