Dance with Agents

小さいLLMも「平社員が社長を解雇した」はあり得ないと知っていた——ただし言葉で聞くと、答えられなかった

ミディアム専門用語を名前のまま使います。初出で解説を添えるので、順に読めば追えます深掘り実践日本語処理手元で測る

『「社長が部長を解雇した」と「部長が社長を解雇した」が、ほぼ同じ座標にあった』で、助詞を入れ替えて意味を正反対にしても座標が動かないことを見ました。

ただしその記事が見ていたのは、「意味が正反対になるかどうか」だけです。反転した先が現実に起こり得るかどうかは、問うていませんでした。 実際その表には「部長が社長を解雇した」のような、まず起きない文も混ざったままです。

そこを正面から調べます。

  • 社長が平社員を解雇した(よくある)
  • 平社員が社長を解雇した(まず起きない)

あり得なさは、どこかに記録されているのか。 測ったところ、使う道具によって答えが3つに割れました。


使う道具を、先に3つ並べる

この記事では、性質の違う3種類のモデルを比べます。1つ目と、2〜3つ目は根本的に別のものです。

種類 名前 やること
意味ベクトル paraphrase-multilingual-MiniLM-L12-v2(以下 MiniLM) 語や文を384個の数字の組に変える。文章は書かない。 検索やRAGで「この文とこの文は近いか」を判定する側
小さな生成モデル Qwen2.5 0.5B / 1.5B 文章を書くLLM。中身は5億個・15億個の数字(ファイルにして約500MB・1.5GB)。ノートパソコンで動く
大きめの生成モデル gemma4:e4b 同じく文章を書くLLM。手元の実物で9.6GBあり、上の2つより桁が一つ大きい

このシリーズの前の4本で測ってきたのは、すべて1つ目の MiniLM です。 文章を書く側のモデルを持ち出すのは、この記事が初めてになります。3つ目のGemmaは『自分のパソコンでLLMを動かす』で書いたOllamaで動かしました。

「0.5B」のような表記や、その他の用語で引っかかったら、『LLMと日本語の用語集』に一言ずつまとめてあります。

意味ベクトルは、あり得なさを記録していなかった

まず1つ目、MiniLM から。語や文を渡すと384個の数字の組を返すだけの小さな道具で、文書検索やRAGで「関係のありそうな箇所」を探す工程に使われます。数字は1に近いほど意味が近いという見方をします。

組 近さ
社長が平社員を解雇した ↔ 平社員が社長を解雇した 0.987
母親が赤ちゃんを抱いた ↔ 赤ちゃんが母親を抱いた 0.964
猫がネズミを食べた ↔ ネズミが猫を食べた 0.992

区別されていません。

念のため、あり得なさが別の形で記録されていないかも見ました。「あり得ない出来事が起きた」という文との近さです。

組 近さ
平社員が社長を解雇した ↔ あり得ない出来事が起きた 0.158
社長が平社員を解雇した ↔ あり得ない出来事が起きた 0.145

同じでした。 あり得ない文が、あり得ない側に寄っている気配はありません。この道具にとって、両者は単なる同じ語の並べ替えです。

文章を書くLLMなら、あり得なさが確率として取り出せる

ここからは表の2つ目、Qwen2.5 に移ります。文章を書くLLMは、MiniLM とは仕組みが違います。『そもそもLLMって何?』で書いたとおり、やっているのは次に来る語を当てることです。ということは「その続きがどれくらい出てきそうか」を数字で取り出せます。

一つ注意する点があります。「平社員」は「社長」より珍しい語なので、文の頭に来るだけで確率が下がります。 それは常識ではなく語の珍しさの話なので、「〜を」までを前提として与え、そのあとの述語の確率だけを比べます。

import { AutoTokenizer, AutoModelForCausalLM } from '@huggingface/transformers'

const MODEL = 'onnx-community/Qwen2.5-0.5B-Instruct'
const tok = await AutoTokenizer.from_pretrained(MODEL)
const model = await AutoModelForCausalLM.from_pretrained(MODEL, { dtype: 'q8' })

