バックプロパゲーション

**バックプロパゲーション**（, backprop）または**誤差逆伝播法**（ごさぎゃくでんぱほう、）とは、ニューラルネットワークの損失関数のパラメータに関する偏微分を、自動微分のトップダウン型（リバース・モード）と同様の手法により、出力側から偏微分を計算し、誤差を伝播させる方法で、効率よく計算する手法である。一般的には、ここで計算した偏微分を使用し、確率的勾配降下法でニューラルネットワークを学習させる。用語は曖昧に使用されていて、バックプロパゲーションに確率的勾配降下法まで含んで使われている事も多い。

## 概要
バックプロパゲーションは数理モデルであるニューラルネットワークのパラメータに関する偏微分を計算する手法で、確率的勾配降下法はパラメータを更新する（学習する）手法である。

バックプロパゲーションおよび確率的勾配降下法は次の通りである：

# ニューラルネットワークに学習のためのサンプルを与える。
# ネットワークの出力を求め、出力層における誤差を求める。その誤差を用い、各出力ニューロンについて誤差を計算する。
# 個々のニューロンの期待される出力値と倍率 (scaling factor)、要求された出力と実際の出力の差を計算する。これを局所誤差と言う。
# 各ニューロンの重みを局所誤差が小さくなるよう調整する。
# より大きな重みで接続された前段のニューロンに対して、局所誤差の責任があると判定する。
# そのように判定された前段のニューロンのさらに前段のニューロン群について同様の処理を行う。

誤差逆伝播法という名称が示唆するように、誤差（および学習）は出力ノードから入力ノードへと逆向きに伝播する。技術的に言えば、バックプロパゲーションはネットワーク上の変更可能なパラメータについて、誤差の傾斜、つまり損失関数の偏微分を計算するものである。数式での実際の計算方法は後述する。

出力側から偏微分を計算すると計算効率が良くなる理由は、損失関数の出力がスカラーであることに起因するのだが、詳細は自動微分を参照。

### 確率的勾配降下法

バックプロパゲーションで計算した偏微分値は、ほとんどの場合、損失関数の誤差を最小にするアルゴリズムである確率的勾配降下法と共に使用される。

y を教師データとし、モデル \hat{y}=f(x;w) に対する損失関数 L(\hat{y}, y) を定義したとき、現在の重み w_k = a_{now} における L の傾きすなわち偏微分値 \left.{\partial L \over \partial w_k}\right|_{w_k=a_{now}} がわかれば、最適化手法である確率的勾配降下法を用いて損失 L が小さくなるように w_k を更新（=学習）できる。バックプロパゲーションの目的はこの偏微分値を効率よく計算することである。

本来は偏微分の計算方法だけを指すのだが、「バックプロパゲーション」という用語は曖昧に使われ、偏微分の計算方法と確率的勾配降下法も含めた全体を示す事に使われることも多い。確率的勾配降下法は通常収束して、対象ネットワークの誤差の局所解(区間を限定したときの極小値、極値参照)を探し出す。人工ニューロン(または「ノード」)で使われる活性化関数は微分可能関数でなければならない。

数理最適化問題の一種であるため、バッチ学習・オンライン学習のいずれかが採用される。典型的には確率的勾配降下法を用いたミニバッチ学習が行われる。

### 自動微分

バックプロパゲーションは、自動微分のトップダウン型（リバース・モード）という汎用技法の特殊ケースである。昔は手作業で偏微分の式変形を行っていたが、現在は PyTorch や TensorFlow などのニューラルネットワークのライブラリには自動微分の機能が含まれているので、簡単に使えるようになっている。膨大数の偏微分値を自動微分により高速計算することで、極めて多次元の最適化計算の実用的な高速化が可能となる。

## 計算方法
現代では、通常は、損失関数のパラメータに関する偏微分（バックプロパゲーション）は自動微分を使用するものであるが、ここでは手計算で式変形を行う。計算内容は自動微分のトップダウン型（リバース・モード）と同一である。

