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

- ソフトマックス(softmax) = バラバラの生スコア(ロジット)を、合計100%の割合に変える関数。ひとことで言えば「点数を割合に直す」装置。
- 大事なのは出力側で「次のトークンの確率」を作る役目。生のスコアのままでは選べないので、合計1の確率分布 (#024) に変換する。
- イメージは選挙の得票数を得票率に直すのと同じ。さらに差を強調するので、スコアが大きいものはより目立つ割合になる(計算式は本文で)。
ロジット (#039) = W_u (#038) が出力する vocab_size 次元の実数ベクトル。負の値もありえる、合計も決まっていない、ただの実数の並び。
でも次に AI が 「1個の単語」 を選ぶには、これを 確率分布 (#024) に変換しないといけない。全部正の値、合計が1。これを担う関数が softmax。
定義 — 実数ベクトルを確率分布に変換する関数
softmax の処理は たった2ステップ:
- 各要素に exp() をかける → 全部正の値に変わる、かつ大きい入力ほど大きく増幅される
- 全要素の合計で割る → 合計がきっかり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 に独立に 適用する(隣の要素の値は計算に関係ない)。御託の銘酒会の数字で電卓を叩くと:
- 鳳凰美田:
e^(+8.5)≒ 4,914 - 十四代:
e^(+7.8)≒ 2,441 - 獺祭:
e^(+6.2)≒ 493 - 久保田:
e^(+4.0)≒ 55 - ハイボール:
e^(-∞)= 0(理論上の極限)
ポイント: 入力が 負の値 でも exp() の出力は 必ず正(漸近的に 0 に近づくだけ、絶対に負にはならない)。例えば e^(-2) ≒ 0.135、e^(-10) ≒ 0.000045。これで「確率は 0 以上」という条件を自動で満たす。
では「全部を正にして合計1にする」だけなら、別に exp() を使わなくてもいい。例えば 絶対値を取って合計で割る でも、形だけは確率分布になる。なぜわざわざ exp() なのか。
理由は 「大きい差を、もっと際立たせたい」 から。御託の銘酒会で見たとおり:
- ロジット段階: +8.5 と +7.8 の差は 0.7(約 9% 差)
- exp() 通過後: 4914 と 2441 の差は 2473(約 2倍差)
- 確率段階: 0.62 と 0.31(2倍差)
「9% の好み差」を「2倍の選びやすさ」に変換している。これが exp() の指数的増幅。少しの自信差で、選ばれる確率は何倍にもなる。「はっきりとした選好」 を表現するため の数学的選択。
逆に、ロジットの差が小さい場合(例: +5.0 vs +4.9、差 0.1)は、確率も近い値になる(例: 0.52 vs 0.48)。差が大きいほど、確率はより極端に振れる。これが softmax が 「確信のレベル」 を表現する仕組み。
性質 ① — 順位は崩れない、全員に同じ数を足しても結果は同じ
順位は崩れない: 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…』ってボソボソ点数化 してるんだよ。お酒なのに点数つけんなよって思った。
(20本ですか…ちなみに私、先月の おおぞら12号 に乗った時に 停車22駅 の到着時刻と乗降客数を時刻表片手に1駅ずつ点数化したことがありまして、似たような遊びかもしれません。新得駅は +9.2 でした、駅蕎麦が想定外で…)
あら、川口さんも点数化なさるの。私も 銀座カフェ巡り で Instagram に出す写真は 映え度 で並べておりますけれど、御託さんみたいに 口には出しません わよ。心の中で シュッ と決めて指でタップして投稿、それがレディの嗜み。20本にカウンターで20分かけるなんて、私には絶対に真似できませんわね、ホホ。
俺はパワポレビューで案を見せられても 「いいねいいね、全部いいよ」 しか言わないからなぁ。御託の 点数化エネルギー、別の意味でうらやましいわ。…そういえば、最近ベランダのトマトに肥料を3種類試してるんだけど、その時は 葉の艶 と 実の張り で点数つけてるな、俺。お酒には興味ないけど。
フッ、凡田、私の銘酒会の話を社内で広めるな。…まあいい、20本に時間をかけるのは別に無駄ではない。あれは 「今夜の自分との対話」 であってだな、お前らみたいに「美味けりゃいい」「映えればいい」「葉の艶」では到達できない領域がある。ちなみに私は その日の体調 によっても点数の重み付けが変わる。疲れた夜は1本に絞られ、元気な夜は全銘柄に広がる。
(出た、「今夜の自分との対話」。…単にお酒選ぶだけだろ。御託さん、銘酒会のたびに20分悩むのに、結局1番点数高い銘柄を選んでるじゃないか、と思いつつ口には出さない。あと 「体調で重み付けが変わる」 ってさらっと言ったの、たぶん次の温度の話で出てくるやつだ。)

応用 — softmax が出てくる場所の整理
本記事の余談として、LLM / NN の中で softmax が出てくる主要な場所を整理:
- 出力層(本記事の主題): W_u から出たロジットを確率分布に変換、次トークン予測の最終ステップ。
- アテンションのスコア正規化: Q · K^T のスコアを softmax で「どのトークンにどれだけ注目するか」の確率分布に変換。Q/K/V (#035) の核心処理の一部。
- 分類タスク全般: 画像分類、感情分析、言語判定など、N 個のクラスから1つを選ぶ全てで softmax + cross-entropy がデフォルト。
- 強化学習の方策ネットワーク: 各行動の 「選ばれる確率」 を softmax で出力。
つまり softmax は 「N 個の選択肢から1つを確率的に選びたい時の標準装置」。LLM の中で何百回も呼び出され、ニューラルネットワーク全般で最も頻出する活性化関数の1つ。
深掘り記事 ・ 公開中温度(Temperature) (#041)softmax 前にロジットを温度で割って分布の 「とがり/平坦さ」 を調整する技