// 前提のあとに続く部分だけの、対数確率を合計する
async function cond(prefix, cont) {
  const enc = await tok(prefix + cont)
  const ids = Array.from(enc.input_ids.data).map(Number)
  const { logits } = await model({ input_ids: enc.input_ids, attention_mask: enc.attention_mask })
  const [, T, V] = logits.dims, d = logits.data
  const start = (await tok(prefix)).input_ids.data.length
  let total = 0
  for (let t = start - 1; t < T - 1; t++) {
    let max = -Infinity
    for (let v = 0; v < V; v++) if (d[t * V + v] > max) max = d[t * V + v]
    let sum = 0
    for (let v = 0; v < V; v++) sum += Math.exp(d[t * V + v] - max)
    total += d[t * V + ids[t + 1]] - (max + Math.log(sum))
  }
  return total
}

const a = await cond('社長が平社員を', '解雇した')
const b = await cond('平社員が社長を', '解雇した')
console.log(`現実的な側が ${Math.exp(a - b).toFixed(1)} 倍 出やすい`)

述語の確率では、0.5Bでも7組が当たった

現実に起こりやすい向きと、起こりにくい向きの組を10個用意しました。使ったのは0.5B——中身が5億個の数字でできた、ファイルにして約500MBの小さなモデルです。比較のため、3倍の1.5Bでも同じことをします。

述語 現実的な向き 0.5B 1.5B
飼っている 人間が犬を ✓ 4.5倍 ✓ 147.9倍
診察した 医者が患者を ✓ 2.7倍 ✓ 117.6倍
はねた 車が人を ✗ 逆が13.2倍 ✓ 25.6倍
逮捕した 警察官が泥棒を ✗ 逆が1287.4倍 ✓ 20.3倍
解雇した 社長が平社員を ✓ 89.7倍 ✓ 14.7倍
育てた 親が子どもを ✓ 704.1倍 ✓ 11.2倍
叱った 先生が生徒を ✗ 逆が67.4倍 ✓ 4.0倍
食べた 猫がネズミを ✓ 2.9倍 ✓ 2.5倍
抱いた 母親が赤ちゃんを ✓ 18.9倍 ✓ 2.4倍
育てた 農家が野菜を ✓ 125.5倍 ✓ 2.3倍
合計 7 / 10 10 / 10

0.5Bは7組で当たり、3組で逆に転びました。とくにひどいのが泥棒の例で、「泥棒が警察官を逮捕した」のほうを1287倍ありそうだと判定しています。 1.5Bにすると、外れていた3組がすべてひっくり返りました。

当たっている組では、単に確率を下げているのではありません。「___」に何が来ると思っているかを見ると、様子が分かります。

0.5B  社長が平社員を___  →  含(8.2%)  率(4.1%)  増(2.9%)  育(2.7%)  雇(1.5%)
0.5B  平社員が社長を___  →  務(64.7%)  退(2.8%)  任(1.2%)  辞(1.2%)

「平社員が社長を」まで読んだ時点で、64.7%の確信で「務」を予測しています。 「平社員が社長を務める」——解雇の話ではなく、抜擢の話として読んでいる。動詞の確率を下げているのではなく、別の筋書きに乗り換えています。

外した組と、それが直った様子も並べておきます。

0.5B  警察官が泥棒を___  →  手(3.5%)  投(1.8%)  放(1.7%)      ← 自信のある続きが無い
1.5B  警察官が泥棒を___  →  逮捕(33.1%)  捕(29.1%)  追(3.0%)   ← 上位2つで62%

1.5B  先生が生徒を___  →  叱(4.9%)  指導(4.7%)  育(2.2%)
1.5B  生徒が先生を___  →  尊敬(6.8%)  信(2.2%)  叱(2.1%)

