ゼロから作るDeepLearning まとめ メモ

# 第1章　Python入門
###1.1 Python

- プラットフォーム・ライブラリが豊富である
- 数値計算、処理速度が速い
- インプリンタ型で超高級言語
- オブジェクト指向プログラミング
    - オブジェクトは、コンピュータ上で操作や処理の対象となる何らかの実体のこと。
    - オブジェクトにはそれぞれ固有のデータ（属性/プロパティ）と手続き（メソッド）があり、外部からのメッセージを受けてメソッドを実行し、データを操作する。
    - オブジェクトに付随するデータの操作は原則としてすべてオブジェクト中のメソッドによって行われる。オブジェクトを定義する雛形をクラス（class）、クラスに基づいてプログラム実行時にコンピュータのメモリ上に展開されたオブジェクトのことをインスタンス（instance）と言うが、実際上はインスタンスのことを指してオブジェクトと呼ぶことも多い。

### 1.3.4 リスト

- a[1: ] インデックスの1番目から最後まで取得
- a[ :3] 最初から3番目まで（3番目は含まない）
- a[ :-1] 最初から最後の要素の一つ前まで取得
- a[ :-2] 最初から最後の要素の２つ前まで取得

### 1.4.2 クラス

```
class クラス名: 
    def _ _ init _ _(self, 引数1, ...)  ←コンストラクタ(初期化用メソッド)
        ...
    def 関数1(self, 引数1, ...)
        ...
    def 関数2(self, 引数1, ...)
        ...
```


コンストラクタはnameという引数をとり、、以下省略。

### 1.5 Numpy

- NumpyはほとんどがC/C++で書かれているから処理速度が速い

### 1.6 Matplotlib

- グラフを描写するときはモジュールであるpyplotを使うのがいい。
- 画像表示はimread, imshow

# 第2章　パーセプトロン

- パーセプトロンとは、複数の信号を入力として受け取り、一つの信号を出力する。
- 入力信号は、ニューロンに送られる際に、送られてきた信号の総和が計算され、その総和がある限界値を超えた場合にのみ１を出力する。(発火するとも言う。)
- 重みは、入力信号への重要度を調節するパラメータ。バイアスは発火のしやすさを調整するパラメータ。
- グラフが直線形になる関数が線形関数で、そうでない関数が非線形関数です。
- XORゲートは単層のパーセプトロンでは表現できない。（だから前ページでは非線形関数を利用して表現した。）しかし、複数の層を重ねることでXORゲートは再現できる。
- XOR = (NAND + OR) → OR
- 層を重ねることでより柔軟な表現が可能になったパーセプトロンのことを、多層パーセプトロン(MLP)と呼ぶ。

# 第3章　ニューラルネットワーク

- MLPとNNの違い
    - MLPの重みを設定する作業、適切な重みパラメータをデータから自動で学習できるようにした。
    - 活性化関数の有無。入力信号の総和を出力信号に変換する関数。
- ステップ関数とシグモイド関数の共通点は非線形関数である。
- (重要)NNでは、活性化関数に非線形関数を用いる必要がある。線形関数を用いるとNNで層を深くすることが出来なくなる。h(x) = cxとするなら、h(h(h(x))) = c**3 x = axとなり、中間層の意味がなくなってしまう。つまり多層にして複雑化することが出来なくなるため、非線形関数を使う。
- NNの計算は、行列の計算としてまとめて行える。各層の計算は行列積(np.dot)で行うことで、一度の演算でできるのが良い。
- shape揃えてA1 = np.dot(X, W1) + B1からのZ1 = sigmoid(A1)で、入力層から第一層。(p.61に詳細)

### 手書き数字認識

