Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

誤差逆伝播法

これまでは、ニューラルネットワークの各パラメータについての目的関数の数値微分を計算することで勾配を求める方法を説明しました。

勾配ベクトルの各成分は、各層の結合重みと各ユニットのバイアスでの損失関数の微分です。

しかし、ニューラルネットワークの層数が多くなると、数値微分の計算は膨大な時間がかかるでしょう。さらに、数値微分ではパラメータごとに順伝播の計算を繰り返す必要があるため、計算量はパラメータ数に比例して増えていきます。

ここで、パラメータの勾配の計算を効率よく行う手法である「誤差逆伝播法」について学びます。

誤差逆伝播法 (backpropagation) の計算過程

1連鎖律

複数の関数によって構成される関数を合成関数と呼びます。

z=t2t=x+y\begin{align} z &= t^2 \\ t &= x + y \end{align}

合成関数の微分は、「ttに関するzzの微分∂z∂t\frac{\partial z}{\partial t}」と「xxに関するttの微分∂t∂x\frac{\partial t}{\partial x}」の積のように、それぞれの関数の微分の積で求められます。

∂z∂x=∂z∂t∂t∂x\frac{\partial z}{\partial x} = \frac{\partial z}{\partial t} \frac{\partial t}{\partial x}

2線形変換の逆伝播の導出

入力データx\mathbf{x}は(N×D)(N \times D)の行列、W\mathbf{W}は(D×H)(D \times H)の行列、b\mathbf{b}は要素数HHのベクトルと考え、線形変換の計算は以下の式で表します。

y=xW+b=(x0,0x0,1⋯x0,D−1x1,0x1,1⋯x1,D−1⋮⋮⋱⋮xN−1,0xN−1,1⋯xN−1,D−1)(w0,0w0,1⋯w0,H−1w1,0w1,1⋯w1,H−1⋮⋮⋱⋮wD−1,0wD−1,1⋯wD−1,H−1)+(b0b1⋯bH−1)=(∑d=0D−1x0,dwd,0+b0∑d=0D−1x0,dwd,1+b1⋯∑d=0D−1x0,dwd,H−1+bH−1∑d=0D−1x1,dwd,0+b0∑d=0D−1x1,dwd,1+b1⋯∑d=0D−1x1,dwd,H−1+bH−1⋮⋮⋱⋮∑d=0D−1xN−1,dwd,0+b0∑d=0D−1xN−1,dwd,1+b1⋯∑d=0D−1xN−1,dwd,H−1+bH−1)=(y0,0y0,1⋯y0,H−1y1,0y1,1⋯y1,H−1⋮⋮⋱⋮yN−1,0yN−1,1⋯yN−1,H−1)\begin{aligned} \mathbf{y} &= \mathbf{x} \mathbf{W} + \mathbf{b} \\ &= \begin{pmatrix} x_{0,0} & x_{0,1} & \cdots & x_{0,D-1} \\ x_{1,0} & x_{1,1} & \cdots & x_{1,D-1} \\ \vdots & \vdots & \ddots & \vdots \\ x_{N-1,0} & x_{N-1,1} & \cdots & x_{N-1,D-1} \end{pmatrix} \begin{pmatrix} w_{0,0} & w_{0,1} & \cdots & w_{0,H-1} \\ w_{1,0} & w_{1,1} & \cdots & w_{1,H-1} \\ \vdots & \vdots & \ddots & \vdots \\ w_{D-1,0} & w_{D-1,1} & \cdots & w_{D-1,H-1} \end{pmatrix} + \begin{pmatrix} b_0 & b_1 & \cdots & b_{H-1} \end{pmatrix} \\ &= \begin{pmatrix} \sum_{d=0}^{D-1} x_{0,d} w_{d,0} + b_0 & \sum_{d=0}^{D-1} x_{0,d} w_{d,1} + b_1 & \cdots & \sum_{d=0}^{D-1} x_{0,d} w_{d,H-1} + b_{H-1} \\ \sum_{d=0}^{D-1} x_{1,d} w_{d,0} + b_0 & \sum_{d=0}^{D-1} x_{1,d} w_{d,1} + b_1 & \cdots & \sum_{d=0}^{D-1} x_{1,d} w_{d,H-1} + b_{H-1} \\ \vdots & \vdots & \ddots & \vdots \\ \sum_{d=0}^{D-1} x_{N-1,d} w_{d,0} + b_0 & \sum_{d=0}^{D-1} x_{N-1,d} w_{d,1} + b_1 & \cdots & \sum_{d=0}^{D-1} x_{N-1,d} w_{d,H-1} + b_{H-1} \end{pmatrix} \\ &= \begin{pmatrix} y_{0,0} & y_{0,1} & \cdots & y_{0,H-1} \\ y_{1,0} & y_{1,1} & \cdots & y_{1,H-1} \\ \vdots & \vdots & \ddots & \vdots \\ y_{N-1,0} & y_{N-1,1} & \cdots & y_{N-1,H-1} \end{pmatrix} \end{aligned}

ここで、「nn番目の出力データのhh番目の項yn,hy_{n,h}」は、

