からっぽのしょこ

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

3.2.2:ステップ関数の実装【ゼロつく1のノート(実装)】

はじめに

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

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

 この記事は、3.2.2項「ステップ関数の実装」の内容です。ステップ関数をPythonで実装します。

【前節の内容】

www.anarchive-beta.com

【他の節の内容】

www.anarchive-beta.com

【この節の内容】

3.2.2 ステップ関数の実装

 パーセプトロンの活性化関数として用いられるステップ関数(Step関数)を実装します。

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

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


・数式の確認

 まずは、ステップ関数(Step関数)の定義式を確認します。

 ステップ関数は、次の式で定義されます。

$$ h(x) = \begin{cases} 0 \quad (x \leq 0) \\ 1 \quad (x > 0) \end{cases} \tag{3.3} $$

 ステップ関数$h(x)$の入力$x$が、0以下であれば0を、0より大きければ1を出力する関数です。(関数は変換器のようなもので、イメージする方程式とは異なるかもしれませんがこのような条件式も関数です。)

・処理の確認(1)

 次に、ステップ関数で行う処理を確認します。

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

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


 2.3.2項で実装したパーセプトロンの出力部分と同様に、if文を使って(条件分岐して)入力xの値に従い01の値を出力します。

# 条件に従って値を出力
if x > 0: # 入力が0より大きい場合
    # 1を出力
    print(1)
else: # 入力が0以下の場合
    # 0を出力
    print(0)
0

 x0より大きければ1を、そうでなければ(0以下であれば)0を出力します。

 処理の確認ができたので、ステップ関数を関数として実装します。

# ステップ関数の実装
def step_function(x):
    # 条件に従って値を出力
    if x > 0: # 入力が0より大きい場合
        return 1
    else: # 入力が0以下の場合
        return 0


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

# ステップ関数による活性化
print(step_function(-4))
print(step_function(5.5))
0
1

 これでステップ関数を実装できました。

 活性化関数を利用する際には、一度に複数のデータを処理する必要があります。しかし、step_function()に複数の入力(配列)を渡すとエラーになります。

# 仮の入力を作成:(複数)
x = np.array([-2, -1, 0, 1, 2, 3])

# ステップ関数による活性化
print(step_function(x))

・エラーメッセージ(クリックで展開)

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-7-1cda945bc064> in <module>
      3 
      4 # ステップ関数による活性化
----> 5 print(step_function(x))


<ipython-input-5-160d50ab2f00> in step_function(x)
      2 def step_function(x):
      3     # 条件に従って値を出力
----> 4     if x > 0: # 入力が0より大きい場合
      5         return 1
      6     else: # 入力が0以下の場合


ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

 NumPy配列を入力しても処理できるようする必要があります。

・処理の確認(2)

 続いて、複数の入力(NumPy配列)に対応したステップ関数の処理を確認します。

 入力$\mathbf{x} = (x_0, x_1, \cdots, x_n)$をNumPy配列として作成します。Pythonのインデックスに合わせて、$\mathbf{x}$の添字を0からにしています。

# 仮の入力を指定
x = np.array([-2, -1, 0, 1, 2, 3])

 負の値・0・正の値を持つように配列を作成しておくと、うまく処理できているかを確認しやすくなります。

 入力xの各要素が0より大きいかを比較演算子>を使って調べます。

# 0との大小関係を比較
y_bool = x > 0
print(y_bool)
[False False False  True  True  True]

 0より大きい要素はTrue0以下の要素はFalseとなります。

 NumPyの型変換メソッドastype()を使って、論理値(bool)型から整数(int)型に変換します。

# 整数型に変換
y_int = y_bool.astype(np.int)
print(y_int)
[0 0 0 1 1 1]

 組み込みの整数型intではなく、NumPyライブラリの整数型np.intを利用します。

 入力x01の値に変換して出力できました。

 または、np.array()のデータ型の引数dtypenp.intを指定することで、同じ処理を1行で行えます。

# ステップ関数の計算
y = np.array(x > 0, dtype=np.int)
print(y)
[0 0 0 1 1 1]


 以上がステップ関数で行う処理です。

・実装

 処理の確認ができたので、ステップ関数を関数として実装します。

# ステップ関数の実装
def step_function(x):
    # 0との大小関係を比較
    y = x > 0
    
    # 整数型に変換して出力
    return y.astype(np.int)

 こちらは、本に載っている実装例に対応しています。

# ステップ関数の実装
def step_function(x):
    # ステップ関数を計算:式(3.3)
    return np.array(x > 0, dtype=np.int)

 こちらは、commonフォルダ内のfunctions.pyにある実装例に対応しています。

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

# ステップ関数による活性化
print(step_function(-4.5))
print(step_function(0.0))
print(step_function(10))
print(step_function(np.array([-2, -1, 0, 1, 2, 3])))
0
0
1
[0 0 0 1 1 1]

 数式をそのまま再現するのではなく、Pythonの機能をうまく利用することも大切です。この関数で、2次元以上の多次元配列も処理できます。

・グラフの確認

 最後に、ステップ関数の入力に対する出力の変化をグラフで確認します。

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

# 入力を指定(x軸の値を作成)
x = np.arange(-5.0, 5.0, 0.01)
print(np.round(x[450:550], 2))
[-0.5  -0.49 -0.48 -0.47 -0.46 -0.45 -0.44 -0.43 -0.42 -0.41 -0.4  -0.39
 -0.38 -0.37 -0.36 -0.35 -0.34 -0.33 -0.32 -0.31 -0.3  -0.29 -0.28 -0.27
 -0.26 -0.25 -0.24 -0.23 -0.22 -0.21 -0.2  -0.19 -0.18 -0.17 -0.16 -0.15
 -0.14 -0.13 -0.12 -0.11 -0.1  -0.09 -0.08 -0.07 -0.06 -0.05 -0.04 -0.03
 -0.02 -0.01 -0.    0.01  0.02  0.03  0.04  0.05  0.06  0.07  0.08  0.09
  0.1   0.11  0.12  0.13  0.14  0.15  0.16  0.17  0.18  0.19  0.2   0.21
  0.22  0.23  0.24  0.25  0.26  0.27  0.28  0.29  0.3   0.31  0.32  0.33
  0.34  0.35  0.36  0.37  0.38  0.39  0.4   0.41  0.42  0.43  0.44  0.45
  0.46  0.47  0.48  0.49]

 この例では、-5から5まで(正確には未満)を範囲として、0.01間隔で要素を作成します。ステップ関数の垂直の部分が傾く場合は、第3引数の値を小さくしてください。

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

# ステップ関数による活性化(y軸の値を計算)
y = step_function(x)
print(y[450:550])
[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]

 全ての要素が01の値に変換されました。

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

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

ステップ関数

 $x \leq 0$の範囲では$y = 0$で一定で、$x > 0$の範囲では$y = 1$で一定です。$x = 0$の点でのみ、出力(y軸の値)が0から1に一気に変化しているのが分かります。

 以上で、ステップ関数を実装できました。次項では、シグモイド関数を実装します。

参考文献

github.com

おわりに

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

【次節の内容】

www.anarchive-beta.com