init version
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
# 时序作为模态的多模态模型 · 实现计划
|
||||
|
||||
> **对应规格**:`docs/superpowers/specs/2026-06-29-ts-as-modality-design.md`
|
||||
> **日期**:2026-06-29
|
||||
> **目标**:把规格拆成有序、可验证的实现任务,按里程碑 M1→M5 推进
|
||||
> **原则**:每个任务都有明确的"完成判定"(可跑一条命令/测试验证);任务间依赖清晰;先建最小可跑通骨架,再迭代填充
|
||||
|
||||
---
|
||||
|
||||
## 阶段总览
|
||||
|
||||
```
|
||||
M1 数据管线 ──► M2 模型可跑通 ──► M3 阶段①对齐训练 ──► M4 阶段②SFT ──► M5 完整评测
|
||||
(data) (model) (train stage1) (train stage2) (eval)
|
||||
└─ 合成+真实 └─ TS Encoder └─ 50万 2-3ep └─ 10万 3ep └─ VUS-PR/问答/基线
|
||||
```
|
||||
|
||||
每里程碑结束有"出口验证",通过才进下一个。首版先做"小规模冒烟"(数据 1k、训练几十步)确认管线通,再放大到全量。
|
||||
|
||||
---
|
||||
|
||||
## M1 · 数据管线
|
||||
|
||||
**目标**:能产出合法 JSONL 样本(合成)+ 能加载真实 benchmark 窗口。
|
||||
|
||||
### T1.1 项目脚手架
|
||||
- 创建 `pyproject.toml`:依赖 `torch`, `transformers`, `peft`, `accelerate`, `datasets`, `numpy`, `tqdm`, `pyyaml`, `pytest`
|
||||
- 创建 `src/tsmm/__init__.py`、`configs/`、`scripts/`、`tests/` 目录骨架
|
||||
- 建 `data/`、`checkpoints/` 并加 `.gitignore`
|
||||
- **完成判定**:`python -c "import tsmm"` 不报错;`pytest tests/` 能跑(哪怕空)
|
||||
|
||||
### T1.2 属性词表与采样 `data/attributes.py`
|
||||
- 定义变量名词表(CPU/内存/流量/延迟/温度/请求量…)、单位、采样率档位
|
||||
- `sample_attributes(n_channels)` → 返回 `[{"name","unit","freq"}, ...]`
|
||||
- **完成判定**:单元测试 `tests/test_attributes.py` — 采样结果字段齐全、数量正确、可复现(设 seed)
|
||||
|
||||
### T1.3 成分模型与时序合成 `data/synthesis.py`
|
||||
- 实现 `generate_series(T, C, seed)`:趋势+周期+基线+噪声(高斯/Student-t)叠加
|
||||
- 实现 `inject_anomaly(series, types)`:尖刺/水平偏移/方差膨胀/缺失段/缓慢漂移,返回 `(series, labels)`,labels 为逐点 0/1 + 段元数据
|
||||
- 实现 `couple_event(series, t, kind)`:在 t 注入阶跃并返回事件文本描述
|
||||
- 实现 `add_missing(series, rate)`:随机丢弃 5-10% 点(用 NaN 占位)
|
||||
- **完成判定**:`tests/test_synthesis.py` — 给定 seed 输出确定;异常段位置与 labels 一致;事件 t 处确有阶跃;可视化 1 条样本人工确认形态合理
|
||||
|
||||
### T1.4 指令与回答生成 `data/instruct.py`
|
||||
- 定义 6 类指令模板(描述/异常/根因/预测/比较/事件关联)
|
||||
- `build_instruction(series_meta, labels, events, category)` → `(instruction, answer)`,answer 含 JSON 区间(异常类)或数值(统计类)或文本(解释类)
|
||||
- Evol-Instruct 演化:用模板组合 + 随机改写生成多样化问法
|
||||
- **完成判定**:`tests/test_instruct.py` — 每类至少产 1 条,answer 的 JSON 可被 `json.loads` 解析;异常类 answer 段与 labels 吻合
|
||||
|
||||
### T1.5 离线生成脚本 `scripts/gen_synthetic.py`
|
||||
- 多进程跑 T1.2-T1.4,产出 `data/align.jsonl`(50万)+ `data/sft.jsonl`(10万,Evol 演化)+ `data/eval_synth.jsonl`(2k held-out,固定 seed)
|
||||
- 支持 `--n`、`--out`、`--seed`、`--workers` 参数;带 tqdm 进度
|
||||
- **完成判定**:`python scripts/gen_synthetic.py --n 1000` 跑通;抽样 5 条人工可视检 schema 合规(含 series/attributes/timestamps/events/instruction/answer/labels)
|
||||
|
||||
### T1.6 真实 benchmark 加载 `data/real_bench.py`
|
||||
- 加载 SMD/MSL/SMAP/SWaT/PSM(先用本地缓存或公开下载脚本;若无现成包,至少实现 SWaT/MSL 两个)
|
||||
- `load_windows(name, T=512, stride=256)` → 滑窗 + 归一化 + 异常标签
|
||||
- 用 LLM/模板把异常段转成问答对(评测用,不进训练),存 `data/eval_real.jsonl`
|
||||
- **完成判定**:能加载至少 2 个数据集;窗口形状 `[N, T, C]`;标签形状 `[N, T]`;问答对非空
|
||||
|
||||
> **M1 出口验证**:`gen_synthetic.py --n 1000` 产出可视检合法的 JSONL;`real_bench.py` 能加载 ≥2 数据集。人工抽看 5 条合成样本确认成分/异常/事件正确。
|
||||
|
||||
---
|
||||
|
||||
## M2 · 模型可跑通
|
||||
|
||||
**目标**:TS Encoder + Projector + 多模态拼接能在 3060 上前向+反向不 OOM。
|
||||
|
||||
### T2.1 TS Encoder `model/ts_encoder.py`
|
||||
- `Patchify(patch=8, stride=4)`:通道独立切 patch,线性嵌入到 d=256
|
||||
- `TSEncoder(d=256, layers=2, heads=4)`:2 层 Transformer + 可学习位置编码
|
||||
- 前向:`[B, T, C]` → `[B, n_patches, 256]`
|
||||
- **完成判定**:`tests/test_ts_encoder.py` — 随机输入 `[2, 512, 5]` 输出 `[2, 128, 256]`;参数量 ≈4M
|
||||
|
||||
### T2.2 Projector `model/projector.py`
|
||||
- `Projector(256 → 896)`:Linear + LayerNorm
|
||||
- **完成判定**:输出 `[B, 128, 896]` 对齐 Qwen2.5-0.5B hidden
|
||||
|
||||
### T2.3 多模态拼接 `model/multimodal.py`
|
||||
- 用 Qwen2.5-0.5B tokenizer 把 `[属性][时间戳][事件][问题]` 文本 tokenize
|
||||
- 把 TS token([B,128,896])作为 inputs_embeds 插入对应位置:`[属性][时间戳][TS tok][事件][问题]`
|
||||
- 统一构造 `inputs_embeds`(文本走 `get_input_embeddings()`,TS 走 Projector 输出)+ `attention_mask` + `labels`(仅回答段非 -100)
|
||||
- **完成判定**:`tests/test_multimodal.py` — 拼接后 seq_len ≤1024;mask/labels 形状对;回答段 label 非 -100
|
||||
|
||||
### T2.4 训练/推理封装 `model/wrapper.py`
|
||||
- `MultimodalTSModel`:组合 TS Encoder + Projector + LLM + LoRA 挂载开关
|
||||
- `forward(batch)` 返回 loss;`generate(batch)` 返回文本
|
||||
- 支持 `freeze_llm`(阶段①)和 `enable_lora(r=16)`(阶段②)两种模式
|
||||
- **完成判定**:单 batch `forward` 在 3060 不 OOM;`generate` 能出文本(哪怕乱码)
|
||||
|
||||
### T2.5 Collator `data/collator.py`
|
||||
- 把 JSONL 样本 batch 化为 `(series, attributes, timestamps, events, instruction, answer)` → 张量
|
||||
- 处理变长 C(padding + mask)、变长文本(padding + attention_mask)
|
||||
- **完成判定**:`tests/test_collator.py` — batch=4 输出张量形状一致、无 NaN
|
||||
|
||||
> **M2 出口验证**:单 batch 前向+反向在 3060 跑通,loss 是有限值且下降趋势;阶段①模式峰值显存 ~5GB。
|
||||
|
||||
---
|
||||
|
||||
## M3 · 阶段① 对齐训练
|
||||
|
||||
**目标**:50万条 2-3 epoch,TS token 不被忽略。
|
||||
|
||||
### T3.1 损失函数 `train/losses.py`
|
||||
- `lm_loss(logits, labels)`:仅回答段计 LM loss(labels mask)
|
||||
- `contrastive_loss(model, batch)`:扰动时序(加噪/平移)→ 回答 embedding 应变化(InfoNCE 或扰动一致性)
|
||||
- 总 loss = `lm_loss + λ * contrastive_loss`(λ 可配,默认 0.1)
|
||||
- **完成判定**:`tests/test_losses.py` — loss 标量、可反传、对比损失对扰动敏感
|
||||
|
||||
### T3.2 阶段① 训练脚本 `train/stage1.py` + `scripts/train_stage1.sh`
|
||||
- 加载 `data/align.jsonl`(datasets 流式)
|
||||
- `freeze_llm=True`,仅训 TS Encoder + Projector(AdamW, lr=1e-4)
|
||||
- 配置:bs=8, grad_accum=4, ctx=512, BF16, 梯度检查点
|
||||
- 每 2000 step 存 ckpt 到 `checkpoints/stage1/`,TensorBoard 记录
|
||||
- **完成判定**:`--max_steps 100` 冒烟跑通不 OOM;loss 下降;峰值显存 ≤6GB
|
||||
|
||||
### T3.3 TS-token 有效性检验
|
||||
- 训练后取 held-out 样本:原时序 vs 扰动时序,对比模型回答是否变化
|
||||
- "必看时序"样本:问具体数值/段位置,看模型能否答对
|
||||
- **完成判定**:扰动后回答变化率 >50%;"必看时序"样本答对率显著高于纯 LLM 基线
|
||||
|
||||
> **M3 出口验证**:阶段① ckpt 产出;扰动检验通过;显存 ≤6GB。失败则回查对比损失权重/数据质量。
|
||||
|
||||
---
|
||||
|
||||
## M4 · 阶段② SFT
|
||||
|
||||
**目标**:10万条 Evol-Instruct 3 epoch + LoRA,6 类任务遵循指令。
|
||||
|
||||
### T4.1 阶段② 训练脚本 `train/stage2.py` + `scripts/train_stage2.sh`
|
||||
- 加载阶段① ckpt(TS Encoder + Projector)
|
||||
- `enable_lora(r=16)` on q/v_proj,LLM 其余冻结
|
||||
- 加载 `data/sft.jsonl`,配置:bs=4, grad_accum=8, ctx=1024, BF16, 梯度检查点
|
||||
- 每 2000 step 存 ckpt(含 LoRA 适配器)到 `checkpoints/stage2/`
|
||||
- **完成判定**:`--max_steps 100` 冒烟跑通;峰值显存 ≤11GB;loss 下降
|
||||
|
||||
### T4.2 指令遵循抽检
|
||||
- 6 类任务各取 10 条 held-out,人工/规则看回答是否遵循格式与语义
|
||||
- 异常类:JSON 可解析、段位置合理
|
||||
- 解释类:回答切题、引用事件
|
||||
- **完成判定**:6 类任务回答可用率 >70%;JSON 解析成功率 >80%
|
||||
|
||||
> **M4 出口验证**:阶段② ckpt 产出;6 类任务抽检达标;显存 ≤11GB。若 OOM 按风险对策降批量/开 CPU offload。
|
||||
|
||||
---
|
||||
|
||||
## M5 · 完整评测
|
||||
|
||||
**目标**:产出 VUS-PR/Aff-F1/问答分 + 4 类基线对比。
|
||||
|
||||
### T5.1 回答解析 `eval/parse_answer.py`
|
||||
- 从模型文本回答中提取 JSON 异常段 → 逐点分数 `[T]`(段内 1.0,段外 0.0)
|
||||
- 解析失败 → 全 0 + 记录失败标记
|
||||
- **完成判定**:`tests/test_parse.py` — 多种回答格式(含噪声/嵌套)能解析;失败有兜底
|
||||
|
||||
### T5.2 异常检测指标 `eval/ts_metrics.py`
|
||||
- 用 `tsb_uad` 算 VUS-PR(主);自实现 Affiliation-F1(λ=0.1/0.5/1.0)、AUC-PR、Point-F1(无PA)
|
||||
- PA-F1 单独算作对照
|
||||
- **完成判定**:`tests/test_ts_metrics.py` — 对已知段能算出合理值;trivial 基线(全报异常)VUS-PR 不虚高
|
||||
|
||||
### T5.3 问答评测 `eval/qa_judge.py`
|
||||
- 规则解析轨:JSON/数值容差比对,产出准确率
|
||||
- LLM-judge 轨:调 GPT-4o 对 (问题,时序摘要,参考答案,模型答案) 打 0-5 分(可换开源 judge 做 sanity)
|
||||
- 不一致样本导出供人工抽检
|
||||
- **完成判定**:能对 eval 集产出 6 类任务的 {规则准确率, judge 均分, 解析成功率}
|
||||
|
||||
### T5.4 对照基线 `eval/baselines.py`
|
||||
- 纯 LLM 数值喂文本:时序数值拼字符串喂 Qwen2.5-0.5B,同评测脚本
|
||||
- Time-LLM 风格重映射:同样 0.5B 骨干(简化复现)
|
||||
- ChatTS(若可复现则纳入,否则标注未复现)
|
||||
- Trivial:Random / Constant / 全报异常
|
||||
- 全部走同一套 `parse_answer` + `ts_metrics`,保证同口径
|
||||
- **完成判定**:4 类基线均产出同口径指标表
|
||||
|
||||
### T5.5 评测脚本与报告 `scripts/run_eval.sh`
|
||||
- 跑 `eval_synth.jsonl` + `eval_real.jsonl`,产出 markdown 报告 `reports/eval-YYYYMMDD.md`
|
||||
- 报告含:每数据集×每任务的 VUS-PR/Aff-F1/AUC-PR/Point-F1/PA-F1(对照)/问答分/解析成功率/消融/基线对比
|
||||
- 标注是否用 PA、含 trivial 对照
|
||||
- **完成判定**:一键 `run_eval.sh` 产出完整报告;报告满足规格 §5.4 必报清单
|
||||
|
||||
> **M5 出口验证**:报告满足规格 §6.5 成功标准 —— 真实 benchmark VUS-PR 显著优于纯 LLM 基线;时序消融后指标明显下降;问答均分超基线;评测可复现含 trivial。
|
||||
|
||||
---
|
||||
|
||||
## 执行顺序与依赖
|
||||
|
||||
```
|
||||
T1.1 ─► T1.2 ─► T1.3 ─► T1.4 ─► T1.5 ┐
|
||||
├─► [M1 出口] ─► T2.1 ─► T2.2 ─► T2.3 ─► T2.4 ─► T2.5 ─► [M2 出口]
|
||||
T1.6 ────────────────┘ │
|
||||
▼
|
||||
T3.1 ─► T3.2 ─► T3.3 ─► [M3 出口]
|
||||
│
|
||||
▼
|
||||
T4.1 ─► T4.2 ─► [M4 出口]
|
||||
│
|
||||
▼
|
||||
T5.1 ─► T5.2 ┐
|
||||
T5.3 ────────┼─► T5.4 ─► T5.5 ─► [M5 出口]
|
||||
```
|
||||
|
||||
## 风险触发时的回退
|
||||
|
||||
- **M2 OOM**:先降 ctx 到 256 / bs 到 2;仍不行退到只验证阶段①模式
|
||||
- **M3 TS token 被忽略**:提升对比损失 λ;增加"必看时序"样本占比;检查 Projector 是否饱和
|
||||
- **M4 OOM**:降 bs=2/grad_accum=16;开 `optim=adamw_8bit` + CPU offload;ctx 降到 768
|
||||
- **M5 合成→真实泛化差**:在阶段②掺入 `real_bench` 改写样本重训;报告以真实 benchmark 为准
|
||||
|
||||
## 首次跑通的"冒烟路径"(先做这个)
|
||||
|
||||
不等全量数据,先用最小路径确认端到端通:
|
||||
1. `gen_synthetic.py --n 200` 产小数据
|
||||
2. T2.1-T2.4 单 batch 跑通
|
||||
3. `stage1.py --max_steps 50` + `stage2.py --max_steps 50` 冒烟
|
||||
4. `run_eval.sh` 在 200 样本上产出报告骨架
|
||||
|
||||
冒烟通过后再放大到 M1 全量数据 + 完整训练。
|
||||
|
||||
---
|
||||
|
||||
> 本计划把规格拆成 22 个任务、5 个带出口验证的里程碑。每个任务有"完成判定"可独立验证。建议从"冒烟路径"开始,确认端到端通后再放大规模。
|
||||
@@ -0,0 +1,343 @@
|
||||
# 时序作为模态的多模态模型 · 设计规格
|
||||
|
||||
> **日期**:2026-06-29
|
||||
> **状态**:已通过设计评审,待写实现计划
|
||||
> **背景**:基于 `MTSAD-技术深度调研报告.md`,沿用 ChatTS「时序作为新模态」路线,在消费级硬件上做可复现的实验性落地
|
||||
> **目标读者**:算法工程师(实现者)、技术决策者(评审者)
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标与约束
|
||||
|
||||
### 1.1 目标
|
||||
|
||||
构建一个把**多变量时序视为独立模态**、与文本/事件模态联合注入小型 LLM 的多模态模型,端到端任务是**时序问答与推理**(ChatTS 路线):以多变量时序为输入,支持自然语言问答、根因分析、异常解释等推理任务。
|
||||
|
||||
### 1.2 硬约束
|
||||
|
||||
| 约束 | 取值 | 影响 |
|
||||
|------|------|------|
|
||||
| 算力 | **单张 3060 12GB 消费级显卡** | 骨干 ≤0.5B;依赖 LoRA/QLoRA + 短上下文 + 小批量;TS 编码器单独轻量训练 |
|
||||
| 模态范围 | 数值序列 + 变量属性 + 时间戳 + 事件 | 投影层需支持 TS token 与多类文本 token 并存;面向 AIOps 时序+事件联合推理 |
|
||||
| 数据 | **合成数据为主** | 需要 CPU 离线合成管线;评测锚定真实 benchmark 防止合成过拟合 |
|
||||
| 模型尺寸 | ≤0.5B(可更小) | 选用 Qwen2.5-0.5B-Instruct 作为骨干 |
|
||||
|
||||
### 1.3 非目标(YAGNI)
|
||||
|
||||
- 不做从零预训练 LLM(成本不允许,且非本实验目的)
|
||||
- 不做多卡分布式训练(单卡约束)
|
||||
- 不追求学术 SOTA 排名,追求「在 12GB 上跑通、可复现、时序模态确有增益」的可验证结论
|
||||
- 不做端侧部署优化(先验证方法)
|
||||
|
||||
---
|
||||
|
||||
## 2. 整体架构
|
||||
|
||||
### 2.1 数据流
|
||||
|
||||
```
|
||||
多变量时序 [T×C]
|
||||
│ Patchify (patch=P, stride=S, 通道独立)
|
||||
▼
|
||||
Patches [(T/P)×d] ──► TS Encoder (2层Transformer) ──► Projector (Linear→LLM hidden)
|
||||
│
|
||||
▼ TS Tokens [(T/P)×h]
|
||||
变量属性 / 时间戳文本 / 事件标记 / 指令问题 ──► Tokenize ──► 文本/事件 Tokens
|
||||
│
|
||||
[属性][时间戳][TS tokens][事件][问题] 拼接
|
||||
▼
|
||||
LLM Backbone (Qwen2.5-0.5B, LoRA)
|
||||
▼
|
||||
自然语言回答 (+ 可选 JSON 异常区间)
|
||||
```
|
||||
|
||||
### 2.2 关键设计决策
|
||||
|
||||
| 项 | 选择 | 理由 |
|
||||
|----|------|------|
|
||||
| 骨干 LLM | Qwen2.5-0.5B-Instruct | 0.5B 中英均衡、有 Instruct 版、社区生态成熟;BF16 约 1GB,12GB 余量充足 |
|
||||
| TS Encoder | 2 层 Transformer,d=256,4 头 | 够表达局部时序结构;参数约 4M,可与投影层一起全参训练 |
|
||||
| Patch | P=8, stride=4(重叠),通道独立 | 重叠 patch 保局部连续;通道独立避免 C 增大失配;T=512 → 128 个 TS token |
|
||||
| Projector | Linear(256→896) + LayerNorm | 把 TS 表示映射到 LLM 隐藏维(Qwen2.5-0.5B hidden=896),作为可学习 soft token 注入 |
|
||||
| LLM 微调 | LoRA r=16 (q/v_proj) + 冻结其余 | 12GB 关键约束;可训练参数约 2-3M |
|
||||
| 上下文 | ≤1024 token(128 TS + ~500 文本/事件) | 12GB 显存友好;T=512 时间步足够覆盖 AIOps 局部窗口 |
|
||||
| 输入拼接顺序 | `[属性][时间戳][TS tokens][事件][问题]` | 属性先给语义,时序居中,事件定位在对应时间,问题在末尾便于回答 |
|
||||
|
||||
### 2.3 与候选方案的对比(为什么选 Patch-Project + 轻量编码器)
|
||||
|
||||
- **方案 A(本设计)Patch-Project + 轻量编码器**:时序切 patch → 小编码器 → 线性投影成独立 TS token。真正的"时序作为模态",12GB 可训,patch 捕捉局部结构、变长友好。需训练编码器+投影层(已在显存预算内)。
|
||||
- **方案 B 时序 Tokenization(Chronos 风格)**:数值量化成离散 token、扩展词表。最"时序即语言"但量化丢精度、异常细节易损;逐点 token 序列长,12GB 上下文吃紧。放弃。
|
||||
- **方案 C Reprogramming(Time-LLM 风格)**:冻结 LLM 用文本原型重映射。参数最省但受限于已有文本嵌入流形、表达力弱,时序算不上"真新模态",复杂推理/事件联合弱。放弃。
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据与合成管线
|
||||
|
||||
### 3.1 总体管线(全 CPU 离线)
|
||||
|
||||
```
|
||||
① 属性采样 → ② 时序生成 → ③ 自动标注 → ④ 指令生成(Evol-Instruct) → ⑤ 回答生成
|
||||
```
|
||||
|
||||
产物为 JSONL,每条含:`series` / `attributes` / `timestamps` / `events` / `instruction` / `answer` / `labels`。
|
||||
|
||||
### 3.2 合成时序的成分模型
|
||||
|
||||
每条时序由可配置成分叠加,覆盖 AIOps 常见形态:
|
||||
|
||||
| 成分 | 实现 | 覆盖场景 |
|
||||
|------|------|----------|
|
||||
| 趋势 trend | 分段线性 / log / 阶跃 | 容量增长、版本切换 |
|
||||
| 周期 seasonal | 多周期正弦叠加(日/周) | 流量昼夜规律 |
|
||||
| 基线水平 | 常数 + 缓慢漂移 | 稳态负载 |
|
||||
| 噪声 | 高斯 + 重尾(Student-t) | 真实传感器抖动 |
|
||||
| 异常注入 | 尖刺/水平偏移/方差膨胀/缺失段/缓慢漂移 | 对应 MTSAD 报告异常类型谱 |
|
||||
| 事件耦合 | 在指定 t 注入阶跃,并生成对应事件文本 | 部署/扩容 → 指标跳变 |
|
||||
| 缺失/不规则 | 随机丢弃 5-10% 点 | 真实采集缺陷 |
|
||||
|
||||
**核心红利**:异常段、事件时间戳、各成分参数全部作为 ground-truth 自动记录——免费且精确的标签。
|
||||
|
||||
### 3.3 指令任务类型(Evol-Instruct 扩展)
|
||||
|
||||
| 类别 | 示例问题 | 对齐目的 |
|
||||
|------|----------|----------|
|
||||
| 描述/统计 | "这段时序的均值/趋势是什么?" | 基础数值→文本对齐 |
|
||||
| 异常检测 | "哪些时段出现异常?类型?" | 核心任务,带段标签 |
|
||||
| 根因/解释 | "t=320 后为何突增?" | 结合事件做因果推理 |
|
||||
| 预测 | "未来 32 步走势?" | 时序外推能力 |
|
||||
| 比较 | "变量 A 和 B 谁更稳定?" | 跨通道关系建模 |
|
||||
| 事件关联 | "这次异常和部署事件有关吗?" | 时序+事件模态融合 |
|
||||
|
||||
### 3.4 规模(12GB 友好)
|
||||
|
||||
- 对齐预训练阶段:**~50 万条**合成三元组(CPU 生成,约 1-2 天可跑完)
|
||||
- 指令微调阶段:从 50 万中 **Evol-Instruct 演化出 ~10 万条**高质量多轮对话
|
||||
- 评测集:**固定 2,000 条** held-out 合成 + 公开 benchmark 抽样
|
||||
- 每条时序 T=512, C∈[3,12],单条约 2-4KB,总量约 2-3GB,训练时流式加载
|
||||
|
||||
### 3.5 评测用的真实锚点
|
||||
|
||||
合成数据训练,但评测锚定真实分布,避免"合成上 SOTA、真实上崩盘":
|
||||
|
||||
| 用途 | 数据 | 处理 |
|
||||
|------|------|------|
|
||||
| 真零样本问答评测 | SMD / MSL / SMAP / SWaT 窗口 | 用 LLM 把异常段转成"问答对"做评测(不参与训练) |
|
||||
| 异常检测指标 | 同上 + PSM | 模型输出文本中的异常区间 → 解析为二值分数 |
|
||||
| 对照基线 | — | ChatTS / Time-LLM / 纯 LLM(数值喂文本)同口径对比 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 训练流程与阶段
|
||||
|
||||
### 4.1 三阶段
|
||||
|
||||
**阶段 ① 时序-文本对齐预训练**(~50 万条合成三元组)
|
||||
- 可训练:TS Encoder + Projector(全参,~4.2M)
|
||||
- 冻结:LLM 主体
|
||||
- 目标:让 TS token 在 LLM 表示空间"能被读懂"
|
||||
- 损失:回答 token 的 LM loss(仅回答段计 loss)+ 对比损失(扰动时序→回答应变)
|
||||
- ~2-3 epoch
|
||||
|
||||
**阶段 ② 指令微调 SFT**(~10 万条 Evol-Instruct 多轮)
|
||||
- 可训练:TS Encoder + Projector + LoRA(r=16),~7M
|
||||
- 冻结:LLM 其余权重
|
||||
- 目标:建立指令遵循 + 推理 + 异常/事件关联
|
||||
- 损失:SFT LM loss,对回答做 mask
|
||||
- ~3 epoch
|
||||
|
||||
**阶段 ③ 评测与可选 DPO**(2k held-out + 真实 benchmark)
|
||||
- 评测:问答准确率 + 异常检测指标
|
||||
- 可选:DPO 用正确/错误回答对偏好优化
|
||||
- 可选:真实数据少量微调做领域适配
|
||||
|
||||
### 4.2 显存预算(12GB 3060)
|
||||
|
||||
| 项 | 阶段① 对齐预训练 | 阶段② SFT |
|
||||
|----|------------------|-----------|
|
||||
| 可训练参数 | TS Encoder(4M)+Projector(0.2M) ≈ **4.2M** | + LoRA(2-3M) ≈ **7M** |
|
||||
| LLM 状态 | BF16 冻结(~1GB 权重) | BF16 + LoRA 适配器 |
|
||||
| 优化器 | AdamW(仅训 4.2M,显存极省) | AdamW + LoRA |
|
||||
| 批量 | per_device=8, grad_accum=4 → eff 32 | per_device=4, grad_accum=8 → eff 32 |
|
||||
| 上下文 | 512 token | 1024 token |
|
||||
| 梯度检查点 | 开 | 开 |
|
||||
| 混合精度 | BF16(3060 支持) | BF16 |
|
||||
| 预估峰值显存 | **~4-5GB** | **~9-10GB** |
|
||||
| 单 epoch 时长(估) | ~6-10 小时 | ~8-12 小时 |
|
||||
|
||||
### 4.3 关键工程要点
|
||||
|
||||
- **阶段① 省显存的核心**:LLM 冻结 → 不需要存 LLM 的优化器状态和梯度,12GB 绰绰有余,甚至能加大批量
|
||||
- **阶段② 才上 LoRA**:仅给 LLM 加 r=16 的 q/v_proj 适配器,可训练参数 ~2-3M,配合梯度检查点压在 10GB 内
|
||||
- **分阶段 checkpoint**:阶段①产物 = "TS Encoder+Projector";阶段②在此之上叠加 LoRA,互不污染、可回滚
|
||||
- **损失 masking**:仅对回答段 token 计算 LM loss,prompt(属性/时序/事件/问题)段不计
|
||||
- **断点续训**:每 2000 step 存 checkpoint,JSONL 流式加载支持任意 step 续
|
||||
|
||||
### 4.4 防止"时序模态塌缩"的训练技巧
|
||||
|
||||
| 风险 | 对策 |
|
||||
|------|------|
|
||||
| LLM 忽略 TS token,只看文本答题 | 构造"必须看时序才能答"的样本(如具体数值/段位置),并在阶段①用对比损失:扰动时序→回答应变 |
|
||||
| TS Encoder 过拟合合成分布 | 成分参数随机化 + 多套合成配置 + 阶段②引入真实 benchmark 改写样本 |
|
||||
| 异常稀有导致模型回避 | 合成时强制每条至少含 1 类异常,指令中异常类任务占比 ≥40% |
|
||||
| 回答格式不稳定 | 回答模板约束输出 JSON 区间(如 `{"segments":[[320,360]],"type":"spike"}`),便于评测解析 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 评估方法
|
||||
|
||||
### 5.1 三条评测支柱
|
||||
|
||||
**A · 时序问答准确率**
|
||||
- 主:LLM-as-judge(GPT-4o 评分 0-5)
|
||||
- 辅:规则解析 JSON 区间精确匹配
|
||||
- 6 类指令任务分别报分
|
||||
- held-out 合成 2k + 真实改写
|
||||
|
||||
**B · 异常检测指标**(严守 MTSAD 报告评估纪律)
|
||||
- 主:**VUS-PR**(阈值无关)
|
||||
- Affiliation-F1(λ=0.1/0.5/1.0)
|
||||
- AUC-PR、Point-F1(无 PA)
|
||||
- **PA-F1 仅对照、不得作主指标**
|
||||
|
||||
**C · 泛化与消融**
|
||||
- 跨数据集:SMD→MSL/SWaT
|
||||
- 模态消融:去掉事件/属性/时序
|
||||
- trivial 基线对照(Random/Constant)
|
||||
- 同口径对比 ChatTS/Time-LLM/纯 LLM
|
||||
|
||||
### 5.2 异常检测:从自然语言回答 → 数值分数
|
||||
|
||||
| 步骤 | 做法 |
|
||||
|------|------|
|
||||
| 1. 约束输出格式 | 训练时要求回答含 `{"segments":[[s,e],...],"type":...,"score":...}` |
|
||||
| 2. 解析区间 | 正则/JSON 解析模型回答中的异常段 |
|
||||
| 3. 生成逐点分数 | 段内点赋 1.0,段外 0.0;可叠加模型自报置信度 score |
|
||||
| 4. 算指标 | 用 `tsb_uad` / 自实现 VUS-PR、Aff-F1、AUC-PR、Point-F1 |
|
||||
| 5. 鲁棒性兜底 | 解析失败 → 分数全 0(计为漏报),单独统计解析成功率 |
|
||||
|
||||
### 5.3 问答评测:LLM-judge + 规则双轨
|
||||
|
||||
| 轨 | 适用任务 | 方法 |
|
||||
|----|----------|------|
|
||||
| 规则解析(客观) | 异常检测、统计描述、预测 | JSON 区间/数值容差比对,可重复、零成本 |
|
||||
| LLM-judge(主观) | 根因解释、事件关联、比较 | GPT-4o 对 (问题,时序摘要,参考答案,模型答案) 打 0-5 分 + 理由 |
|
||||
| 交叉校验 | 全部 | 两类不一致的样本人工抽检,定位系统性偏差 |
|
||||
|
||||
### 5.4 必报指标与报告规范
|
||||
|
||||
**必报(每数据集×每任务):**
|
||||
- 异常检测:VUS-PR(主)、Affiliation-F1(多λ)、AUC-PR、Point-F1(无PA)
|
||||
- 问答:LLM-judge 均分、规则解析准确率、解析成功率
|
||||
- 泛化:跨数据集 F1/VUS-PR 衰减比例
|
||||
- 消融:去掉各模态后的指标变化
|
||||
|
||||
**禁止:** 仅报 PA-F1 / 单数据集称 SOTA / 不报 trivial 基线 / 不标是否用 PA。
|
||||
|
||||
### 5.5 对照基线(同口径同评测脚本)
|
||||
|
||||
- **纯 LLM 数值喂文本**:把时序数值直接拼成文本喂 Qwen2.5-0.5B —— 检验"TS 模态"是否真带来增益
|
||||
- **Time-LLM 风格重映射**:同样 0.5B 骨干,对比"重映射 vs 我们的新模态"
|
||||
- **ChatTS**(若可复现):对比同类多模态时序 LLM
|
||||
- **Trivial**:Random / Constant / "全报异常" —— 确保不是评估虚高
|
||||
|
||||
---
|
||||
|
||||
## 6. 工程落地与代码结构
|
||||
|
||||
### 6.1 项目布局
|
||||
|
||||
```
|
||||
ts-as-modality/
|
||||
├── README.md
|
||||
├── pyproject.toml # 依赖:torch, transformers, peft, accelerate, datasets
|
||||
├── configs/
|
||||
│ ├── ts_encoder.yaml # TS Encoder/Projector 超参
|
||||
│ ├── stage1_align.yaml # 对齐预训练
|
||||
│ ├── stage2_sft.yaml # 指令微调
|
||||
│ └── eval.yaml
|
||||
├── src/tsmm/
|
||||
│ ├── __init__.py
|
||||
│ ├── data/
|
||||
│ │ ├── synthesis.py # 成分模型 + 异常注入 + 事件耦合
|
||||
│ │ ├── attributes.py # 属性词表采样
|
||||
│ │ ├── instruct.py # Evol-Instruct 指令/回答生成
|
||||
│ │ ├── collator.py # 拼接 [属性][时间戳][TS tok][事件][问题]→ token流
|
||||
│ │ └── real_bench.py # SMD/MSL/SMAP/SWaT/PSM 加载 + 问答改写
|
||||
│ ├── model/
|
||||
│ │ ├── ts_encoder.py # Patchify + 2层TF + Projector
|
||||
│ │ ├── projector.py # Linear→LLM hidden
|
||||
│ │ ├── multimodal.py # 组装 TS token + 文本 token 进 LLM
|
||||
│ │ └── wrapper.py # 训练/推理统一封装(含 LoRA 挂载)
|
||||
│ ├── train/
|
||||
│ │ ├── stage1.py # 冻结LLM,训 Encoder+Projector
|
||||
│ │ ├── stage2.py # 加 LoRA SFT
|
||||
│ │ └── losses.py # LM loss mask + 对比损失
|
||||
│ ├── eval/
|
||||
│ │ ├── parse_answer.py # 文本→JSON 区间→逐点分数
|
||||
│ │ ├── ts_metrics.py # VUS-PR / Aff-F1 / AUC-PR / Point-F1
|
||||
│ │ ├── qa_judge.py # 规则解析 + LLM-judge
|
||||
│ │ └── baselines.py # 纯LLM/Time-LLM/ChatTS/trivial 同口径
|
||||
│ └── utils/
|
||||
├── scripts/
|
||||
│ ├── gen_synthetic.py # 离线生成 50万 + 10万 JSONL
|
||||
│ ├── train_stage1.sh
|
||||
│ ├── train_stage2.sh
|
||||
│ └── run_eval.sh
|
||||
├── data/ # 生成产物(git-ignored)
|
||||
├── checkpoints/ # 分阶段 ckpt(git-ignored)
|
||||
└── tests/ # 各模块单元测试
|
||||
```
|
||||
|
||||
### 6.2 技术栈
|
||||
|
||||
| 层 | 选型 | 理由 |
|
||||
|----|------|------|
|
||||
| 骨架 | Qwen2.5-0.5B-Instruct (HF Transformers) | 0.5B、中英、Instruct 版现成 |
|
||||
| 微调 | PEFT (LoRA) + Accelerate | 12GB 标配组合 |
|
||||
| 数据 | datasets 流式 + JSONL | 2-3GB 无需全载内存 |
|
||||
| 合成 | NumPy + tqdm,纯 CPU 多进程 | 不占显存,可后台跑 |
|
||||
| 评估 | tsb_uad(VUS-PR)+ 自实现 Aff-F1 | 对齐报告推荐实现 |
|
||||
| LLM-judge | OpenAI/GPT-4o API(评测时才调) | 仅评测用,不进训练 |
|
||||
| 实验追踪 | TensorBoard / wandb(可选) | 轻量 |
|
||||
|
||||
### 6.3 交付里程碑
|
||||
|
||||
| 里程碑 | 内容 | 验证点 |
|
||||
|--------|------|--------|
|
||||
| M1 · 数据管线 | 合成生成 + 真实 benchmark 加载,产出 1k 样本可视检 | 成分/异常/事件正确,JSONL schema 合规 |
|
||||
| M2 · 模型可跑通 | TS Encoder+Projector+多模态拼接,单 batch 前向+反向在 3060 不 OOM | 形状对、显存<12GB、loss 下降 |
|
||||
| M3 · 阶段① 对齐训练 | 50万条 2-3 epoch,TS token 不被忽略 | 扰动时序→回答变化 |
|
||||
| M4 · 阶段② SFT | 10万条 3 epoch + LoRA,6 类任务能遵循指令 | held-out 问答可用 |
|
||||
| M5 · 完整评测 | VUS-PR/Aff-F1/问答分,4 类基线同口径对比 | 超纯LLM基线、非PA虚高 |
|
||||
|
||||
### 6.4 风险与对策
|
||||
|
||||
| 风险 | 概率 | 对策 |
|
||||
|------|------|------|
|
||||
| 12GB 仍 OOM(阶段②) | 中 | 降批量/上下文、开 CPU offload 优化器、退回阶段①-only 报告 |
|
||||
| 合成→真实泛化差距大 | 高 | 阶段②掺真实改写样本;评测以真实 benchmark 为准 |
|
||||
| LLM 忽略 TS token | 中 | 对比损失 + "必看时序"样本 + 消融实验定位 |
|
||||
| 回答 JSON 解析失败率高 | 中 | 训练强化格式约束 + 解析兜底 + 单独报成功率 |
|
||||
| GPT-4o judge 成本 | 低 | 仅评测 2k 样本调用;可换开源 judge 做 sanity |
|
||||
|
||||
### 6.5 整体成功标准(可验证)
|
||||
|
||||
1. 全流程在单张 3060 12GB 跑通,阶段②峰值显存 ≤ 11GB
|
||||
2. 真实 benchmark(SMD/MSL/SMAP/SWaT)VUS-PR **显著优于纯 LLM 数值喂文本基线**
|
||||
3. 时序消融后指标明显下降,证明"时序模态"确有贡献
|
||||
4. 6 类问答任务 LLM-judge 均分 > 纯 LLM 基线
|
||||
5. 评测脚本可复现,含 trivial 基线对照、标注是否用 PA
|
||||
|
||||
---
|
||||
|
||||
## 7. 开放问题(实现阶段再定)
|
||||
|
||||
- TS Encoder 层数/d 是否需在小规模上 sweep(2 层是否够)
|
||||
- Patch P=8/stride=4 是否最优,是否需对比 P=16
|
||||
- 对比损失的具体形式(InfoNCE vs 扰动一致性)与权重
|
||||
- DPO 是否纳入首版(建议首版先不做,M5 后视效果决定)
|
||||
- 真实 benchmark 改写问答的数量与质量校验流程
|
||||
|
||||
---
|
||||
|
||||
> 本规格定义了「长什么样、吃什么数据、怎么训、怎么评、怎么落地」。下一步进入实现计划(writing-plans)。
|
||||
Reference in New Issue
Block a user