からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

3.2.4:シグモイド関数の実装【ゼロつく1のノート(実装)】

はじめに

 「プログラミング」初学者のための『ゼロから作るDeep Learning』攻略ノートです。『ゼロつくシリーズ』学習の補助となるように適宜解説を加えています。本と一緒に読んでください。

 関数やクラスとして実装される処理の塊を細かく分解して、1つずつ実行結果を見ながら処理の意図を確認していきます。

 この記事は、3.2.1項「シグモイド関数」と3.2.4項「シグモイド関数の実装」の内容です。Sigmoid関数をPythonで実装します。

【前節の内容】

www.anarchive-beta.com

【他の節の内容】

www.anarchive-beta.com

【この節の内容】

3.2.4 シグモイド関数の実装

 ニューラルネットワークの活性化関数として用いられるシグモイド関数(Sigmoid関数)を実装します。

 利用するライブラリを読み込みます。

# 3.2.4項で利用するライブラリ
import numpy as np
import matplotlib.pyplot as plt


・数式の確認

 まずは、シグモイド関数(Sigmoid関数)の定義式を確認します。

 シグモイド関数は、次の式で定義されます。

$$ h(x) = \frac{1}{1 + \exp(-x)} \tag{3.6} $$

 シグモイド関数は、0から1の値を出力します。そのため、シグモイド関数の出力は確率として解釈できます。指数関数$\exp(x)$については「指数関数(1):指数関数とは【ゼロつく1のノート(数学)】 - からっぽのしょこ」を参照してください。

・処理の確認

 次に、シグモイド関数で行う処理を確認します。

 入力$x$をxとして値を指定します。

# 仮の入力を指定
x = -4
print(-4)
-4


 指数関数$\exp(x)$の計算は、np.exp()で行えます。

# 指数関数の計算
print(np.exp(-x))
54.598150033144236

 xの符号を反転させて入力します。

 式(3.6)の計算をします。

# シグモイド関数の計算:式(3.6)
y = 1 / (1 + np.exp(-x))
print(y)
0.01798620996209156

 入力$x$を$0 < y < 1$となる値に変換して出力できました。

 以上がシグモイド関数で行う処理です。

・実装

 処理の確認ができたので、シグモイド関数を関数として実装します。

# シグモイド関数の実装
def sigmoid(x):
    # シグモイド関数の計算:式(3.6)
    return 1 / (1 + np.exp(-x))


 実装した関数を試してみましょう。

# シグモイド関数による活性化
print(sigmoid(-4.5))
print(sigmoid(0.0))
print(sigmoid(10))
print(sigmoid(np.array([-2, -1, 0, 1, 2, 3])))
0.01098694263059318
0.5
0.9999546021312976
[0.11920292 0.26894142 0.5        0.73105858 0.88079708 0.95257413]

 この関数で、2次元以上の多次元配列も処理できます。

・グラフの確認

 最後に、シグモイド関数の入力に対する出力の変化をグラフで確認します。

 入力$x$としてグラフに表示する範囲を指定します。np.arange()の第1引数に最小値、第2引数に最大値、第3引数に分割する間隔を指定します。

# 入力を指定(x軸の値を作成)
x = np.arange(-10, 10, 0.1)
print(np.round(x, 1))
[-10.   -9.9  -9.8  -9.7  -9.6  -9.5  -9.4  -9.3  -9.2  -9.1  -9.   -8.9
  -8.8  -8.7  -8.6  -8.5  -8.4  -8.3  -8.2  -8.1  -8.   -7.9  -7.8  -7.7
  -7.6  -7.5  -7.4  -7.3  -7.2  -7.1  -7.   -6.9  -6.8  -6.7  -6.6  -6.5
  -6.4  -6.3  -6.2  -6.1  -6.   -5.9  -5.8  -5.7  -5.6  -5.5  -5.4  -5.3
  -5.2  -5.1  -5.   -4.9  -4.8  -4.7  -4.6  -4.5  -4.4  -4.3  -4.2  -4.1
  -4.   -3.9  -3.8  -3.7  -3.6  -3.5  -3.4  -3.3  -3.2  -3.1  -3.   -2.9
  -2.8  -2.7  -2.6  -2.5  -2.4  -2.3  -2.2  -2.1  -2.   -1.9  -1.8  -1.7
  -1.6  -1.5  -1.4  -1.3  -1.2  -1.1  -1.   -0.9  -0.8  -0.7  -0.6  -0.5
  -0.4  -0.3  -0.2  -0.1  -0.    0.1   0.2   0.3   0.4   0.5   0.6   0.7
   0.8   0.9   1.    1.1   1.2   1.3   1.4   1.5   1.6   1.7   1.8   1.9
   2.    2.1   2.2   2.3   2.4   2.5   2.6   2.7   2.8   2.9   3.    3.1
   3.2   3.3   3.4   3.5   3.6   3.7   3.8   3.9   4.    4.1   4.2   4.3
   4.4   4.5   4.6   4.7   4.8   4.9   5.    5.1   5.2   5.3   5.4   5.5
   5.6   5.7   5.8   5.9   6.    6.1   6.2   6.3   6.4   6.5   6.6   6.7
   6.8   6.9   7.    7.1   7.2   7.3   7.4   7.5   7.6   7.7   7.8   7.9
   8.    8.1   8.2   8.3   8.4   8.5   8.6   8.7   8.8   8.9   9.    9.1
   9.2   9.3   9.4   9.5   9.6   9.7   9.8   9.9]

 この例では、-10から10まで(正確には未満)を範囲として、0.1間隔で要素を作成します。

 xsigmoid()に入力して、出力をyとします。

