火曜の夜21時、銀座の隠れ家バー、月1の銘酒会、カウンターに20本の純米吟醸が並ぶ…
御託(シニアコンサル・39)

フッ、今夜も 20本 並んだか。…私は、カウンターを見渡しながら頭の中で 各銘柄にスコアを付ける 癖がある。鳳凰美田 +8.5十四代 +7.8獺祭 二割三分 +6.2久保田 千寿 +4.0、…そして店のサービス ハイボール、これは -∞。絶対に選ばない。

凡田(チームリーダー・38, 主人公)

(これ完全に W_u が出すロジット の話だ。20銘柄=vocab、各銘柄のスコア=ロジット、ハイボール -∞ は Causal Mask 相当の 「禁止」 設定。御託さんが、自分が softmax 直前のロジットベクトル出してることに気づかずに語ってる…)

御託

ここからが私の流儀だ。各スコアに exp() をかける。+8.5 は約 4914、+7.8 は約 2441、+6.2 は約 493、+4.0 は約 55。…一気に 差が拡大 する。そして全部を 合計で割る。すると 鳳凰美田 0.62、十四代 0.31、獺祭 0.06、久保田 0.01、ハイボールは 0.00。合計ぴったり 1、これが私の 「今夜の気分配分」 だ。

凡田

(出た、完全な softmax の手計算 だ。御託さん、それ ChatGPT が 1トークン出すたびに 5万次元でやってる作業 なんですよ…と言いたいが哲学引用で30分返ってくるから飲み込む。それにしても、ロジットの +8.5 と +7.8 の 0.7 差 が、確率では 0.62 と 0.31 の 2倍差 になってる。これが exp の 「差を増幅」 って性質か。)

