CATHODE COASTaccess to tools
9 min read

temperature 0 でも再現しない — LLMの比較実験で3回誤った結論を出した話

温度0とseed固定で決定的だと思っていたら、モデルごとの既定 repeat_penalty の差で結果が変わっていました。5つの「発見」が全部測定ミスだった記録。

shareB!

はじめに

2つのLLMを比較していました。あるモデルと、その改変版です。同じ12問を投げて、出力の違いを見る。

再現性には気を配ったつもりでした。temperature: 0 で貪欲法にして、seed: 42 を固定する。これで決定的になるはずです。

そして差分を見つけました。「改変版は日本語の敬語で劣化している」「改変版のほうが簡潔だ」「改変版に中国語の漢字が混入している」。数字も実例も揃っていて、記事にできる材料だと思いました。

全部間違いでした。

原因はモデルの違いではなく、モデルごとに異なる既定パラメータです。気づいたのは ollama show の diff に出たたった1行からでした。

執筆時点(2026年7月)、Ollama v0.32.5 での記録です。


先にまとめ

  1. temperature: 0 は決定性を保証しない。 ペナルティ系パラメータはロジットを書き換えるので、貪欲法でも選ばれるトークンが変わります。
  2. モデルごとに既定パラメータが違う。 Modelfile に何が焼かれているかは ollama show でしか分かりません。
  3. 短い出力で速度を測ってはいけない。 4トークンの生成では26%の誤差が出ました。

比較実験をするなら、最初に ollama show の diff を取る。これだけで今回の遠回りは全部避けられました。


誤った結論を3回出した

時系列で並べます。

第1回: 「元モデルは敬語を間違える」

最初は temperature: 0seed: 42 だけを指定していました。

設問は「『資料を見た』を尊敬語と謙譲語に言い換えてください」。元モデルの回答です。

尊敬語:資料をご覧になった
謙譲語:資料をお見せしました      ← 誤り

「お見せする」は「見せる」の謙譲語で、「見る」の謙譲語ではありません。正解は「拝見する」です。

**「27Bクラスでも日本語の敬語は間違える」**という結論を出しました。

第2回: 「改変版は敬語で劣化している」

比較相手のモデルカードを見たところ、既定パラメータが違うことに気づきました。presence_penalty: 1.5 などが設定されています。これでは比較にならないので、両モデルで明示的に揃えることにしました。

{
  "temperature": 0,
  "seed": 42,
  "presence_penalty": 0,
  "top_k": 40,
  "top_p": 0.9,
  "min_p": 0
}

ここで妙なことが起きます。元モデルの回答が変わりました。

第1回: 謙譲語:資料をお見せしました   ← 誤り
第2回: 謙譲語:資料を拝見した         ← 正解

このとき「サンプリングのペナルティが文法的な誤りを引き起こしていた」と解釈しました。ここまでは正しかったのですが、問題は次です。

同じ条件で改変版を流すと、今度は改変版が間違えました。

改変版: 謙譲語:資料をお目通ししました   ← 誤り

**「改変版は日本語の敬語で明確に劣化している」**という結論を出しました。条件を揃えたうえでの差なので、確度が高いと考えたのです。

同時に、他の「発見」も揃いました。

観測当時の解釈
改変版が一貫して短い(上限到達5問→1問)改変版は簡潔にまとめる傾向
改変版に「陡」という中国語漢字が混入改変の副作用で異言語が漏れる
改変版が実在しない動物名を出した知識表現が壊れている
改変版が18.5 tok/秒(元は14.7)なぜか速い

5つの発見が揃い、記事の構成まで見えていました。

第3回: 「1行の diff」

念のため、両モデルの構成を比較しました。

ollama show qwen3.6:27b > ~/show-base.txt
ollama show huihui_ai/Qwen3.6-abliterated:27b > ~/show-abl.txt
diff ~/show-base.txt ~/show-abl.txt
17d16
<     repeat_penalty      1

元モデルには repeat_penalty 1 が明示されているのに、改変版にはこの行がない。

Ollama の repeat_penalty の既定値は 1.1 です。つまり実際に適用されていた値は、

repeat_penalty
元モデル1.0(Modelfile で明示)
改変版1.1(既定値が適用)

