はじめに
「プログラミング」学習初手『ゼロから作るDeep Learning』民のための実装攻略ノートです。『ゼロつく1』学習の補助となるように適宜解説を加えています。本と一緒に読んでください。
関数やクラスとして実装される処理の塊を細かく分解して、1つずつ処理を確認しながらゆっくりと組んでいきます。
この記事は、3.1節「パーセプトロンからニューラルネットワークへ」と3.2.5項「シグモイド関数とステップ関数の比較」の内容です。活性化関数について確認します。
【前節の内容】
【他の節の内容】
【この節の内容】
3.1 パーセプトロンからニューラルネットワークへ
2章では、パーセプトロンを次の式で表しました。
この式を、重み付き和の計算
と、出力に関する計算
に分解します。
$h(a)$は、重み付き和$a$を出力$y$に変換する関数で、パーセプトロン(3.1)の場合は次の式になります。
この関数はステップ関数と言い、関数の入力(パーセプトロンだと重み付き和)が0以下のとき0を、0より大きいとき1を出力します。
この関数のように、重み付き和に非線形な変換(活性化)を行う関数を活性化関数と言います。ニューラルネットワークでは、非線形関数である活性化関数を用いる必要があります。
3.2 活性化関数
活性化関数として用いられる3つの関数ステップ関数・シグモイド関数・ReLU関数を実装します。
各関数の実装は、次の記事を参照してください。
3.2.5 活性化関数の比較
この節で実装した3つの活性化関数(ステップ関数・シグモイド関数・ReLU関数)を簡単に比較します。
利用するライブラリを読み込みます。
# 3.2.7項で利用するライブラリ import numpy as np import matplotlib.pyplot as plt
また、3.2節で実装したstep_function()
・sigmoid()
・relu()
の関数定義を実行している必要があります。
まずは、ステップ関数とシグモイド関数のグラフを比較します。
作図に用いる入力$x$の値を作成します。
# 入力を指定(x軸の値を作成) x = np.arange(-10, 10, 0.1) print(np.round(x[50:150], 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]
この例では、-10
から10
まで(正確には未満)を範囲として、0.1
間隔で要素を作成します。
ステップ関数step_function()
とシグモイド関数sigmoid()
にx
を入力して、それぞれの出力を計算します。
# ステップ関数の計算 y_step = step_function(x) print(y_step[50:150]) # シグモイド関数の計算 y_sigmoid = sigmoid(x) print(np.round(y_sigmoid[50:150], 2))
[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 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 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
[0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.02 0.02 0.02 0.02 0.02
0.03 0.03 0.03 0.04 0.04 0.04 0.05 0.05 0.06 0.06 0.07 0.08 0.08 0.09
0.1 0.11 0.12 0.13 0.14 0.15 0.17 0.18 0.2 0.21 0.23 0.25 0.27 0.29
0.31 0.33 0.35 0.38 0.4 0.43 0.45 0.48 0.5 0.52 0.55 0.57 0.6 0.62
0.65 0.67 0.69 0.71 0.73 0.75 0.77 0.79 0.8 0.82 0.83 0.85 0.86 0.87
0.88 0.89 0.9 0.91 0.92 0.92 0.93 0.94 0.94 0.95 0.95 0.96 0.96 0.96
0.97 0.97 0.97 0.98 0.98 0.98 0.98 0.98 0.99 0.99 0.99 0.99 0.99 0.99
0.99 0.99]
ステップ関数の出力をy_step
、シグモイド関数の出力をy_sigmoid
とします。
ステップ関数とシグモイド関数のグラフを重ねて表示します。
# 作図 plt.figure(figsize=(8, 6)) # 図の設定:(サイズを指定) plt.plot(x, y_step, label='step') # ステップ関数 plt.plot(x, y_sigmoid, label='sigmoid') # シグモイド関数 plt.title('Activait Function', fontsize=20) # タイトル plt.xlabel('x') # x軸ラベル plt.ylabel('y') # y軸ラベル plt.grid() # グリッド線 plt.legend() # 凡例 plt.show() # グラフを表示
どちらの関数も、0から1の値を出力するのを確認できます。しかし、0から1への変化の仕方が大きく違いますね。滑らかな曲線であるということは、連続的な値を出力する(表現できる)ことを意味します。また、どの点においても傾きを持つことも意味します。
ただし、シグモイド関数の出力は0にも1にも達していません。グラフに表示する範囲を狭めて確認しましょう。
・ほとんど同じなので省略(クリックで展開)
# 作図 plt.figure(figsize=(8, 6)) # 図の設定:(サイズを指定) plt.plot(x, y_step, label='step') # ステップ関数 plt.plot(x, y_sigmoid, label='sigmoid') # シグモイド関数 plt.title('Activait Function', fontsize=20) # タイトル plt.xlabel('x') # x軸ラベル plt.ylabel('y') # y軸ラベル plt.grid() # グリッド線 plt.legend() # 凡例 plt.xlim(5, 11) # x軸の表示範囲 plt.ylim(0.999, 1.001) # y軸の表示範囲 plt.show() # グラフを表示
$x$が大きくなるに従って、シグモイド関数の出力が1に漸近しているのが分かります。逆に、$x$が小さくなるに従って、0に漸近します。このことも含めて、滑らかな関数と言えます。
同様に、ReLU関数のグラフも重ねて確認しましょう。
# 入力を指定(x軸の値を作成) x = np.arange(-5, 5, 0.01) # 活性化(y軸の値を計算) y_step = step_function(x) y_sigmoid = sigmoid(x) y_relu = relu(x)
# 作図 plt.figure(figsize=(8, 6)) # サイズ plt.plot(x, y_step, label='step') # ステップ関数 plt.plot(x, y_sigmoid, label='sigmoid') # シグモイド関数 plt.plot(x, y_relu, label='ReLU') # ReLU関数 plt.title('Activation Function', fontsize=20) # タイトル plt.xlabel('x') # x軸ラベル plt.ylabel('y') # y軸ラベル plt.grid() # グリッド線 plt.legend() # 凡例 plt.ylim(-0.1, 1.5) # y軸の表示範囲 plt.show() # グラフを表示
ReLU関数も$x > 0$の範囲で傾きを持ちます。傾きがあることが学習において重要になります。ステップ関数は傾きがないため、ニューラルネットワークでは用いられません。詳しくは4章で扱います。
3.2節では、活性化関数について確認しました。次節では、ニューラルネットワーク(重み付き和の計算)について確認します。ニューラルネットワークの出力が、活性化関数の入力になります。
参考文献
おわりに
この記事で『ゼロつく1』シリーズ3記事(3日)目です。明日の更新は、記事中にURLを張ってある指数関数(とネイピア数)を簡単に確認する記事です。投稿日に読んでいただいた方、まだないリンクを張っててすみません。下の【次節の内容】には3.4節の記事を設定しているのですが、明々後日に投稿されます!明後日は、3.4節に関連する内容の記事が更新されます。その記事は3.4節の記事内にリンクが張ってあります。(もう関係ない)
意図的に全ての記事が一直線に繋がらないようにしているので、最初の方にある記事一覧ページも是非確認してください!
ぐだぐだはしてません。まだ順調です。次もよろしくお願いします。
- 2021.07.23:加筆修正しました。その際に、活性化関数ごとに記事を分割しました。
3記事分の内容を分割したら随分短くなった。でも文量的にも内容的にもこれくらいのサイズが読みやすいかな?
【次節の内容】