- 機械学習は「学習」と「推論」と言う２つのフェーズから構成される。初めに訓練データ（学習データ）を使って重みパラメータの学習を行い、推論時には先に学習したパラメータを使って入力データの分類・回帰を行う。
- pickleモジュールは、プログラムの実行中のオブジェクトをファイルとして保存する機能。詳しくは、[https://qiita.com/hatt0519/items/f1f4c059c28cb1575a93](https://qiita.com/hatt0519/items/f1f4c059c28cb1575a93)
- NNにおいて、前処理はよく使われる。[https://www.jstage.jst.go.jp/article/cicsj/36/2/36_35/_pdf/-char/ja](https://www.jstage.jst.go.jp/article/cicsj/36/2/36_35/_pdf/-char/ja)
- バッチとは入力データのまとまりのこと。バッチ単位で推論処理を行うことで、計算を高速に行うことができる

# 第4章　NNの学習

- この章では、NNの学習方法を学ぶ。訓練データから最適な重みパラメータの値を自動で獲得するために、損失関数を設定しその値が最も小さくなるようにパラ探索すると言うことである。
- 特徴量とは、入力データから本質的なデータを的確に抽出できるように設計された変換器
- 損失関数を最小化させる = NNの性能が良くなる
- [https://atmarkit.itmedia.co.jp/ait/articles/2104/15/news030.html](https://atmarkit.itmedia.co.jp/ait/articles/2104/15/news030.html)(損失関数 種類)
- なぜ損失関数を指標に設定するの？認識精度を指標にすれば良くない？
    - 認識精度を指標にすると、パラメータの微分がほとんどの場所で0になってしまうから。
    - 前提として、NNの学習において「微分」は最適なパラメータを探索するための手段となる。NNの学習では、パラメータの勾配を計算し、その微分の値を手がかりにパラメータの値を徐々に更新することで、より小さな損失関数を探す事ができる。←勾配法につながる。
    - ↑認識精度はパラメータの微小な変化にはほとんど反応を示さず、もし反応があるとしてもその値は不連続にいきなり変化する。
- 勾配が示す方向は、各場所において関数の値を最も減らす方向。
- 勾配降下法は、損失関数の最小値を探すことを目的とし、現在地から勾配方向に一定の距離だけ進む→移動地で勾配を求める→その勾配方向に進むを繰り返す、最適化問題でよく使われる手法。
![スクリーンショット 2021-10-10 18.16.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626916/6f552277-b03b-8036-c101-a8da86b27c5b.png "勾配の数式")

- nは更新量、NNでは学習率(learning rate, lr)と呼ばれる。
- ハイパーパラメータと重みやバイアスなどのパラメータとは異なる。ハイパーパラメータは、人の手によって設定されるパラメータであり、これを繰り返し変更することでうまく学習するパターンを探す必要がある。
- まとめ: p112~
- 確率的勾配降下法(SGD)：ミニバッチとして無作為に選ばれたデータを使用して勾配降下法によってパラメータを更新する方法。
- 数値微分(微小な値を与えた時の差分によって微分を求めること)による計算では時間がかかる。そのため、NNでは誤差逆伝播法を使う。
- 1エポックとは、データセット全体をニューラルネットワークに1回与えて処理を行う事である。バッチサイズは1つのバッチ内に存在するトレーニング事例(training samples)の総数で、Iterations(反復)は、1つのエポックを完了するために必要なバッチの数。（参考サイト：https://webbigdata.jp/ai/post-9697）
- 6000個の訓練データがあって、600個×10回に分けて一回分の学習を行うとする。仮に50回学習を行わせるとすると、Epoch = 50で、1Epochに対してBatchsize = 600, Iteration = 10で行う。(参考サイト：https://zenn.dev/nekoallergy/articles/5c9c4ad0657073)


# 第5章　誤差逆伝播法

- 計算グラフを通じて「局所的な微分」を学び、逆伝搬によって「微分」を効率よく計算出来ることを学んだ。
- 「局所的な微分」を伝達する原理として連鎖律による。連鎖律とは合成関数の微分についての性質であり、"ある関数が合成関数で表される場合、その合成関数の微分は、合成関数を構成するそれぞれの関数の微分の積で表すことが出来る。"
- 加算ノードの逆伝播：そのまま次のノードに渡す
- 乗算ノードの逆伝播："ひっくり返した値"をかけて次のノードに渡す
- AddLayer, MulLayer, ReLU, Sigmoid
- AddLayerは何で初期化いらない？
- Affineレイヤ(全結合層)　[https://qiita.com/yuyasat/items/d9cdd4401221df5375b6](https://qiita.com/yuyasat/items/d9cdd4401221df5375b6)
- 「ソフトマックス関数」の損失関数として「交差エントロピー誤差」、「恒等関数」の損失関数として「２乗和誤差」を使うと、逆伝播が(y1 - t1, ..., yi - ti)となるようになっている。
- ミニバッチ→勾配の算出→パラメータの更新→...→ミニバッチ
- NNの構成要素をレイヤとして実装することで、勾配の計算を効率的に求める事ができる（Y = X・W + bみたいな順伝播ではなくて）
- forward_gradientとbackward_gradient両方書いてあるけど、基本的に誤差逆伝播法の実装だけでいいのかな？
- 学習では、順伝播・逆伝播。推論では、学習時のパラメータを基に順伝播。

# 第6章　学習に関するテクニック

- パラメータの更新、最適化問題(optimizer)
- Optimizerの種類はこれ([https://qiita.com/omiita/items/1735c1d048fe5f611f80](https://qiita.com/omiita/items/1735c1d048fe5f611f80))。でもそんないらないかも。
- 重みの初期値でNNの学習速度が変わる。
- 重みの初期値0はだめ！重みが均一になってしまう。
- 勾配消失問題とは、各層の勾配で小さい値が続いた場合、入力側付近の勾配はゼロと見なされてしまい、学習がうまく進まなくなってしまう問題のこと。(解決方法：[https://qiita.com/goroshigeno/items/bf7cb5602fb29ff055de](https://qiita.com/goroshigeno/items/bf7cb5602fb29ff055de))
- 各層のアクティベーションの分布は適度な広がりを持つのが良く、偏っていると勾配消失や表現力の制限が生まれ、学習がうまく行かなくなる。
- Batch Normalizationは強制的にアクティベーションの分布を調節する。やってることは単純でミニバッチの入力データ{x1, x2, ... , xn}を平均0, 分散1のデータ{x'1, x'2, ... , x'n}へと変換する(正規化)と言うもの。その処理を活性化関数の前(または後)に挿入することでデータ分布の偏りを減らす事ができる。
- ロバストになる = 依存しない、頑健である
- 過学習の原因は主に二つ。
    - パラメータを大量に持ち、表現性の高いモデルであること
    - 訓練データが少ないこと
- Weight decay, Dropout
- Dropoutはアンサンブル学習と同じ効果を疑似的に実現している
- 訓練データはパラメータ(重みやバイアス)の学習に利用する。検証データはハイパーパラメータの性能、つまりはモデルの精度や汎化性能を評価するために、テストデータは実証するために使う。
- NNのハイパーパラメータの最適化では、グリッドサーチよりランダムな探索な方がいい。最適な値が存在する範囲を徐々に絞り込んでいくのがいい。もっと洗練された手法はベイズ最適化らしい。
- NNは計算アルゴリズムで、DLは多層化したNNを利用した機械学習手法かな？

### 事前学習　（[AIcia Solid Projectさんの動画](https://www.youtube.com/channel/UC2lJYodMaAfFeFQrGUwhlaQ)）

- 畳み込み層は、内積と同じ計算をすることで画像の局所的な特徴(境界、線など)を抽出する。
- CNN登場以前は画像などのデータ構造をニューラルネットワークを用いて学習する場合、2次元のデータを平滑化して1次元のデータとして扱っており、2次元のデータが持つ重要な相関関係を無視した。
- CNNは画像という2次元のデータ構造を保ったまま特徴量を抜き出していくことで画像認識にブレークスルーを引き起こした。


# 第7章　畳み込みNN

- n層の全結合層によるNNは、{Affine+ReLU} * n-1, {Affine+Softmax} * 1みたいなイメージ。
- CNNは、Convolutional層 と Pooling層が鍵で、Affineに入る前に{Conv+ReLU+(Poo)}を重ねる。
- Affine層の問題点①：データの形状を無視する(１次元まで下げる必要がある)。これは全ての入力データを同等のニューロンとして扱うので、形状に関する情報を活かす事ができない。
- パラメータの共有とはフィルター演算におけるフィルターのことで、これが重みとなる。重みは全ての位置で同じ。
- パディングは周りを0で埋めるテク。出力データを調整するためで、入出力同じサイズで次の層へデータを渡す事ができる。
- ストライドはフィルターを適用する位置の間隔
- ３次元データの場合、チャンネル方向に複数の特徴マップがあるのでチャンネルごとに入力データとフィルターの畳み込み演算を行い、それらの結果を加算してひとつの出力を得る。入力データとフィルターのチャンネル数は同じ値にする。（p.216のブロックで考えるが分かりやすい）
- プーリングには、MaxやAverageがあるが、画像認識の分野ではMaxがよく使われる。
- プーリング層の特徴：「学習するパラメータがない」「チャンネル数は変化しない」「微小な位置変化に対してロバスト（頑健）」
- im2colによる展開 ([https://qiita.com/kuroitu/items/35d7b5a4bde470f69570](https://qiita.com/kuroitu/items/35d7b5a4bde470f69570))、全然分からんけど今は飛ばしてもいいかな
- im2col(input_data, filter_h, filter_w, stride=1, pad=0)
    - input_data - (データ数, チャンネル, 高さ, 横幅)
    - filter系 - filterの高さ幅
- CNNの可視化
    - 一層目の畳み込み層を通すと、そのフィルターが持つ特徴を反映・抽出した学習後データが出てくる。一層目ではエッジやブロフ(塊のある領域)などの低レベルな情報を抽出される。
    - ImageNetなどで学習したCNNでは、(既に述べたように) 各畳み込み層において入力に近い方から順に、「低レベル特徴(コーナーやエッジや色など)」=>「中レベル特徴(パーツ単位)」=>「パーツの組み合わせに相当する特徴(モチーフ単位)」=>「高レベル特徴（物体全体に対する物体検出器のような応答）」がそれぞれ学習されていることに（おおよそ）相当する。CNNを順伝搬すると、これらの階層的な学習済みカーネルの応答が組み合わされた各クラスが、識別結果として終盤のマップに応答が出現するという仕組みである。

# 第8章　ディープラーニング

特に書くことなし！

# 番外　モデル理解編
画像認識で代表的なモデルアーキテクチャについてまとめる。
モデルを理解する上で重要なことが３つある。

   1. どんなタスクを解いたのか
   2. どういうアーキテクチャだったのか
   3. 精度はどのくらいか


#### LeNet('89)（LeNet という語は、一般に、単純な畳み込みニューラルネットワークである LeNet5 を指す。）
  - タスク：手書き数字認識(16 * 16の手書き数字480枚, train:320, test:160)
  - モデル：下図
  - 精度：98.4%
  - 畳み込みを導入しパラメータを削減したこと、チャンネル数を増やしたことが重要だと主張されている。
  - 今の主流と比べて異なる点は、ReLUではなくシグモイド関数である、Maxプーリングではなくサブサンプリングによって中間データのサイズ縮小を行なっている。

#### LeNet5('98)
   - タスク：連続数字の認識
   - モデル：
![LeNet5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626916/3cfebf5e-c076-71a7-d98e-e4b4b7f046a3.png)

        

#### AlexNet(2012)
   - ILSVRC-2012
   - タスク：256*256のカラー画像1000分類(train:1.2M, valid:50K, test150K)
   - [モデル](https://medium.com/ran-ai-deep-learning/understanding-alexnet-4171b4b41996)
    ![AlexNet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626916/d3a5a31b-3e37-fe0b-b8b6-70479b0a07ad.png)
    - ↑なんで２列なの？＝並列計算している。
    - 「ReLUの利用」「Dropoutの利用」「GPUでの学習」「LRN(Local Response Normalization)という局所的正規化を行う層の利用」が革命！
    - AlexNetはCNNの層をシンプルに積み上げたmodel

#### VGG(2014 ILSVRC準優勝)[VGG16, VGG19とも言われる]
   - モデルはとてもシンプルな構造をしており応用性が高い。重みのある層を全部で16(19)層まで重ねてDeppにしている。3*3の小さな畳み込み層を連続で行なっているのが特徴。

#### GoogleNet(2014 ILSVRC優勝)
   - インセプションモジュール
   - ↑９回登場する。Network in Network。複数のフィルタサイズの畳み込みを同一の入力に対して行い結合する。
   - 相関のあるニューロン(発火応答が似ているもの)はまとめよ。
   - 1×1Convの意味＝「同じ位置のニューロンをまとめる。特徴量マップの縦横が同じで深さ方向にだけ伸び、内積とってまとめる。」+「パラメータ削減、情報圧縮」([https://qiita.com/minh33/items/98d78a8a5b03280b100b](https://qiita.com/minh33/items/98d78a8a5b03280b100b))
    - 3×3, 5×5Convの意味＝近くのニューロンをまとめる。


#### ResNet(2015 ILSVRC優勝)
   - degradationが問題（浅いモデルの方が性能良い）。
   - 数学的には深い方が表現力が豊かで性能がいいはず...。（→学習による最適化効率が良くない）
   - Residual Learning
   - Heの初期化
   - Batch Nomalization

#### ResNet以降
   - より層を深く、またはよりパラメータを少なくして精度を高めれるか.
   - どうやってアーキテクチャ作るの？
    - 自分で1から作ることは少ない。
    - 学習済みモデルを作っておいてFine-tuningが一番安全かな。