火曜21時の銀座の隠れ家バー、カウンターに20本の日本酒瓶が並び、御託が指で銘柄を数えながら頭の中で確率分布を計算、隣で凡田が驚き顔でグラスを持つ、思考バブルに棒グラフが浮かぶ図
この記事の要約(3行)
  • ソフトマックス(softmax) = バラバラの生スコア(ロジット)を、合計100%の割合に変える関数。ひとことで言えば「点数を割合に直す」装置。
  • 大事なのは出力側で「次のトークンの確率」を作る役目。生のスコアのままでは選べないので、合計1の確率分布 (#024) に変換する。
  • イメージは選挙の得票数を得票率に直すのと同じ。さらに差を強調するので、スコアが大きいものはより目立つ割合になる(計算式は本文で)。

ロジット (#039) = W_u (#038) が出力する vocab_size 次元の実数ベクトル。負の値もありえる、合計も決まっていない、ただの実数の並び。

でも次に AI が 「1個の単語」 を選ぶには、これを 確率分布 (#024) に変換しないといけない。全部正の値、合計が1。これを担う関数が softmax

定義 — 実数ベクトルを確率分布に変換する関数

softmax の処理は たった2ステップ:

  1. 各要素に exp() をかける → 全部正の値に変わる、かつ大きい入力ほど大きく増幅される
  2. 全要素の合計で割る → 合計がきっかり1になる(=確率分布の定義を満たす)

御託の銘酒会で起きていたことを、表で並べると:

銘柄 ロジット z_i exp(z_i) softmax 後 p_i
鳳凰美田 +8.5 4,914 0.62
十四代 +7.8 2,441 0.31
獺祭 二割三分 +6.2 493 0.06
久保田 千寿 +4.0 55 0.01
ハイボール -∞ 0 0.00
合計 7,903 1.00

2段階の変換だけで、任意の実数の並び合計ぴったり1の確率分布 に変わる。これが softmax の核心。

なぜ exp() を使うのか — 「大きい差を、もっと際立たせる」

まず exp() とは何か。e(ネイピア数)≒ 2.718… という数学定数の x 乗を計算する関数。電卓に「e^x」ボタンがあればそれ。ロジットベクトルの 各要素 z_i に独立に 適用する(隣の要素の値は計算に関係ない)。御託の銘酒会の数字で電卓を叩くと:

ポイント: 入力が 負の値 でも exp() の出力は 必ず正(漸近的に 0 に近づくだけ、絶対に負にはならない)。例えば e^(-2) ≒ 0.135e^(-10) ≒ 0.000045。これで「確率は 0 以上」という条件を自動で満たす。

では「全部を正にして合計1にする」だけなら、別に exp() を使わなくてもいい。例えば 絶対値を取って合計で割る でも、形だけは確率分布になる。なぜわざわざ exp() なのか。

理由は 「大きい差を、もっと際立たせたい」 から。御託の銘酒会で見たとおり:

「9% の好み差」を「2倍の選びやすさ」に変換している。これが exp() の指数的増幅。少しの自信差で、選ばれる確率は何倍にもなる。「はっきりとした選好」 を表現するため の数学的選択。

逆に、ロジットの差が小さい場合(例: +5.0 vs +4.9、差 0.1)は、確率も近い値になる(例: 0.52 vs 0.48)。差が大きいほど、確率はより極端に振れる。これが softmax が 「確信のレベル」 を表現する仕組み。

ロジット [8.5, 7.8, 6.2, 4.0, -∞] → exp [4914, 2441, 493, 55, 0] → 合計で割る → 確率分布 [0.62, 0.31, 0.06, 0.01, 0.00] のステップ図、合計が1になることを強調

図1: softmax の2ステップ — ① 各要素に exp() で増幅、② 合計で割って正規化。御託の銘酒会の数値で追跡

性質 ① — 順位は崩れない、全員に同じ数を足しても結果は同じ

順位は崩れない: softmax を通しても、ロジットの大小の順位はそのまま。御託の銘酒会で言えば、ロジットで +8.5 が1位 なら、softmax 後の確率でも 0.62 が1位。当たり前のように聞こえるが、「変換しても順位は同じ」というのは実は重要な性質(ロジット記事 (#039) でも触れた)。「1位だけ知ればいい場面」では、softmax を通さずロジットの最大値を見るだけで答えが出る、という効率化の根拠になる。

全員に同じ数を足しても結果は同じ(数学者用語: シフト不変): ロジットの 全要素に同じ数を足しても、softmax 後の確率分布は1ミリも変わらない。例えば御託の銘酒会で、全銘柄に +1000 のボーナス点 を加えて、ロジットを [+1008.5, +1007.8, +1006.2, +1004.0, -∞] にしても、出てくる確率分布は元と同じ [0.62, 0.31, 0.06, 0.01, 0.00]

理由は単純で、softmax は 「銘柄同士の差」 しか見ない関数だから。全員に +1000 を足しても、各銘柄 同士の差 は変わらない(+8.5 vs +7.8 の差 0.7 = +1008.5 vs +1007.8 の差 0.7)。ロジット記事の 「差分だけが意味、絶対値は意味薄」 の話と同じこと。

この性質、何の役に立つの? — 計算機の桁あふれ対策

コンピュータで exp(1000) を計算しようとすると、数値が大きすぎて表現できなくなる(桁あふれ = オーバーフロー)。LLM のロジットが理論上どんな大きな値を持ちうるか分からない以上、これは実装上の重大な問題。

そこで 「全要素から最大値を引いてから exp する」 のが標準テクニック。シフト不変なので結果は変わらないが、計算は爆発しない:

def softmax(z):
    z = z - z.max()        # 全要素から最大値を引く(最大値が 0 になる)
    exp_z = exp(z)         # 1位は exp(0) = 1、他は exp(負) で 1 未満
    return exp_z / exp_z.sum()

御託の銘酒会の数字で追跡すると: 元のロジット [+8.5, +7.8, +6.2, +4.0] から最大値 +8.5 を引くと [0, -0.7, -2.3, -4.5]。これに exp() を当てると [1, 0.50, 0.10, 0.011]、全部 1 以下で計算機にやさしい。合計で割って確率分布を出すと [0.62, 0.31, 0.06, 0.01]、引き算前と全く同じ結果。

「ロジットは差分だけが意味」というロジット記事の性質を、実装レベルで活かしている 瞬間。LLM の本番コードでも、softmax 関数の中ではこの引き算が必ず行われている。

性質 ② — 微分可能、cross-entropy 損失との蜜月

softmax が LLM 学習で必須な最大の理由が、微分可能 であること。argmax(=単純に1位を選ぶ)は微分不可能で、「正解と外れたから1位の重みを少し下げる」みたいな勾配計算ができない。

softmax だと 確率分布の全要素が勾配を持つ。「正解の確率を 0.62 → 0.65 に上げ、不正解の確率を 0.31 → 0.28 に下げる」みたいに、全候補に対して同時に少しずつダイヤルを回す ことができる。これが 勾配降下 (#015) + 逆伝播 (#016) で学習を可能にする土台。

さらに、LLM の学習で使う cross-entropy 損失(交差エントロピー)が softmax と数学的に蜜月の関係。両者を組み合わせると、勾配が (予測確率 − 正解 one-hot) という恐ろしくシンプルな形に縮退する。実装も学習も安定する。

「softmax + cross-entropy が LLM 学習の事実上の標準」と言われるのは、この組み合わせの計算的な相性のよさが理由。詳しくは別記事 クロスエントロピー(別記事予定)で扱う。

コンサル感覚 — 「スコア比較」 と 「確率配分」 を切り分ける

本記事の核心メッセージは 「実数ベクトルに softmax を通すと、合計1の確率分布になる」。これを実務で意識するメリット:

① AI スコアモデルの出力解釈: クライアントが「AI が出す数値の意味がわからない」と言う時、それが softmax 前(ロジット) なのか softmax 後(確率) なのかで意味がまったく変わる。前者は「順位・差分」を読む、後者は「全体100%のうち何%」を読む。両者を混同するとレポートが間違う。

② 「自信度」の表現方法: モデルの 「確信」 を可視化する時、softmax 後の確率を見せると 「はっきりした選好」 に見える(0.62 vs 0.31)。一方ロジットの差分を見せると 「微妙な迷い」 も見える(+8.5 vs +7.8 のたった 0.7 差)。クライアントへの伝え方次第で印象が変わる、というのは設計者なら押さえておきたい。

③ 「全候補の合計が100%」 のフレームを使える: コンサル提案で「3案のうちどれを推奨するか」を確率で出すと、説得力が上がる(A案 0.6 / B案 0.3 / C案 0.1、合計1)。これも構造的には softmax と同じ思考フレーム。各案にスコアを付けて、指数で増幅して、合計で割る。

翌日水曜の昼、アイマイ社の給湯室、凡田が昨夜の銘酒会の余韻でぼやく…
凡田

昨日、御託さんの銘酒会で隣に座らされたんだけどさ、20本並んだ純米吟醸を眺めて 指で1本ずつカウントしながら『+8.5、+7.8…』ってボソボソ点数化 してるんだよ。お酒なのに点数つけんなよって思った。

川口(アナリスト・22)

(20本ですか…ちなみに私、先月の おおぞら12号 に乗った時に 停車22駅 の到着時刻と乗降客数を時刻表片手に1駅ずつ点数化したことがありまして、似たような遊びかもしれません。新得駅は +9.2 でした、駅蕎麦が想定外で…)

大蔵(アシスタントマネージャー・35)

あら、川口さんも点数化なさるの。私も 銀座カフェ巡り で Instagram に出す写真は 映え度 で並べておりますけれど、御託さんみたいに 口には出しません わよ。心の中で シュッ と決めて指でタップして投稿、それがレディの嗜み。20本にカウンターで20分かけるなんて、私には絶対に真似できませんわね、ホホ。

赤崎(部長・42)

俺はパワポレビューで案を見せられても 「いいねいいね、全部いいよ」 しか言わないからなぁ。御託の 点数化エネルギー、別の意味でうらやましいわ。…そういえば、最近ベランダのトマトに肥料を3種類試してるんだけど、その時は 葉の艶実の張り で点数つけてるな、俺。お酒には興味ないけど。

御託

フッ、凡田、私の銘酒会の話を社内で広めるな。…まあいい、20本に時間をかけるのは別に無駄ではない。あれは 「今夜の自分との対話」 であってだな、お前らみたいに「美味けりゃいい」「映えればいい」「葉の艶」では到達できない領域がある。ちなみに私は その日の体調 によっても点数の重み付けが変わる。疲れた夜は1本に絞られ、元気な夜は全銘柄に広がる。

凡田

(出た、「今夜の自分との対話」。…単にお酒選ぶだけだろ。御託さん、銘酒会のたびに20分悩むのに、結局1番点数高い銘柄を選んでるじゃないか、と思いつつ口には出さない。あと 「体調で重み付けが変わる」 ってさらっと言ったの、たぶん次の温度の話で出てくるやつだ。)

水曜昼の給湯室でコーヒーマシンを背景に、凡田がホワイトボードに棒グラフを描き、川口がノートPC、大蔵がスマホでInstagramカフェ画像をスライド、赤崎が腕組み、御託が日本酒の徳利を手に持つ5人会議の図

応用 — softmax が出てくる場所の整理

本記事の余談として、LLM / NN の中で softmax が出てくる主要な場所を整理:

つまり softmax は 「N 個の選択肢から1つを確率的に選びたい時の標準装置」。LLM の中で何百回も呼び出され、ニューラルネットワーク全般で最も頻出する活性化関数の1つ。

深掘り記事 ・ 公開中温度(Temperature) (#041)softmax 前にロジットを温度で割って分布の 「とがり/平坦さ」 を調整する技