下記の式変形では合成関数の偏微分の連鎖律を使用しているが、詳細は自動微分を参照。

### モデル
回帰問題で、入力はD次元のベクトル、出力はK次元ベクトル、モデルは2層の多層パーセプトロンとする。

* 入力層: D次元ベクトル x = (x_1, ..., x_D)^T
* 隠れ層: M次元ベクトル
** 重み行列: W^{(1)} （成分 w_{ji}^{(1)} は入力 i から隠れ素子 j への重み）
** バイアス: b^{(1)} （成分 b_j^{(1)}）
** 出力: z = (z_1, ..., z_M)^T
** 活性化関数: \sigma(\cdot)
* 出力層: K次元ベクトル
** 重み行列: W^{(2)} （成分 w_{kj}^{(2)} は隠れ素子 j から出力素子 k への重み）
** バイアス: b^{(2)} （成分 b_k^{(2)}）
** 出力: y = (y_1, ..., y_K)^T
** 活性化関数: 恒等写像（線形）
* 正解データ: t = (t_1, ..., t_K)^T

### 損失関数
損失関数は二乗和誤差を使用する。出力ベクトル y と正解ベクトル t の要素ごとの差の二乗和である。微分を簡単にするため係数 \frac{1}{2} をつける。

: L = \frac{1}{2} \sum_{k=1}^{K} (y_k - t_k)^2

### 順伝播（出力の計算）
隠れ層の計算

: u_j^{(1)} = \sum_{i=1}^{D} w_{ji}^{(1)} x_i + b_j^{(1)}
: z_j = \sigma(u_j^{(1)})

出力層の計算

: u_k^{(2)} = \sum_{j=1}^{M} w_{kj}^{(2)} z_j + b_k^{(2)}
: y_k = u_k^{(2)}

### 逆伝播（バックプロパゲーション）
出力側から損失関数のパラメータに関する偏微分を計算する。

出力層の第 k 番目の素子の内部状態 u_k^{(2)} に対する勾配を求める。損失関数の総和 \sum のうち、u_k^{(2)} に関係するのは第 k 項のみであることに注意する。

: \frac{\partial L}{\partial u_k^{(2)}} = \frac{\partial L}{\partial y_k} \frac{\partial y_k}{\partial u_k^{(2)}} = (y_k - t_k) \cdot 1 = y_k - t_k

これを用いて、出力層の重み w_{kj}^{(2)} とバイアス b_k^{(2)} の勾配を求める。

出力層の重みの勾配

: \frac{\partial L}{\partial w_{kj}^{(2)}} = \frac{\partial L}{\partial u_k^{(2)}} \frac{\partial u_k^{(2)}}{\partial w_{kj}^{(2)}} = \frac{\partial L}{\partial u_k^{(2)}} z_j

出力層のバイアスの勾配

: \frac{\partial L}{\partial b_k^{(2)}} = \frac{\partial L}{\partial u_k^{(2)}} \frac{\partial u_k^{(2)}}{\partial b_k^{(2)}} = \frac{\partial L}{\partial u_k^{(2)}}

次に、誤差を隠れ層へ逆伝播させる。

隠れ層の入力 u_j^{(1)} に対する勾配を求める。

: \frac{\partial L}{\partial u_j^{(1)}} = \frac{\partial L}{\partial z_j} \frac{\partial z_j}{\partial u_j^{(1)}} = \sum_{k=1}^{K} \left( \frac{\partial L}{\partial u_k^{(2)}} \frac{\partial u_k^{(2)}}{\partial z_j} \right) \frac{\partial z_j}{\partial u_j^{(1)}}

ここで、これらを代入すると、

: \frac{\partial u_k^{(2)}}{\partial z_j} = w_{kj}^{(2)}
: \frac{\partial z_j}{\partial u_j^{(1)}} = \sigma'(u_j^{(1)})

隠れ層の誤差は以下になる。

: \frac{\partial L}{\partial u_j^{(1)}} = \sigma'(u_j^{(1)}) \sum_{k=1}^{K} \frac{\partial L}{\partial u_k^{(2)}} w_{kj}^{(2)}

