誤差逆伝播法 その2


AIって結局何なのかよく分からないので、とりあえず100日間勉強してみた Day58


経緯についてはこちらをご参照ください。



■本日の進捗

  • 全結合層の逆伝播を理解


■はじめに

今回も「ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装(オライリー・ジャパン)」で、深層学習を学んでいきます。

今回も良く活用される層の逆伝播を実装していきます。

■全結合層の逆伝播

全結合層(fully connected layer)とは、多層パーセプトロンでも登場した基本的なニューラルネットワークを成す層で、その名の通り前後の全てのニューロンと全結合している層のことです。Affine変換に相当することからAffine層と呼ばれることもあります。

これは各ニューロンで考えれば、これまで何度も見てきたように次のような極めて基本的な線形変換として記述できます。

$$ y = \displaystyle \sum_{i}^n w_i x_i+ b $$

ニューロンの重み付き和は実際には行列積で与えられます。(これまでもニューラルネットワークの計算はNumPy行列を用いてきました。)これを重み行列W、入力ベクトルX、バイアスベクトルBを用いれば下記のように記述できます。もちろんこれは順伝播の式です。

$$ \boldsymbol{ Y } = \boldsymbol{ W } \cdot \boldsymbol{ X } + \boldsymbol{ B } $$

順伝播のみとして実装するのであれば次のようになります。

def Affine(self, x):
    self.x = x
    out = np.dot(self.W, x) + self.b
    return out

順伝播の出力から損失Lが得られるとすれば、

●損失の重み勾配

ベクトルの微分は転置で与えられるので、

$$ \frac{ \partial \boldsymbol{Y} }{ \partial \boldsymbol{W} } = \frac{ \partial }{ \partial \boldsymbol{W} } ( \boldsymbol{W} \cdot \boldsymbol{X} ) + \frac{\partial \boldsymbol{B} }{\partial \boldsymbol{W} } = \boldsymbol{X}^{\mathrm{T}} $$

損失の勾配を連鎖律を用いて表現すれば、

$$ \frac{ \partial L }{ \partial \boldsymbol{W} } = \frac{ \partial L }{ \partial \boldsymbol{Y} } \cdot \frac{ \partial \boldsymbol{Y} }{ \partial \boldsymbol{W} } = \frac{ \partial L }{ \partial \boldsymbol{Y} } \cdot \boldsymbol{X}^{\mathrm{T}} $$

●損失のバイアス勾配

先の式より出力YをバイアスBで偏微分すると下記の通りなので、

$$ \frac{\partial \boldsymbol{Y} }{ \partial \boldsymbol{B} } = \frac{ \partial }{ \partial \boldsymbol{B} } ( \boldsymbol{W} \cdot \boldsymbol{X} ) + \frac{\partial \boldsymbol{B} }{\partial \boldsymbol{B} } = 1 $$

先程と同様に、

$$ \frac{ \partial L }{\partial \boldsymbol{B} } = \frac{\partial L}{\partial \boldsymbol{Y} } \cdot \frac{\partial \boldsymbol{Y} }{ \partial \boldsymbol{B}} = \frac{\partial L}{\partial \boldsymbol{Y} } $$

●損失の入力勾配

こちらもベクトルの微分は転置で与えられるので、

$$ \frac{\partial \boldsymbol{Y} }{\partial \boldsymbol{X} } = \frac{ \partial }{ \partial \boldsymbol{X} } ( \boldsymbol{W} \cdot \boldsymbol{X} ) + \frac{\partial \boldsymbol{B} }{\partial \boldsymbol{X} } = \boldsymbol{W}^{\mathrm{T}} $$

同様に連鎖律を用いて、

$$ \frac{\partial L }{\partial \boldsymbol{X} } = \frac{\partial L}{\partial \boldsymbol{Y}} \cdot \frac{\partial \boldsymbol{Y} }{\partial \boldsymbol{X} } = \frac{\partial L}{\partial \boldsymbol{Y}} \cdot \boldsymbol{W}^{\mathrm{T}} $$


ここまで求めた逆伝播を実装すると下記のようになります。

class Affine:
    def __init__(self, W, b):
        self.W = W
        self.b = b
        self.x = None
        self.dW = None
        self.db = None

    def forward(self, x):
        self.x = x
        out = np.dot(self.W, x) + self.b
        return out

    def backward(self, dout):
        self.dW = np.dot(dout, self.x.T)
        self.db = np.sum(dout, axis=0, keepdims=True)
        dx = np.dot(self.W.T, dout)
        
        return dx



■おわりに

今回はニューラルネットワークの基本的な線形変換を行う全結合層を逆伝播を考慮した層を構築しました。

こちらも参考文献とは別のアプローチから導出してみましたが、やはり参考文献の方が逆伝播をイメージしやすいと思います。ただ、本を読んでいて数式的にもやっとした部分をすっきりさせることも出来たとも思っています。理解の参考になれば幸いです。

■参考文献

  1. Andreas C. Muller, Sarah Guido. Pythonではじめる機械学習. 中田 秀基 訳. オライリー・ジャパン. 2017. 392p.
  2. 斎藤 康毅. ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装. オライリー・ジャパン. 2016. 320p.
  3. ChatGPT. 4o mini. OpenAI. 2024. https://chatgpt.com/
  4. API Reference. scikit-learn.org. https://scikit-learn.org/stable/api/index.html


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です