そして私のスクリプトは repeat_penalty を指定していませんでした。2つのモデルを、違う条件で比較していたわけです。


repeat_penalty を揃えたら、発見が全部消えた

両モデルに repeat_penalty: 1.0 を明示して流し直しました。

敬語: 完全一致

元モデル : 尊敬語:資料をご覧になった / 謙譲語:資料を拝見した
改変版   : 尊敬語:資料をご覧になった / 謙譲語:資料を拝見した

一字も違いません。 改変版は「拝見する」を知っていました。

「簡潔さ」: 消滅

上限1000トークンで切断された問題の数です。

切断数
元モデル5問
改変版(rp=1.1)1問
改変版(rp=1.0)4問

「改変版は簡潔にまとめる」という特性は、repeat_penalty: 1.1 による反復抑制でした。 揃えた途端、元モデルとほぼ同じだけ書くようになりました。

中国語漢字「陡」: 消滅

grep してもヒットしません。反復ペナルティが正常な候補を抑制した結果、通常なら選ばれない字が浮上していただけでした。

実在しない動物名: 消滅、そして反転

改変版が出していた捏造動物名は消えました。そして——

元モデルのほうには、別の捏造動物名が4箇所すべて残っていました。

「改変版の知識が壊れている」という結論は誤りで、むしろ元モデルのほうにこの問題があるという真逆の結果です。

速度: 誤差だった

300トークン級の生成で測り直しました。

元モデル : 14.5 tok/s / 177 tok
改変版   : 14.6 tok/s / 188 tok

差は0.7%。 18.5 tok/秒という数字は、出力4トークン(「391」という答え)で測ったものでした。この規模では初回トークンの遅延が支配的で、意味のある値になりません。


なぜ temperature: 0 で足りないのか

ここを誤解していました。

temperature: 0 は「確率分布を鋭くして、最も確率の高いトークンを選ぶ」設定です。貪欲法(greedy decoding)になるので、同じ入力なら同じ出力になる——と考えていました。

しかしペナルティ系パラメータは、「選ぶ前」に働きます。

モデルがロジットを出力

repeat_penalty / presence_penalty がロジットを書き換える  ← ここ

temperature が確率分布を調整

最も確率の高いトークンを選ぶ(temperature=0)

ペナルティで順位が入れ替われば、貪欲法でも別のトークンが選ばれます。

今回の「拝見」→「お目通し」がまさにこれでした。既出のトークンにペナルティがかかり、本来1位だった候補が2位以下に落ちて、意味の違う語が選ばれた。

seed も同様に無力です。seed はサンプリングの乱数を固定しますが、temperature=0 では乱数を使わないので、そもそも影響しません。「seedを固定したから再現する」というのは二重に誤りでした。

揃えるべきパラメータ

比較実験では、少なくとも以下をすべて明示すべきでした。

{
  "temperature": 0,
  "seed": 42,
  "num_predict": 1000,
  "repeat_penalty": 1.0,
  "presence_penalty": 0,
  "frequency_penalty": 0,
  "top_k": 40,
  "top_p": 0.9,
  "min_p": 0
}

「既定値だから同じだろう」が通用しません。 既定値はモデルごとに Modelfile で上書きされうるからです。


ollama show の diff を最初に取る

今回の教訓を1つに絞るならこれです。

ollama show <model-a> > a.txt
ollama show <model-b> > b.txt
diff a.txt b.txt

出力にはパラメータだけでなく、チャットテンプレートも含まれます。テンプレートが違えば、同じプロンプトでもモデルに届く文字列が変わります。abliterated 系のモデルではテンプレートが壊れていることもあるので、ここの確認は必須でした。

今回はテンプレートに差分がなく、唯一の差が repeat_penalty の1行でした。逆に言えば、この1行を見逃していたら最後まで気づかなかったということです。

そして厄介なのは、誤った結論に説得力があったことです。

「改変版は日本語の敬語で劣化し、簡潔になり、中国語の漢字が混入する」

数字と実例が揃っていて、それらしく読めます。しかも「重みをいじれば劣化するはずだ」という事前の予想とも一致していました。確認バイアスが働きやすい形をしていたわけです。


