『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

ReLU(ランプ関数)

ReLU(ランプ関数)

ReLU (Rectified Linear Unit) は、ニューラルネットワークの分野で活性化関数として用いられる関数の1つです。一般には ランプ関数 (ramp function) とよばれ (ramp は「傾斜」の意)、次式で定義されます。
 \[R(x)=\begin{cases}0 & (x\lt 0)\\[6pt]x & (x\geq 0)\end{cases}\]
$\mathrm{max}$ 関数を用いると
 \[R(x)=\mathrm{max}(x,\ 0)\]
というように簡潔に表現できます。

NumPy パッケージを使用する場合、numpy.max() は渡した配列の全要素の中の最大値を返すので、ReLU を実装する場合は numpy.maximum() を使用します。numpy.maximum(x, a) は配列 x の各要素ごとに数値 a と比較して、小さくない方(x の要素と a が等しい場合があるので “大きい方” という表現は不正確)を配列に格納して返します。次のコードで ReLU のグラフを描くことができます。

# PYTHON_RELU

# In[1]

import numpy as np
import matplotlib.pyplot as plt

# Figureを作成
fig = plt.figure(figsize=(6, 4))

# FigureにAxesを1つ追加
ax = fig.add_subplot(111)

# Axesのタイトルを設定
ax.set_title("ReLU (Rectified Linear Unit)", fontsize=16)

# 目盛線を表示
ax.grid()

# 軸範囲を設定
ax.set_xlim([-6, 6])
ax.set_ylim([0, 6])

# 軸ラベルを設定
ax.set_xlabel("x", fontsize=14)
ax.set_ylabel("y = R(x)", fontsize=14)

# x,yデータの作成
x = np.linspace(-6, 6, 33)
y = np.maximum(x, 0)

# ReLU(ランプ関数)をプロット
ax.plot(x, y, color="blue")

plt.show()

relu (rectified linear unit) のグラフ
SymPy を使用する場合は sympy.Max()関数で ReLU を定義します。

# SYMPY_RELU

# In[1]

import sympy

# 記号xを定義
sympy.var('x')

# ReLuを定義
r = sympy.Max(x, 0)

# x軸の範囲:[-5, 5], 凡例を表示, 線の色は赤
p = sympy.plot(r, (x, -5, 5), legend=True, line_color='red', label='Max(x,0)')

sympy relu関数のグラフ

ReLU関数の微分

定義から明らかなように、ReLU の導関数は ヘヴィサイドの階段関数 となります。
 \[\frac{dR(x)}{dx}=H(x)\]
ヘヴィサイドの階段関数を微分するとデルタ関数となるので、ReLU の 2 階導関数はデルタ関数です。
 \[\frac{d^2 R(x)}{d x^2}=\delta(x)\]
SymPy にはヘヴィサイドの階段関数 Heviside() と デルタ関数 DiracDelta() が組込まれているので確認することができます。

# RELU_DERIVATIVE

# In[1]

import sympy

# 記号xを定義
sympy.var('x')

# ReLuを定義
r = sympy.Max(x, 0)

drdx1 = sympy.diff(r, x)
drdx2 = sympy.diff(r, x, 2)

print("r'(x) = {}".format(drdx1))
print("r\"(x) = {}".format(drdx2))

# r'(x)=Heviside(x)
# r"(x) = DiracDelta(x)

Leaky ReLU

ReLU を改良した Leaky ReLU は次式で定義されます。
 \[R_L(x)=\begin{cases}0.01x & (x\leq 0)\\[6pt]x & (x\gt 0)\end{cases}\]
出力が $0$ となって学習が進まないニューロンが出現する dying ReLU という現象を、$x\leq 0$ においても僅かな値をもたせることで防ぎます。NumPy では numpy.where()関数を使って実装することができます。

# LEAKY_RELU

import numpy as np
import matplotlib.pyplot as plt

# Figureを作成
fig = plt.figure(figsize=(6, 4))

# FigureにAxesを1つ追加
ax = fig.add_subplot(111)

# Axesのタイトルを設定
ax.set_title("Leaky ReLU", fontsize=16)

# 目盛線を表示
ax.grid()

# 軸範囲を設定
ax.set_xlim([-6, 6])
ax.set_ylim([0, 6])

# 軸ラベルを設定
ax.set_xlabel("x", fontsize=14)
ax.set_ylabel("y = RL(x)", fontsize=14)

# x,yデータの作成
x = np.linspace(-6, 6, 33)
y = np.where(x <= 0, 0.01 * x, x)

# ReLU(ランプ関数)をプロット
ax.plot(x, y, color="blue")

plt.show()

python leaky relu のグラフ

コメント

  1. HNaito より:

    RELU_01 と 04 の私の実行結果のグラフは、RELU_02 の実行結果とほとんど同じグラフが得られました。記事のグラフは x=0付近で少しゆるい傾斜の直線がはさまっているようです。
    RELU_02 の実行結果のグラフの凡例が Max(0, x) になっています。私のPCでも同様でしたが、plot( ) の引数に、label=’Max(x, 0)’ を追加したら直りました。

    • あとりえこばと より:

      申し訳ないです。
      グラフを差し替えました。
      ありがとうございます。m(_ _)m