SIGMA-SE Math & Tech Library

SIGMA-SE Math & Tech Library


数学と情報技術をテーマに、書籍や教材だけではつかみにくい考え方を具体例とともに簡潔にわかりやすく伝える解説サイトです。
技術の歴史や背景、関連知識の整理、学習のための覚書や要約記事も掲載しています。

Python - ニューラルネットワーク:4/14 代表的な活性化関数の実装まとめ

概要

ステップ関数、シグモイド関数、ReLU関数、恒等関数、ソフトマックス関数をPythonで実装し、それぞれの使いどころを整理する。

活性化関数はすべて同じ役割ではなく、中間層で使いやすいもの、回帰の出力層で使うもの、分類の出力層で使うものがある。

ここでは、関数ごとの特徴とNumPy実装をまとめて確認する。

この記事の構成

概念の説明と実装サンプル

ステップ関数

  • 0と1を切り替える処理

    前の記事 > ニューラルネットワークの活性化関数と実装サンプル で触れたステップ関数で、不連続な非線形の活性化関数であり階段関数とも呼ばれる。

    • 定義
      \(x\) が \(0\) より大きければ、\(1\) を出力し、\(0\) 以下であれば \(0\) を出力。
    \[ {\normalsize h(x) = \begin{cases} 0 \hspace{5pt}\text{if}\hspace{5pt}x \leqq 0 \\ 1 \hspace{5pt}\text{if}\hspace{5pt}x > 0 \end{cases} } \]
    • 実装
    $ python
     >>> import numpy as np
     >>> import matplotlib.pylab as plt
     >>> def step_func(x):    # ステップ関数の定義
     ...    return np.array(x > 0, dtype=int)
     ...
    
    • グラフ出力
    $ python
     >>> x = np.arange(-5.0, 5.0, 0.1)    # 区間を-5~5まで、描画間隔を0.1刻みに設定
     >>> y = step_func(x)    # ステップ関数をコール
     >>> plt.title("step_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y")    # グラフタイトルを設定
     Text(0.5, 1.0, 'step_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y')
     >>> plt.ylim(-0.1, 1.1)    # y軸の範囲を設定
     (-0.1, 1.1)
     >>> plt.xlabel("x")    # x軸のラベルを設定
     Text(0.5, 0, 'x')
     >>> plt.ylabel("y")    # y軸のラベルを設定
     Text(0, 0.5, 'y')
     >>> plt.plot(x, y)    # グラフの描画
     [<matplotlib.lines.Line2D object at 0x7fc13041e278>]
     >>> plt.savefig('pid18_1.png')    # グラフの出力
    

    pid18_1

シグモイド関数

  • 滑らかな出力への変換

    前の記事 > ニューラルネットワークの活性化関数と実装サンプル で触れたシグモイド関数で、非線形の活性化関数に分類される。

    • 定義
      出力値は、\(x\) が小さいほど \(0\) に近づき、\(x\) が大きいほど \(1\) に近づく。
    \[ h(x) = \frac{1}{1+e^{-x}} \]
    • 実装
    $ python
     >>> import numpy as np
     >>> import matplotlib.pylab as plt
     >>> def sigmoid_func(x):    # シグモイド関数の定義
     ...     return 1 / (1 + np.exp(-x))    # 自然対数の底 (e) の -x 乗
     ...
    
    • グラフ出力
    $ python
     >>> x = np.arange(-5.0, 5.0, 0.1)    # 区間を-5~5まで、描画間隔を0.1刻みに設定
     >>> y = sigmoid_func(x)    # シグモイド関数をコール
     >>> plt.title("sigmoid_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y")    # グラフタイトルを設定
     Text(0.5, 1.0, 'sigmoid_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y')
     >>> plt.ylim(-0.1, 1.1)    # y軸の範囲を設定
     (-0.1, 1.1)
     >>> plt.xlabel("x")    # x軸のラベルを設定
     Text(0.5, 0, 'x')
     >>> plt.ylabel("y")    # y軸のラベルを設定
     Text(0, 0.5, 'y')
     >>> plt.plot(x, y)
     [<matplotlib.lines.Line2D object at 0x7f727fbc1be0>]
     >>> plt.savefig('/var/www/vops/ops/macuos/static/macuos/img/pid18_2.png')    # グラフの出力
    

    pid18_2

