反復思考が止まらないモデルに、何を足して何を引くのか
小さな推論モデルには、答えに届く前に同じ文を何度も繰り返してしまう癖がある。Qwen3.5-0.8B ではそれが特に強く、モデルカードでも指摘されている。MATH-500 では、ベースモデルの回答の 93% が 32,768 トークン上限に突き当たり、結論まで届かなかった。まず壊れているのは精度ではなく、考え続けるための経路そのものだ。
MIT CSAIL の「Sparks of Weight-Space Programming」では、GPT-6 Astra がこの癖を見つけて重みを手で編集した。MATH-500 は 7.9% から 48.1% へ跳ね上がり、しかも変更したのは 0.016% の重みだけだった。派手なのは数字だが、見逃せないのは別の点で、モデルが何を学習したかではなく、どの方向へ考えが流れるかを見ていたことだ。
Nathan Barry の記事は、その編集を分解してみせる。Astra は 50 回の forward pass という制約の中で、どの層のどの列をどれだけ変えるかを試行錯誤で決めた。だが編集の形を追うと、やっていたことの大半は、ほぼ一本の方向に対して「どの重みが、どのくらい押しているか」を探していたにすぎない。ここで問題になるのは、探索が必要だったのか、それとも最初から数式で置けたのか、という問いだ。
この手の修正は、現場でも見覚えがある。大きなモデルの挙動を直したいとき、原因が一つのバグとは限らないのに、実際には「効く方向」を先に見つけた者が勝つ。重み編集も同じで、全部を理解してから直すのではなく、壊れている流れだけを狙う。だからこそ、探索の手触りをそのまま数式に落とせるかどうかが気になる。
残差ストリームという通路で、ループはどこに現れるのか
Transformer では各層の出力が次の層に置き換わるのではなく、入力に足し込まれる。この足し込み先が residual stream と呼ばれる通路で、Qwen3.5-0.8B では 1,024 次元ある。1 トークンごとにこのベクトルが少しずつ書き換わり、層ごとの MLP はそこへ何を加えるかを決める。ループ中のモデルは、この通路の向きが妙に揃ってしまう。
Astra の修正は、その向きを 2 つの層で崩す発想だった。まず、うまく推論できている短文と、同じ局面でループする短文を 4 組用意する。8 本のテキストを流し、各トークンで残差ストリームを記録し、ループ側の平均から生産的な側の平均を引く。すると、ループ時に残差が向かう方向のベクトルが得られる。記事ではこれを loop direction と呼び、以後の編集の軸にする。
ここで重要なのは、重み全体をいじるのではなく、各 MLP の最後にある down_proj の列ベクトルを触っている点だ。各列は、あるニューロンが発火したときに residual stream へ足す「書き込みベクトル」に相当する。列ベクトルのうち、ループ方向にどれだけ成分を持つかが効いてくる。つまり、モデルがループへ押される量は、各列がその方向へ持つ成分の総和として見えてくる。
式は難しそうに見えるが、やっていることは単純だ。ある列がループ方向へ +a だけ押しているなら、その a を消すか、反対向きにひっくり返せばよい。人手で見れば「この列は悪さをしている」と言えるが、LP にすると「どれだけ戻すか」をそのまま決める問題になる。
列を決める探索が、なぜ最適化問題になるのか
Astra の編集は、各列 w_j から u 方向の成分を引く形で表せる。u はループ方向、w_j はニューロンの書き込みベクトルだ。u に沿ってどれだけ押しているかは内積 u^T w_j で測れるので、その分だけ逆向きに戻せばよい。係数を 1 にするとその成分は消え、6 にすると逆向きへ反転して強く押し返す。編集全体は、1 本の方向 u と、各列ごとの係数 v_j に分解できる。
ここからが面白いところで、トークンごとの押し込み量は v · h_t という形になる。h_t はそのトークンでのニューロン活性で、v に対して線形だ。ループ中のトークンでは大きく負にしたい、生産的なトークンではほとんど動かしたくない。どちらも線形不等式で書けるので、v を求める問題は線形計画法になる。しかも目的関数に L1 ノルム Σ|v_j| を置くと、解は疎になりやすい。自然に「少数の列だけを選ぶ」方向へ寄る。
Nathan Barry の試算では、Astra は約 8 時間かけて 28 回の forward pass で v を探していた。一方で、同じ条件を LP に落とすと、制約を並べて解くだけで済む。HiGHS では 20 分超かかるが、PDHG を使った GPU 実装では最適値の 0.2% 以内まで約 1 分で届く。ここで気になるのは、1 分で済むこと自体より、8 時間の探索の中身が本当に「列の選び方」と「押しの強さ」の組み合わせだったのか、という点だ。
しかも日本の開発現場の感覚で見ると、この差はかなり大きい。再現実験で数時間の試行錯誤が必要だと、検証は一部の研究者しか回せない。だが LP に落ちるなら、実装している側は「何を固定し、何を最適化するか」をはっきり切り分けられる。人が勘で調整していた部分を、制約として書けるかどうかが境目になる。
8列しか触らない編集で、どこまで元の修正に近づくのか
実験では、LP が選んだ列数をさらに絞り、各層 8 列だけにしてもかなり近づいた。元の Astra 編集は 130,188 個の重み変更だったのに対し、LP は 16,291 個まで削れた。しかも Astra の方向を使った版では、GSM8K で 69.6%、MATH-500 で 51.7% と、元の編集と誤差の範囲に収まる。列の数を 8 倍減らしても、大勢は崩れていない。
別の見方もある。自動検出したループ痕跡から得た heuristic direction を使った版は、Astra の方向版に少し届かないが、それでも MATH-500 で 47.8%、IFEval で 60.4% まで行く。ここで効いているのは、どの列を触ったか以上に、どの方向へ押したかだと分かる。さらに steering vector の基準も用意され、同じ方向へ一定のベクトルを足すだけでも 50.8% まで出る。つまり、重み編集の本質は「ループから外れる向きに、適切な強さで押す」ことにかなり寄っている。
ただし、この前半だけではまだ答え切れていない疑問が残る。なぜ 8 列で足りるのか、なぜ selective な制約にしても broad な制約より良くならないのか、そして「ループ方向」を変えると何が壊れて何が残るのか。Astra の 8 時間の探索を 1 分で置き換えられるなら、その代わりに失われるものは何か。答えは、LP の解の形と限界の内側にある。
👉 続き(核心はここから)は PaPoo で読めます: https://papoo.work/doc/c3ab83e34606775b
