🤪

高校数学を忘れても分かるソフトマックス関数

2024/08/28に公開

こんにちは,本日はソフトマックス関数について解説します.

ソフトマックス関数とは

  1. ソフトマックス関数の基本概念
    ソフトマックス関数は、入力されたベクトルの各要素を正規化して確率分布に変換します。具体的には、次のように定義されます。
\text{softmax}(u_i) = \frac{\exp(u_i)}{\sum_{j} \exp(u_j)}

ここで、u_i は入力ベクトル u の各要素、\exp は指数関数を表します。

  1. ソフトマックス関数の利用例
    ソフトマックス関数は、分類問題において、クラスごとの確率を計算するために広く使われています。たとえば、ニューラルネットワークの出力層では、次のように使用されます。
y_i = \text{softmax}(z_i) = \frac{\exp(z_i)}{\sum_{k} \exp(z_k)}

ここで、z_i は出力層のロジット(モデルの出力値)です。

  1. ソフトマックス関数の数値安定性
    数値計算の際、ソフトマックス関数を直接計算すると、オーバーフローやアンダーフローが発生する可能性があります。これを防ぐために、すべての u_i から最大値 u_{\text{max}} を引くことで数値計算を安定させます。
\text{softmax}(u_i) = \frac{\exp(u_i - u_{\text{max}})}{\sum_{j} \exp(u_j - u_{\text{max}})}

この操作によって、計算結果には影響を与えず、数値的に安定した結果を得ることができます。ディープラーニングなどの実際の数値計算では、ソフトマックス関数を計算する際に、通常こちらの計算方法が使われます。

もとの計算方法と,最大値を引く計算方法とで,結果に影響を与えないのはなぜ?

まず,指数関数についておさらいしましょう.指数関数の定義は以下の通りです.

\exp(x) = e^x

ここで、e は自然対数の底であり、約 2.71828 です。指数関数は、数学的に非常に重要な関数で、特に成長や減衰をモデル化する際に広く使われます。

指数関数には、以下のような重要な積の法則があります:

e^{x + y} = e^x \cdot e^y

指数関数の積の法則をソフトマックス関数にも当てはめて考えてみましょう.ソフトマックス関数は、次のように定義されると先ほどお話ししました.

\text{softmax}(u_i) = \frac{\exp(u_i)}{\sum_{j} \exp(u_j)}

ここで、\exp(u_i)e の指数関数 e^{u_i} であり、ソフトマックス関数は次のように表記できます.

\text{softmax}(u_i) = \frac{e^{u_i}}{\sum_{j} e^{u_j}}

この式について,分母と分子をどちらもe^{u_{\text{max}}} で割ってみましょう.

\text{softmax}(u_i) = \frac{\frac{e^{u_i}}{e^{u_{\text{max}}}}}{\sum_{j} \frac{e^{u_j}}{e^{u_{\text{max}}}}}

指数関数の性質 \exp(a - b) = \frac{\exp(a)}{\exp(b)} から,上の式はこのように書き換えることができます.

\text{softmax}(u_i) = \frac{e^{u_i - u_{\text{max}}}}{\sum_{j} e^{u_j - u_{\text{max}}}}

もちろん上の式は以下のように表記することができます.

\text{softmax}(u_i) = \frac{\exp(u_i - u_{\text{max}})}{\sum_{j} \exp(u_j - u_{\text{max}})}

するとどうでしょうか.元のソフトマックス関数を変形することで,すべての u_i から最大値 u_{\text{max}} を引いた場合のソフトマックス関数を導出することができました。

このことから,u から u_{\text{max}} を引いても、結果に影響はありません。

Python での実装

ソフトマックス関数を Python で実装するシンプルなコードを以下に示します。

import numpy as np

# 入力ベクトル u の定義
u = np.array([2.0, 1.0, 0.1])

# ソフトマックスの計算(通常)
exp_u = np.exp(u)
sum_exp_u = np.sum(exp_u)
softmax_u = exp_u / sum_exp_u

print("ソフトマックス(通常):", softmax_u)

# 数値安定化のために最大値を引いた場合
max_u = np.max(u)
u_stable = u - max_u
exp_u_stable = np.exp(u_stable)
sum_exp_u_stable = np.sum(exp_u_stable)
softmax_u_stable = exp_u_stable / sum_exp_u_stable

print("ソフトマックス(数値安定化後):", softmax_u_stable)

適当な入力ベクトル u を設定してもらえれば,これで計算できます.上の例では, u = \begin{bmatrix} 2.0 \\ 1.0 \\ 0.1 \end{bmatrix}としています.

具体的な数値例を使ったソフトマックス関数の計算

通常のソフトマックス関数の計算

  1. 入力ベクトルの設定
    まず、入力ベクトル u を次のように設定します。
u = \begin{bmatrix} 2.0 \\ 1.0 \\ 0.1 \end{bmatrix}
  1. 指数関数の計算
    各要素に対して、指数関数を適用します。
\exp(u) = \begin{bmatrix} \exp(2.0) \\ \exp(1.0) \\ \exp(0.1) \end{bmatrix} = \begin{bmatrix} 7.389 \\ 2.718 \\ 1.105 \end{bmatrix}
  1. 合計値の計算
    次に、これらの値の合計を計算します。
\sum_{i=1}^{3} \exp(u_i) = 7.389 + 2.718 + 1.105 = 11.212
  1. ソフトマックスの計算
    各要素のソフトマックス値を計算します。