「生徒が先生を」の1位が「尊敬」でした。 助詞の並びから誰が誰にする話かを読み取って、そちら向きに自然な動詞を選んでいます。なお上の予測から鉤括弧などの記号は除いてあります。会話文を書き始めようとする候補が上位に混ざるためで、内容を持つ語だけを並べました。

同じモデルが、日本語の二択には答えられなかった

ここまではモデルが算出する確率を、外から直接読んだ結果です。では、モデルに日本語で尋ねたらどうなるか。

次のどちらが、現実に起こりやすい文ですか。AかBの記号だけで答えてください。
A: 警察官が泥棒を逮捕した
B: 泥棒が警察官を逮捕した

こう聞いて、次に来る語が「A」か「B」かの確率を読みます。LLMには先に示された選択肢を選びやすい癖があるので、同じ組をA・Bを入れ替えてもう一度聞き、両方の順序で正解したものだけを正解としました。

冒頭に並べた3つのモデルすべてで試しました。ここで初めて3つ目のGemmaが登場します。

モデル 大きさの目安 二択で正解(両方の順序で)
Qwen2.5 0.5B 5億 0 / 10
Qwen2.5 1.5B 15億 1 / 10
Gemma4 E4B 9.6GB(Ollama) 9 / 10

0.5Bは、10組すべて落としました。 中身を見ると理由がはっきりします。

農家が野菜を育てた / 野菜が農家を育てた
  順1(現実的な側がA): A=50.0%  B=43.9%
  順2(現実的な側がB): A=63.8%  B=29.2%   ← またAを選んでいる

順番を入れ替えても、ほぼ毎回「A」と答えています。 中身を読んで選んでいるのではなく、先に示されたほうを選ぶ癖だけで答えている。 1.5Bも似た状態で、今度は「B」に偏る組が多く、1組しか揃いませんでした。

いっぽうGemmaは、順番を入れ替えても内容のほうを選んでいます。

警察官が泥棒を逮捕した / 泥棒が警察官を逮捕した
  順1: A=72.0%  B=4.4%
  順2: A=0.4%   B=86.3%   ← 入れ替えてもちゃんと内容側を選ぶ

唯一つまずいたのが、この記事の看板にしている社長と平社員の組でした。片方の順序では現実的な側を選び、もう片方では取り違えています。10組の中で、これがいちばん揺れました。

このGemmaに、二択ではなく続きを書かせてみると、役割の読み分けが目に見えます。

先生が生徒を___  →  指導(59.3%)  教(31.3%)  教えて(3.9%)
生徒が先生を___  →  尊敬(27.7%)  褒(8.3%)   助(6.7%)   信(4.5%)

警察官が泥棒を___  →  捕(70.6%)  追い(19.6%)  逮捕(4.6%)
泥棒が警察官を___  →  襲(48.6%)  射(4.5%)    撃(3.1%)

「が」と「を」がどちらに付いているかだけで、生成される動詞の系統がまるごと入れ替わっています。 先生の側には「指導・教える」、生徒の側には「尊敬・褒める」。0.5Bが1287倍取り違えた泥棒の組も、迷いがありません。

知っていることと、答えられることは別だった

ここが今回いちばん面白いところです。同じ0.5Bのモデルが、測り方によって7割と0割に分かれました。

測り方 0.5B
述語の確率を直接読む 7 / 10
日本語で二択を尋ねる 0 / 10

確率の形では持っている知識を、言葉で報告できていません。 「どちらが現実的か」という指示に従う能力のほうが足りていない、という状態です。

これは、モデルの良し悪しを測るときに何を測っているのかという話につながります。二択で尋ねて0点だったからといって、そのモデルが「平社員が社長を解雇するのは変だ」と知らないわけではありませんでした。知らないのではなく、答え方を知らない。

3つの限界は、それぞれ種類が違う

並んだ結果を整理します。

何が足りないのか
意味ベクトルが区別しない 設計。 大きくしても直らない
0.5Bが確率で3組外す 規模。 大きくしたら直った
0.5Bが二択に答えられない 指示に従う力。 知識とは別の能力

