前回、Deep Learning基礎としてニューラルネットワークや順伝搬法についてまとめました。
elsammit-beginnerblg.hatenablog.com
今回もこちらの本を読み勉強した内容について引き続きまとめて行きたいと思います!!
ゼロから作るDeep Learning ?Pythonで学ぶディープラーニングの理論と実装 新品価格 |
内容は誤差逆伝搬についてです!!
ここから急に難しくなり進みが遅くなってきました😨
頑張って進めていきたいと思います!!
■誤差逆伝搬法とは
誤差逆伝搬法とは、
ニューラルネットワークを学習させる際に用いられるアルゴリズム
です。
バックプロパゲーション - Wikipedia
ニューラルネットワークの順方向とは逆方向に重みパラメータを変更しながら計算を行っていき、
最適なパラメータを算出方法になります。
順伝搬法は簡単に実装できますが、数値微分をして1つ1つ実行しながら進めるため、時間がかかってしまう欠点がありました。
この誤差逆伝搬法はパラメータの更新が効率よく実施できる方法となっております。
■足し算の誤差逆伝搬
足し算の誤差逆伝搬では、こちらのようになります。
z = x + yをx、yそれぞれで偏微分すれば確かにこちらのような結果になりますね。
pythonで実装するとこちらのようになります。
class AddLayer: def __init__(self): pass def forward(self,x,y): return x+y def backward(self, dout): dx = dout*1 dy = dout*1 return dx,dy
■乗算の逆伝搬
乗算の誤差逆伝搬では、こちらのようになります。
z = x × yをx、yそれぞれで偏微分すれば確かにこちらのような結果になりますね。
pythonで乗算の逆伝搬を実装するとこちらのようになります。
class MulLayer: def __Init__(self): self.x = None self.y = None def forward(self, x, y): self.x = x self.y = y out = x * y return out def backward(self, dout): dx = dout * self.y dy = dout * self.x return dx,dy
■Affine変換層の逆伝搬
そもそもAffine変換とは?ですが、幾何学の分野での行列の積のことを言います。
こちらのことですね。
O = np.dot(X,A)
例えば、Y = X・Wをニューラルネットワーク構築し、逆伝搬させるとこちらの通りになります。
このAffine変換層の逆伝搬をpythonで実装するとこちらになります。
class Affine: def __init__(self, W, b): self.W =W self.b = b self.x = None self.original_x_shape = None self.dW = None self.db = None def forward(self, x): self.original_x_shape = x.shape x = x.reshape(x.shape[0], -1) self.x = x out = np.dot(self.x, self.W) + self.b return out def backward(self, dout): dx = np.dot(dout, self.W.T) self.dW = np.dot(self.x.T, dout) self.db = np.sum(dout, axis=0) dx = dx.reshape(*self.original_x_shape) return dx
■ReLU層の逆伝搬
ReLUとは、活性化関数の1つで、
x>0でy=x、x<=0でy=0の式で表されます。
こちらの逆伝搬ですが、
それぞれ、
x > 0の場合 dy/dx x<=0の場合 0
になります。
pythonでReLUの逆伝搬を実装すると、
class Relu: def __init__(self): self.mask = None def forward(self,x): self.mask = (x<=0) out = x.copy() out[self.mask] = 0 return out def backward(self,dout): dout[self.mask] = 0 dx = dout return dx
■誤差逆伝搬法に対応したニューラルネットワーク
最後にこちらのように2層構成のニューラルネットワークの順伝搬・逆伝搬の構成をpythonで実装します。
今回のニューラルネットワークはこちらのような構成です。
ここで、
・W1:第1層の重みパラメータ
・W2:第2層の重みパラメータ
・b1:第1層のバイアス
・b2:第2層のバイアス
を示しております。
class TwoLayerNet: def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01): # 重みの初期化 self.params = {} self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) self.params['b1'] = np.zeros(hidden_size) self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) self.params['b2'] = np.zeros(output_size) # レイヤの生成 self.layers = OrderedDict() self.layers['Affine1'] = Affine(self.params['W1'], self.params['b1']) self.layers['Relu1'] = Relu() self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2']) self.lastLayer = Softmax() def loss(self, x, t): y = self.predict(x) return self.lastLayer.forward(y, t) def gradient(self, x, t): # forward self.loss(x, t) # backward dout = 1 dout = self.lastLayer.backward(dout) layers = list(self.layers.values()) layers.reverse() for layer in layers: dout = layer.backward(dout) grads = {} grads['W1'], grads['b1'] = self.layers['Affine1'].dW, self.layers['Affine1'].db grads['W2'], grads['b2'] = self.layers['Affine2'].dW, self.layers['Affine2'].db return grads
■最後に
今回は誤差逆伝搬についてまとめました。
まだまだ勉強中なので、素人レベルの記事になってしまっております😢
後、もっとわかりやすくまとめておきたいな。。。
頑張って勉強進めます!!