17 KiB
17 KiB
时序作为模态的多模态模型 · 设计规格
日期: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 整体成功标准(可验证)
- 全流程在单张 3060 12GB 跑通,阶段②峰值显存 ≤ 11GB
- 真实 benchmark(SMD/MSL/SMAP/SWaT)VUS-PR 显著优于纯 LLM 数值喂文本基线
- 时序消融后指标明显下降,证明"时序模态"确有贡献
- 6 类问答任务 LLM-judge 均分 > 纯 LLM 基线
- 评测脚本可复现,含 trivial 基线对照、标注是否用 PA
7. 开放问题(实现阶段再定)
- TS Encoder 层数/d 是否需在小规模上 sweep(2 层是否够)
- Patch P=8/stride=4 是否最优,是否需对比 P=16
- 对比损失的具体形式(InfoNCE vs 扰动一致性)与权重
- DPO 是否纳入首版(建议首版先不做,M5 后视效果决定)
- 真实 benchmark 改写问答的数量与质量校验流程
本规格定义了「长什么样、吃什么数据、怎么训、怎么评、怎么落地」。下一步进入实现计划(writing-plans)。