深層学習で登場する、活性化関数(activation function)の式と実装、グラフを同時に掲載していきます。
辞書的な役割での用途を想定しています。
シグモイド関数
\begin{equation} \operatorname{sigmoid(x)} = \frac{1}{ 1 + exp(-x)} \end{equation}
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10, 100)
def sigmoid(x):
return 1 / (1 + np.exp(-x))
y = sigmoid(x)
fig, ax = plt.subplots(figsize=(6,3), dpi=100)
ax.set_ylim([-0.1, 1.1])
ax.set_title("sigmoid function")
ax.plot(x, y)
シグモイド関数の導関数
def sigmoid_derivative(x):
return sigmoid(x) * (1 - sigmoid(x))
x = np.linspace(-10, 10, 100)
y = sigmoid_derivative(x)
fig, ax = plt.subplots(figsize=(6,3), dpi=100)
ax.set_title("sigmoid function derivative")
ax.plot(x, y)
シグモイド関数の導関数は、最大で、0.25 最小で0の関数形になることがわかりました。このように、何回もシグモイド関数を通ることで、その勾配は、0 – 0.25 が毎回かかった値になることがわかります。
つまり、シグモイド関数を何回も通るような場合、勾配消失が起こってしまうのは、これに起因します。
ステップ関数
\begin{equation} \operatorname{step(x)} = \begin{cases} 1 & \text{if } x \geq 0 \\ 0 & \text{if } x \lt 0 \end{cases} \end{equation}
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10, 100)
def step(x):
return np.array(x > 0, dtype=np.int)
y = step(x)
fig, ax = plt.subplots(figsize=(6,3), dpi=100)
ax.set_ylim([-0.1, 1.1])
ax.set_title("step function")
ax.plot(x, y)
ReLU関数(ランプ関数)
ReLU(Rectified Linear Unit)は、ステップ関数と似ていますが、入力値$x$が$x > 0$の時に、0ではなく、$x$を返すのが、ステップ関数と違いです。
ReLU関数は活性化関数として実用的に非常によく利用されます。
\begin{equation} \operatorname{ReLU(x)} = \begin{cases} x & \text{if } x \geq 0 \\ 0 & \text{if } x \lt 0 \end{cases} \end{equation}
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10, 100)
def relu(x):
return np.maximum(0, x)
y = relu(x)
fig, ax = plt.subplots(figsize=(6,3), dpi=100)
ax.set_title("ReLU function")
ax.plot(x, y)
LeakyReLU関数
LeakyReLU(Leaky Rectified Linear Unit)は、ReLUに少し改変を加えた活性化関数です。
入力値$x$の範囲が、$x \geq 0$の時は、ReLUと同様に、入力値と同様の$x$を返しますが、$x < 0$の時は、$\alpha x$ を返す関数となっています。ここで、$\alpha$は任意の定数で学習パラメータになりうる値ですが、基本的には$\alpha = 0.01$として利用さっることが多いようです。
\begin{equation} \operatorname{Leaky ReLU(x)} = \begin{cases} x & \text{if } x \geq 0 \\ \alpha x & \text{if } x \lt 0 \end{cases} \end{equation}
LeakyReLUに関しては、グラフを見ればこういう活性化関数なんだなとすぐにわかります。ReLUとの違いがわかりやすくなるように、同時にプロットしてみます。
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
def relu(x):
return np.maximum(0, x)
def leakyrelu(x, alpha=0.01):
return np.where(x >= 0.0, x, alpha * x)
y = leakyrelu(x, 0.1)
y_relu = relu(x)
fig, ax = plt.subplots(figsize=(6,3), dpi=100)
ax.set_title("LeakyReLU function")
ax.plot(x, y, label="LeakyReLU")
ax.plot(x, y_relu, ls="-.", label="ReLU")
ax.legend()
LeakyReLUのLeaky は漏れ出るという意味です。上のグラフを見るとわかりますが、ReLU関数は$x < 0$の領域で値が0になっているのに対し、LeakyReLUでは、下に少しずつ下がっているのがわかりますね。このようなグラフの形状をしていることから、LeakyReLUという名前がついています。