これを用いて、隠れ層のパラメータの勾配を求める。

隠れ層の重みの勾配

: \frac{\partial L}{\partial w_{ji}^{(1)}} = \frac{\partial L}{\partial u_j^{(1)}} \frac{\partial u_j^{(1)}}{\partial w_{ji}^{(1)}} = \frac{\partial L}{\partial u_j^{(1)}} x_i

隠れ層のバイアスの勾配

: \frac{\partial L}{\partial b_j^{(1)}} = \frac{\partial L}{\partial u_j^{(1)}} \frac{\partial u_j^{(1)}}{\partial b_j^{(1)}} = \frac{\partial L}{\partial u_j^{(1)}}

## 歴史
確率的勾配降下法およびバックプロパゲーション（出力側から偏微分）に相当するニューラルネットワークの学習手法は1960年代に開発されたものだが、定着せず、その後、何度も再発見され、1986年より標準的な手法として普及した。

* 1951年、Herbert Robbins等が確率的勾配降下法を発表した。
* 1960年、とマーシャン・ホフが、二値分類問題に対して、損失関数が二乗誤差損失の形式ニューロン（入出力が二値の線形分類器、つまり、活性化関数が符号関数の1層の単純パーセプトロン）を確率的勾配降下法で学習させる方法を発表した。Widrow-Hoff法（デルタルール）と命名した。学習させる際は、活性化関数の符号関数を外して内側の線形モデルに対して学習させる。二乗誤差の線形モデルなので、偏微分は出力誤差を使用したものになり、論文では、誤差のフィードバックで学習させていると書かれているが、単なる線形モデルなので、誤差を伝播させる話ではない。
* 1964年、R.E. Wengertが自動微分を発表した。論文で書かれていたのは入力側から偏微分する方法（ボトムアップ型、フォーワード・モード）で、Andreas Griewank によると、計算の効率化のために出力側から偏微分する方法（トップダウン型、リバース・モード）を誰が考案したのか判然とはしないが、1960年代後半には提案されていた。出力側から偏微分する方法はバックプロパゲーションと同じ計算方法である。
* 1967年、甘利俊一がニューラルネットワークの最も基本的な形である多層パーセプトロンを確率的勾配降下法で学習させ、その理論的解析を書いた論文を発表した。翌年1968年に書籍『情報理論II ―情報の幾何学的理論―』にて詳しく解説した。書籍には判別面がギザギザの線形分離不可能な例を学習させるものが紹介されている。1967年の論文には具体例がなく、1968年の書籍のp.119に載っている具体例のモデルは、入力が2次元ベクトル、出力がスカラーの二値分類問題で、1966年のR. O. Duda等の手書き文字認識のモデルを改変した w^{(5)}\max\{ W^{(1)} x, W^{(2)} x \} + w^{(6)}\min\{ W^{(3)} x, W^{(4)} x \} という区分的線形識別関数のモデルであり、これは、中間層の活性化関数にReLUを使用した場合の多層パーセプトロンと等価ではあるが、これが多層パーセプトロンであるという記述は書籍側にはなく、また、出力側から偏微分を計算するという話も書かれてはいない。
* 1969年、& : 多段動的システム最適化手法として提案
* 1974年、: ニューラルネットワークにおける応用を示唆
* 1986年、デビッド・ラメルハート、ジェフリー・ヒントン、: *backwards propagation of errors*（逆向きの誤差の伝播）の略からバックプロパゲーションの名で出力側から偏微分を計算する方法を再発明し、この論文では確率的勾配降下法ではなく最急降下法が使用されているのだが、直後から以後、確率的勾配降下法を使用する方法を含めて定着した。

## その他
ニューラルネットワークを学習させる際のテクニックや限界などはニューラルネットワークを参照。

## 脚注

## 関連項目
*ニューラルネットワーク
*ディープラーニング
*パターン認識
*受容野
*自己組織化写像
*教師なし学習