yn,h=∑d=0D−1xn,dwd,h+bhy_{n,h} = \sum_{d=0}^{D-1} x_{n,d} w_{d,h} + b_h

で計算できるのが分かります。

2.1重みの勾配

例えば、損失関数に二乗誤差

L=12∣∣y(x)−d∣∣2L = \frac{1}{2}||y(x)-d||^2

を選んだとき、連鎖律より、∂L∂wd,h\frac{\partial L}{\partial w_{d,h}}は次の式で求められます

∂L∂wd,h=∑n=0N−1∂L∂yn,h∂yn,h∂wd,h\frac{\partial L}{\partial w_{d,h}} = \sum_{n=0}^{N-1} \frac{\partial L}{\partial y_{n,h}} \frac{\partial y_{n,h}}{\partial w_{d,h}}
  • ∂L∂yn,h\frac{\partial L}{\partial y_{n,h}}は、yn,hy_{n,h}に関するLLの微分です。

  • ∂yn,h∂wd,h\frac{\partial y_{n,h}}{\partial w_{d,h}}は、wd,hw_{d,h}に関するyn,hy_{n,h}の微分です。

ここで、∂yn,h∂wd,h\frac{\partial y_{n,h}}{\partial w_{d,h}}は、

∂yn,h∂wd,h=∂∂wd,h{∑d′=0D−1xn,d′wd′,h+bh}=∂∂wd,h{xn,0w0,h+⋯+xn,dwd,h+⋯+xn,D−1wD−1,h+bh}=0+⋯+xn,d+⋯+0+0=xn,d\begin{aligned} \frac{\partial y_{n,h}}{\partial w_{d,h}} &= \frac{\partial}{\partial w_{d,h}} \left\{ \sum_{d'=0}^{D-1} x_{n,d'} w_{d',h} + b_h \right\} \\ &= \frac{\partial}{\partial w_{d,h}} \Bigl\{ x_{n,0} w_{0,h} + \cdots + x_{n,d} w_{d,h} + \cdots + x_{n,D-1} w_{D-1,h} + b_h \Bigr\} \\ &= 0 + \cdots + x_{n,d} + \cdots + 0 + 0 \\ &= x_{n,d} \end{aligned}

になるため、

∂L∂wd,h=∑n=0N−1∂L∂yn,hxn,d\frac{\partial L}{\partial w_{d,h}} = \sum_{n=0}^{N-1} \frac{\partial L}{\partial y_{n,h}} x_{n,d}

2.2バイアスの勾配

同じく連鎖律より、∂L∂bh\frac{\partial L}{\partial b_h}は次の式で求められます。

∂L∂bh=∑n=0N−1∂L∂yn,h∂yn,h∂bh\frac{\partial L}{\partial b_h} = \sum_{n=0}^{N-1} \frac{\partial L}{\partial y_{n,h}} \frac{\partial y_{n,h}}{\partial b_h}
∂yn,h∂bh=∂∂bh{∑d=0D−1xn,dwd,h+bh}=0+1=1\begin{aligned} \frac{\partial y_{n,h}}{\partial b_h} &= \frac{\partial}{\partial b_h} \left\{ \sum_{d=0}^{D-1} x_{n,d} w_{d,h} + b_h \right\} \\ &= 0 + 1 \\ &= 1 \end{aligned}

まとめると、

∂L∂bh=∑n=0N−1∂L∂yn,h\frac{\partial L}{\partial b_h} = \sum_{n=0}^{N-1} \frac{\partial L}{\partial y_{n,h}}

3ニューラルネットワークにおける誤差逆伝播法の計算例

連鎖律より勾配を計算する考え方をニューラルネットワークにも適用する計算例を見ましょう。

具体的には、ニューラルネットワークを構成する関数が持つパラメータについての目的関数の勾配を、順伝播で通った経路を逆向きにたどるようにして途中の関数の勾配の掛け算によって求めます。

ここから、手計算を通じて誤差逆伝播法の実装を理解しましょう。

  • 入力

i1=0.05,i2=0.10i_{1} = 0.05,i_{2} = 0.10
  • 初期パラメータ

w1=0.15,w2=0.20,w3=0.25,w4=0.30w_{1} = 0.15,w_{2} = 0.20,w_{3} = 0.25,w_{4} = 0.30
w5=0.40,w6=0.45,w7=0.50,w8=0.55w_{5} = 0.40,w_{6} = 0.45,w_{7} = 0.50,w_{8} = 0.55
  • バイアス(各層で共通)

b1=0.35,b2=0.60b_{1} = 0.35,b_{2} = 0.60
  • 活性化関数: シグモイド関数

h(x)=11+exp⁡(−x)h(x) = \frac{1}{1 + \exp(-x)}
  • 教師データ

    o1=0.01,o2=0.99o_{1} = 0.01,o_{2} = 0.99
  • 目的関数は二乗誤差を用いることにします(微分の式を簡単にするため12\frac{1}{2}を付けます)。

L=12∑k=12(tk−yk)2L = \dfrac{1}{2} \sum_{k=1}^{2} (t_{k} - y_{k})^2
ニューラルネットワークの実装例

ニューラルネットワークの実装例

3.1順伝播の流れ

net_h1=0.3775
out_h1=0.5932699921071872
net_h2=0.39249999999999996
out_h2=0.596884378259767
out_o1=0.7513650695523157
out_o2=0.7729284653214625
Loss=0.2983711087600027

例えば、w5w_5の勾配を計算する際には、

誤差逆伝播法でw_5の勾配を求める

誤差逆伝播法でw5w_5の勾配を求める

∂L∂w5=∂L∂outo1∂outo1∂neto1∂neto1∂w5\frac{\partial L}{\partial w_5} = \frac{\partial L}{\partial out_{o1}}\frac{\partial out_{o1}}{\partial net_{o1}}\frac{\partial net_{o1}}{\partial w_5}

∂L∂outo1\frac{\partial L}{\partial out_{o1}}を計算する

L=12(targeto1−outo1)2+12(targeto2−outo2)2L= \frac{1}{2}(target_{o_{1}}-out_{o_{1}})^2+\frac{1}{2}(target_{o_{2}}-out_{o_{2}})^2

合成関数の微分g(f(x))=g′(f(x))f′(x)g(f(x))= g^{\prime}(f(x))f^{\prime}(x)によって

∂L∂outo1=2∗12(targeto1−outo1)∗−1+0\frac{\partial L}{\partial out_{o1}}= 2*\frac{1}{2}(target_{o_{1}}-out_{o_{1}})*-1+0
d_out_o1=0.7413650695523157

∂outo1∂neto1\frac{\partial out_{o1}}{\partial net_{o1}}を計算する

outo1=sigmoid(neto1)out_{o1}= sigmoid(net_{o_{1}})

Sigmoid関数の微分は f′(x)=f(x)(1−f(x))f^{\prime}(x)=f(x)(1-f(x)) なので

∂outo1∂neto1=outo1(1−outo1)\frac{\partial out_{o1}}{\partial net_{o1}}= out_{o1}(1-out_{o1})
d_net_o1=0.18681560180895948

∂neto1∂w5\frac{\partial net_{o1}}{\partial w_5}を計算する

neto1=w5∗outh1+w6∗outh2+b2∗1net_{o_{1}}=w_{5}*out_{h_{1}}+w_{6}*out_{h_{2}}+b_{2}*1
∂neto1∂w5=outh1\frac{\partial net_{o1}}{\partial w_5}= out_{h_{1}}
d_w5=0.08216704056423078

パラメータを更新する

w5+=w5−η∂L∂w5w_5^+ = w_{5}- \eta \frac{\partial {L}}{\partial w_5}

3.2多層ネットワークへの一般化

以上の計算例では、2層ネットワークの場合の損失関数の勾配を誤差逆伝播法で計算できました。各層での勾配計算が連鎖律に従っているため、層数が増えても理論的には同じ流れで処理できるため、任意の層数のネットワークに拡張することができます。

  • 入力:学習サンプルxnx_nおよび目標出力dnd_nのペア

  • 出力:損失関数Ln(w)L_n(w)の各層llのパラメータについての微分∂L∂wji(l)\frac{\partial {L}}{\partial w_{ji}^{(l)}}

  1. 順伝播: 入力データが層を通過して出力に達するまで順番に計算が行われます。

  2. 損失の計算: ネットワークの最終出力(予測値)と実際のラベルとの誤差(損失)を損失関数で計算します。出力層の誤差δ(L)\delta^{(L)}は損失関数と出力層の活性化関数の組み合わせで決まります(例:二乗誤差と恒等関数、またはソフトマックスと交差エントロピーの場合はδj(L)=zj(L)−dj\delta_j^{(L)}=z_j^{(L)}-d_j)。

  3. 逆伝播: 各隠れ層l=L−1,L−2,…l=L-1, L-2,\dotsでは、次の層の誤差δ(l+1)\delta^{(l+1)}を重みの転置で逆向きに伝え、活性化関数の導関数を要素ごとに掛けてδ(l)\delta^{(l)}を計算します(連鎖律)。

δ(l)=((W(l+1))Tδ(l+1))⊙f′(u(l))\delta^{(l)} = \bigl( (\mathbf{W}^{(l+1)})^{\mathrm{T}} \delta^{(l+1)} \bigr) \odot f'(\mathbf{u}^{(l)})
ここで、$\mathbf{u}^{(l)}$は第$l$層の活性化前の値(重み付き和)、$\mathbf{z}^{(l)}=f(\mathbf{u}^{(l)})$は第$l$層の出力です。
  1. 勾配の計算とパラメータの更新: 各層の勾配は、逆伝播で得られたδ(l)\delta^{(l)}と前の層の出力z(l−1)z^{(l-1)}から

∂L∂wji(l)=δj(l)zi(l−1),∂L∂bj(l)=δj(l)\frac{\partial L}{\partial w_{ji}^{(l)}} = \delta_j^{(l)} z_i^{(l-1)},\quad \frac{\partial L}{\partial b_j^{(l)}} = \delta_j^{(l)}
と求まります。これらを用いて、各層の重みとバイアスを更新します。