tysgydk/Qwen3-4B-LoopIntervention
English summary. This repository is a research workbench for "loop intervention" on a frozen Qwen3-4B trunk: it ships 38 small intervention-network checkpoints plus the complete training, data-construction, evaluation and diagnostic scripts, together with the author's lab notebook and model registry. It contains no full model weights — every .pt file is a state dict of the intervention modules only (about 1 MB to 79 MB each) and must be combined with a separately downloaded Qwen/Qwen3-4B. Nothing here is loadable with from_pretrained, and none of these checkpoints is a production-ready model.
这是什么
- 主干固定不变:
Qwen/Qwen3-4B(官方 Instruct 后训练版,d=2560,36 层)全程冻结,只训练一个外挂的干预网络;目标是让"把同一段计算多走几圈"不坍缩,甚至变成真正的等效深度增益。 - 仓库性质:这是实验胶水代码 + 中间检查点集合,不是成品模型。作者自己的定位见
model_registry.md(变体注册表 + 继承链)与实验记录.md(427 行实验史,含作者批注)。 - 三条架构线(
model_registry.md记录):旧主线(主干重复循环,已全部废弃)、残差循环(主干只 forward 一次,隐状态上叠低秩残差块)、变换循环(每圈用满秩 Proj 把隐状态翻译回 embedding 空间后重新 forward 主干)。
不含完整权重(重要澄清)
ckpt/下所有文件都是干预网络的state_dict,两种格式:- 残差/旧架构:
{'step', 'r', 'sd'} - 变换循环:
{'step', 'r', 'loop_sd'}(内含proj.*、loop_gate.*,可选interv_loop.*、v_tokens.*)
- 残差/旧架构:
- 仓库内没有
config.json、tokenizer、model.safetensors或主干pytorch_model.bin;因此AutoModelForCausalLM.from_pretrained("<本仓库>")不能工作。 - 使用方式只有一种:先自行获取
Qwen/Qwen3-4B,再把.pt里的干预参数加载到脚本定义的模块中(参见scripts/train_residual.py的ResidualLoop)。
仓库内容
Qwen3-4B-LoopIntervention/
├── README.md # 原卡片(含旧 front matter,声明 license: Apache License 2.0)
├── 实验记录.md # 427 行实验史(含作者批注),日期标注 2026-08-18 ~ 2026-08-26
├── model_registry.md # 变体注册表:继承链 + 每个变体的结构/成绩/状态,最后更新标注 2026-08-27
├── .gitattributes # 声明 *.pt 等走 LFS(实际仓库内 0 个 LFS 对象,.pt 为普通文件)
├── ckpt/ # 38 个干预网络检查点(见下表)
└── scripts/ # 41 个训练/数据/评测/探针脚本(见下)
ckpt/:38 个检查点逐个说明
成绩口径(引自 model_registry.md / 实验记录.md,均为作者自测,除注明外为 MATH-500 第 201~260 题、60 题子集、cap1024、greedy):**纯主干 r1 = 16.7%**。
A. 旧主线(主干重复循环,train_interv.py 的结构:虚拟 token + 循环入口 FiLM + 共享/块化低秩加性修正)
| 文件(大小) | 结构 | 记录中的状态/成绩 |
|---|---|---|
interv_step7500.pt (2.0 MB) |
约 50 万参数,纯 GSM8K train 从头 7500 步 | GSM8K r1 75.0%,文本"客场"崩;废弃 |
intervgen_step7500.pt (2.0 MB) |
纯 fineweb + zh 语料从头 7500 步 | wikitext CE 2.76,数学客场 43.3%;废弃 |
intervmix_step4000.pt (2.0 MB) |
混合数据 mix_v1 4000 步("蓝莓",通用打底) |
登记为 GSM8K r1 83.3% / r2 71.7%,MATH r2 18~40%;废弃(旧架构) |
intervmargin005_step2000.pt (2.0 MB) |
蓝莓 + margin 0.05 的反例 | 75.0%(掉 8.3 点,用于证明损失侧无油水);废弃 |
intervpollute_step2000.pt (2.0 MB) |
蓝莓 + 污染纠错数据 pollute_v1s("草莓") |
纠错 100% / 保持 100%;MATH r2 31.7%;废弃 |
intervmathcorr_step2000.pt (2.0 MB) |
蓝莓 + 真实错误配对数据 | MATH 11.7%(CE 教不会纠错);废弃 |
intervthink_step7500.pt (2.0 MB) |
思考专家 v1:自蒸馏思维链从头 7500 步 | 21.7% 翻车(思维漫游);废弃 |
intervthinkv2_step3000.pt (2.0 MB) |
思考专家 v2:v1 续训(思维链截断 + 短答案) | 66.7%(收尾救回但仍输通才);废弃 |
intervcap1_step4000.pt (3.98 MB) |
容量档一:蓝莓 + 每圈 128 虚拟 token + 秩 64,约 110 万参数 | 无增益(容量假设否定);废弃 |
intervblk6_step4000.pt (5.29 MB) |
块化基线 6 块 × 2 圈 × 秩 16,约 132 万参数 | MATH r1 23.3% / r2 25.0%(r2 首超 r1);废弃(基线) |
intervcot1536_step6515.pt (5.29 MB) |
块化 + cot_mix_v1 思维链语料 6515 步 |
MATH r1 31.7%(旧架构最佳单圈)/ r2 18.3%(第二圈失活);废弃 |
intervcot6ep_step26060.pt (5.29 MB) |
cot1536 续训 4 epoch(累计 5 epoch) | r1 退化到 23.3%(过拟合反例);废弃 |
intervscore_step500.pt (5.29 MB) |
SCoRe R=2:train_score.py 的 REINFORCE,reward = 第二圈增量 |
r2 23.3%(微升);RL 路线废弃 |
intervr3_step6515.pt (7.93 MB) |
R=3 课程式:继承 cot1536 前 2 圈 + 新训第 3 圈,约 198 万参数 | r3 25.0%(第三圈 gate 0.96 全开,但 r3 < 单圈 31.7%);废弃 |
intervscore_step100.pt (7.93 MB) |
SCoRe R=3:冻结前 2 圈只训第 3 圈,lr=1e-3 | r3 崩到 0%;RL 第二次失败 |
intervgrpo_step5.pt (7.93 MB) |
GRPO R=3(reward = r3 是否优于 r2) | 调试中断,80 步 reward 全 -1 未收敛;废弃 |
B. 新架构一:残差循环(主干只 forward 一次 + 低秩残差块堆叠,train_residual.py,W2 零初始化)
| 文件(大小) | 结构 | 记录中的状态/成绩 |
|---|---|---|
intervres_step2000.pt (1.31 MB) |
残差 R=2,秩 32,约 32.7 万参数 | **MATH r2 50.0%**(对比纯主干/恒等第二圈 16.7%);注册表登记的最终点 |
intervres_step3000.pt (1.31 MB) |
同一条线(tag=res)的另一个打点 | 注册表未单独登记(登记的是 step2000) |
intervres3_step2000.pt (1.97 MB) |
残差 R=3:继承 r2 前两圈 + 新训第 3 圈,约 49 万参数 | MATH r3 45.0%;第三圈 CE 增量仅 -0.008~-0.017(第二圈 -0.68)⇒ 甜点 R=2 |
intervres3_best_step2000.pt (1.97 MB) |
同上线的"最优快照"(脚本在早停时回滚保存 *_best_step*.pt) |
与 intervres3_step2000 同点 |
intervres3c_step1500.pt / intervres3c_best_step500.pt (1.97 MB) |
R=3 重训版 | 实验记录.md:res3b 被 CE 早停阈值(1e-4 过敏感)误触发,修成 1e-3 + patience 8 后重训为 res3c,确认加第三圈无增益;注册表未单列 |
intervres3freeze_step2000.pt / intervres3freeze_best_step1000.pt (1.97 MB) |
冻结实验:--freeze 1(冻结 t=1,只训 t=2) |
坐实 r3 无增益的归因是"冻结主干在 t=1 残差后无可优化方向"(空间耗尽),而非抢梯度 |
intervresrank64_step1500.pt / intervresrank64_best_step1000.pt (2.62 MB) |
同一架构把秩 32→64 重训 | r2 46.67%(低于秩 32 的 50%),val_ce 1.17 高于 1.14 ⇒ 提容量无益 |
intervresblk6_step2000.pt / intervresblk6_best_step500.pt (0.99 MB) |
分块残差:主干 forward 一次 + 中间层 6 块 × 秩 8 的 hook,约 24.6 万参数 | r2 40.0%,val_ce 0.93 虚低但正确率低(CE 与正确率背离)⇒ 中间层干预无效 |
C. 新架构二:变换循环(每圈重新 forward 主干 + 满秩 Proj 圈间翻译 + 门控,train_residual.py --loop)
| 文件(大小) | 结构 | 记录中的状态/成绩 |
|---|---|---|
intervloop2_step2000.pt (52.5 MB) |
变换循环 R=2,满秩 Proj(2560×2560/圈 ×2)约 1310 万参数 | MATH r2 46.67%(欠训版,曾被误判"未白嫖深度") |
intervloop2x_step4000.pt (52.5 MB) |
从 loop2 续训 4000 步(累计 6000 步 ≈ 2 epoch) | **MATH r2 58.33%(35/60)+ 复验 55%(33/60),120 题综合 56.67%**,首次超过单层残差 50.0% |
intervloop3_step6000.pt (78.7 MB) |
变换循环 R=3 从头训 6000 步,约 1968 万参数 | r3 50.0%,mean_len 589(R=2 为 480),第三圈 gate 掉到 0.34 ⇒ 甜点 R=2 |
intervloopblk2_step2000.pt (52.5 MB) |
大小与 loop2 同档,属变换循环系列;文件名未出现在 实验记录.md / model_registry.md 中,无法从仓库内容确定其确切配置 |
未登记(推测为块化尝试,但无仓库内文字依据) |
intervloopind2b_step2000.pt (54.5 MB) |
变换循环 + 中间层分块 hook(附加 interv_loop 模块) |
r2 45.0%,无效(中间层干预 + 变换循环叠加无增益) |
intervloopind2bx_step4000.pt (54.5 MB) |
loopind2b 续训 4000 步 | r2 45.0% 持平,gate 失活到 0.104 ⇒ 非欠训、是失活 |
intervloopcur1_step2000.pt (53.5 MB) |
大小与 loopcur2 同档,按命名属课程式变换循环一族;该文件名未出现在 实验记录.md / model_registry.md 中 |
未登记(记录里只有 cur2) |
intervloopcur2_step2000.pt (53.5 MB) |
课程式变换循环:先训 Proj 再解冻 3 层靠后 hook | r2 48.33%(打平单层,mean_len 495);废弃 |
intervloopcur2x_step4000.pt (53.5 MB) |
loopcur2 续训 4000 步 | r2 46.67%(降 1.66),gate 失活到 0.2 ⇒ 补训无效 |
intervvtok2_step2000.pt (52.7 MB) |
变换循环 + 每圈 8 个输入端可学习虚拟 token(vtoken 约 4 万参数) | r2 43.33%(26/60)/ mean_len 409 ⇒ 输入端软提示无效,且仍过早停止 |
scripts/:41 个脚本分组
训练(3 个)
train_interv.py(287 行):旧架构 R=2 训练。冻结主干 + 虚拟 token(默认每圈 64 个)+ 循环入口 FiLM(scale/shift)+ 逐层块化低秩加性修正(6 块 × 秩 16,W2 零初始化);损失L = mean(各圈 CE) + lam * relu(CE_t - CE_{t-1} + margin);每 400 步做一次功能探针(各圈 CE、Δh 比率、top1 一致率、基座 CE 参照)。train_residual.py(596 行,当前主线):四种模式合一——残差堆叠(默认)、--loop真·变换循环、--n-blocks分块残差、--vtok虚拟 token;含val_ce早停、MATH 小样本早停(--eval-n,默认 8 题)、最优快照回滚。train_score.py:REINFORCE 式 SCoRe 训练,冻结前 R-1 圈只更新最后一圈,outcome reward(末圈答对 +1 / 答错 -1)+ 滑动平均 baseline。
数据构造(8 个)
build_mix.py(50% GSM8K train / 30% fineweb-edu / 20% Ultra-FineWeb-zh → mix_v1.jsonl)、build_cot_data.py(NuminaMath + OpenThoughts + fineweb 按 4:4:2 包装成 Qwen3 chat+thinking 格式 → cot_mix_v1)、build_corr_data.py(用蓝莓 r2 的错误输出造纠错配对)、build_pollute.py(末步运算符翻转 / 答案转写扰动造污染纠错数据)、build_thinkv2.py(思维链截断到约 400 token + 30% GSM8K 短答案)、gen_distill.py(自蒸馏:主干开 thinking 生成 GSM8K 思维链,只留答对的)、gen_cached.py / gen_cached_v2.py(KV cache 版循环生成器,把 O(len²) 降到 O(len);v2 修了采样版索引 bug,加 temperature/top_p)。
评测(14 个)
eval_math500.py(位置参数 CKPT MODE_R N_PROBLEMS CAP TEMP TOP_P OFFSET,默认 60 题/cap512)、eval_math500_collect.py、eval_math500_base.py(纯主干基线,口径与前者一致)、eval_math500_samp.py(采样 + 自洽性多数投票,验证 greedy 是否低估循环)、eval_gsm8k.py、eval_aime.py(AIME 2024)、eval_cmmlu.py(选择题,关 thinking)、eval_loop.py / eval_residual.py(加载 loop / 残差 ckpt 跑 MATH 指定区间,默认 --offset 200 --n 20 或 --n 60)、eval_gen.py(GSM8K 前 60 题四臂:base / r1 / r2 / r2_zero)、eval_think.py(thinking on/off)、eval_cont.py(wikitext-2 CE + 续写定性)、eval_correct.py(纠错率 / 保持率)、eval_base_long.py(纯主干长链,用 caps 区分"真深度"与"长度换密度")、eval_dump.py、base_think.py、think_test.py。
探针 / 冒烟 / 运维(7 个)
probe_baseline.py(零干预循环坍缩基线:把 36 层当映射 M 反复施加)、probe_renorm.py(每轮重归一化范数,区分范数漂移与语义漂移)、probe_think.py、smoke_loop.py / smoke_loop_blk.py / smoke_blockwise.py(显存/梯度/不坍缩起点冒烟)、verify_freeze.py(验证冻结圈权重不变)、diag_r2.py / diag_r3.py(排查 r2 是"CE 训坏"还是"结构坍缩";采样 r3 排查 0 正样本)、accept.sh(验收三件套:GSM8K 公平评测 + wikitext CE + 引力面板)、cross_test.sh(数学/通用/通才三方主客场互测)、sweep_caps.sh(cap ∈ {64,128,256,1024} 的 token 效率曲线)、run_samp_after_base.sh(等某 PID 结束后自动跑采样评测)。
脚本用法(脚本内取证的真实命令)
所有脚本都把基座与数据写成绝对路径,例如 train_residual.py:12 → MODEL = '/root/autodl-tmp/models/Qwen/Qwen3-4B'、train_interv.py:15-18 → 数据在 /root/autodl-tmp/data/...、ckpt 输出到 CKPT_DIR = '/root/autodl-tmp/loop-exp/ckpt'、MATH = '/root/autodl-tmp/data/math500/test.jsonl'。直接跑之前必须改这些常量或建同名软链。
# 残差循环 R=2(默认值即线上配置:steps=2000, bs=2, lr=1e-3, rank=32, tag=res)
python scripts/train_residual.py --r 2 --rank 32 --tag res
# 变换循环(真深度):加 --loop;门控是每圈一个标量 loop_gate
python scripts/train_residual.py --loop --r 2 --rank 32 --tag loop2
# 变换循环续训(loop2x 即 --tag loop2x 从 loop2 的最终点继承,续训 4000 步)
python scripts/train_residual.py --loop --r 2 --rank 32 --tag loop2x \
--init-ckpt <intervloop2_step2000.pt> --steps 4000
# 课程式变体:先只训 Proj/gate,再解冻靠后 hook(loopind/loopcur 系列用到)
python scripts/train_residual.py --loop --n-blocks 6 --rank 8 --freeze-interv --tag loopind2b
python scripts/train_residual.py --loop --n-blocks 6 --rank 8 --tag loopind2bx \
--init-ckpt <intervloopind2b_step2000.pt> --steps 4000
# 分块残差 / 虚拟 token / R=3 继承 / 冻结实验
python scripts/train_residual.py --n-blocks 6 --rank 8 --tag resblk6
python scripts/train_residual.py --loop --vtok 8 --tag vtok2
python scripts/train_residual.py --r 3 --rank 32 --tag res3 --init-ckpt <intervres_step2000.pt>
python scripts/train_residual.py --r 3 --rank 32 --freeze 1 --tag res3freeze
# 旧架构 R=2 训练(虚拟 token 数/秩可用 --nvt/--rank 覆盖,默认 nvt=64, rank=16)
python scripts/train_interv.py --steps 7500 --bs 1 --lr 1e-3 --tag '' --data <gsm8k train parquet>
# 评测
python scripts/eval_residual.py <intervres_step2000.pt> --r 2 --n 60 --offset 200 --cap 1024 --rank 32
python scripts/eval_loop.py <intervloop2x_step4000.pt> --r 2 --n 20 --offset 200 --cap 1024
python scripts/eval_math500.py <ckpt.pt> 2 60 1024 - - 200 # 位置参数:ckpt r n cap temp top_p offset
python scripts/eval_math500_base.py base 1024 60 # 纯主干对照,提取器与上一致
python scripts/eval_aime.py --base # 或带 ckpt 跑 loop2x
关键超参(脚本内默认值):残差循环 --lr 1e-3 --weight-decay 0.01 --val-ratio 0.08 --ce-every 200 --eval-every 500 --eval-n 8 --patience 2,梯度裁剪 5.0;train_interv.py 用 --lr 1e-3、裁剪 5.0,损失里的 margin 默认 0.01、lam 1.0。
技术要点
- 坍缩 vs 失活:作者先用
probe_baseline.py证明"把 36 层反复施加"会结构性坍缩(第二圈恒等即 0%),再用残差堆叠(h_t = h_{t-1} + gate_t·W2_t·SiLU(W1_t·h_{t-1}),W2 零初始化保证恒等起点)解决它——这是本仓库第一个主线突破(r2 从 16.7% 到 50.0%)。 - 欠训假说:变换循环的 Proj 是满秩 2560×2560(约 1310 万参数,是残差循环 32.7 万的约 40 倍),2000 步(约 0.67 epoch)只打平单层;续训到累计 6000 步后 r2 达 58.33%。
- 干预加在哪是分水岭(作者结论):加在圈间(Proj + gate)有效;加在主干内部(中间层 hook)或输入端(虚拟 token)都失效——三个补训实验(loop2x 涨 11.66、loopcur2x 降 1.66、loopind2bx 持平)用于区分"欠训"与"失活"。
- 长度换密度 + 真深度(作者四测试集复验结论):loop2x cap1024 前 30 题为 70%(mean_len 480),纯主干 cap8192 前 30 题为 60%(mean_len 4236);GSM8K 上 loop2x 72% 反输主干 98%,AIME2024 同分但顶帽率 10% vs 76.7%。作者定性为"无显著正确率优势,核心价值是压缩思考成本 + 消除顶帽短板"。
- 失败的反例也被保留在仓库里:margin 反例、污染纠错、容量档、rank64、RL(SCoRe ×2 + GRPO)等,都与注册表里的"废弃/反例"标记对应。
- 训练数据:
mix_v1记录为 14973 篇;cot_mix_v1用于残差/变换循环,intervcot1536记录为 6515 步 ≈ 260 万 token。
已知限制
- 不是模型发行物:无 config/tokenizer/主干权重,不能
from_pretrained,也不能直接接 HF pipeline。 - 许可为 Apache-2.0:仓库已随附
LICENSE全文(原 README 的 front matter 亦声明 Apache License 2.0)。 - 所有脚本硬编码绝对路径(
/root/autodl-tmp/...、/root/loop-exp/...),且依赖不在仓库内的数据文件:math500/test.jsonl、gsm8k2/main/*.parquet、cot_mix_v1.jsonl、cmmlu_sample200.jsonl、aime2024.jsonl;数据构造脚本还依赖 NuminaMath / OpenThoughts / fineweb-edu / Ultra-FineWeb-zh 等外部语料,仓库未给出这些语料的版本或下载清单。 - 成绩全部是作者自测,主要口径为 MATH-500 第 201~260 题(60 题)、cap1024、greedy,样本量小;
model_registry.md与实验记录.md对同一变体的早期数字口径不一致(例如 intervmix 的 GSM8K 数字),引用前需确认口径。 - ckpt 与注册表不严格一一对应:
intervres3c_*、intervres3freeze_*、intervloopcur1_step2000、intervloopblk2_step2000、intervres_step3000未在注册表单列;intervgrpo_step5是调试中断点。 .gitattributes声明*.pt走 LFS,但仓库内当前 0 个 LFS 对象(.pt是普通文件)——迁移到 HF 时需要自行决定 LFS 策略。- 参数量、gate 值、成绩均转引自作者记录,未在本仓库内重新复算。
未说明的信息:cot_mix_v1 等训练语料的样本量与 token 总量;各变体的训练时长/算力开销;除早期报告提到"AutoDL 魔改 4090 48G"以外的硬件环境;仓库的上传或最后更新时间;上传者的环境版本(torch/transformers 版本未记录)。
许可
- 原 README 的 front matter 声明
license: Apache License 2.0,本卡片据此写license: apache-2.0。 - 仓库已随附 Apache-2.0 许可全文(根目录
LICENSE,11,343 字节,取自上游官方仓库原文,未作任何改动)。版权署名:Copyright 2026 我本是我沐。 - 主干模型
Qwen/Qwen3-4B的许可以其自身仓库为准(本仓库未再分发其权重)。
引用
- 本仓库(ModelScope):https://modelscope.cn/models/tysgydk/Qwen3-4B-LoopIntervention
- 本仓库(Hugging Face):
- 基座:
Qwen/Qwen3-4B(https://modelscope.cn/models/Qwen/Qwen3-4B,需自行下载) - 配套数据集(原卡片声明,存在于 ModelScope):
tysgydk/Qwen3-4B-LoopIntervention-Data - 仓库内一手材料:
实验记录.md(427 行实验史)、model_registry.md(变体注册表与继承链) - 本仓库未附带论文、arXiv 编号或 BibTeX 条目;如引用请引用上面的仓库地址。