AIの生の出力「スコア」は直感的ではありません。Softmax関数は、このスコアを合計100%の「確率(信頼度)」に変換する重要な役割を担います。これにより、AIの予測を誰もが理解し、比較・活用できるようになります。ここではその仕組みと実装の要点を解説します。
AIが出力する生の数値(ロジット)は、大小関係は分かっても、その絶対的な意味や信頼度が不明確です。これでは実用的な判断材料になりません。
確率にすることで、①共通の尺度での比較、②意思決定の支援、③AIの効率的な学習、という3つのメリットが生まれ、AIの予測が実用的な価値を持ちます。
1. 強調: 指数関数 (ex) でスコアの差を際立たせます。
2. 正規化: 全体の合計値で各値を割り、合計が100%になる「確率」に変換します。
巨大なスコアによる計算破綻を防ぐため、計算前に全スコアから最大値を引きます。この工夫で結果を変えずに数値計算を安定させることができます。
はじめに:AIの「スコア」を「信頼度」に変換する
これまでの講座で、AIが学習という名の「山下り」を経て、賢くなっていく様子を追いかけてきましたね。学習を終えたAIは、新しいデータ、例えば一枚の胸部X線画像を受け取ると、その内部で膨大な計算を行い、最終的な「答え」を出力します。
しかし、その「答え」は、私たちが普段目にするような「肺炎です」という言葉ではありません。AIの最終層から出てくるのは、多くの場合、次のような生の「スコア」のリストなのです。
この [2.5, 4.1, 1.2] というスコア(専門的にはロジットと呼ばれます)を見て、私たちはどう判断すれば良いでしょうか。確かに「気胸」のスコアが一番高いので、これが最も可能性が高そうだと推測はできます。
でも、「AIの自信度は何%?」と聞かれたら、答えに窮してしまいますよね。「4.1」と「2.5」の差は、臨床的にどれほどの意味を持つのか。このままでは、AIの「思考」の途中経過を覗いているだけで、最終的な診断の根拠としては、あまりに心許ないと思いませんか?
私たちが臨床現場で本当に必要としているのは、こうした曖昧なスコアではなく、「気胸である確率79%、肺炎である確率16%、正常である確率5%」といった、誰にでも解釈可能で、かつ定量的な「信頼度」です。
今回の講座では、この生のスコア(ロジット)を、私たちの意思決定に役立つ美しい「確率」のリストへと変換してくれる、魔法のような関数、Softmax関数の扉を開きます。これは、AIの「思考」を、私たちが理解できる「言葉」へと翻訳してくれる、非常に重要な通訳者なのです。
1. なぜ「確率」で出力する必要があるのか? — スコアを「信頼度」に翻訳する意味
前のセクションで、私たちはAIが出力した [2.5, 4.1, 1.2] という生のスコアを前に、少し途方に暮れてしまいましたね。このままでは、AIの「思考」は私たちにとって解読困難な暗号のようです。
この暗号を、誰もが理解できる「言葉」に翻訳し直すこと、つまり確率として表現し直すことには、大きく分けて3つの計り知れないメリットがあります。
上の図は、同じAIの判断を、2つの異なる形式で表現したものです。左側(A)が生のスコア、右側(B)がそれを確率に変換したものです。この変換が、なぜこれほど重要なのでしょうか。
- 共通の“ものさし”で話せるようになる
第一に、比較可能な共通の指標になることです。生のスコアは、モデルの作りによってスケールがバラバラで、「4.1」という値が絶対的にどれほどの意味を持つのか、他のAIモデルが出したスコア「10.5」とどう比べれば良いのか、全く分かりません。一方、確率なら常に「0%から100%」という誰もが知る共通の尺度の上で議論できます。これにより、異なる予測結果やモデル間の性能比較が、初めて公平に行えるようになるのです。 - 臨床現場での意思決定に直接役立つ
第二に、そしてこれが最も重要なのですが、私たちの臨床判断に直接的な示唆を与えてくれる点です。例えば、ある治療法に対するAIの予測が、生のスコアで「奏効: 3.2, 非奏効: 2.8」と出たとします。これでは、「奏効の可能性が少し高そう」くらいにしか思えませんよね。しかし、これが確率で「奏効: 60%, 非奏効: 40%」と示されれば、その不確実性を具体的に認識した上で、「他の選択肢も検討しよう」あるいは「まずは試してみる価値がある」といった、より繊細な臨床判断を下すための材料になります(1)。 - AI自身の学習効率が上がる
最後の理由は、AI自身の学習が効率的になるからです。第5回で学んだように、分類問題の学習で使う「交差エントロピー誤差」という採点基準は、AIの出力が確率であることを前提に作られています。AIが自らの間違いを確率という言葉で認識することで、より効率的にパラメータを修正し、賢くなっていくことができるのです。
要するに、生のスコアを確率に変換するプロセスは、AIの思考を「自分だけが分かるメモ書き」から、「誰もが理解し、議論できるカルテ」へと清書するようなものです。この清書された情報があって初めて、AIは医療というチームの一員として機能できる、と言えるかもしれません。
では、この魔法のような変換を行うSoftmax関数とは、一体どのような仕組みなのでしょうか。次のセクションで、その中身を詳しく見ていきましょう。
2. Softmax関数 — スコアを「信頼度」に変換する魔法のレシピ
前のセクションで、AIの生のスコアを、解釈しやすい「確率」に変換する必要がある、という話になりましたね。では、その変換は、具体的にどのような計算で行われているのでしょうか。
その役割を担うのがSoftmax関数ですが、その中身は、実は2つのとても簡単なステップでできた、一種の「レシピ」なんです。先ほどの例、[肺炎スコア: 2.5, 気胸スコア: 4.1, 正常スコア: 1.2] を使って、その調理工程を見ていきましょう。
Step 1: ネイピア数 \(e\) の力で、スコアの個性を際立たせる
最初のステップの目的は2つあります。一つは、スコアがマイナスの値も取りうるため、全ての値を確実に正の数にすること。もう一つは、各スコアの大小関係を、より「メリハリ」のついた形に強調することです。
この両方を一度に解決してくれるのが、ネイピア数\(e\)を底とする指数関数(\(e^x\)、exp(x))です。この関数に入力すると、元のスコアが大きいほど、出力は爆発的に大きくなります。
私たちの例 [2.5, 4.1, 1.2] では、
- \(e^{2.5} \approx 12.18\)
- \(e^{4.1} \approx 60.34\)
- \(e^{1.2} \approx 3.32\)
となり、最大値だった 4.1 の出力 60.34 が、他の値に比べて圧倒的に大きくなっているのがわかりますよね。AIが「これが一番それっぽい!」と考えている選択肢を、より際立たせる効果があるのです。
Deep Dive! なぜSoftmaxは、2や10ではなく「ネイピア数 (e)」を使うのか?
Softmax関数の最初のステップで、なぜ私たちは中途半端に見える「\(e \approx 2.718\dots\)」という数を使うのでしょうか。「2」や「10」といった、もっとキリの良い数ではダメなのでしょうか?
これは素晴らしい質問で、その答えは、AIの学習プロセスの心臓部である「微分」のしやすさに隠されています。
思い出してみてください。AIの学習とは、損失関数の「勾配」を計算し、その情報を使ってパラメータを更新していくプロセスでした。つまり、AIの学習は、微分計算そのものと言っても過言ではありません。Softmax関数も、当然ながらこの微分計算の対象となります。
ここで、ネイピア数\(e\)を底とする指数関数 \(f(x) = e^x\) が持つ、奇跡のように美しい性質が登場します。それは、
「\(e^x\) は、微分しても形が変わらない唯一の関数である」
という性質です。数式で書くと、こうなります。
\[ \frac{d}{dx}e^x = e^x \]
\(e^x\)の、ある点での「瞬間の傾き」は、その点自身の値と全く同じなのです。
では、もし底を「10」に変えて、\(f(x) = 10^x\) という関数を使ったらどうなるでしょうか。これを微分すると、次のようになります。
\[ \frac{d}{dx}10^x = 10^x \ln(10) \]
おまけとして、\(\ln(10)\) という余計な項がくっついてきてしまいました。これは、ネイピア数\(e\)以外の数を底として使った場合に、必ず現れる「補正項」のようなものです。
微分の「伝言ゲーム」におけるエレガントさ
AIの学習は、誤差逆伝播法(バックプロパゲーション)という、連鎖律を使った「微分の伝言ゲーム」で行われるのでしたね。もし、Softmax関数に \(10^x\) を使ってしまうと、この伝言ゲームの途中で、常に「\(\times \ln(10)\)」という余計な計算を付け加えながら、情報を伝播させていかなければなりません。これは非常に煩雑で、数式も美しくありません。
一方で、\(e^x\) を使えば、微分しても形が変わらないため、この伝言ゲームが極めてシンプルかつエレガントに進みます。
自然対数 \(\ln\) との「相性」
さらに、分類問題でSoftmaxとペアで使われる損失関数は、交差エントロピー誤差でした。この関数は、\(e\)の「逆再生ボタン」である自然対数 \(\ln\) を使って定義されています。
つまり、AIは、
- \(e^x\) を持つSoftmax関数で、スコアを確率に変換し、
- \(\ln(x)\) を持つ交差エントロピー誤差で、その間違いを測る
という、非常に相性の良いペアで設計されているのです。このペアは、どちらも微分したときの形が非常にシンプルであるため、勾配計算全体が劇的に簡潔になり、コンピュータにとっても効率的なのです。
結論として、Softmax関数でネイピア数\(e\)が使われるのは、単に値を正にするためだけでなく、AIの学習の根幹である微分計算において、最も数学的に「自然」で「美しい」性質を持っているから、と言えるでしょう。それは、AIの設計における、先人たちの偉大な知恵の結晶なのです。
Step 2: 全体の合計で割って、「確率」としての資格を与える
Step 1で得られた [12.18, 60.34, 3.32] という値は、大小関係ははっきりしましたが、まだ「確率」とは呼べません。なぜなら、確率の重要なルールである「全ての選択肢の値を合計すると、必ず1(100%)になる」を満たしていないからです。
そこで、このルールを満たすために、各値を、全ての値の合計で割るという、非常にシンプルな操作を行います。この操作を正規化 (Normalization) と呼びます。
- 合計値の計算: \(12.18 + 60.34 + 3.32 = 75.84\)
- 各確率の計算:
- 肺炎の確率: \(\frac{12.18}{75.84} \approx 0.16\) (16%)
- 気胸の確率: \(\frac{60.34}{75.84} \approx 0.79\) (79%)
- 正常の確率: \(\frac{3.32}{75.84} \approx 0.05\) (5%)
これで、元のスコア [2.5, 4.1, 1.2] は、合計するとちゃんと1になる、美しい確率のリスト [0.16, 0.79, 0.05] に見事に翻訳されたわけです。
Softmax関数の定義式
この2ステップのプロセスを、一つの数式でまとめると、Softmax関数の定義式が完成します。入力スコアのリストを \((y_1, y_2, \dots, y_n)\) とすると、i番目のクラスの確率は次のように計算されます。
\[\text{Softmax}(y_i) = \frac{e^{y_i}}{\sum_{j=1}^{n} e^{y_j}}\]
- \(e^{y_i}\): これがStep 1です。各スコアを指数関数で変換し、個性を際立たせます。
- \(\sum_{j=1}^{n} e^{y_j}\): これがStep 2の分母。変換されたスコアの「合計値」を計算しています。
- \(\frac{…}{…}\): そして全体として、Step 1の結果をStep 2の合計値で割り、正規化しています。
分母の \(\sum\) 記号は「全てのjについて合計する」という意味なので、これはまさに「ある要素の指数値を、全要素の指数値の合計で割る」という、一連のプロセスそのものですね。
3. PythonでSoftmax関数を実装する — 安定した計算のための「ひと工夫」
理論がわかったところで、いよいよSoftmax関数をPythonコードに落とし込んでみましょう。定義式をそのまま実装するのは簡単ですが、実はそこにはコンピュータならではの、思わぬ「落とし穴」が潜んでいます。その問題をどう回避するのか、という実践的なテクニックも合わせて見ていきましょう。
a) 素朴な実装とその問題点(オーバーフロー)
まずは、Softmaxの定義式 \(\frac{e^{y_i}}{\sum e^{y_j}}\) を、素直にそのままコードにしてみます。
import numpy as np
def softmax_naive(x):
"""
単純なSoftmax関数の実装(オーバーフローの危険性あり)
"""
# Step 1: 入力値のネイピア数eのべき乗を計算
exp_x = np.exp(x)
# Step 2: 全てのべき乗の合計値を計算し、それで各値を割る
sum_exp_x = np.sum(exp_x)
y = exp_x / sum_exp_x
return y
このコードは、入力スコアが [2.5, 4.1, 1.2] のような小さな値のうちは、全く問題なく動作します。しかし、AIの学習が進むと、モデルが出力するスコア(ロジット)は、時に [1010, 1000, 990] のような非常に大きな値になることがあります。
このとき、コンピュータは \(e^{1010}\) という、天文学的な数値を計算しようとしてしまいます。これは、コンピュータが表現できる数値の上限を遥かに超えてしまうため、結果は無限大 (infinity) となり、最終的な計算は失敗(nan: Not a Number)してしまいます。これをオーバーフローと呼びます。
b) 安定版の実装 — 「オーバーフロー」を回避する賢い工夫
この問題を解決するために、私たちは計算の前に、ある「おまじない」をかけます。それは、入力値のすべてから、その中の最大値を引くという、とてもシンプルな操作です。
なぜ、こんな操作でうまくいくのでしょうか?実は、Softmax関数には「入力値に同じ定数を足したり引いたりしても、出力結果は変わらない」という、とても美しい性質があるからです。(\(c\) を定数とすると、\(\text{Softmax}(y_i) = \text{Softmax}(y_i – c)\) が成り立ちます。)
そこで、この定数 \(c\)として、入力値の最大値を使うのです。
この工夫を取り入れた、安定版のSoftmax関数を見てみましょう。
【実行前の準備】
以下のコードで日本語のグラフを表示させるには、あらかじめターミナルやコマンドプロンプトで pip install japanize-matplotlib を実行してライブラリをインストールしてください。
# NumPyライブラリをインポートします
import numpy as np
def softmax_stable(x):
"""
オーバーフロー対策を施した、安定版のSoftmax関数
"""
# 入力値から最大値を引く(この一行が重要!)
x = x - np.max(x)
exp_x = np.exp(x)
sum_exp_x = np.sum(exp_x)
y = exp_x / sum_exp_x
return y
# --- 例1:通常のスコア ---
scores1 = np.array([2.5, 4.1, 1.2])
probs1 = softmax_stable(scores1)
print(f"--- スコア {scores1} の場合 ---")
print(f"確率: {np.round(probs1, 3)}") # 小数点3桁に丸めて表示
print(f"確率の合計: {np.sum(probs1)}")
print("\n")
# --- 例2:非常に大きなスコア ---
scores2 = np.array([1010, 1000, 990])
probs2 = softmax_stable(scores2)
print(f"--- スコア {scores2} の場合(安定版)---")
print(f"確率: {np.round(probs2, 3)}")
print(f"確率の合計: {np.sum(probs2)}")
▼上記コードの実行結果
--- スコア [2.5 4.1 1.2] の場合 ---
確率: [0.162 0.795 0.043]
確率の合計: 1.0
--- スコア [1010 1000 990] の場合(安定版)---
確率: [0.999 0. 0. ]
確率の合計: 1.0
この softmax_stable 関数では、最初に x = x - np.max(x) という一行が入っています。scores2 = [1010, 1000, 990] の場合、最大値は 1010 なので、exp を計算する前に入力は [0, -10, -20] に変換されます。これらの値なら、exp を計算してもオーバーフローの心配はありません。そして、数学的な性質から、最終的な確率の計算結果は、この操作をしなかった場合と全く同じになるのです。これは、Softmaxを扱う上で、必ず知っておくべき、非常に重要な実装テクニックです(6)。
理解度チェッククイズ
1. Softmax関数の出力される値の合計は、常にいくつになりますか?
- 0
- 1
- 入力値の合計に等しい
2. Softmax関数が、入力値を最初に変換するために使う基本的な関数は何ですか?
- 対数関数 (\(\log\))
- 三角関数 (\(\sin\))
- 指数関数 (\(e^x\))
3. Softmaxの実装において、入力値から最大値を引く工夫は何のためですか?
- 計算を速くするため
- オーバーフローを防ぎ、数値計算を安定させるため
- 出力される確率の値を大きくするため
答え1-b, 2-c, 3-b
まとめ:AIの「自信」を誰もがわかる言葉へ
- AIの分類モデルが出力する生の「スコア」は、それだけでは解釈が難しく、標準化されていません。
- Softmax関数は、ネイピア数\(e\)の力を借りて、任意のスコアのリストを、合計が1になる確率のリストへと変換します。
- この変換により、AIの予測を「信頼度」という、人間にも理解しやすく、かつ数学的にも扱いやすい形で表現することが可能になります。
Softmax関数は、AIの「思考」の最終段階で、その内部的な判断を、私たちが意思決定に使える「言葉」へと翻訳してくれる、極めて重要なコミュニケーターの役割を果たしているのです。
次回、第8回「固有値と次元削減 — 主成分分析(PCA)で本質を見抜く」では、再び線形代数の世界に戻り、AIが大量のデータから「本当に重要な情報」だけを見つけ出すための、強力なテクニックを探求します。
参考文献
- Bishop CM. Pattern Recognition and Machine Learning. New York: Springer; 2006. Chapter 4.
- Goodfellow I, Bengio Y, Courville A. Deep Learning. MIT Press; 2016. Chapter 6.
- Murphy KP. Machine Learning: A Probabilistic Perspective. MIT Press; 2012.
- Deisenroth MP, Faisal AA, Ong CS. Mathematics for Machine Learning. Cambridge, UK: Cambridge University Press; 2020.
- Liu W, Wen Y, Yu Z, Yang M. Large-margin softmax loss for convolutional neural networks. In: Proceedings of the 33rd International Conference on Machine Learning. 2016.
- CS231n Convolutional Neural Networks for Visual Recognition [Internet]. Stanford University. Available from: https://cs231n.github.io/linear-classify/#softmax
ご利用規約(免責事項)
当サイト(以下「本サイト」といいます)をご利用になる前に、本ご利用規約(以下「本規約」といいます)をよくお読みください。本サイトを利用された時点で、利用者は本規約の全ての条項に同意したものとみなします。
第1条(目的と情報の性質)
- 本サイトは、医療分野におけるAI技術に関する一般的な情報提供および技術的な学習機会の提供を唯一の目的とします。
- 本サイトで提供されるすべてのコンテンツ(文章、図表、コード、データセットの紹介等を含みますが、これらに限定されません)は、一般的な学習参考用であり、いかなる場合も医学的な助言、診断、治療、またはこれらに準ずる行為(以下「医行為等」といいます)を提供するものではありません。
- 本サイトのコンテンツは、特定の製品、技術、または治療法の有効性、安全性を保証、推奨、または広告・販売促進するものではありません。紹介する技術には研究開発段階のものが含まれており、その臨床応用には、さらなる研究と国内外の規制当局による正式な承認が別途必要です。
- 本サイトは、情報提供を目的としたものであり、特定の治療法を推奨するものではありません。健康に関するご懸念やご相談は、必ず専門の医療機関にご相談ください。
第2条(法令等の遵守)
利用者は、本サイトの利用にあたり、医師法、医薬品、医療機器等の品質、有効性及び安全性の確保等に関する法律(薬機法)、個人情報の保護に関する法律、医療法、医療広告ガイドライン、その他関連する国内外の全ての法令、条例、規則、および各省庁・学会等が定める最新のガイドライン等を、自らの責任において遵守するものとします。これらの適用判断についても、利用者が自ら関係各所に確認するものとし、本サイトは一切の責任を負いません。
第3条(医療行為における責任)
- 本サイトで紹介するAI技術・手法は、あくまで研究段階の技術的解説であり、実際の臨床現場での診断・治療を代替、補助、または推奨するものでは一切ありません。
- 医行為等に関する最終的な判断、決定、およびそれに伴う一切の責任は、必ず法律上その資格を認められた医療専門家(医師、歯科医師等)が負うものとします。AIによる出力を、資格を有する専門家による独立した検証および判断を経ずに利用することを固く禁じます。
- 本サイトの情報に基づくいかなる行為によって利用者または第三者に損害が生じた場合も、本サイト運営者は一切の責任を負いません。実際の臨床判断に際しては、必ず担当の医療専門家にご相談ください。本サイトの利用によって、利用者と本サイト運営者の間に、医師と患者の関係、またはその他いかなる専門的な関係も成立するものではありません。
第4条(情報の正確性・完全性・有用性)
- 本サイトは、掲載する情報(数値、事例、ソースコード、ライブラリのバージョン等)の正確性、完全性、網羅性、有用性、特定目的への適合性、その他一切の事項について、何ら保証するものではありません。
- 掲載情報は執筆時点のものであり、予告なく変更または削除されることがあります。また、技術の進展、ライブラリの更新等により、情報は古くなる可能性があります。利用者は、必ず自身で公式ドキュメント等の最新情報を確認し、自らの責任で情報を利用するものとします。
第5条(AI生成コンテンツに関する注意事項)
本サイトのコンテンツには、AIによる提案を基に作成された部分が含まれる場合がありますが、公開にあたっては人間による監修・編集を経ています。利用者が生成AI等を用いる際は、ハルシネーション(事実に基づかない情報の生成)やバイアスのリスクが内在することを十分に理解し、その出力を鵜呑みにすることなく、必ず専門家による検証を行うものとします。
第6条(知的財産権)
- 本サイトを構成するすべてのコンテンツに関する著作権、商標権、その他一切の知的財産権は、本サイト運営者または正当な権利を有する第三者に帰属します。
- 本サイトのコンテンツを引用、転載、複製、改変、その他の二次利用を行う場合は、著作権法その他関連法規を遵守し、必ず出典を明記するとともに、権利者の許諾を得るなど、適切な手続きを自らの責任で行うものとします。
第7条(プライバシー・倫理)
本サイトで紹介または言及されるデータセット等を利用する場合、利用者は当該データセットに付随するライセンス条件および研究倫理指針を厳格に遵守し、個人情報の匿名化や同意取得の確認など、適用される法規制に基づき必要とされるすべての措置を、自らの責任において講じるものとします。
第8条(利用環境)
本サイトで紹介するソースコードやライブラリは、執筆時点で特定のバージョンおよび実行環境(OS、ハードウェア、依存パッケージ等)を前提としています。利用者の環境における動作を保証するものではなく、互換性の問題等に起因するいかなる不利益・損害についても、本サイト運営者は責任を負いません。
第9条(免責事項)
- 本サイト運営者は、利用者が本サイトを利用したこと、または利用できなかったことによって生じる一切の損害(直接損害、間接損害、付随的損害、特別損害、懲罰的損害、逸失利益、データの消失、プログラムの毀損等を含みますが、これらに限定されません)について、その原因の如何を問わず、一切の法的責任を負わないものとします。
- 本サイトの利用は、学習および研究目的に限定されるものとし、それ以外の目的での利用はご遠慮ください。
- 本サイトの利用に関連して、利用者と第三者との間で紛争が生じた場合、利用者は自らの費用と責任においてこれを解決するものとし、本サイト運営者に一切の迷惑または損害を与えないものとします。
- 本サイト運営者は、いつでも予告なく本サイトの運営を中断、中止、または内容を変更できるものとし、これによって利用者に生じたいかなる損害についても責任を負いません。
第10条(規約の変更)
本サイト運営者は、必要と判断した場合、利用者の承諾を得ることなく、いつでも本規約を変更することができます。変更後の規約は、本サイト上に掲載された時点で効力を生じるものとし、利用者は変更後の規約に拘束されるものとします。
第11条(準拠法および合意管轄)
本規約の解釈にあたっては、日本法を準拠法とします。本サイトの利用および本規約に関連して生じる一切の紛争については、東京地方裁判所を第一審の専属的合意管轄裁判所とします。
For J³, may joy follow you.

