Files
llmiotsafe/DPO_TRAINING_DESIGN.md
2026-05-12 17:01:39 +08:00

279 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DPO 训练数据设计方案
## 1. 总体规划
### 1.1 数据规模
| 数据集 | 用途 | 数量 | 说明 |
|--------|------|------|------|
| `data/train_pref/` | DPO 训练 | **2500 对** | preference pairs (chosen + rejected) |
| `data/dev_pref/` | 验证/早停 | **300 对** | 从训练集中分出 |
| `data/benchmark/` | 测试(不动) | 1200 episodes | 已有的,完全隔离 |
### 1.2 隔离原则
```
Benchmark (测试集) Training (训练集)
───────────────── ─────────────────
35 个场景 (INS-01~05, DF-01~06...) 40 个新场景 (完全不同的 causal pattern)
35 个 FP 变体 40 个新 FP 变体
4 种布局 (A/B/C/D) 4 种新布局 (E/F/G/H) 或同布局不同配置
3 种画像 3 种新画像变体
固定 query 模板 重写的 query 模板
```
---
## 2. 训练场景设计40 个新场景,与 benchmark 的 35 个完全不重叠)
### 2.1 Intrusion 类8 个新场景)
| ID | 场景名 | 与 benchmark 的区别 |
|----|--------|-------------------|
| T-INS-01 | 临时访客码在非预约时段使用 | benchmark INS-05 是被盗凭证,这个是合法码被滥用 |
| T-INS-02 | 连续多天同一时间段出现陌生运动模式 | benchmark INS-01 是单次破窗,这个是持续性异常 |
| T-INS-03 | 门锁解锁后无对应 occupancy 触发 | benchmark 没有这种"缺失信号"型入侵 |
| T-INS-04 | 阳台门深夜打开+室内无对应活动 | benchmark INS-01 是窗户,这个是阳台门 |
| T-INS-05 | 多个窗户传感器短时间内依次触发 | benchmark 没有"扫描式"入侵模式 |
| T-INS-06 | 门锁被远程解锁但住户手机不在家 | 需要推断"远程操作+无人在家"的矛盾 |
| T-INS-07 | 安防系统被 Disarm 但无对应的门锁操作 | 系统被绕过的信号 |
| T-INS-08 | 住户出门后家中出现规律性运动(每天同一时间) | 跟 benchmark BA-05 不同——这个是规律性的 |
### 2.2 Fire/Gas 类6 个新场景)
| ID | 场景名 | 与 benchmark 的区别 |
|----|--------|-------------------|
| T-FG-01 | 多个房间温度同时异常上升(非单一热源) | benchmark FG-02 是单房间,这个是全屋 |
| T-FG-02 | 灶具关闭后温度持续上升(余热异常) | benchmark FG-01 是忘关火,这个是关了但温度还涨 |
| T-FG-03 | 烟雾传感器 ContaminationState 逐步恶化 | benchmark DF-05 是突发故障,这个是渐进退化 |
| T-FG-04 | 厨房 CO 浓度缓慢上升(不触发报警阈值) | benchmark FG-03 是直接 COAlarm这个是亚阈值 |
| T-FG-05 | 电器运行时间异常长(洗碗机 3 小时不停) | 可能过热风险 |
| T-FG-06 | 多个烟雾报警器的 InterconnectSmokeAlarm 触发 | benchmark 没有互联报警场景 |
### 2.3 Water Damage 类4 个新场景)
| ID | 场景名 | 与 benchmark 的区别 |
|----|--------|-------------------|
| T-WD-01 | 漏水传感器间歇性触发(每隔几小时一次) | benchmark WD-01 是持续触发,这个是间歇性 |
| T-WD-02 | 卫生间湿度持续升高但无人使用 | 隐蔽漏水的间接信号 |
| T-WD-03 | 洗衣机运行结束后漏水传感器延迟触发 | 排水管问题 |
| T-WD-04 | 多个房间的漏水传感器先后触发(水蔓延) | benchmark 只有单点漏水 |
### 2.4 Device Fault 类8 个新场景)
| ID | 场景名 | 与 benchmark 的区别 |
|----|--------|-------------------|
| T-DF-01 | 空调运行但温度不下降(制冷失效) | benchmark 没有空调故障 |
| T-DF-02 | 两个相邻房间温度传感器读数差异突然增大 | 交叉验证型故障检测 |
| T-DF-03 | 洗衣机 OperationalState=Running 但 CountdownTime 不减少 | benchmark DF-06 是窗帘,这个是洗衣机 |
| T-DF-04 | 运动传感器在确认无人时段持续报 Occupied | benchmark DF-03 是周期性,这个是持续性 |
| T-DF-05 | 门窗传感器状态与窗帘位置矛盾 | 窗户关着但窗帘显示全开位置 |
| T-DF-06 | 温度传感器读数出现物理不可能的跳变 | 瞬间从 23°C 跳到 -5°C |
| T-DF-07 | 灯的 OnOff 状态与 LevelControl 矛盾 | OnOff=False 但 Level=200 |
| T-DF-08 | 设备频繁离线重连(通信不稳定) | benchmark 没有通信层故障 |
### 2.5 Elderly 类6 个新场景)
| ID | 场景名 | 与 benchmark 的区别 |
|----|--------|-------------------|
| T-EL-01 | 老人连续多天活动范围缩小(只在一个房间) | 渐进性退化 |
| T-EL-02 | 老人用餐时间逐步推迟(作息漂移) | benchmark EL-04 是突然不起床,这个是渐变 |
| T-EL-03 | 老人夜间在非卧室区域长时间停留 | 可能迷路/意识模糊 |
| T-EL-04 | 老人出门频率突然下降(从每天到隔天到不出门) | 社交退缩信号 |
| T-EL-05 | 老人做饭时间异常短(从 30 分钟缩短到 5 分钟) | 可能不再正常进食 |
| T-EL-06 | 老人半夜反复开关同一个灯 | 可能意识混乱 |
### 2.6 Child 类4 个新场景)
| ID | 场景名 | 与 benchmark 的区别 |
|----|--------|-------------------|
| T-CH-01 | 儿童在家长睡觉后使用厨房电器 | benchmark CH-02 是白天,这个是深夜 |
| T-CH-02 | 儿童反复尝试打开被锁定的房间 | 好奇心驱动的危险行为 |
| T-CH-03 | 儿童活动区域突然从儿童房转移到阳台 | 高处坠落风险 |
| T-CH-04 | 放学后长时间只有浴室有活动信号 | 可能的自伤风险(需谨慎处理) |
### 2.7 Behavioral Anomaly 类4 个新场景)
| ID | 场景名 | 与 benchmark 的区别 |
|----|--------|-------------------|
| T-BA-01 | 住户回家后不开灯不开空调直接进卧室 | 情绪/健康异常信号 |
| T-BA-02 | 设备使用频率突然翻倍(强迫性行为) | benchmark BA-03 是灯光闪烁,这个是全设备 |
| T-BA-03 | 住户连续多天不使用厨房(不做饭不吃东西) | 生活能力下降 |
| T-BA-04 | 两个住户的活动时间完全不重叠(回避行为) | 家庭关系异常 |
---
## 3. 训练 FP 变体设计原则
每个训练场景都配一个 FP 变体,设计原则:
**与 benchmark FP 的区别**
- benchmark 的 FP 是"同一事件的正常解释"(如:窗户打开→住户通风)
- 训练集的 FP 要设计"不同但相似的正常模式"(如:临时访客码使用→预约的清洁工按时到达)
**FP 难度分层**
- 30% Easy FP明显正常有直接的正常证据
- 50% Medium FP需要推理才能排除证据模糊
- 20% Hard FP极其接近 TP只有一个细微差异
---
## 4. DPO Pair 构造方案
### 4.1 Chosen正确回答的来源
| 来源 | 比例 | 说明 |
|------|------|------|
| 规则生成 | 40% | 根据 ground truth 直接构造标准答案is_anomaly + threat_type + 推理链) |
| 强模型生成 | 40% | 用 DeepSeek V4 / Claude 跑训练集,筛选答对且推理链好的 |
| 人工编写 | 20% | 对高难度场景手写高质量推理链 |
### 4.2 Rejected错误回答的来源
| 来源 | 比例 | 错误类型 |
|------|------|---------|
| 模型实际错误 | 50% | 用 Qwen3.5-9B baseline 跑训练集,收集错误输出 |
| 构造性错误 | 30% | 人工/规则构造典型错误模式 |
| 对调错误 | 20% | 把 TP 的 chosen 改成 is_anomaly=false漏报把 FP 的 chosen 改成 is_anomaly=true误报 |
### 4.3 构造性错误的具体类型
```
错误类型 1: 漏报TP 场景判为正常)
- "温度波动在正常范围内" ← 实际是 stuck-at 故障
- "运动传感器触发可能是宠物" ← 实际是入侵
错误类型 2: 误报FP 场景判为异常)
- "温度上升可能是火灾" ← 实际是正常做饭
- "凌晨运动可能是入侵" ← 实际是住户失眠
错误类型 3: 类型判错
- 把 sensor_stuck 判成 fire_risk
- 把 intrusion 判成 behavioral_anomaly
错误类型 4: 证据编造
- 引用了日志中不存在的事件
- 时间戳引用错误
错误类型 5: 推理链断裂
- 结论跟证据不匹配
- 跳过关键推理步骤
```
---
## 5. 数据分布设计
### 5.1 按场景类别
| 类别 | 训练场景数 | TP pairs | FP pairs | TN pairs | 总 pairs |
|------|-----------|----------|----------|----------|----------|
| Intrusion | 8 | 400 | 300 | — | 700 |
| Fire/Gas | 6 | 250 | 200 | — | 450 |
| Water Damage | 4 | 150 | 100 | — | 250 |
| Device Fault | 8 | 350 | 250 | — | 600 |
| Elderly | 6 | 150 | 100 | — | 250 |
| Child | 4 | 100 | 80 | — | 180 |
| Behavioral | 4 | 100 | 70 | — | 170 |
| TN (纯正常) | — | — | — | 200 | 200 |
| **合计** | **40** | **1500** | **1100** | **200** | **2800** |
### 5.2 按难度分布
| 难度 | 比例 | 说明 |
|------|------|------|
| L1 (直接信号) | 20% | 让模型学会"有报警就报" |
| L2 (推理检测) | 45% | 核心训练重点 |
| L3 (复合推理) | 35% | 提升上限 |
### 5.3 按错误类型分布
| Rejected 错误类型 | 比例 | 目的 |
|------------------|------|------|
| 漏报 | 35% | 提升 Recall |
| 误报 | 30% | 降低 FA |
| 类型判错 | 15% | 提升 threat_type 准确率 |
| 证据编造 | 10% | 提升推理链质量 |
| 推理断裂 | 10% | 提升推理链质量 |
---
## 6. Query 模板隔离
### Benchmark 的 query不能用于训练
```
SQ1: "请检查以下设备状态历史,判断 {room} 区域的传感器是否工作正常。"
SQ2: "以下是刚刚发生的事件。请判断这是否构成安全威胁,并说明理由。"
SQ3: "以下是过去 {N} 小时的设备活动日志。请分析是否存在异常行为模式。"
```
### 训练集的 query重写同任务不同措辞
```
SQ1 等价: "根据以下传感器数据记录,评估 {device_name} 的工作状态是否正常。"
SQ2 等价: "系统记录了以下设备状态变化。请评估这些变化是否指示安全风险。"
SQ3 等价: "以下是 {time_range} 内的设备活动记录。请识别其中是否存在可疑模式。"
SQ4 等价: "综合以下多个设备的状态信息,评估家庭整体安全状况。"
SQ5 等价: "监控系统标记了潜在异常。请分析情况并建议应对措施。"
```
---
## 7. 布局隔离方案
### 方案 A推荐同布局不同设备配置
复用 Layout A/B/C/D 的房间结构,但:
- 设备数量不同(比如训练集的 Layout A 有 2 个温度传感器而非 3 个)
- 设备位置不同(比如烟雾报警器在卧室而非厨房)
- 增加 benchmark 没有的设备(如加湿器、扫地机器人的运行状态)
### 方案 B全新布局
- Layout E: 复式楼(上下两层)
- Layout F: 开放式公寓(厨房客厅一体)
- Layout G: 合租房(多个独立卧室共用客厅厨房)
- Layout H: 带地下室的独栋
**我建议用方案 A**——因为布局本身不是训练重点,设备配置的微调就够了,省工作量。
---
## 8. 实施步骤
```
Step 1: 写 40 个新场景的 JSON 模板 (data/train_pref/scenarios/)
Step 2: 写 40 个对应的 FP 变体
Step 3: 修改 generate.py 支持从训练场景库生成 episodes
Step 4: 生成 2800 个训练 episodes
Step 5: 用 Qwen3.5-9B baseline 跑训练集,收集 rejected
Step 6: 用 DeepSeek/Claude 跑训练集,收集 chosen
Step 7: 组装 DPO pairs (chosen + rejected)
Step 8: QLoRA DPO 训练 Qwen3.5-9B
Step 9: 在 benchmark 1200 上评测
```
---
## 9. 预期效果
| 指标 | 训练前 (EDRC) | 训练后 (DPO) 预期 |
|------|-------------|-----------------|
| Recall | 80.5% | **75-85%**(保持) |
| FA% | 64.3% | **25-35%**(大幅下降) |
| F1 | 0.628 | **0.70-0.78** |
| Threat Type Acc | ~50% | **65-75%** |
DPO 的核心价值不是提升 RecallEDRC 已经 80%),而是**在保持 Recall 的同时大幅降低误报**——因为训练数据中 30% 的 rejected 是误报案例,模型会学到"什么时候不该报"。
---
## 10. 风险与缓解
| 风险 | 概率 | 缓解 |
|------|------|------|
| 训练后 Recall 下降 | 中 | rejected 中 35% 是漏报案例,平衡训练信号 |
| 过拟合训练场景 | 中 | 训练/测试场景完全隔离 + dev set 早停 |
| 2×A100 显存不够 | 低 | QLoRA 4-bit9B 模型只需 ~12GB |
| DPO 训练不稳定 | 低 | 用 TRL 的 DPOTrainer成熟框架 |
| 效果不如预期 | 中 | 先跑 500 对 pilot看趋势再扩 |