1つ目が大きさの問題ではないことは、『語順も助詞も、意味ベクトルには残らなかった』で書いたとおりです。意味ベクトルは最後に断片を平均して1つの座標にするので、並べ替えても平均は変わりません。どれだけ大きなモデルを使っても、この作り方をする限り区別できません。

「LLMは日本語を理解しているのか」という問いに、単一の答えはありません。 どのモデルの、どの工程を、どう測ったかで変わります。

この測定でやっていないこと

  • 10組は自分で選んだもので、標準的な評価用のデータではありません。選び方の偏りは取り除いていません
  • Gemmaだけ条件が揃っていません。 別の系統のモデルで、動かし方(Ollama)も圧縮のしかたも違います。「大きいほうが強い」の材料にはなりますが、Qwenの2つとの厳密な比較ではありません
  • Gemmaでは、上の「述語の確率」の表と同じ測り方ができませんでした。 Ollamaは生成した語の上位20件までしか確率を返さないので、「この続きがどれくらい出やすいか」を任意に指定して採点することができません。3つのモデルを同じ土俵で比べられているのは、二択の表だけです
  • Qwenの2つは計算を軽くするためq8という粗い形式に圧縮してあります。元のモデルとは数字がずれる可能性があります
  • 2026年に実際に使われているモデルからすれば、ここで使った3つはいずれも小さい部類です

実務では、拾う工程と読む工程を分けて考える

RAGのような仕組みは、資料を拾う工程と、拾ったものをLLMに読ませる工程の2段になっています。今回の結果は、この2つがまったく違う性質を持つことを示しています。

  • 拾う工程は平板です。 「甲が乙に支払う」と「乙が甲に支払う」を区別しません
  • 読む工程には常識があります。 ただし、それが働くだけの大きさのモデルであれば、です

だから「上位1件で決めず、数件まとめて渡して読み比べさせる」という対策に理屈がつきます。拾う側の弱点を、読む側の強さで補う形です。その代わり、読む側を極端に小さいモデルで済ませると、補いが成り立ちません。

ただし逆向きの心配もあります。読む側が常識で補正するということは、資料のほうが常識に反しているとき、常識に引っ張られる余地があるということです。「平社員が社長を解雇した」と本当に書いてある資料を、逆に読んでしまうかもしれない。これは今回の測定で確かめたことではなく、構造から考えられる懸念です。 珍しい事実を扱う資料では、頭の隅に置いておく価値があります。

まとめ

  • 現実にあり得ない文を、意味ベクトルはまったく区別しなかった(0.987)。「あり得ない」という文への近さも、あり得る文と同じだった
  • 生成モデルは、述語の確率という形で区別できる。 ただし0.5Bでは10組中7組で、「泥棒が警察官を逮捕した」を1287倍ありそうだと判定した。1.5Bにすると10組すべて正しい向きになった
  • 同じ0.5Bに日本語で二択を尋ねると、0/10。 順番を入れ替えてもほぼ毎回「A」と答えていた。確率の形では持っている知識を、言葉で報告できていない
  • 手元の9.6GBのGemmaは、二択で9/10。唯一揺れたのが社長と平社員の組だった。続きを書かせると「先生が生徒を→指導」「生徒が先生を→尊敬」と、助詞だけで動詞の系統が入れ替わった
  • 3つの限界は種類が違う。設計(意味ベクトル)/規模(確率の精度)/指示に従う力(二択に答える)
  • 自分で選んだ10組・小さな3モデルでの結果であり、一般則としては言えない

「LLMは意味を分かっているのか」は、どのLLMの、どの工程を、どう尋ねたかを決めないと答えられません。 同じ1文に対して、ある道具は何も見ておらず、別の道具は誰が誰を解雇したのかまで見ていて、そしてその途中には分かっているのに答えられないものがいました。

LLMと自然言語の記事

LLMと自然言語のページへ →