# Traj-MC vs SVD-LLM — 主实验 (trajmc_main) 本目录自包含。从零实现 Traj-MC (ours) vs SVD-LLM (baseline) 主实验, 不复用本仓库其它代码/结果(仅作实现参考)。所有产物写入 `results/` 下对应子目录。 --- ## 0. 冲突裁决原则(后续所有设置分歧按此处理) 当 **SVD-LLM (ICLR 2025)** 与 **LLaDA 官方 / Sink-Aware** 的实验设置不一致时, **一律按 LLaDA 官方那条线走。** 理由:我们压缩和评测的对象是 LLaDA,用的是 LLaDA 生态的评测栈 (`eval_llada.py` / lm-eval dLLM 适配),对照表是 Sink-Aware(模型 GSAI-ML/LLaDA-8B-Base)。 SVD-LLM 是 AR 模型(LLaMA/OPT/Mistral)上的工作,其评测惯例不适用于 dLLM 评测栈。 **SVD-LLM 只在【压缩算法本身】上作为权威**:白化数学、rank 公式、full SVD、 Cholesky 及其 except 分支、校准数据的角色。**评测协议一律以 LLaDA 官方为准。** **目标模型 = LLaDA-8B-Base**(推翻早先的 Instruct 倾向)。依据官方 `EVAL.md`: Base 有 ppl(条件似然)评测协议,Instruct 只有 gen(条件生成)、且需逐任务不同的 gen 参数——ARC-C 在 Base(ppl)是 47.9、在 Instruct(gen)是 88.5,是两种不同问法, 不可比。用 Base 才能与 Sink-Aware 同模型同协议、REF 行直接对表。 通用性证据留给 **Dream-7B / LLaDA-1.5**(跨架构家族),不用 Instruct,本轮暂不发。 **评测引擎 = 官方 lm-eval harness**(`eval/llada_harness.py`,vendored 自官方 `eval_llada.py` + 兼容我们 A/B 权重的注入),跑真·lm-eval,逐任务 fewshot/cfg/mc_num、 acc/acc_norm、fewshot 采样、gsm8k 提取全部由权威 harness 处理,零重实现风险。 --- ## 0b. 三个对象(全程只有这三个,命名固定,不得混用) | 名称 | 定义 | 作用 | |---|---|---| | **Dense** | 未压缩的原始 LLaDA。不做任何压缩。 | 上界参照线(压缩前分数)。与 SVD 无关。 | | **BASE** | SVD-LLM 照官方代码原样应用于 LLaDA:t=0 干净文本校准,一次前向收激活,whitening + 截断。已发表方法直接套用,是我们的对手。称 **"SVD-LLM (t=0)"**。 | baseline。 | | **OURS** | Traj-MC:t~U[0,1] 加噪校准,一次前向收激活,其余与 BASE **完全相同**。称 **"Traj-MC (ours)"**。 | 我们的方法。 | 主表三行:**Dense | BASE | OURS**。 BASE 与 OURS 是【单变量对比】:唯一差异 = 校准输入是否加噪。 ⛔ 不存在第四个对象。不引入"稠密轨迹收集/每步收集/dense 压缩臂"——不在本实验范围内。 --- ## 1. 命题与双 claim(一字不改) **【Gap】** SVD-LLM 的 truncation-aware whitening 隐含假设"校准分布 = 推理 分布"。对自回归模型天然成立(推理永远是干净文本,一次前向)。对 LLaDA 不成立:推理是 T 步去噪,输入含大量 MASK,激活分布随步漂移。照官方代码 原样套用(BASE),校准落在一个模型推理时从不经历的干净分布上。 **【方法立论】** t~U[0,1] 的全序列均匀打码,正是 LLaDA 的前向扩散过程, 因此单次采样的校准分布即覆盖模型去噪轨迹上的输入分布,且 X^T X 是轨迹 协方差的无偏估计。Traj-MC 只改校准输入的加噪方式,不改 objective、 白化数学、截断与管线。 ⛔ 不写"prompt 可见 / prefix 保护"——本实验用连续 2048 窗口, 没有 prompt/answer 之分,那套表述与窗口构造矛盾。 **【Claim 1 · performance】** 完全相同管线下单变量对比,OURS 下游表现优于 BASE。 **【Claim 2 · efficiency】** OURS 与 BASE 校准成本相同(均 O(N) 一次前向、 内存 O(d²)/层),但 OURS 的校准分布覆盖去噪轨迹而 BASE 不覆盖—— 即"零额外成本换取轨迹覆盖"。 要覆盖轨迹的朴素替代做法是每个去噪步都收集激活(O(T·N) 前向), 本实验用它作为【论证性对照】说明成本差距,不实现为实验臂。 ⛔ 措辞红线:不得笼统写"比 SVD-LLM 快"——BASE 与 OURS 同为 O(N)。 正确表述:与 BASE 同等成本、额外获得轨迹覆盖;朴素的每步收集才是 O(T·N) 的那个,我们相对它是 O(1)。 --- ## 8. 统计与判读(预注册,出数后一字不改) - **BASE vs OURS 用 McNemar 配对检验**(b=BASE错OURS对,c=BASE对OURS错, χ²=(b−c)²/(b+c)),报 raw acc +(b,c)+ 配对 p。⛔ 禁止非配对 z。 实现对 scipy 校验。 - **7 个 benchmark 同时检验用 Holm-Bonferroni 校正**,报校正前后 p (m=7 时族系错误率约 30%,故需校正)。 - **判读**(每个 benchmark 一视同仁,不预测方向): - 显著 = Holm 校正后 p<0.05; - 多数 benchmark 同向且 ≥2 个校正后显著 → **claim 1 成立**; - 方向分裂或仅 1 个显著 → 报混合结果,不夸大; - OURS 在某些 benchmark 上显著更差 → 如实报 limitation。 - ⛔ **地板规则**:任一臂在某 benchmark 低于 REF 的 15% → 该格作废不解读。 - **"显著但差距很小"** → BASE/OURS 同加 2 个校准 seed 复核,不得事后改判据。 输出到 `results/stats/`。 --- ## Related work / limitation:SVD-LLM 的"校准数据不敏感"消融 ⚠️ **这是 claim 1 最可能被攻击的点,必须正面回应。** SVD-LLM 原文做过校准数据消融:改变校准**数量**、**随机 seed**、**来源数据集** (WikiText-2 / C4 / PTB 等),下游性能变化 **<3%**,据此得出"whitening 对校准数据 不敏感"的结论。若不加区分,这条消融会被直接用来反驳我们:"既然校准数据不敏感, 你换个加噪方式凭什么会有差别?" **我们的论证:mask 维度与"换文本数据集"是性质不同的分布变化。** 1. **他们变的是同一族内的采样。** 数量/seed/来源数据集三者都是从**同一个分布族** —— 干净自然文本 —— 里重新采样。无论 WikiText-2 还是 C4,输入永远是 **完全可观测的干净 token 序列**,MASK 占比恒为 0。换语料只是重新加权了 主题与文体,X^T X 的**精细结构**变了,**支撑集与谱型没变**。<3% 正是 "在干净文本族内部不敏感"的正确读数。 2. **我们变的是前向扩散的坐标 t,不是另一份干净文本。** 在噪声水平 t 下, 有 t 比例的位置被替换成**同一个** id(MASK_ID=126336)。这是范畴上不同的干预: - **token 边缘分布出现质点**:权重为 t 的点质量压在单一 token 上。任何 换语料都造不出这种分布。 - **二阶矩变成 t-混合**:X^T X(t) ≈ (1−t)·Σ_clean + t·Σ_mask + 交叉项。 t→1 时输入趋近常量嵌入序列,协方差朝 MASK 嵌入方向**秩塌缩**。 干净语料之间的互换永远进不了这个区域。 - **白化矩阵就是这个二阶矩**。所以截断子空间是沿一条**以 t 为参数的单参数族** 移动,而不是在同族样本云里抖动。 3. **他们的消融回答的是"哪份干净语料",不是"校准分布是否等于推理分布"。** 对 AR 模型这两件事重合(推理永远是干净文本、一次前向),所以"换语料不敏感" ⇒"校准问题已解决"。对扩散语言模型两者**分离**:推理沿 t 从 1 走到 0, 而干净文本校准(t=0)是模型在推理轨迹上**几乎不停留**的一个端点。 4. **可证伪 + 建议加做的对照。** 如果 mask 维度真的只是又一个良性扰动, 那 BASE vs OURS 也应当 <3% 且统计不显著 —— claim 1 正是对此的直接检验。 **建议补一个廉价对照**:比较 ① 干净族内部(BASE seed1 vs BASE seed2)的截断子空间主夹角 ② 跨 mask 轴(BASE vs OURS)的主夹角(`analysis/subspace_angle.py`)。 若 ② ≫ ①,则从**几何上**直接证明他们的消融没有覆盖我们这条轴。 (需额外一份 BASE 换 seed 的压缩产物,成本 = 1 个压缩 job。) 5. **诚实的 limitation。** 若实测 BASE vs OURS 差距同样 <3% 且 Holm 校正后不显著, 则说明 SVD-LLM 的不敏感结论**外推到了 mask 轴**,claim 1 不成立 —— 按第 8 节如实报告,不做事后改判据。 **附带好处**:因为他们自证"校准语料/数量不敏感(<3%)",我们用 C4-256 而非官方 WikiText2-256 这一偏离(**样本数已与官方一致,仅换语料**),**对 BASE 不构成削弱** —— 按他们自己的结论,这个差异是无关紧要的,故 BASE 仍是忠实、非稻草人的 baseline (见 `docs/svdllm_port_diff.md`)。 --- ## 评测集合(全部 benchmark 平权,不设主副,不预测方向) ⛔ 不得出现"主判据/副判据/预期持平/预期更好"。 **评测协议 = 官方 LLaDA-8B-Base lm-eval 设置**(逐字节核验自 `scripts/eval_llada_lm_eval.sh`,与 Sink-Aware `eval_llada.sh` 完全相同)。 **逐任务不同参数**(不是一刀切)。single source of truth = `common.LMEVAL_TASKS`: | benchmark | lm-eval task | num_fewshot | cfg | mc_num | 打分方式 | **主指标(预注册)** | 官方 EVAL.md Dense | |---|---|---|---|---|---|---|---| | ARC-C | arc_challenge | 0 | 0.5 | 128 | 条件似然 | **acc** | 47.9 | | ARC-E | arc_easy | 0 | 0.5 | 128 | 条件似然 | **acc** | — | | PIQA | piqa | 0 | 0.5 | 128 | 条件似然 | **acc_norm** | 74.4 | | HellaSwag | hellaswag | 0 | 0.5 | 128 | 条件似然 | **acc_norm** | 72.5 | | WinoGrande | winogrande | **5** | **0.0** | 128 | 条件似然 | **acc** | 74.8 | | MMLU | mmlu | **5** | **0.0** | **1** | 条件似然 | **acc** | 65.9 (w/o CFG) | | GSM8K | gsm8k | 5 | — | — | 生成 gen=256/steps=256/**block=256**(全扩散) | **exact_match** | 70.0 | 固定:`is_check_greedy=False`。⛔ GSM8K 是 **block_length=gen_length 全扩散**, **不是** Instruct 的 block=8 半自回归 block diffusion。 ### 主指标预注册(三臂统一,出数后一字不改) 已核实:SVD-LLM 全用 acc、且只用 ARC-E 不用 ARC-C,但按第 0 节裁决**跟 LLaDA**。 LLaDA 官方 EVAL.md 逐任务用 acc 或 acc_norm(见上表),与我们体检实测吻合 (ARC-C acc 46.2≈47.9;HellaSwag acc_norm 70.0≈72.5;PIQA acc_norm 74.2≈74.4)。 ⚠️ acc 与 acc_norm 判对的是**不同的题**,McNemar 是逐题配对检验 —— **主指标压缩前钉死,不得事后择优**。acc/acc_norm 两列都逐项落盘供附录, 但**配对检验只跑上表的主指标列**(`analysis/lmeval_to_items.py` 按 `common.primary_metric` 提取)。 ⛔ **不再使用**"MMLU 单 token mc_num=1 精确"论证与 assert(改用官方 mmlu 5-shot/cfg=0/mc_num=1)。 ### 全量评测(取消一切子采样) **主表 = 7 个 benchmark**(HellaSwag 于 2026-07-24 并入主表)。全部跑全量: GSM8K 1319 / ARC-C 1172 / ARC-E 2376 / PIQA 1838 / WinoGrande 1267 / MMLU **14042** / HellaSwag ~10042(不再 2000 子集)。理由:主表是自比 (BASE vs OURS 同流水线),外部对表只是 sanity;全量把抽样误差压到最低, 且避免"子集选择"成为新自由度。GSM8K 用 harness 内置 accelerate 数据并行 (单 job/单 seed/单 git-hash,gather 原子一致)。 ### 生成域普适性任务(预注册 2026-07-29,出数后不改) **动机**:主表 6/7 显示 OURS 的优势集中在**生成任务 GSM8K**(+9.0, p=2.8e-14), 判别式任务中性偏负。为检验"GSM8K 的胜利是**高-mask 生成任务的共性**、而非单数据集 偶然",追加 4 个生成域任务:**SVAMP / MATH-500 / HumanEval / MBPP**。 **预注册规则(先写死,出数后一字不改)**: - 全部 **三臂 REF/BASE/OURS**、全部 **per-item + McNemar 配对**;Holm 的族大小 **m 相应增大** 到含全部纳入的新任务。 - ⛔ **无论输赢,纳入的任务全部进最终表,不允许只报赢的**。 - **地板规则照旧**:任一臂 < 0.15×REF → 该格标注**作废**(理由=地板,与结果方向无关)。 - **打分器**:新任务一律接入主流水线(`common.LMEVAL_TASKS` + `eval/llada_harness.py`), 与主表同一套;**不用旧 `eval_benchmarks.py`**。生成配置三臂一致、对齐 GSM8K 的 Base 全扩散(block_length=gen_length)。 **执行顺序(按坑大小,不并发)**: 1. **SVAMP**(`eval/lm_tasks/svamp.yaml`,自定义 lm-eval task):与 GSM8K 同类,复用其 数字抽取(flexible-extract)。协议 `fs=5, gen_length=256/steps=256/block_length=256, exact_match`。冒烟已过(ref 4/4)。→ 直接三臂全量(test 300)。 2. **MATH-500**(`eval/lm_tasks/math500.yaml`,复用 minerva_math 的 boxed 抽取 + `is_equiv`): 协议 `fs=4, gen_length=512/steps=512/block_length=512, exact_match`。 ⚠️ **先只跑 REF(dense)一个数**:若 **REF < ~20 分 → 整个任务不纳入**(Base 竞赛数学 固有局限,此决定在看到 BASE/OURS 前做出,非选择性排除)。REF 够高才跑三臂。 3. **HumanEval / MBPP**(代码生成,lm-eval 现成 `humaneval.yaml`/`mbpp.yaml`,**pass@1 实测执行** = 生成代码跑测试 assert;需 `HF_ALLOW_CODE_EVAL=1` + `--confirm_run_unsafe_code`)。 ⛔ **不做代码指令微调**:前提是 LLaDA-8B-Base 未微调,一旦微调整个主表+对照全部作废; 且比的是 OURS−BASE 相对差,模型绝对代码水平不影响 claim。 ⚠️ **同 MATH-500 的 REF 前置门槛**(决定在看 BASE/OURS 前做,理由=REF 水平非结果方向): 先只跑 **REF 全量(HumanEval 164 / MBPP 500)**;**REF pass@1 ≥ 20% → 发三臂**; **< 20%(接近地板)→ 标注"REF 过低不纳入"**(压后 BASE/OURS 大概率双双触地板、无解读空间)。 20–25% 灰区按 REF 数当场判,仍在看 BASE/OURS 前。冒烟已过(8 题验证判分正确,但方差太大不作数)。 ### Dense sanity check(压缩评测的前置闸门) REF 用官方 harness 全量跑,与**官方 EVAL.md**(内部自洽)对表(见上表末列)。 ⚠️ **不再用 Sink-Aware Dense 行**:其 MMLU 65.97(需 5-shot)与 WinoGrande 69.30(只能 0-shot)在单一协议下互不自洽;按第 0 节裁决以 LLaDA 官方为准。 ### MMLU 5pp 归因记录(不改协议) 体检 0-shot/cfg=0.5/mc_num=128 得 MMLU 61.0,官方 5-shot/cfg=0/mc_num=1 是 65.9。 Δ 是**问法不同**,非 pipeline bug:官方 MMLU/WinoGrande 都是 **5-shot**;0-shot 低于 5-shot 属预期(WinoGrande 官方 5-shot 74.8 vs 我们 0-shot 69.0 同此规律)。 → **不为追平修改协议**,改用官方 per-task 设置后 REF 应自然接近 65.9。 **REF 对不上官方 → 先查 pipeline,不往下跑任何压缩评测。** --- ## 工作点与对象 - **唯一主工作点 = all-linear r=0.7**。主表 = BASE vs OURS @ all-linear r=0.7(单工作点)。 attn-only r=0.8 的两个压缩产物 **parked(保留权重,不做任何评测)**——r=0.8 压缩幅度不够, 不作为工作点;日后若要压缩率趋势再另议。 - **`ratio` 语义(钉死,防历史歧义)**:`k = int(ratio·d_out·d_in/(d_out+d_in))`, 故 compressed ≈ `ratio·d_out·d_in` = `ratio × 原始参数量`。即 **`ratio` = 参数保留比例**: `r=0.7` 保留约 70% 参数(压掉约 30%)。实测:q_proj kept=0.6997、ff kept=0.700。 `compression_summary.json` **同时落实测 `kept_fraction = compressed/orig`**——以实测比值为准, 不以 `ratio` 符号为准。summary diff 门禁核对 BASE/OURS 的 `kept_fraction` 与逐层 rank 一致。 - **评测协议差异备注(本轮不处理)**:我们 REF 已对齐 LLaDA 官方 EVAL.md 逐任务协议 (arc/piqa/hella 0-shot、winogrande/mmlu 5-shot、cfg 逐任务),与 Sink-Aware 论文表格所用的 统一 0-shot 不同。这只影响"能否直接引用 Sink-Aware 表格数字",**不影响主 claim** (BASE vs OURS 同流水线自比)。是否补跑统一 0-shot 对表协议,等主实验结果出来后再定。 - 压缩范围:`model.model.transformer.blocks` 内全部目标 Linear(32 blocks × 7 = **224 层**); `lm_head` 保持 dense(加载器硬防线)。 - MASK_ID = 126336;nsamples = 256;连续 2048 token 窗口。 --- ## 目录 ``` trajmc_main/ ├── README.md ← 本文件(命题 + 判读规则) ├── docs/svdllm_port_diff.md ← 忠实移植差异表(进论文附录) ├── docs/JOBS.md ← job 台账(每提交一个 job 追加一行) ├── common.py ← 共享工具(模型加载/层遍历/hash/rank 公式) ├── calib/build_calib.py ← 唯一允许 BASE/OURS 有差异的模块(加噪开关) ├── compress/compress.py ← 共享压缩管线(增量 XtX + Cholesky 白化) ├── compress/official_collect.py← 官方结构收集路径(仅内存实测用,不产权重) ├── eval/eval.py ← 共享评测 + per-item 落盘 ├── analysis/{mcnemar,holm,merge_shards,subspace_angle}.py ├── jobs/ ← sbatch 脚本 ├── weights/{ref,base,ours}/ └── results/{calib,compress,eval/{ref,base,ours},efficiency,stats}/ ``` ⚠️ 所有产物一律写入 `results/` 下对应子目录,不散落到代码目录或 home。 每个结果文件名带 job id 与 git hash 前缀,便于追溯。 --- ## 执行顺序(第 9 节,③ 后必须停下等确认) ① 归档旧目录 + 建目录 + 本 README + port_diff + JOBS · ② 写全部代码 + 全部自检 · ③ BASE/OURS dry_run 自检 → **停下等确认** · ④ 4 个压缩 job → summary diff · ⑤ 官方结构内存实测 · ⑥ 评测 Dense+BASE+OURS · ⑦ mcnemar+holm 出表 · ⑧ 视结果定 CoT 1:1 消融范围。