\text{softmax}(u_1) = \frac{\exp(2.0)}{11.212} = \frac{7.389}{11.212} \approx 0.659
\text{softmax}(u_2) = \frac{\exp(1.0)}{11.212} = \frac{2.718}{11.212} \approx 0.242
\text{softmax}(u_3) = \frac{\exp(0.1)}{11.212} = \frac{1.105}{11.212} \approx 0.099

したがって、ソフトマックス関数を適用した結果は次のようになります。

\text{softmax}(u) = \begin{bmatrix} 0.659 \\ 0.242 \\ 0.099 \end{bmatrix}

数値安定化のためのソフトマックス関数の計算

  1. 数値安定化のための最大値の引き算
    数値計算の安定化のために、u の各要素から最大値である 2.0 を引きます。
v = u - \text{max}(u) = \begin{bmatrix} 2.0 - 2.0 \\ 1.0 - 2.0 \\ 0.1 - 2.0 \end{bmatrix} = \begin{bmatrix} 0.0 \\ -1.0 \\ -1.9 \end{bmatrix}
  1. 引き算後の指数関数の計算
    引き算後の各要素に対して、再度指数関数を適用します。
\exp(v) = \begin{bmatrix} \exp(0.0) \\ \exp(-1.0) \\ \exp(-1.9) \end{bmatrix} = \begin{bmatrix} 1.0 \\ 0.3679 \\ 0.1496 \end{bmatrix}
  1. 合計値の再計算
    再度、これらの値の合計を計算します。
\sum_{i=1}^{3} \exp(v_i) = 1.0 + 0.3679 + 0.1496 = 1.5175
  1. 数値安定化後のソフトマックスの計算
    最後に、数値安定化後のソフトマックス値を計算します。
\text{softmax}(v_1) = \frac{\exp(0.0)}{1.5175} = \frac{1.0}{1.5175} \approx 0.659
\text{softmax}(v_2) = \frac{\exp(-1.0)}{1.5175} = \frac{0.3679}{1.5175} \approx 0.242
\text{softmax}(v_3) = \frac{\exp(-1.9)}{1.5175} = \frac{0.1496}{1.5175} \approx 0.099

したがって、引き算後のソフトマックス結果も同様に次のようになります。

\text{softmax}(v) = \begin{bmatrix} 0.659 \\ 0.242 \\ 0.099 \end{bmatrix}

おまけ:もっと複雑な具体的な数値例を使ったソフトマックス関数の計算

※最大値を引き算する方法のみ

u の初期値

u = \begin{bmatrix} 2.0 & 1.0 & 0.1 \\ 1.5 & 2.2 & 0.3 \\ 0.8 & 0.7 & 0.9 \end{bmatrix}

1.各行の最大値を計算
まず、各行の最大値 u_{\text{max}} を計算します。

u_{\text{max}} = \begin{bmatrix} 2.0 \\ 2.2 \\ 0.9 \end{bmatrix}

2.最大値を引いた後の行列を計算
次に、行列 𝑢の各要素から対応する行の最大値を引きます。

u - u_{\text{max}} = \begin{bmatrix} 2.0 - 2.0 & 1.0 - 2.0 & 0.1 - 2.0 \\ 1.5 - 2.2 & 2.2 - 2.2 & 0.3 - 2.2 \\ 0.8 - 0.9 & 0.7 - 0.9 & 0.9 - 0.9 \end{bmatrix} = \begin{bmatrix} 0.0 & -1.0 & -1.9 \\ -0.7 & 0.0 & -1.9 \\ -0.1 & -0.2 & 0.0 \end{bmatrix}

3. 指数関数を適用
この結果に対して、指数関数 exp を適用します。

\exp(u - u_{\text{max}}) = \begin{bmatrix} \exp(0.0) & \exp(-1.0) & \exp(-1.9) \\ \exp(-0.7) & \exp(0.0) & \exp(-1.9) \\ \exp(-0.1) & \exp(-0.2) & \exp(0.0) \end{bmatrix}

これを計算すると、

= \begin{bmatrix} 1.0 & 0.3679 & 0.1496 \\ 0.4966 & 1.0 & 0.1496 \\ 0.9048 & 0.8187 & 1.0 \end{bmatrix}

4.各行の合計を計算
次に、各行の合計を計算します。

\text{sum}(\exp(u - u_{\text{max}})) = \begin{bmatrix} 1.0 + 0.3679 + 0.1496 \\ 0.4966 + 1.0 + 0.1496 \\ 0.9048 + 0.8187 + 1.0 \end{bmatrix} = \begin{bmatrix} 1.5175 \\ 1.6462 \\ 2.7235 \end{bmatrix}

5.ソフトマックスの計算
最後に、各要素をその行の合計で割り、ソフトマックス値を計算します。

\text{softmax}(u) = \begin{bmatrix} \frac{1.0}{1.5175} & \frac{0.3679}{1.5175} & \frac{0.1496}{1.5175} \\ \frac{0.4966}{1.6462} & \frac{1.0}{1.6462} & \frac{0.1496}{1.6462} \\ \frac{0.9048}{2.7235} & \frac{0.8187}{2.7235} & \frac{1.0}{2.7235} \end{bmatrix}

計算結果は次のようになります。

\text{softmax}(u) = \begin{bmatrix} 0.659 & 0.242 & 0.099 \\ 0.302 & 0.607 & 0.091 \\ 0.332 & 0.301 & 0.367 \end{bmatrix}

Discussion