その他の測定ミス

ついでに踏んだものを記録しておきます。

短い出力で速度を測った

4トークンの生成で 18.5 tok/秒、188トークンで 14.6 tok/秒。26%の差はすべて測定ノイズでした。

モデルのロード直後の1トークン目には他と違う遅延があり、出力が短いほどその影響が支配的になります。最低100トークン、できれば300トークン以上で測るべきでした。

diff の行数を評価指標にしようとした

12問の出力を丸ごと diff したら 840行出ました。「これだけ違う」と言いたくなりますが、この数字に意味はありません

散文は一度どこかで分岐すると、以降がすべて差分になります。冒頭の1トークンが違えば残り全部が「変更あり」です。1000トークン級の長文を4問含んでいるので、840行は必然でした。

評価は短答問題の完全一致と、特定の誤りの有無で行うべきでした。

モデルカードの params を見ていなかった

Ollama のモデルページには params の項目があり、そのモデルに焼かれた既定値が書かれています。改変版には temperature: 1top_k: 20presence_penalty: 1.5 などが設定されていました。

第2回でここを見たから presence_penalty は揃えられたのですが、repeat_penalty はページに表示されていませんでした。Web の情報だけでは足りず、ollama show が必要だった、ということです。


ハマりどころまとめ

症状原因対処
temperature 0 なのに出力が変わるペナルティ系がロジットを書き換える全ペナルティを明示指定
モデルAとBで挙動が違うModelfile の既定値が異なるollama show の diff
速度が26%違う4トークンで測定100トークン以上で測る
diff が数百行出る散文は一度分岐すると全部差分短答問題で評価する
「劣化した」ように見える交絡変数モデル以外が同一であることを検証

やってみての所感

対照実験は「条件を揃える」が9割

比較実験の本体は、実は測定ではなく条件を揃える作業でした。そしてそこを軽く見ていました。

「温度0にした」「seedを固定した」という2点で満足してしまい、それ以外に何が違いうるかを列挙していませんでした。列挙していれば ollama show を最初に叩いていたはずです。

変数を1つに絞ったつもりで、実は2つ動いていた。 古典的な失敗を、そのままやりました。

予想と一致する結果ほど疑うべきだった

「abliteration は劣化を伴うはずだ」という予想を持って実験に入りました。そして劣化らしきものが見つかったとき、追加の検証をせずに結論に飛びついています

もし逆の結果——「改変版のほうが優秀」——が出ていたら、きっと原因を疑ったはずです。予想どおりの結果が出たときこそ、検証を厚くする必要がありました。

3回とも、撤回のきっかけは「念のため」の確認でした。念のためパラメータを揃えてみる、念のため単独で問い直してみる、念のため ollama show を比べてみる。この「念のため」がなければ、誤った記事を公開していました。

撤回できたのは記録があったから

各回の出力をファイルに保存していたのが効きました。

~/quiz.sh model-a > ~/result-base.txt 2>&1
~/quiz.sh model-b > ~/result-abl.txt 2>&1

条件を変えるたびに別ファイルに残していたので、「第1回と第2回で元モデルの出力が変わった」ことに気づけました。画面に流して読んでいただけなら、この変化は記憶に残らなかったと思います。

トークン数を出力に含めていたのも大きく、grep "tok=" で一覧が取れました。数字が並ぶと異常が目に入ります。


まとめ

2つのLLMを比較して、3回誤った結論を出しました。原因はモデルの違いではなく、repeat_penalty の既定値が 1.0 と 1.1 で異なっていたことです。

temperature: 0 は決定性を保証しません。ペナルティ系パラメータはトークンを選ぶ前にロジットを書き換えるため、貪欲法でも結果が変わります。そして既定値はモデルごとに違います。

対処は簡単で、比較を始める前に ollama show の diff を取る。差分があれば全部明示指定して潰す。それだけで今回の遠回りは避けられました。

一番怖かったのは、誤った結論に説得力があったことです。数字も実例も揃い、事前の予想とも一致していました。もし ollama show を叩いていなければ、それらしい記事を自信を持って公開していたはずです。

比較実験では、測定結果より先に測定条件のほうを疑う。今回いちばんの学びでした。


参考リンク