673 views
【1】やりたいこと
PyTorchや TensorFlowなどの機械学習ライブラリを使わない場合、ライブラリが提供してくれている機能を自力実装する必要がある。
前回の投稿では、活性化関数 tanh(x) の微分を見た。
「逆伝播で使う微分」シリーズの投稿は以下の通り。
(56) 逆伝播で使う tanh(x)の微分
(57) 逆伝播で使う sigmoid(x)の微分 ←今回
(58) 逆伝播で使う ReLU(x)の微分
(59) 逆伝播で使う MSE(平均二乗誤差)の微分
(60) 他クラス分類で使う Softmax
(61) 機械学習で多用されるネイピア数とは?
今回は、同じく活性化関数として使われる sigmoidの微分について見てみる。
【2】やってみる
1) sigmoidとは?
sigmoid(x), sigmoid'(x) をまとめて図示する。

sigmoid関数は S字曲線なので、微分値は x=0で最大値を取り、S字の端へ向かって 0へ収束していく。
これは tanh(x)のときと同じだ。
import numpy as np
import matplotlib.pyplot as plt
#//////////////////////////////////////////////////////////////////////////
def sigmoid(x): # シグモイド関数
return 1 / (1 + np.exp(-x))
#//////////////////////////////////////////////////////////////////////////
def sigmoid_derivative(x): # 微分(sigmoid(x) * (1 - sigmoid(x)))
s = sigmoid(x)
return s * (1 - s)
#//////////////////////////////////////////////////////////////////////////
x = np.linspace(-10, 10, 500) # x の範囲
y_sigmoid = sigmoid(x)
y_deriv = sigmoid_derivative(x)
#//////////////////////////////////////////////////////////////////////////
plt.figure(figsize=(10, 6)) # グラフ表示
plt.plot(x, y_sigmoid, label="sigmoid(x)", linewidth=2)
plt.plot(x, y_deriv, label="sigmoid'(x)", linestyle='--', linewidth=2)
plt.title("sigmoid Function and Its Derivative")
plt.xlabel("x")
plt.ylabel("value")
plt.grid(True)
plt.legend()
plt.show()
2) S字関数を使う理由は?
■長所
非線形なので、複雑な関数やパターンが学べる。
出力が一定範囲に収まるため、安定性がある。
なめらかで微分可能(=連続的)なため、勾配降下法が使える。
■短所
xの絶対値が大きくなると、微分がほぼ 0になる。→ 勾配消失
3) sigmoid'(x)の計算式

■証明
以下、愚直にこれを証明してみる。

ここで、以下のように二つの関数に分け、合成関数の微分にする。

こうすると、合成関数の微分の連鎖律(chain rule)により、以下のように展開できる。
・・・(1)
ここで、

これらを (1) に代入すると、

OKだ!
4) sigmoidの微分を Pythonで実装する。
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
シンプルな実装に見えるが、ここには Python + Numpyの底力が隠れている。
numpyのベクトル化関数を使っているので、入力値 xは多次元配列(ndarray)を使える。
→ ミニバッチデータ等、複数データをまとめて処理できる。
※実際のデータ並列処理はライブラリ内部に隠蔽されている。