權重空間編程 是做什麼的?
透過直接編輯權重來改善小型開放式模型在特定目標上的表現,無需優化器。此方法遵循「Sparks of Weight-Space Programming」(Takehi, Teoh, Zhang, Khattab, MIT CSAIL, 2026年11月2日)中的實驗8:Qwen3.5-0.8B的思考迴圈被追溯到由第15層和第19層MLP寫入的一個殘差方向,對每層64個down_proj欄位進行秩-1編輯後,MATH-500從7.9%提升至48.1%。
請依序遵循以下快速路徑。 每個腳本都位於 scripts/ 目錄中且經過測試。除非某個步驟失敗,否則請勿重新設計流程或編寫新工具。
此技能保證的內容,以及無法保證的內容。 沒有任何方法能保證編輯一定有效:有些模型沒有單一習慣可以關閉。此技能保證的是流程:
- 不會遺失工作:當機時會以更小的批次重新啟動並從中斷處繼續;
- 任何編輯在通過衡量過的練習檢查之前,都不會進入保留的測試集;
- 失敗的檢查會透過固定步驟升級,而不是直接停止;
- 每次執行都會以明確的結論和數據結束,如果沒有任何方法有效,則會還原副本。
參考資料(僅供詳細資訊):
references/goals.md:其他目標;如何編寫匹配對;評分器;食譜。references/engines.md:哪個引擎適用於哪個OS和GPU、安裝、大小調整、潛在問題、冒煙測試。references/evaluation.md:資料分割、抽樣協定、MMLU-Pro的特定事項、配對統計、報告範本。references/method.md:每個步驟的數學原理和作者的精確食譜。
快速路徑
先設定四個佔位符(PowerShell:$env:SKILL = "...",然後 $env:SKILL):
SKILL=<此技能資料夾> BASE=<基礎模型資料夾> COPY=<基礎模型資料夾>-<目標> WORK=<結果資料夾>
在背景中執行每個生成任務(Claude Code:使用Bash工具的 run_in_background,而非shell的 &)並等待其完成通知,而非輪詢。生成佔據大部分時間,因此請預先告知使用者預算:在消費者GPU上,預設配置需要1.5–3小時;在資料中心GPU上使用vLLM則快得多。
0. 僅詢問您需要的資訊(一個問題)。詢問目標。如果是數學或科學,則使用預設:無需更多問題。否則,也請詢問或協助編寫:
- 顯示失敗的提示,格式為
{"id", "prompt", "answer"?, "group"?}JSON lines; - 如何對其進行評分(
references/goals.md第3節); - 對於非迴圈行為,需要12+個匹配對(第2節)。
確認「編輯權重,無訓練」。
1. 檢查機器(2分鐘):python $SKILL/scripts/device.py --model $BASE --jobs 2。在新機器上,也請執行 references/engines.md 第6節中的冒煙測試。
2. 複製模型(1分鐘)。每次編輯都會進入此副本的檔案;每次評估都會載入此副本。
python $SKILL/scripts/copy_model.py --base $BASE --copy $COPY
3. 資料分割(數秒)。
- 科學預設:
python $SKILL/scripts/make_splits.py --task mmlu --source <MMLU-Pro 測試 parquet 檔案> --out $WORK/splits。 - 數學預設: 同上,但使用
--task math --source <MATH-500 測試 test.jsonl> --practice 25 --heldout 75。 - 自訂目標: 將您的提示檔案分割成
practice.jsonl和heldout.jsonl,依據固定規則,再加上一個包含約30個保留ID的test_ids.txt,所有這些都應在任何答案被看到之前決定。
下文中,T 是任務(mmlu、math 或 jsonl),G 是評分器選項(預設配置為無;否則參見 references/goals.md)。
4. 同時啟動兩個基礎運行:
python $SKILL/scripts/run_eval.py --task $T --model $BASE --label base --data $WORK/splits/practice.jsonl --out $WORK/practice/base.jsonl --max-tokens 16384 --jobs 2
python $SKILL/scripts/run_eval.py --task $T --model $BASE --label base --data $WORK/splits/heldout.jsonl --ids-file $WORK/splits/test_ids.txt --out $WORK/test/base.jsonl --jobs 2
對於其他模型,請使用模型卡的取樣設定(--profile 或覆蓋標誌;references/engines.md)。保留的運行不依賴於編輯。
5. 取得對比。
- 迴圈(預設配置,或任何答案達到上限的目標): 迴圈僅在答案達到上限時出現。使用
grep -c '"length"' $WORK/practice/base.jsonl計算它們;如果達到15個或更多,則停止練習運行。 - 其他行為: 您需要配對,而練習運行只需要完成以提供基線。
然後進行評分:
python $SKILL/scripts/grade.py --task $T $G $WORK/practice/base.jsonl --out $WORK/practice/summary.json
進行/停止決策。 估計改善空間:顯示該行為的答案比例,乘以未顯示該行為的答案的分數。如果該值約低於10%,請在繼續前告知使用者預期改善有限。
6. 讀取方向、建構候選、篩選(數分鐘,僅前向傳遞)。迴圈:
python $SKILL/scripts/probe.py collect --task $T --model $BASE --data $WORK/splits/practice.jsonl --runs $WORK/practice/base.jsonl --out $WORK/probes
配對(添加 --runs、--data 和 --task 以獲得乾淨的副作用視窗):
python $SKILL/scripts/probe.py collect-pairs --model $BASE --pairs pairs.jsonl --thinking on --out $WORK/probes
然後建構第一輪候選項、對照組並進行篩選:
for spec in "15 19:128:6" "15 19:256:6" "15 19:64:6" "11 15 17 19 21:128:6"; do IFS=: read L K A <<< "$spec"; python $SKILL/scripts/probe.py build --probes $WORK/probes --model $BASE --layers $L --k $K --alpha $A --out "$WORK/edits/L${L// /-}_k${K}_a${A}.safetensors"; done
python $SKILL/scripts/probe.py build --probes $WORK/probes --model $BASE --layers 15 19 --k 128 --alpha 6 --control random --out $WORK/edits/random.safetensors
python $SKILL/scripts/probe.py screen --probes $WORK/probes --model $BASE --edits $WORK/edits/*.safetensors
在Windows PowerShell上,請分別執行每個 build 行。上述層級適用於24層模型。對於其他模型,請使用深度約60%和80%的層級、五層擴展以及較深的單獨層。
根據 unwanted 上的下降對候選項進行排名,僅保留其 wanted 和 clean 下降低於此值三分之一的候選項。隨機對照組必須保持在接近0的數值;如果它移動了與最佳候選項相同的幅度,則表示該方向不具體,因此請進入停止步驟。
7. 將最佳候選項寫入副本並驗證(1分鐘)。永遠不要評估記憶體中的編輯。
python $SKILL/scripts/apply_edit.py --base $BASE --copy $COPY --edit $WORK/edits/<候選項>.safetensors
python $SKILL/scripts/diff_edit.py --base $BASE --edited $COPY --out $WORK/edit_report.json
差異必須僅顯示預期的 down_proj 張量,changed_columns = k,秩-1佔比約為1,中位數 α 約為選擇的 α。
8. 練習檢查:門控(15–25分鐘,與基礎保留運行並行)。對基礎模型失敗的每個練習問題(截斷、錯誤或標記),加上6個基礎模型處理良好的問題,執行副本:
python -c "import json; g=json.load(open('$WORK/practice/summary.json'))['graded']['base']; bad=[x['id'] for x in g if x['cut'] or x['correct'] is False or x['flagged']]; ok=[x['id'] for x in g if x['id'] not in bad]; open('$WORK/check_ids.txt','w').write('\n'.join(bad+ok[::max(1,len(ok)//6)][:6])+'\n')"
python $SKILL/scripts/run_eval.py --task $T --model $COPY --label copy --data $WORK/splits/practice.jsonl --ids-file $WORK/check_ids.txt --out $WORK/practice/copy.jsonl --max-tokens 16384 --jobs 2
python $SKILL/scripts/grade.py --task $T $G $WORK/practice/base.jsonl $WORK/practice/copy.jsonl
門控通過僅當滿足以下所有條件:
- fixed ≥ max(3, 所檢查的基礎模型失敗數的20%),
- broke ≤ fixed ÷ 4,
- 並且,對於迴圈目標,截斷比例至少下降四分之一。
通過:前往步驟10。失敗:步驟9。
9. 按此順序升級;每個階梯都是一次額外的練習檢查。
- 下一個排名的候選項。 還原副本(
copy_model.py --base $BASE --copy $COPY --restore),套用它,然後重複步驟7–8。最多對另外兩個候選項執行此操作。 - 第二輪,當行為移動而非消失時。 例如,思考現在關閉了,但迴圈在
response之後重新開始,或者副本的回答中出現了新的不想要的模式。將編輯後的副本視為新的基礎:- 使用
copy_model.py --base $COPY --copy $COPY2製作COPY2; - 使用
--model $COPY --runs $WORK/practice/copy.jsonl執行probe.py collect(或collect-pairs); - 使用
--model $COPY建構並篩選; - 使用
--base $COPY --copy $COPY2套用; - 如同步驟8檢查
COPY2。
- 使用
- 停止。 三次檢查後(或在使用者設定的時間預算後)沒有可靠的改善。還原副本,並報告結論「無可靠改善」,附上所有候選項的數據。對於Qwen3.5-0.8B,提供已發布的數學編輯作為比較(在作者的日誌中,它將MMLU-Pro的截斷比例從28.9%降低到0.5%;參見此檔案末尾)。僅在使用者同意時使用它。
永遠不要使用保留結果來做選擇;只有練習檢查決定。
10. 從副本進行保留測試(30–60分鐘)。當基礎保留運行超過其最長答案時開始:
python $SKILL/scripts/run_eval.py --task $T --model $COPY --label copy --data $WORK/splits/heldout.jsonl --ids-file $WORK/splits/test_ids.txt --out $WORK/test/copy.jsonl --jobs 2
python $SKILL/scripts/grade.py --task $T $G $WORK/test/base.jsonl $WORK/test/copy.jsonl --out $WORK/test/summary.json
根據配對結果給出結論:
- 「明確改善」 當 fixed > broke 且符號檢定 p < 0.05。
- 「與改善一致,但未證實」 當 fixed > broke 但 p ≥ 0.05;建議進行更大規模的測試。
- 「無改善」 當 fixed ≤ broke;建議還原副本。
11. 報告 使用 references/evaluation.md 中的範本:
- 保留測試的前後分數,以及配對的 fixed/broke 計數;
- 行為比率(截斷、標記、思考關閉);
- 每個候選項及其篩選和檢查數據,以及隨機對照組;
- 更改的權重;
- 注意事項:關閉習慣不等於獲得新能力。
曾耗費數小時的錯誤(請勿重複)
- 批次過大,或兩個長時間任務在峰值時重疊。 記憶體不足的當機會導致正在進行中的答案遺失,而這些答案正是迴圈。請使用
--batch auto --jobs 2,並且永遠不要在第一個32k任務處於最長答案階段時啟動第二個32k任務。監督器會以一半的批次重新啟動當機的運行。 - 等待整個運行完成。 約15個迴圈就足夠了。
- 對記憶體中的編輯進行評估。 只有
probe.py screen會在記憶體中套用編輯,且僅用於教師強制讀取。 - 僅信任篩選結果。 在迴圈上,−0.10的篩選下降在生成中僅破壞了26個迴圈中的3個,因此始終執行門控檢查。
- 對部分運行進行評分,或根據哪個先完成來選擇測試問題。
- 使用
pkill -f <文字>停止任務, 這也會殺死那些指令行中包含該文字的觀察器。
規則(如文章中所述)
請遵循這些規則,並在報告中說明您已遵守。
- 無訓練。 無反向傳遞、自動梯度、優化器,或迭代地將權重擬合到損失函數。調整 α 或權重直到指標改善視為擬合。從上述固定候選列表中選擇則不算。
- 允許用於測量的前向傳遞: 生成、教師強制對數機率、隱藏狀態和MLP激活,以及這些或權重的統計資料(均值、差異、SVD)。
- 不在範圍內:
- 嵌入層、(綁定的)輸出頭和最終歸一化層(
weights.py拒絕它們); - 將整個張量乘以一個常數;
- 全局銳化或平滑化;
- 無論問題如何強制思考提前關閉;
- 移除安全行為:拒絕、安全防護、對有害請求的順從。
- 嵌入層、(綁定的)輸出頭和最終歸一化層(
- 僅權重值改變。 保持名稱、形狀、資料類型、配置、分詞器、對話範本和解碼設定不變。
- 資料分割紀律。 練習集和保留集不相交,並在任何編輯之前固定。保留結果僅查看一次,且是在編輯凍結之後。
- 揭露選擇過程。 報告列出每個嘗試過的候選項以及選擇優勝者的指標。
為什麼每個步驟是這個樣子
- 對比: 方向是每層輸出處,不想要的文本與匹配的想要的文本之間的平均差異。
- 對於迴圈,
loops.py取迴圈開始前1,024個令牌和迴圈內1,024個令牌:相同的問題,相同的答案,幾乎相同的位置。開始點是下一個512個令牌中90%重複較早的16-gram的第一個點。 - 對於其他行為,配對提供了匹配。
- 對於迴圈,
- 寫入者欄位: score_j = (mean unwanted − mean wanted activation of neuron j) × (u · W_down[:, j]);取前k個。僅靠靜態寫入u·W是不夠的:在已發布的每層64個欄位中,只有21–22個在其前64個中。
- 編輯: W'[:, S] = W[:, S] − α u (uᵀ W[:, S]),從被編輯的模型中以float32計算。α = 1會移除該分量,這對迴圈沒有作用;α = 6會將其翻轉為−5c,因此這些神經元會對抗該行為進行寫入。
- 篩選: 套用編輯後,平均對數機率的變化。不想要的文本應變得更不可能;想要的和乾淨的文本應保持不變。相同欄位上範數匹配的隨機方向是對照組。
- 門控: 篩選數字只能寬鬆地預測生成(參見下方結果),因此在保留測試之前,一個簡短的練習問題生成檢查可以決定。
- 儲存:
weights.py僅從原始檔案重寫受影響的 safetensors 分片。推理引擎在載入時會重寫或丟棄張量,因此永遠不要從推理引擎儲存權重。 - 協定: 思考開啟,溫度0.6,top_p 0.95,top_k 20,僅對生成的令牌施加存在懲罰1.5,32,768個新令牌(
--profile thinking)。所有引擎都符合vLLM的語義。 - 配對: 引擎和批次大小會改變隨機數,因此請在單次比較中按問題配對。永遠不要比較在不同問題上或使用不同引擎測量的分數。
R
…
[因翻譯需求而截斷]