ディープラーニング入門への最小知識

# この記事について
* 想定する最低知識: 微分とかがかろうじて思い出せるといいですが、細かい説明はしないので多分大丈夫です
* 読んだ後のゴール: [ブラウザで試すディープラーニング入門](https://qiita.com/ozota/items/b5ae799635c7d479a4b8)がかろうじて分かる
* 厳密な言い回しより、何となく分かるフレーズを多用します
* 私が今まさに入門中なので間違ってたらすいません


# ディープラーニングとは
機械学習と呼ばれる手法の１つです
## 機械学習とは
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/b3713048-9455-8f2a-a9f3-4f8de55f4da5.png)

* データを学習させてAIを生成します
* 例えば猫画像を判定するAIを作る場合、大雑把に次のようになります
  * 猫の画像を集める
  * 学習プログラムに猫画像を入れる
  * 猫画像判定AIが生成される 

* 学習のさせ方や生成されるAIの構造には様々なものがあります
* 機械学習のうち、生成されるAIが「ニューラルネットワーク」という構造になる方法がディープラーニングです
* なのでまずは「ニューラルネットワーク」について解説します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/cbe2ab27-99d4-074a-baed-5d512b527207.png)

# ニューラルネットワークとは
* 「単純パーセプトロン」というものを組み合わせたものです
* なので、先に単純パーセプトロンの解説をします
 
### 単純パーセプトロンとは
* 単純パーセプトロンとは、n個の入力から1つの出力を計算するものです。
  * 各入力に重みを掛け、その結果を足し合わせます
  * 出力結果に活性化関数というものを適用します
      * 単純パーセプトロンでは活性化関数は次の計算をする「ステップ関数」です
          * 閾値以上 ⇒ 1
          * 閾値より小さい ⇒ 0 
* よく次のような図で表されます。  
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/7bf8739a-c445-0f3b-160c-0dfc39e313c7.png)
    * この図は次を表します
        * 入力: $x_1,x_2,...x_N$
        * 重み: $w_1,w_2,...w_N$ 
        * 閾値: $θ$
        * $x_1*w_1+x_2*w_2+...+x_N*w_N$ について
          * $θ$以上　⇒ 出力$y=1$
          * $θ$より小さい　⇒ 出力$y=0$

#### 単純パーセプトロンの例
* ANDを表す単純パーセプトロン  
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/1ecad37c-b551-9da2-2821-0a336efc34df.png)
  * $x_1,x_2$は0か1の値をとる
  * 重みは2つとも1
  * 閾値は1.5
  * $x_1+x_2$は入力が両方1の時のみ閾値1.5を超えるので、両方が1の時のみ出力も1。すなわちAND

#### 単純パーセプトロンを組み合わせる
* XORは単純パーセプトロンでは作れないことが知られています
* しかし単純パーセプトロンを組み合わせると作れます  
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/5f05f6e3-9e27-37e8-b08a-6858fc51e18b.png)

* 沢山組み合わせるともっとすごいことが出来るようになります

## 再び、ニューラルネットワークとは
* 単純パーセプトロンを組み合わせたものです
* ただし、活性化関数はステップ関数以外にも様々なものを選べます
* 何層にも重ねることができますし、出力も複数にできます  
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/fbb9d121-87ac-1929-fffc-d52ce3a326bd.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/50592651-3191-b9f3-206e-a764c6929cca.png)

* 例えば、手書き数字画像から書かれている数値を判定するニューラルネットワークの場合
  * 入力は画像を1次元配列に変換したもの
  * 出力は要素数10の1次元配列。値が1となるインデックスが判定結果
      * `output[2] == 1`のときAIが画像を2と判定したことになる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/62bc9d08-a20a-b7c3-679e-2ac9d83dc29b.png)

* 各層ごとに重みがあるので、層が増えると重みは大量にあります

* このニューラルネットワークの重みをうまいことデータから自動で導き出すのが学習です 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/eeff1ad2-679e-f4e7-8e0e-8768fe31393d.png)

# 学習とは
* ニューラルネットワークの重みを導出する方法です
* 学習データと期待される答えを元に、最適な重みを見つけ出します
  * 重みを少しずつ変化させながらニューラルネットワークの判定結果が期待される答えに近づく値を探します
  * 最初は手掛かりがないので、ランダムな重みで初期化します
* 次の損失関数と重み更新アルゴリズムを組み合わせます
  * 損失関数も重み更新アルゴリズムもライブラリで隠蔽されているのでチュートリアルを流す上では細かい理解は不要です
* 注意：学習の前にすでにネットワークの構造（層の数、入力の数、出力の数）は決まっています
  * 学習で求まるのは重みの値です
  * ネットワークの構造をモデルと呼んだりします

## 損失関数とは
* 入力した値とニューラルネットワークの出力を比べて、どれだけ間違えているかを表す関数です
  * 値が大きいほど間違えています
* 学習とは損失関数が最小になるような重みを探すことと言い換えられます
* 損失関数には次のようなものがあります。
  * 二乗誤差
      * ニューラルネットワークの出した答えと求められる答えの差の2乗を足し合わせたものです
  * クロスエントロピー
      * 私の説明能力を超えるので[ここ](http://cookie-box.hatenablog.com/entry/2017/05/07/121607)を参照してください
      * 中身は知る必要はなく、「誤差が大きいときに学習の速度が速い」、「分類するAIでよく使う」ぐらいに思えばいいと思われます

## 重み更新をどうするのか
* 重みをどう変化させると損失関数が小さくなるのかを知る必要があります
* そこで微分をします。各重み変数で損失関数を微分し、微分結果をもとに損失関数が小さくなるような重みの変化を求めます
  * 変化させる大きさを学習率といいます。微分結果にかけ合わせます
  * 微分結果のことを勾配といいます
  * 細かいやり方はいくつかあるのですが、次の確率的勾配降下法(SGD)だけ取り上げます
      * ランダムに学習データを1つ選んで損失関数を計算し、その勾配方向にパラメータを修正することを繰り返す   
* 各重みの勾配を計算することをバック・プロパゲーションといいます
  * 計算の都合上、出力側の層の重みから導出していき、最後に入力側の重みを導出するという逆順の作業になるためそう呼ばれます

## 学習のまとめ
* 次をすればよいことになります
  * 損失関数を設定する
  * 重み更新アルゴリズムを設定する
  * 次をAIの判定精度が十分になるまで繰り返す
      *  ニューラルネットにデータを入力する
      * 出力と期待される結果を元に損失関数の勾配を計算する
      * 勾配を元に重みを更新する

# まとめ
* ディープラーニングはニューラルネットワークを生成する方法です
* ニューラルネットワークは単純パーセプトロンを組み合わせたものです
  * 何層にも重ねられます
* 各層の重みを導出するのが学習です

* [ブラウザで試すディープラーニング入門](https://qiita.com/ozota/items/b5ae799635c7d479a4b8)で実際にAIを作ってみるとわかりやすいと思います  

# 補足
* ディープラーニングとGPUについて
  * GPUはもともとグラフィック用の処理をするものでした
  * GPUは行列演算が得意です
  * 学習は内部で行列演算を多用しており、GPUを使うと学習も速くなります
  * GPUなしと比べて30倍ほど速くなります

# 外部サイト
[参考にしたサイト](http://hokuts.com/2015/11/25/ml2_perceptron/)
[ニューラルネットの画像を借りたサイト](http://nkdkccmbr.hateblo.jp/entry/2016/10/06/222245) 
[いらすとや](https://www.irasutoya.com/)