tysgydk/Qwen3.6-35B-A3B-LoopIntervention
English summary. A work-in-progress research repository for "loop intervention" on a frozen Qwen3.6-35B-A3B-FP8 trunk: it contains a small GRU-gated intervention network (about 12.59M parameters) that is inserted between two forward passes of the frozen MoE trunk, plus the glue scripts used to train it, probe per-layer expert-routing overlap between loop 1 and loop 2, run smoke evaluations, and watch a training run. Despite the repository name, there are no 35B model weights here — only two ~50 MB intervention checkpoints and ten scripts; the base model must be downloaded separately. Not a ready-to-use model.
这是什么
- 研究目标:在冻结的
Qwen3.6-35B-A3B-FP8(作者卡片描述:35B MoE、FP8、hidden 2048、40 层)之上叠加循环干预网络,把"循环干预"从稠密模型迁移到 MoE 架构上做实验。 - 干预网络(
scripts/train_qwen36.py的IntervNet):proj(2048→1024→2048 的 SiLU MLP,输出层零初始化)+gate(Linear(4096→2048),对[h; fh]逐维输出 update gate)。前向流程:pass1 用no_grad跑一趟主干取last_hidden_stateh1 →h1' = (1-z)⊙h1 + z⊙proj(h1+噪声)→ pass2 以h1'作inputs_embeds再过一遍 40 层(主干冻结,但梯度穿到干预网),只在这一圈算 CE。作者卡片给出约 12.59M 参数(脚本运行时会打印约 12.6M)。 - 仓库性质:训练/探针/评测的胶水代码 + 少量中间检查点,不是成品模型。作者在原卡片顶部标注「⚠️ 半成品 / Work in Progress …… 干预网络 ckpt 均为实验中间产物,不是可用于正式场景的成品模型」。
不含 35B 权重(重要澄清)
- 作者本人的明确说明:「这个 35B 的库里面其实没有 35B 的模型,我放的是胶水代码。」
- 文件清单也能核实这一点:整个仓库只有 16 个条目(含
ckpt/、scripts/两个目录条目),0 个 LFS 对象,最大的文件是两个约 50 MB 的.pt检查点。没有任何(分片)权重文件,没有config.json,没有 tokenizer/safetensors。 - 因此:不要指望在这里下载到 35B 模型;
AutoModelForCausalLM.from_pretrained("<本仓库>")也不能工作。要复现必须自行准备Qwen/Qwen3.6-35B-A3B-FP8基座(脚本里的路径是本地目录/root/autodl-tmp/models/Qwen/Qwen3.6-35B-A3B-FP8)。
仓库内容
Qwen3.6-35B-A3B-LoopIntervention/
├── README.md # 原卡片(无 license 字段)
├── .gitattributes # 标准模板,声明 *.pt 走 LFS(实际 0 个 LFS 对象)
├── ckpt/ # 2 个干预网络检查点(各约 50 MB)
└── scripts/ # 10 个脚本
ckpt/:2 个检查点(每个约 50 MB)
| ckpt(大小) | 结构(引自原卡片) | 状态(引自原卡片) |
|---|---|---|
qwen36_r2_v4_step1500.pt (50.4 MB) |
GRU 逐维门控 R=2,数据 v3(纯 OpenR1 长链 12000 条),bs=1 | 当前基线(MATH 前 7 题 7/7 全对) |
qwen36_r2_v5_step500.pt (50.4 MB) |
v4 基础上 bs=4 续训 500 步(累计约 0.37 ep) | 欠训检验中 |
- 文件内容是干预网络,不是主干:
train_qwen36.py:220保存的是{'interv': interv.state_dict(), 'step': step, 'args': vars(args)}—— 只有干预模块参数 + 该次训练的启动参数,没有任何主干权重。 - 命名对应训练时的
--outdir与打点步:脚本写出<outdir>/step{N}.pt,--save-every默认 500。仓库里只保留了 v4 的 step1500 与 v5 的 step500 两个点。 - 部分脚本仍指向不在仓库内的旧检查点:
eval_qwen36_r2_smoke.py、probe_expert_overlap_qwen36.py、probe_expert_overlap_math500.py默认用qwen36_r2_v3/step1000.pt;仓库内只有 v4/v5。
scripts/:10 个脚本
训练(2 个,互为单条/批量版本)
train_qwen36.py(229 行,R=2 单条训练):load_model()加载 FP8 主干(device_map='auto'、max_memory={0:'42GiB','cpu':'700GiB'}、主干全部requires_grad_(False)、非重入梯度检查点);数据按<|im_start|>assistant\n切分,prompt 标-100;在每层mlp.gate(router)上挂 forward hook 记录圈1/圈2 的 top-k 专家索引,每 10 步算一次重叠率写入expert_overlap.jsonl;lm_head 计算按CH = 512分块控显存。train_qwen36_bs.py(231 行,批版,--bs默认 4):右 padding + attention_mask;CE 改为手工梯度分块——no_grad逐块算 logits,解析求dCE/dlogits = softmax - onehot,累加成grad_h后一次性h2s.backward(grad_h),使 logits 不建图、峰值显存与序列长度脱钩;bs>1 时跳过专家重叠打点。其余(架构/噪声/lr/数据/ckpt 格式)与单条版一致。- 两者共同的默认超参:
--steps 3000 --lr 5e-4 --noise 0.05 --save-every 500 --seed 0(批量版--steps 30)。 - 两者都依赖模块
qwen36_fp8_patch(注释为"FP8 加载/算子修复"),该文件不在仓库内。
探针(4 个,专家路由重叠)
probe_expert_overlap_qwen36.py:GSM8K 10 题、R=2 双 cache 生成,hook 每层 router 的 top-k 索引,统计同一 token 同一层上"圈1 vs 圈2"选中专家的重合率(cap=2048,thinking on)。probe_expert_overlap_qwen36_v4.py:同上,默认 ckpt 换成 v4/step1500。probe_expert_overlap_qwen36_v5.py:单题细粒度版——每 token 每层保存原始重叠计数(int8)而不预聚合,另记录每 token 门控 z 的 min/max/mean 与</think>边界,落盘.npz供离线切分"思维链段 / 正文段"两相,并可设--temp > 0采样。probe_expert_overlap_math500.py:MATH500 前 20 题同口径探针,另随机抽 1 题把完整答案写盘,并用最后一个\boxed{...}做粗略评分(作者注明数学答案归一化不可靠、仅供参考)。
评测与辅助(4 个)
eval_qwen36_r2_smoke.py/eval_qwen36_r2_smoke_v4.py:GSM8K 前 20 题对比 base R=1(主干官方generate)vs 干预 R=2(双 cache 增量解码),按#### 数字评分并输出 jsonl + 控制台 acc。score_probe.py:从文本中提取最后一个\boxed{...}(手写括号配对解析)。watch_train.py:训练看门狗,静默监视PID + 日志路径——进程退出但无[DONE]→ 退出码 1,日志 mtime 停滞超过打点预算的 2.5 倍 → 2,loss 出现 nan/inf 或 >1.5 → 3,gnorm > 10 → 4,打点步 tok/s < 50 → 5,出现[DONE]→ 0,平时不打印任何内容。
脚本用法(脚本内取证的真实命令)
# 训练 v4(单条版;默认 steps=3000, lr=5e-4, noise=0.05, save-every=500)
python scripts/train_qwen36.py --outdir /root/autodl-tmp/ckpt/qwen36_r2_v4
# 从 v4 继承:--resume-proj 只复用 proj(gate 新建),--resume 则整体恢复
python scripts/train_qwen36.py --steps 500 \
--resume-proj /root/autodl-tmp/ckpt/qwen36_r2_v4/step1500.pt \
--outdir /root/autodl-tmp/ckpt/qwen36_r2_v5
# 批量续训(v5 的 bs=4 续训走这个脚本)
python scripts/train_qwen36_bs.py --bs 4 --steps 500 \
--resume /root/autodl-tmp/ckpt/qwen36_r2_v4/step1500.pt \
--outdir /root/autodl-tmp/ckpt/qwen36_r2_v5
# 专家重叠探针(细粒度版;--i 题号,--data math|gsm8k,--cap 生成长度,--temp>0 采样)
python scripts/probe_expert_overlap_qwen36_v5.py --i 0 --data math --cap 8192 \
--ckpt /root/autodl-tmp/ckpt/qwen36_r2_v4/step1500.pt
# 冒烟评测(GSM8K 前 20 题,base R=1 vs 干预 R=2)
python scripts/eval_qwen36_r2_smoke_v4.py
# 训练看门狗:<pid> <log_path> [打点时间预算秒数]
python scripts/watch_train.py <pid> <train.log> 400
运行前注意:所有脚本硬编码了绝对路径——MODEL = '/root/autodl-tmp/models/Qwen/Qwen3.6-35B-A3B-FP8'、DATA = '/root/autodl-tmp/data/qwen36_train_v3.jsonl'、探针写出 /root/loop-exp/probe_v5_*.npz、评测读 /root/autodl-tmp/data/math500/test.jsonl 与 /root/autodl-tmp/data/gsm8k2/main/test-00000-of-00001.parquet;这些数据文件与 FP8 patch 模块都不在仓库内。
技术要点
- 初始化设计(
train_qwen36.py:26-43):proj 的输出层零初始化(开局等价于恒等,不破坏主干输出)、gate 的 bias 设为log(z0/(1-z0))使起始 sigmoid ≈ 0.05(贴近主干"安全点");训练时给 proj 输入加高斯噪声--noise 0.05增强稳健性。 - 只对第二圈算 CE:prompt 部分标
-100,序列以<|im_end|>收尾;token 边界与 prompt 前缀不一致的样本会被跳过(train_qwen36.py:80-95打印跳过的条数)。 - FP8 主干加载:
qwen36_fp8_patch+Qwen3_5MoeForCausalLM,FP8 反量化走纯 torch fallback;显存靠device_map='auto'、max_memory与梯度检查点控制。 - 显存工程:单条版把 lm_head 分块(
CH=512逐块算 CE);批量版进一步改成解析梯度的手工分块,使 logits 不进入计算图。 - 专家重叠统计当作可解释性工具:hook
layer.mlp.gate的 forward 输出第 3 项(top-k 索引),只在打点步计算以免拖慢训练;细粒度版把原始计数落盘,支持按 think/body 两相切分后再统计。 - 作者给出的结论(原卡片「当前结论」):
- MoE 真循环的专家分工是真实且分相位的——圈1 vs 圈2 的 top-8 专家重叠率 think 段 0.164 > body 段 0.134(7/7 题同向),分层从浅层约 0.05 单调爬到末层 0.46。
- v4 是当前基线:MATH 前 7 题 7/7 全对、全自然收尾(cap8192)。
- v5 欠训检验:在 v4 基础上以 bs=4 续训 500 步,loss 缓降未停,方向性支持"仍欠训"。
已知限制
- 仓库名会误导 + 没有 35B 权重:仓库名里的
Qwen3.6-35B-A3B只是研究的目标基座,作者原话是「这个 35B 的库里面其实没有 35B 的模型,我放的是胶水代码」;文件清单一并核对(16 个条目、0 LFS、最大文件 50 MB)与之一致。 - 许可:Apache-2.0(上游
Qwen/Qwen3.6-35B-A3B-FP8官方标为apache-2.0);仓库已随附LICENSE全文。 - 不是可用的模型:半成品 / Work in Progress;作者自述的成绩只是 MATH 前 7 题、GSM8K 前 20 题这类小样本冒烟结果,样本量太小,不构成任何能力结论。
- 缺失依赖(现状下脚本跑不起来):两个训练脚本
import qwen36_fp8_patch(不在仓库内),两个冒烟评测脚本from gen_qwen36_r2 import gen_two_cache(不在仓库内);主干与数据也需自行准备。 - 版本错配:
probe_expert_overlap_qwen36.py、probe_expert_overlap_math500.py、eval_qwen36_r2_smoke.py默认指向qwen36_r2_v3/step1000.pt,该检查点不在仓库内(仓库只有 v4/v5)。 - 脚本硬编码绝对路径;依赖的数据文件(
qwen36_train_v3.jsonl、MATH500/GSM8K 测试集)不在仓库内,训练数据来源与规模无法在本仓库内核实。 - 检查点里虽然存了启动参数
args,但仓库没有附带训练日志/指标文件,超参与耗时只能从 argparse 默认值和文件名推断。 .gitattributes声明*.pt走 LFS,但仓库内当前 0 个 LFS 对象(.pt是普通文件)。- 作者卡片提到的"数据 v3(纯 OpenR1 长链 12000 条)"以及专家重叠率数值,均没有对应的结果文件或日志随仓库发布。
未说明的信息:基座 Qwen/Qwen3.6-35B-A3B-FP8 的权重可获取性(仓库内没有它的 config.json,无法在这里核对;许可已核实为 apache-2.0);训练数据 qwen36_train_v3.jsonl 的实际规模与构造方式;训练硬件与每步耗时(脚本里有 tok/s 打点、看门狗里有时间预算参数,但没有结果);两个检查点之外的历史打点;仓库的上传/最后更新时间。
许可
Apache License 2.0。 上游主干 Qwen/Qwen3.6-35B-A3B-FP8 的官方 model card 标为 apache-2.0(已核实),作者已确认本仓库按 Apache-2.0 开源,故 front matter 写 license: apache-2.0。
干预检查点本身不含主干权重;主干权重以其自身仓库为准(本仓库未再分发其任何文件)。
本仓库已随附 Apache-2.0 许可全文(根目录 LICENSE,11,343 字节,取自上游官方仓库原文,未作任何改动)。版权署名:Copyright 2026 我本是我沐(ModelScope @tysgydk / Hugging Face @tysgydke)。
引用
- 本仓库(ModelScope):https://modelscope.cn/models/tysgydk/Qwen3.6-35B-A3B-LoopIntervention
- 本仓库(Hugging Face):
- 基座:作者 README 声明为
Qwen/Qwen3.6-35B-A3B-FP8(脚本中的加载路径为本地目录/root/autodl-tmp/models/Qwen/Qwen3.6-35B-A3B-FP8;本仓库不含其任何文件) - 同作者相关仓库:
tysgydk/Qwen3-4B-LoopIntervention(稠密模型版)、tysgydk/DeepSeek-V2-Lite-LoopIntervention(MoE 版) - 本仓库未附带论文、arXiv 编号或 BibTeX 条目;如引用请引用上面的仓库地址。