RELUでニューラルネットワークを実装しようとしています。
入力層-> 1つの隠れ層-> relu->出力層-> softmax層
上記は私のニューラルネットワークのアーキテクチャです。このreluの逆伝播について混乱しています。 RELUの導関数の場合、x <= 0の場合、出力は0です。x> 0の場合、出力は1です。したがって、勾配を計算するとき、x <= 0の場合、勾配を適切に削除しますか?
誰かが私のニューラルネットワークアーキテクチャの逆伝播を「段階的に」説明できますか?
x <= 0の場合、出力は0です。x> 0の場合、出力は1です
ReLU関数は次のように定義されます:x> 0の場合、出力はx、つまりf(x max(0、x))==
したがって、微分f '(x)の場合、実際には次のようになります。
x <0の場合、出力は0です。x> 0の場合、出力は1です。
導関数f '(0)は定義されていません。したがって、通常は0に設定されるか、アクティベーション関数を変更して、小さなeに対してf(x) = max(e、x)になります。
一般的に、ReLUは整流器作動機能を使用するユニットです。つまり、他の隠れ層とまったく同じように機能しますが、tanh(x)、sigmoid(x)、または使用するアクティベーションを除き、代わりにf(x) = max(0、バツ)。
シグモイドアクティベーションを使用して動作する多層ネットワークのコードを記述した場合、文字通り1行の変更になります。順方向または逆方向の伝播に関するアルゴリズム的な変更はありません。シンプルなモデルがまだ機能していない場合は、戻って最初にそれから始めてください。それ以外の場合、あなたの質問はReLUについてではなく、NN全体の実装についてです。
アーキテクチャが示唆するように、単一のReLUで作成されたレイヤーがある場合、はい、0
でグラデーションを削除します。トレーニング中、ReLUは0
を出力レイヤーに返し、ロジスティック単位を使用している場合は0
または0.5
を返し、softmaxはそれらを押しつぶします。したがって、現在のアーキテクチャでの0
の値は、前方伝播部分にとってもあまり意味がありません。
たとえば、 this を参照してください。できることは、0
のような0.01
の小さな値である「漏れやすいReLU」を使用することです。
私はこのアーキテクチャを再考しますが、単一のReLUを他のユニットの束に供給してからソフトマックスを適用することはあまり意味がありません。
これは良い例です。ReLUを使用してXORを実装します:reference、 http://pytorch.org/tutorials/beginner/pytorch_with_examples.html
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
# N is batch size(sample size); D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 4, 2, 30, 1
# Create random input and output data
x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])
# Randomly initialize weights
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)
learning_rate = 0.002
loss_col = []
for t in range(200):
# Forward pass: compute predicted y
h = x.dot(w1)
h_relu = np.maximum(h, 0) # using ReLU as activate function
y_pred = h_relu.dot(w2)
# Compute and print loss
loss = np.square(y_pred - y).sum() # loss function
loss_col.append(loss)
print(t, loss, y_pred)
# Backprop to compute gradients of w1 and w2 with respect to loss
grad_y_pred = 2.0 * (y_pred - y) # the last layer's error
grad_w2 = h_relu.T.dot(grad_y_pred)
grad_h_relu = grad_y_pred.dot(w2.T) # the second laye's error
grad_h = grad_h_relu.copy()
grad_h[h < 0] = 0 # the derivate of ReLU
grad_w1 = x.T.dot(grad_h)
# Update weights
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
plt.plot(loss_col)
plt.show()
ReLUの派生物の詳細については、こちらをご覧ください。 http://kawahara.ca/what-is-the-derivative-of-relu/
はい、元のRelu関数には、説明した問題があります。そのため、彼らは後で式に変更を加え、Releayと呼びました。本質的にLeaky Reluは関数の水平部分を非常にわずかに傾けます。詳細については、これを見てください:
さらに、ここでcaffeフレームワークの実装を見つけることができます: https://github.com/BVLC/caffe/blob/master/src/caffe/layers/relu_layer.cpp
Negative_slopeは、負の部分を0に設定するのではなく、勾配値で乗算することで「リーク」するかどうかを指定します。もちろん、古典的なバージョンを使用するには、このパラメーターをゼロに設定する必要があります。