ゼロつくDeepLearning_cp5

# はじめに

こちらは「[ゼロつく3DeepLearning_cp4](https://qiita.com/ponponnsan/items/321670629c15aea21fd2)」の記事の続きです。

「[ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585)」についてのまとめを数回に分けて行いたいと思います。

YOUTUBEでのおすすめチャンネルは以下の通り
- [ヨビノリ](https://www.youtube.com/@yobinori)
- [AIcia Solid Project](https://www.youtube.com/@AIcia_Solid)
- [3Blue1BrownJapan](https://www.youtube.com/@3Blue1BrownJapan)

# 何をまとめるのか
さて、このまとめではpythonのコードを動かしたり、何か実装するということは行いません。

ちなみに、書籍のソースコードは[こちら](https://github.com/oreilly-japan/deep-learning-from-scratch)にまとめられています。

なので1章はとばし、2章からのスタートになります。

今回は**5章**をまとめます。

引き続き個人的に重要だと思うポイントを記載したいと思います。

## 5章 誤差逆伝播法

4章で勾配法について勉強し、ニューラルネットワークの重みの勾配は、微分を用いて求めました。順伝播では、通常の計算を行います。入力と同じ順番で重みを計算していくと次の層の全ての重みも変化してしまうため、計算に時間がかかるという難点があります。
誤差逆伝播法では、最終層からの微分を行うことで、勾配を求めることができ、重みを時間を節約しながら計算することができます。

### 計算グラフと逆伝播

以下の例題を考えてみたいと思います。

「1個100円のりんごを2個買いました。支払う金額は何円ですか？ただし、消費税が10%適応されるものとします。」

計算グラフによって書かれた計算は以下のようになります。
計算グラフはノードと矢印によて計算の過程を表します。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159060/2b456225-2e52-5783-eedc-92fa4504c0a9.jpeg" width="500">

計算グラフの結果から答えは220円になります。

上記の図では、左から右へと順番に計算が進んでいます。これを順伝播と言います。

逆伝播は、順伝播の逆、右から左へ計算が進んでいきます。

簡単な例題を計算グラフで表しました。なぜ計算グラフで書いたかというと、逆伝播の伝播によって計算された微分を表せることができるからです。

では、上記の「リンゴの値段が値上がりした場合、最終的な支払い金額にどのように影響するか」を考えてみましょう。これは、支払い金額をりんごの値段で微分した値と同じになります。
このような値は、逆伝播で表すことができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159060/1a8175a1-20a2-dee0-a7e7-d9a07b8a15ad.jpeg" width="500">

逆伝播の特徴は、「局所的な計算(微分)」を伝播できる点にあります。
局所的とは、「自分に関係する小さな範囲の計算(微分)」ということを意味します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159060/cbe5aa2d-e5dc-5186-a233-5506279bc3fd.jpeg" width="500">

全体の計算がどんなに複雑であったとしても、各ステップでは「自分に関する小さな範囲の計算(微分)」が行われます。
逆伝播はその局所的な計算(微分)結果を伝達することで、計算の結果を得ています。

この例では、支払い金額をリンゴの値段で微分する形でしたが、支払い金額を「消費税」や「リンゴの個数」で微分を行なう場合でも同じ手順で計算することができます。
そしてその際には、途中まで求めた微分の結果も共有することができ、複数の微分を計算することができます。


### 連鎖律

局所的な微分を伝達する原理は連鎖律によるものです。
連鎖律は、合成関数の微分についての性質であり、本では次のように定義されています。

> ある関数が合成関数で表される場合、その合成関数の微分は合成関数を構成するそれぞれの関数の微分の積によって表すことができる。

合成関数は、複数の関数によって構成される関数のことです。

公式は以下のような数式になります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159060/f257fbd5-783a-00ad-bb1b-76ca5db9815f.jpeg" width="500">

考え方としては、多変数の部分($x^2+3x+1$)を$u$と置いて微分してしまおうというところですね。
これを逆誤差伝播でも用います。計算グラフで表すと以下の通りです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159060/2527d006-01c6-8dac-9e21-6c756a26eb21.jpeg" width="500">

一番左の逆伝播の結果を見ての通り、合成関数の公式と一致し、「$y$を$x$で微分」することに対応します。

つまり、逆伝播が行っていることは、連鎖律の原理から構成されています。

### RELU関数の時の逆伝播

活性化関数はシグモイド関数やハイパボリックタンジェントなどがありましたが、最近ではRELU関数がよく使われています。理由としては、LLMの登場でパラメータ数が多くなると、シグモイド関数などを用いると計算が複雑になり、時間がかかってしまうからです。
そこで、RELU関数のような、$x$が0より大きければ次の層に伝え、0より小さければ次の層には伝えないという単純な関数が使われるようになりました。

RELU関数の図は「ゼロつくDeepLearning_cp3」にありますので、ぜひ確認してみてください。

RELU関数は次の式で表されます。

$$y = \begin{cases} x & (x > 0) \newline 0 & (x ≦ 0) \end{cases}$$

そしてRELU関数の$x$に関する$y$の微分は以下の式になります。

$$\frac{dy}{dx} = \begin{cases} 1 & (x > 0) \newline 0 & (x ≦ 0) \end{cases}$$

順伝播時の入力である$x$が0より大きければ、逆伝播は上流の値をそのまま下流に渡します。
逆に順伝播時に$x$が0以下であれば、逆伝播では下流への信号はストップします。計算グラフで表すと、図のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159060/cc523a51-1a2c-461d-36ad-8704522a800b.jpeg" width="500">