ReLU関数

  • 0以下を0にする処理

    ReLU(Rectified Linear Unit:正規化線形ユニット)と呼ばれ、非線形の活性化関数に分類される。
    ※ 最近では、ニューラルネットワークにおいて、シグモイド関数より、ReLU関数が多く用いられるようになった。

    • 定義
      \(x\) が \(0\) より大きい場合、\(x\) を出力し、\(0\) 以下である場合、\(0\) を出力。
    \[ {\normalsize h(x) = \begin{cases} x \hspace{5pt}\text{if}\hspace{5pt}x > 0 \\ 0 \hspace{5pt}\text{if}\hspace{5pt}x \leqq 0 \end{cases} } \]
    • 実装
    $ python
     >>> import numpy as np
     >>> import matplotlib.pylab as plt
     >>> def relu_func(x):    # ReLU関数の定義
     ...     return np.maximum(0, x)
     ...
    
    • グラフ出力
    $ python
     >>> x = np.arange(-5.0, 5.0, 0.1)    # 区間を-5~5まで、描画間隔を0.1刻みに設定
     >>> y = relu_func(x)    # ReLU関数をコール
     >>> plt.title("relu_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y")    # グラフタイトルを設定
     Text(0.5, 1.0, 'relu_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y')
     >>> plt.xlabel("x")    # x軸のラベルを設定
     Text(0.5, 0, 'x')
     >>> plt.ylabel("y")    # y軸のラベルを設定
     Text(0, 0.5, 'y')
     >>> plt.plot(x, y)
     [<matplotlib.lines.Line2D object at 0x7fbf1cfeecc0>]
     >>> plt.savefig('/var/www/vops/ops/macuos/static/macuos/img/pid18_3.png')
     >>>
    

    pid18_3

恒等関数

  • 入力をそのまま出力する処理

    出力層で使われる線形の活性化関数に分類される。

    • 定義
      \(x\) をそのまま出力。
    \[ {\normalsize h(x) = x } \]
    • 実装
    $ python
     >>> import numpy as np
     >>> import matplotlib.pylab as plt
     >>> def identity_func(x):    # 恒等関数の定義
     ...     return x
     ...
    
    • グラフ出力
    $ python
     >>> x = np.arange(-5.0, 5.0, 0.1)    # 区間を-5~5まで、描画間隔を0.1刻みに設定
     >>> y = identity_func(x)    # 恒等関数をコール
     >>> plt.title("identity_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y")    # グラフタイトルを設定
     Text(0.5, 1.0, 'identity_func\n# arange:-5.0, 5.0, 0.1, xlabel:x, ylabel:y')
     >>> plt.xlabel("x")    # x軸のラベルを設定
     Text(0.5, 0, 'x')
     >>> plt.ylabel("y")    # y軸のラベルを設定
     Text(0, 0.5, 'y')
     >>> plt.plot(x, y)
     [<matplotlib.lines.Line2D object at 0x7fba4d928f60>]
     >>> plt.savefig('/var/www/vops/ops/macuos/static/macuos/img/pid18_4.png')
     >>>
    
    

    pid18_4

ソフトマックス関数

  • 確率分布への変換

    分類問題で使われる非線形の活性化関数に分類される。

    • 定義
      \(k=1,\ldots,n\) とすると、\(k\) 番目の出力 \(h(x_{k})\) を次の式で表す。各出力は入力ベクトル全体に依存し、出力の合計は\(1\)になる。
    \[ {\normalsize h(x_{k}) = \frac{e^{x_{k}}}{\sum_{i=1}^{n} e^{x_{i}}} } \]
    • 実装
    $ python
     >>> def softmax_func(x):    # ソフトマックス関数の定義
     ...     shifted_x = x - np.max(x)    # オーバーフローを防ぐ
     ...     exp_x = np.exp(shifted_x)
     ...     sum_exp_x = np.sum(exp_x)
     ...     y = exp_x / sum_exp_x
     ...     return y
     ...    
    
    • 実行例
    $ python
     >>> x = np.array([0.3, 2.9, 4.0])
     >>> y = softmax_func(x)
     >>> y
     array([0.01821127, 0.24519181, 0.73659691])
     >>> np.sum(y)
     1.0
    

まとめ

  • ReLUは0以下を0、正の値をそのまま出力し、ステップ関数とは正の領域の扱いが異なる。中間層でよく使われる。
  • 恒等関数は入力値をそのまま出力するため、主に回帰問題の出力層で使われる。
  • ソフトマックス関数は多クラス分類の出力層で使われ、指数計算のオーバーフローを避ける数値安定化が必要になる。

参考文献

この記事を共有
Xで共有 Facebookで共有 LINEで共有



Copyright SIGMA-SE All Rights Reserved.
s-hama@sigma-se.jp