活性化関数について
パーセプトロンでは、入力値をウエイトで掛けた総和を0か1の値にして出力します。この、出力信号を変換する関数のことを活性化関数と言います。
けれども、現実問題ではこれだけでは複雑な処理ができません。
そこで、複雑な問題を解くことができるようにパーセプトロンの層を重ねることと、それに対応した活性化関数の工夫がなされました。
活性化関数の特徴は、線形関数を複数の層にしても意味がないこと、また数学的に微分を活用したいなどの理由により非線形関数(1次関数以外)を用います。
また、活性化関数は、中間層と出力層でその働きに違いがあります。
特に出力層においては、回帰なら連続した数値が必要ですし、分類ならそれぞれの確率が必要になります。
そこで中間層や出力層で適切な値を返すための関数が考えられました。
主な活性化関数
ここからPythonのコードを使いながら、活性化関数の挙動を可視化します。
事前に、numpyとmatplotlibがinstall されていることが前提で、次のimoport を行なっておきます。
import numpy as np import matplotlib.pylab as plt
ステップ関数
ステップ関数はある閾値を境にして、出力値が突然「1」か「0」に変わる関数です。
パーセプトロンの活性化関数はステップ関数です。
def step_function(x): return np.array(x > 0, dtype=np.int) X = np.arange(-5.0, 5.0, 0.1) Y = step_function(X) plt.plot(X, Y) plt.show()
恒等関数
入力値にウエイトを掛けた総和をそのまま出力する関数で、回帰の出力層の活性関数として使われます。
def identity(a): return a X = np.arange(-5.0, 5.0, 0.1) Y = identity(X) plt.plot(X, Y) plt.show()
シグモイド関数
シグモイド関数は、入力値を0から1までの値として出力します。
下の式やグラフからも分かるようにシグモイド関数は非線形関数です。
そのため、各々ニューロンの活性化関数として活用することができます。
シグモイド関数
$$
f(x)=\frac{1}{1+e^{-x}}
$$
また、出力値が0から1までの値を出力することから、確率を出力していると解釈できるため2値分類の出力層で用いられます。
けれども、現実問題としてシグモイド関数は、ニューロンの層が深くなった場合に勾配消失問題が起こるため、中間層ではあまり使用されなくなっています。
\(e^{-x}\)はnumpyのexp(-x) exponential関数で表現できます。
def sigmoid(x): return 1 / (1 + np.exp(-x)) X = np.arange(-5.0, 5.0, 0.1) Y = sigmoid(X) plt.plot(X, Y) plt.ylim(-0.1, 1.1) plt.show()
ReLU関数
ReLU関数 (Rectified Linear Unit)は一般にランプ関数と呼ばれていますが、レル関数と読む場合もあります。
シグモイド関数に変わって、中間層の活性化関数として使われる場合が多い関数です。
ReLU関数の入力が0以上ならその値を出力し、0以下なら0を出力
np.maximum(0, x)は第1引数と第2引数を比較して大きい方を返す。
def relu(x): return np.maximum(0, x) x = np.arange(-5.0, 5.0, 0.1) y = relu(x) plt.plot(x, y) plt.ylim(-1.0, 5.5) plt.show()
ソフトマックス関数
ソフトマックス関数は、2値以上の多値分類の出力層で使われる活性化関数です。
ニューラルネットワークで分類を行う場合、出力層のニューロンの数を分類したい数にします。
3分類したい場合は3個のニューロンが存在してその出力結果が分類の判定に使われます。
その際、最も簡単に判定する方法として、3つの出力値が確率になっていると良いわけです。
確率はそれぞれの確率を合計すると1になることはお分かりと思います。
最終出口のニューロンの値は0から1の間の値でなおかつそれぞれの合計が1になれば、確率として扱うことができます。
ソフトマックス関数を使うとそのような結果を得ることができます。
$$
k:ノード番号 \\
f(k)=\frac{e^{N_k}}{\sum_{i=1}^n e^{N_i}}
$$
オーバーフローについて:指数関数を使うと値があまりに大きくなりすぎる場合があります。例えば\(e^{1000}\)などは無限大になってしまい計算できなくなります。これがオーバーフローです。
オーバーフロー対策としては、Cという定数を分子、分母に掛けてその後展開したものを使用します。
一般的にCの値は入力値の最大値を使用します。
def softmax(a): c = np.max(a) exp_a = np.exp(a - c) # オーバーフロー対策 # リストの全要素の合計を算出する sum_exp_a = np.sum(exp_a) y = exp_a / sum_exp_a return y print(softmax([ 0.3, 2.9, 4.0]))
ディープラーニングを学習する際に以上の活性化関数の特徴を押さえておくと困ることは無いと思います。実務で使用する場合はさらに多くの活性化関数が使われますので、論文などを参考にして活用してみると良いでしょう。
コメントを投稿するにはログインしてください。