From 150e3bd9fd1fec3df8fb517a42648972515f7256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=AE=97=E5=B9=B3?= Date: Fri, 3 Jul 2026 11:52:09 +0000 Subject: [PATCH] docs(ts-as-modality): archive after cross-domain generalization failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full diagnostic chain (synth→real zero-shot→real finetune→held-out) shows the TS-modality approach works in-distribution but fails to generalize across entities: same SMD dataset, same 38 channels, just a different machine (1→2) collapses output to repetition garbage. Root cause is the lightweight TS encoder (2-layer TF, 2.1M params) learning dataset/machine- specific patterns rather than transferable time-series representations. This is a valuable negative result: it cleanly rules out the '0.5B LLM + 2-layer TS encoder + single-distribution synth training' route for general time-series understanding, which is more credible than any 'looks like it works but never tested cross-domain' result. Records: - tasks.md: M6 diagnostic section (6.1-6.5) with evidence + archive decision - proposal.md: Status header flagging archive + pointer to diagnosis - docs/diagnosis-2026-07-02-cross-domain.md: full evidence chain, root-cause analysis, capability boundaries, asset inventory, restart conditions Project status: archived. Code/data/checkpoints/reports preserved. Restart requires any of: (1) larger encoder + real-data from-scratch training, (2) channel-agnostic patch strategy, (3) multi-dataset joint training with held-out-dataset generalization proof. --- docs/diagnosis-2026-07-02-cross-domain.md | 140 ++++++++++++++++++++ openspec/changes/ts-as-modality/proposal.md | 4 + openspec/changes/ts-as-modality/tasks.md | 29 ++++ reports/eval-2026-07-02.md | 57 ++++++++ 4 files changed, 230 insertions(+) create mode 100644 docs/diagnosis-2026-07-02-cross-domain.md create mode 100644 reports/eval-2026-07-02.md diff --git a/docs/diagnosis-2026-07-02-cross-domain.md b/docs/diagnosis-2026-07-02-cross-domain.md new file mode 100644 index 0000000..a1a55a3 --- /dev/null +++ b/docs/diagnosis-2026-07-02-cross-domain.md @@ -0,0 +1,140 @@ +# 诊断报告 · ts-as-modality 跨域泛化失败与方案封存 + +> **日期**:2026-07-02 +> **状态**:方案封存(资产保留,不再投入) +> **决定性问题**:合成域有效的「TS-as-modality」方案,能否泛化到真实时序? + +--- + +## TL;DR + +方案在合成域内有效,但在真实时序上**跨实体泛化失败**——同一 SMD 数据集、同样 38 通道、仅换了机器(machine-1 → machine-2),模型输出从合法 JSON 崩溃为 repetition garbage。证据链完整指向:TS encoder 学到的是数据集/机器特有模式,而非可泛化的时序表征。方案作为研究性 PoC 划定了清晰的能力边界,但当前架构无法支撑「通用时序理解」这一目标,故封存。 + +--- + +## 完整诊断链 + +### 阶段 1:合成域内验证(成立) + +在全量合成数据(50 万对齐 + 10 万 SFT)训练后: + +| 指标 | model | pure_llm | 结论 | +|---|---|---|---| +| 时序消融 change_rate | 0.98/50 | — | TS token 确实被消费 ✅ | +| QA 均分(6 类) | 2.41 | 0.90 (2.7×) | TS 模态是必要非装饰 ✅ | +| anomaly JSON 解析率 | 0.98 | 0.01 | 格式学习成功 ✅ | +| VUS-PR | 0.22 | 0.24 | ⚠️ 输给 trivial baseline | + +**阶段 1 结论**:机制可行,QA 能力真实,但异常精准定位弱(VUS-PR 输 trivial)。 + +### 阶段 2:zero-shot 跨域(崩溃) + +用未微调的合成 ckpt 直接评测真实 SMD(machine-1/2/2-1 合并,prevalence 5.8% vs 合成 26%): + +| 指标 | model(real) | 解读 | +|---|---|---| +| parse_rate | **0.00** | 没有任何输出可解析 | +| Aff-F1 | **0.00** | 完全无定位能力 | +| QA mean | **0.00** | vs synth 的 2.41 | +| VUS-PR | 0.2263 | = all_report,是**假象** | + +**输出样本**(repetition collapse,LLM 在 OOD 输入下的典型崩溃): +``` +'ERYoticaisonaisonanxietyaisonaisonanaisonanaison...' +'horizon: horizon: horizon: horizon: horizon:...' +``` + +**VUS-PR=0.2263 的真相**:模型输出全是 garbage → `parse_anomaly_segments` 失败 → `answer_to_point_scores` 返回全 0 → `vus_pr(全0, y)` 退化为 prevalence(=0.226)。所以「VUS-PR 与 trivial 持平」是假象,模型实际**什么都没做**,只是被 prevalence 下限兜住了。这是一个**评测陷阱**:低质量输出在低 prevalence 下会被误读为「不算太差」。 + +**干扰变量排除**:改写 instruction(短措辞 / 通用模板)后输出仍是 garbage,排除「指令过长/格式不兼容」因素,确认是 TS embedding 的分布偏移所致: +- 通道数:5(合成)→ 38(SMD) +- 数值分布:合成 mean~46/std~23 vs SMD z-score 后 mean~0/std~0.6 + +### 阶段 3:SMD 微调(训练域内有效) + +从 stage2_final 继续训 LoRA on SMD train(machine-1-1/1-2,141 样本,500 步,EMA 1.27→1.00): + +**训练域内输出**(machine-1-1/1-2,微调后): +``` +{"anomaly_regions": [{"start": 309, "end": 412}], "n_regions": 1} ✅ +{"anomaly_regions": [{"start": 0, "end": 136}], "n_regions": 1} ✅ +{"anomaly_regions": [{"start": 103, "end": 126}], "n_regions": 1} ✅ +``` +4/5 产出合法 JSON,格式与语义均正确。**机制在训练域内正常工作**。 + +### 阶段 4:跨实体 held-out(崩溃,决定性) + +用同一个微调后模型评测 SMD held-out(machine-2-1,同数据集/同 38 通道/同样 z-score 分布,仅换机器): + +``` +[anomaly] '{"}\xa0\n\xa0\n\xa0\n\n\xa0\xa0 (since)...' ❌ +[anomaly] '{"id": 1, "name": "nan \n\n\n...' ❌ +[describe] '------------{"}10M 参数,且用真实多数据集从头训练(非仅微调),让 encoder 有足够容量和分布覆盖学到通用表征。 +2. **channel-agnostic patch 策略**:消除「通道数」这一硬约束(当前 patch embed 固定 5 通道,是跨域的物理障碍),如 per-channel 独立编码后聚合。 +3. **多真实数据集混合训练验证泛化**:在 SMD/SWaT/PSM 等多个真实数据集上联合训练,并在完全 held-out 的数据集上验证——只有这种泛化成立,方案才算「通用」。 + +在以上任一条件未满足前,本方案不再投入。 diff --git a/openspec/changes/ts-as-modality/proposal.md b/openspec/changes/ts-as-modality/proposal.md index 52af8bb..9113674 100644 --- a/openspec/changes/ts-as-modality/proposal.md +++ b/openspec/changes/ts-as-modality/proposal.md @@ -1,3 +1,7 @@ +## Status + +**已封存(2026-07-02)**。完整诊断与结论见 `docs/diagnosis-2026-07-02-cross-domain.md`。摘要:合成域内有效(QA 2.41 vs pure_llm 0.89,TS token 消费率 0.98),但真实时序**跨实体泛化失败**——同 SMD 数据集换机器即崩溃为 garbage 输出。TS encoder(2层TF/2.1M参数)学到数据集特有模式而非通用时序表征。方案作为研究性 PoC 划定了能力边界(合成域可行/跨域不可行),资产保留,重启条件见诊断报告。 + ## Why 当前 AIOps 场景下,多变量时序的异常检测与解释仍依赖专用模型,缺乏「以自然语言对时序提问、做根因/事件关联推理」的统一能力。基于 `MTSAD-技术深度调研报告.md`,沿用 ChatTS「时序作为新模态」路线,我们希望在**单张 3060 12GB 消费级显卡**上做一个可复现的实验性落地,验证「把多变量时序视为独立模态、与文本/事件模态联合注入小型 LLM」这一方法在算力受限条件下是否切实可行、且「时序模态」是否真带来可量化的增益。现在做是因为:0.5B 级开源 LLM 与 PEFT/LoRA 工具链已足够成熟,使该实验在消费级硬件上首次成为可能。 diff --git a/openspec/changes/ts-as-modality/tasks.md b/openspec/changes/ts-as-modality/tasks.md index 9b3693d..53f8621 100644 --- a/openspec/changes/ts-as-modality/tasks.md +++ b/openspec/changes/ts-as-modality/tasks.md @@ -50,3 +50,32 @@ - ✅ **全量重训验证假设**:小规模时 VUS-PR 弱的根因是数据量(5万→50万),而非算法本身——全量后 VUS-PR +57% 且 Aff-F1 碾压 pure_llm。 - 结论:实验性单卡管线全量跑通;模态融合 + QA + 时序定位(相对纯 LLM)均达成,绝对定位精度待后续。real benchmark(SMD/SWaT 等)需下载后补入 `data/eval_real.jsonl` - 全量训练产物:stage1 `stage1_final.pt`(31250 步 EMA 1.26)+ stage2 `stage2_final.pt`+`lora_adapter`(9375 步 EMA 0.75) + +## 6. M6 · 真实 benchmark 接入与跨域诊断(封存前最终验证) + +> 目的:回答「合成域有效,但方案能否泛化到真实时序?」这一决定性问题。结论决定方案去留。 + +- [x] 6.1 SMD 真实数据接入(`data/real/smd/`):下载 NetManAIOps/OmniAnomaly 的 machine-1-1/1-2/2-1 的 test+test_label(.txt→.npy,3机合并 75867 步 ×38 通道,prevalence **5.8%** vs 合成 26%,构成低-prevalence 对照)。loader `real_bench._load_npy_pair('smd')` 验证通过 +- [x] 6.2 生成 `data/eval_real.jsonl`(SMD machine-2-1,46 样本:14 anomaly + 32 describe,严格 held-out)+ SMD 微调数据 `data/smd_ft/sft.jsonl`(machine-1-1/1-2,141 样本:47 anomaly + 94 describe) +- [x] 6.3 zero-shot 跨域评测(`reports/eval-2026-07-02.md`,未微调 stage2): + - **real 上 model parse_rate=0、Aff-F1=0、QA=0.00**——输出是 repetition collapse(`aisonaison...`/`horizon: horizon:...`),LLM 在 OOD 输入下的典型崩溃; + - VUS-PR=0.2263 恰好等于 all_report 是**假象**:解析失败→全 0 分数→vus_pr 退化为 prevalence,模型实际什么都没检测; + - 干扰变量排除:改写 instruction(短/通用措辞)输出仍是垃圾,确认非指令长度/格式问题,是 TS embedding 分布偏移(38通道 vs 5通道、z-score 分布 vs 合成数值范围)。 +- [x] 6.4 SMD 微调实验(`checkpoints/stage2_smd/`,500 步 EMA 1.27→1.00):从 stage2_final 继续训 LoRA on SMD train(machine-1-1/1-2)。 +- [x] 6.5 微调后跨实体泛化诊断(决定性实验): + - **SMD 训练域内**(machine-1-1/1-2):4/5 产出合法 `{"anomaly_regions":[...]}` JSON ✅——机制正常; + - **SMD held-out**(machine-2-1,同数据集/同 38 通道/仅换机器):仍是垃圾输出 ❌; + - 结论:**跨实体泛化失败**。同数据集换机器就崩溃,证明 TS encoder 学到的是数据集/机器特有模式,而非可泛化的时序表征。 + +### 初步结论(方案封存依据) + +**证据链**:合成域内有效(QA 2.41 vs 0.89、change_rate 0.98)→ SMD 训练域内有效(4/5 合法 JSON)→ SMD held-out machine 崩溃(全 garbage)。 + +**方案意义与边界**(详见 `docs/diagnosis-2026-07-02-cross-domain.md`): +- ✅ **成立**:TS 模态融合机制可行(token 被消费、非噪声);合成域内 QA 能力真实(TS 模态是必要非装饰);格式学习能力正常(141 样本即可学会)。 +- ❌ **未立住**:跨实体泛化失败(同数据集换机器就崩)——非调参可解,是 TS encoder(2层TF/2.1M参数)学到数据集特有模式;合成域 VUS-PR 0.22 仍输 trivial;zero-shot 跨域不存在。 +- 🏷 **方案定位**:作为「轻量 TS-modality 融合」的研究性 PoC,其价值在于**清晰地划定了能力边界**——合成域内可行,但当前架构无法泛化到真实时序。这是有价值的负结果,优于任何「看起来 work 但未测跨域」的结果。 + +### 封存决定 + +**方案封存**。资产保留(代码/数据/checkpoints/报告均 git-tracked 或备份),不再投入。重启条件(任一即可):① 更大 encoder(>10M 参数)+ 真实数据从头训练(非仅微调);② channel-agnostic patch 策略(消除通道数硬约束);③ 多真实数据集混合训练验证泛化。 diff --git a/reports/eval-2026-07-02.md b/reports/eval-2026-07-02.md new file mode 100644 index 0000000..f4ee1e9 --- /dev/null +++ b/reports/eval-2026-07-02.md @@ -0,0 +1,57 @@ +# Eval Report — 2026-07-02 + +Generated by `scripts/run_eval.sh` → `tsmm.eval.report`. + +## Discipline notes +- **Main metric: VUS-PR** (threshold-free). +- **Point-F1 reported WITHOUT point-adjust.** PA-F1 shown separately as a CONTROL only. +- Trivial baselines (random / constant / all-report) are included. +- LLM-judge backend: `stub`. + +## Dataset: synth + +| predictor | n | VUS-PR | Aff-F1 | AUC-PR | Point-F1 | PA-F1(control) | parse_rate | +|---|---|---|---|---|---|---|---| +| model | 361 | 0.2241 | 0.2474 | 0.3050 | 0.2186 | 0.5018 | 0.98 | +| pure_llm | 361 | 0.2420 | 0.0023 | 0.2941 | 0.0013 | 0.0071 | 0.01 | +| random | 361 | 0.3266 | 0.3970 | 0.2689 | 0.3266 | 0.9771 | 1.00 | +| constant | 361 | 0.2601 | 0.4302 | 0.2951 | 0.3914 | 1.0000 | 1.00 | +| all_report | 361 | 0.2601 | 0.4302 | 0.2951 | 0.3914 | 1.0000 | 1.00 | + +_PA = point-adjust; shown as control only, not headline._ + +### QA judge (stub 0-5) — synth + +| predictor | anomaly | compare | describe | event | forecast | root_cause | mean | +|---|---|---|---|---|---|---|---| +| model | 2.45 | 2.75 | 1.34 | 3.89 | 0.03 | 3.99 | 2.41 | +| pure_llm | 0.02 | 1.21 | 0.17 | 1.62 | 0.11 | 2.20 | 0.89 | +| random | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | +| constant | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | +| all_report | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | + +_QA judge = offline stub token-overlap heuristic; swap `--judge_backend openai` for GPT-4o scoring._ + +## Dataset: real + +| predictor | n | VUS-PR | Aff-F1 | AUC-PR | Point-F1 | PA-F1(control) | parse_rate | +|---|---|---|---|---|---|---|---| +| model | 39 | 0.2263 | 0.0000 | 0.4516 | 0.0000 | 0.0000 | 0.00 | +| pure_llm | 39 | 0.2236 | 0.0001 | 0.4516 | 0.0000 | 0.0000 | 0.00 | +| random | 39 | 0.2546 | 0.3070 | 0.2894 | 0.2546 | 0.9744 | 1.00 | +| constant | 39 | 0.2263 | 0.3321 | 0.4516 | 0.3088 | 1.0000 | 1.00 | +| all_report | 39 | 0.2263 | 0.3321 | 0.4516 | 0.3088 | 1.0000 | 1.00 | + +_PA = point-adjust; shown as control only, not headline._ + +### QA judge (stub 0-5) — real + +| predictor | anomaly | describe | mean | +|---|---|---|---| +| model | 0.00 | 0.00 | 0.00 | +| pure_llm | 0.28 | 0.00 | 0.14 | +| random | 0.00 | 0.00 | 0.00 | +| constant | 0.00 | 0.00 | 0.00 | +| all_report | 0.00 | 0.00 | 0.00 | + +_QA judge = offline stub token-overlap heuristic; swap `--judge_backend openai` for GPT-4o scoring._