# シグモイド関数による活性化(y軸の値を計算)
y = sigmoid(x)
print(np.round(y, 3))
[0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.
 0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.
 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.002
 0.002 0.002 0.002 0.002 0.002 0.003 0.003 0.003 0.004 0.004 0.004 0.005
 0.005 0.006 0.007 0.007 0.008 0.009 0.01  0.011 0.012 0.013 0.015 0.016
 0.018 0.02  0.022 0.024 0.027 0.029 0.032 0.036 0.039 0.043 0.047 0.052
 0.057 0.063 0.069 0.076 0.083 0.091 0.1   0.109 0.119 0.13  0.142 0.154
 0.168 0.182 0.198 0.214 0.231 0.25  0.269 0.289 0.31  0.332 0.354 0.378
 0.401 0.426 0.45  0.475 0.5   0.525 0.55  0.574 0.599 0.622 0.646 0.668
 0.69  0.711 0.731 0.75  0.769 0.786 0.802 0.818 0.832 0.846 0.858 0.87
 0.881 0.891 0.9   0.909 0.917 0.924 0.931 0.937 0.943 0.948 0.953 0.957
 0.961 0.964 0.968 0.971 0.973 0.976 0.978 0.98  0.982 0.984 0.985 0.987
 0.988 0.989 0.99  0.991 0.992 0.993 0.993 0.994 0.995 0.995 0.996 0.996
 0.996 0.997 0.997 0.997 0.998 0.998 0.998 0.998 0.998 0.998 0.999 0.999
 0.999 0.999 0.999 0.999 0.999 0.999 0.999 0.999 0.999 1.    1.    1.
 1.    1.    1.    1.    1.    1.    1.    1.    1.    1.    1.    1.
 1.    1.    1.    1.    1.    1.    1.    1.   ]

 xの値が小さいほどyの値が0に近くなり、xの値が大きいほどyの値が1に近づいていますね。ただし、0にも1にもなりません。

 np.round()によって小数点以下を丸めずに、yの最初と最後の要素の値を全て表示してみます。

# 最初の要素を確認
print(y[0])

# 最後の要素を確認
print(y[-1])
4.5397868702434395e-05
0.9999498278353162

 添字(インデックス)に-1を指定すると、配列の最後の要素を取り出せます。

 $x = -10$のとき$y = 0.0000453978$で、$x = 9.9$のとき$y = 0.9999498278$となりました。

 matplotlibライブラリのpyplotモジュールを利用して、シグモイド関数のグラフを作成します。

# シグモイド関数を作図
plt.figure(figsize=(8, 6)) # 図の設定:(サイズを指定)
plt.plot(x, y) # 折れ線グラフ
plt.title('Sigmoid Function', fontsize=20) # タイトル
plt.xlabel('x') # x軸ラベル
plt.ylabel('y') # y軸ラベル
plt.grid() # グリッド線
plt.show() # グラフを表示

シグモイド関数

 S字型の滑らかな曲線です。入力$x$の値に関わらず、出力は0から1の値になります。また、入力における大小関係は出力でも変わりません。つまり、$x_1 > x_2$であれば、$y_1 > y_2$となります。

 以上で、シグモイド関数が実装できました。次項では、ReLU関数を実装します。この本では、主にシグモイド関数を活性化関数として使います。

参考文献

github.com

おわりに

 加筆修正の際に記事を分割しました。

【次節の内容】

www.anarchive-beta.com

【関連する記事】

www.anarchive-beta.com

www.anarchive-beta.com