深層学習-後編1

ラピッドチャレンジで学習したことを忘れないように残そうかと。
はい。

#再帰的ニューラルネットワーク

## RNN
Recurrent Neural Network
時系列データに対応可能なニューラルネットワーク。
音声データや株価。

データの流れは
x入力、z中間層->z中間層(中間層の出力を中間層の入力として再び使う)... 、y出力

RNNは、前の層からの入力に対しても重みを加える。

初期の状態と過去の時間 t-1 の状態を保持する。
そこから次の時間での t を再帰的に求める。

### 準伝播の式

z : 中間層の状態
u, v : 活性化関数。
y : 出力

入力 x -> 活性化関数u() -> z ->活性化関数 v() -> 出力 y
$z^{t-1}$は前の中間層の出力として、下記式になる。

重みは3つある。

- 入力から中間層に至る重み ($W_{(in)}$)
- 中間層から出力に至る重み (W)
- 前の中間層から中間層に至る重み ($W_{(out)}$)

中間層の状態(z) を求める

```math
\begin {eqnarray}
u^t &=& W_{(in)}x^t + Wz^{t-1} + b\\
z^t &=& f(u^t)\\
&=& f(W_{(in)x^t + Wz^{t-1} + b})
\end {eqnarray}
```

出力(y) を求める

```math
\begin {eqnarray}
v^t &=& W_{(out)}z^t + c\\
y^t &=& g(v^t)\\
&=& g(W_{(out)}z^t + c)
\end {eqnarray}
```

## BPTT (RNNでのパラメータ調整方法)
Backpropagation Through Time
誤差逆伝播を使う。

RNNは3つ重みがあるので、ぞれぞれに対して微分する必要がある。
RNNの準伝播の式を覚えておきましょう。

Eをuで微分したものが、$\delta$

```math
\frac{\partial E} {\partial u} = \delta
```

右肩の T は時間を遡るという意味。

(1) $W_{(in)}$ で微分する。

```math
\begin {eqnarray}

\frac{\partial E}{\partial W_{(in)}}
= \frac{\partial E}{\partial u^t} \left [\frac{\partial u^t}{\partial W_{(in)}} \right ]^T
= \delta^t[x^t]^T\\
\end {eqnarray}
```

(2) $W_{(out)}$ で微分する。

```math
\begin {eqnarray}
\frac{\partial E}{\partial W_{(out)}}
= \frac{\partial E}{\partial v^t} \left [ \frac{\partial v^t}{\partial W_{(in)}} \right ]^T
= \delta^{out,t}[z^t]^T\\
\end {eqnarray}
```

(3) 前の中間層の出力に対する重み W で微分する。

```math
\begin {eqnarray}
\frac{\partial E}{\partial W}
&=& \frac{\partial E}{\partial u^t} \left [ \frac{\partial u^t}{\partial W} \right ]^T
&=& \delta^{t}[z^{t-1}]^T\\
\end {eqnarray}
```

(4)バイアスbで微分する。

```math
\begin {eqnarray}
\frac{\partial E}{\partial b}
&=& \frac{\partial E}{\partial u^t} \frac{\partial u^t}{\partial b}\\
&=& \delta^{t}\\

\frac{\partial u^t}{\partial b}
&=& 1
\end {eqnarray}
```

(5)バイアスcで微分する。

```math
\begin {eqnarray}
\frac{\partial E}{\partial c}
&=& \frac{\partial E}{\partial v^t} \frac{\partial v^t}{\partial c}\\
&=& \delta^{out, t}\\

\frac{\partial v^t}{\partial c}
&=& 1
\end {eqnarray}
```

(6) $\delta$ を計算しよう！

```math
\begin {eqnarray}
\frac{\partial E}{\partial u^t}
&=& \frac{\partial E}{\partial v^t}[\frac{ \partial v^t}{\partial u^t}]\\
&=& \frac{\partial E}{\partial v^t} \frac{ \partial \{ W_{(out)}f(u^t)+c \} } {\partial u^t} \\
&=& f'(u^t)W^T_{(out)}\delta^{out,t}\\
&=& \delta ^t\\
\end {eqnarray}
```

(7) 時間を1つ遡った$\delta$ は下記のようになる。

```math
\begin {eqnarray}
\delta ^{t-1} &=& \frac{\partial E} {\partial u^{t-1}} \\
&=&\frac{\partial E} {\partial u^{t}} \frac{\partial u^t} {\partial u^{t-1}} \\
&=& \delta^t \left \{ \frac {\partial u^t} {\partial z^{t-1}} \frac {\partial z^{t-1}} {\partial u^{t-1}} \right \} \\
&=& \delta ^t \{Wf'(u^{t-1}) \}\\
\end {eqnarray}
```

(8) 時間をz回分戻ると、$\delta$ は下記のようになる。

```math
\begin {eqnarray}
\delta^{t-z-1} &=& \delta^{t-z} \{ Wf'(u^{t-z-1})\}
\end {eqnarray}
```

(7)(8)を見ると時間的なつながりがあることを見て取れる。

## パラメータの更新式
重みは3つある。

(1) 入力層から中間層への重み
時間を遡るのでシグマがある。

```math
\begin {eqnarray}

W^{t+1}_{(in)}
&=& W^t_{(in)} - \epsilon \frac{\partial E}{\partial W_{(in)}}\\
&=& W^t_{(in)} - \epsilon \sum^{T_t}_{z=0} \delta^{t-z} [x^{t-z}]^T
\end {eqnarray}
```

(2) 中間層から出力層への重み
時間を遡る必要がないので、シグマがない。

```math
\begin {eqnarray}
W^{t+1}_{(out)}
&=& W^t_{(out)} - \epsilon \frac{\partial E}{\partial W_{(out)}}\\
&=& W^t_{(out)} - \epsilon \delta^{out,t} [z^t]^T\\
\end {eqnarray}
```

(3) 中間層から中間層への重み
時間を遡るのでシグマがある。

```math
\begin {eqnarray}
W^{t+1}
&=& W^t_ - \epsilon \frac{\partial E}{\partial W}\\
&=& W^t_{(in)} - \epsilon \sum^{T_t}_{z=0} \delta^{t-z} [z^{t-z-1}]^T\\
\end {eqnarray}
```

(4) バイアスb

```math
\begin {eqnarray}
b^{t+1}
&=& b^t_ - \epsilon \frac{\partial E}{\partial b}\\
&=& b^t - \epsilon \sum^{T_t}_{z=0} \delta^{t-z}\\
\end {eqnarray}
```

(5) バイアスc

```math
\begin {eqnarray}
c^{t+1}
&=& c^t_ - \epsilon \frac{\partial E}{\partial c}\\
&=& c^t - \epsilon \delta^{put, t}\\
\end {eqnarray}
```

(6) 誤差関数
t 時時刻の誤差関数は、下記のようになる。

```math
\begin {eqnarray}
E^t &=& loss(u^t, d^t)\\
&=& loss(g(W_{(out)}z^t +c), d^t)\\
&=& loss(g(W_{(out)}f(W_{(in)}x^t + Wz^{t-1}+b) +c), d^t)\\
\end {eqnarray}
```

$W_{(in)}x^t + Wz^{t-1}+b$ をさらに展開する。。。

```math
\begin {eqnarray}
W_{(in)}x^t + Wz^{t-1} + b
&=& W_{(in)}x^t + Wf(u^{t-1}) + b\\
&=& W_{(in)}x^t + Wf(W_{(in)}x^{t-1} + Wz^{t-2}+b) + b
\end {eqnarray}
```

f()の中に、$z^{t-2}$が存在するのがポイント。
zは中間層の出力。過去の時間を数珠つながりに扱っていることを示す。
おお〜。なるほど。。。

### RNNの課題
時系列を遡れば遡るほど、勾配が消失していく。
そのため、長い時系列の学習が難しい。

シグモイド関数を微分すると、入力値が0の時に最大値を取る。
その値は 0.25 だよ。

# LSTM
RNN の一種。
RNN の勾配消失をニューラルネットワークの構造自体を変えて解決したもの。
セル(CEC)とゲート(入力ゲート、出力ゲート、忘却ゲート)で構成されている。

【用語】
勾配爆発：逆伝播するごとに勾配が指数関数的に大きくなること。学習率を1/10とかにすると比較的すぐに発生する。

## CEC
記憶するだけのCECを導入する。
計算と記憶を中間層に任せていた。
時間を遡っても勾配がなくなったり、爆発無ければ良いだろうという。
→勾配が1であれば解決できる。


```math
\begin {eqnarray}

\delta^{t-z-1} &=& \delta^{t-z} \{ Wf'(u^{t-z-1}) \} = 1\\

\frac {\partial E} {\partial c^{t-1}} 
&=& \frac {\partial E} {\partial c^t} \frac {\partial c^t} {\partial c^{t-1}} \\

&=& \frac {\partial E} {\partial c^t}\frac {\partial } {\partial c^{t-1}} \{ a^t-c^{t-1} \}\\

&=& \frac {\partial E} {\partial c^{t}} 
\end {eqnarray}
```

CECは記憶するだけ。学習機能はない。
入力ゲート、出力ゲートと組み合わせて使う。

## 入力ゲート
CECにこんな感じで覚えてね！と教えてあげる。入力ゲートは覚え方を教える方法を学習する

## 出力ゲート
CECの覚えたものを、どうやって使えば良いか、学習する。

## 忘却ゲート
CECは過去の情報が全て保管する。
でも、過去の情報がいらなくなった時は忘れる必要がある。
(古すぎる情報に影響されてしまわない様にする)
CECに覚えているものを忘れさせる。

### 覗き穴結合
CECの保存されている過去の情報を任意のタイミングで他のノードに伝播させたり、任意のタイミングで忘却させる。
CEC自身の値に、重み行列を介して伝播可能にした構造。

### LSTMの誤差逆伝播
RNNと同じBPTTを使う。
RNNと比べてパラメータすうが4倍と多い。
勾配爆発を避けるため、勾配クリッピングを使うことがある。
(大きい勾配に対してノルムを閾値以下に正規化する)

# GRU
リセットゲート、更新ゲートがある。

LSTMはパラメータ数が多く(CEC, 入力ゲート、出力ゲート、忘却ゲートがある)、計算負荷が高くなる問題を解決したもの。
パラメータを大幅に削減し、精度は同等以上。

CEC, 入力ゲート、出力ゲート、忘却ゲートをなくし、リセットゲートと更新ゲートで構成する。

隠れ層に計算結果を保持する。
前回の記憶と今回の記憶の割合で計算する。

# 双方向RNN
過去の情報だけでなく、未来の情報を加味することで精度を向上。
未来の情報 = 文章作成の場合、生成する文章。過去の情報は作成済み文章。

【適用先】
- 文章の推敲
- 機械翻訳

# Seq2Seq
Encorder-Decorder モデルの一種
機械対話、機械翻訳に使用。
Encorder から Decorder に内部状態ベクトルを渡している。
これが鍵になる。

### Encorder RNN
自然言語での適用例は下記。

- Taking
    - テキストデータを単語などのトークンに分割してIDをつける。(one hot ベクトルにする)
    - 数万とかいうオーダーになる。
- Embedding
    - IDからトークンを表す分散表現ベクトルに変換する
    - 数百のオーダーになる。(似てる表現は似通った値にする。意味を抽出する感じ。)
    - RNNへの入力にする。
- Encorder RNN
    - ベクトルを順番にRNNに入力する。

Embedding が難しい。
Deep Learnigでは、MLM (Masked Language Model)がある。

### Decorder RNN
アウトプットデータをトークンごとに生成する。

- Decorder RNN
    - Encorder RNNの final state からtokenの生成確率を出力する。
    - final state をDecoder RNNの initial stateとして設定する。
- Sampling
    - 生成確率に基づいて tokenをランダムに選ぶ。
- Embedding
    - tokenをEmbeddigしてDecorder RNNへの入力にする。
- Detokenize
    - 上記をく理科絵師、tokenを文字列に直す。

#### Seq2seq の課題
一問一答しかできない。

### HRED
過去 n-1 個の発話から、次の発話を生成する。
Seq2seqは会話の文脈無視だったが、より人間らしい文章が生成される。
文脈の意味を取れる様にした。

HRD = Seq2Seq + Context RNN

#### Context RNN
Encorder のまとめた各文章の系列をまとめて、会話コンテキスト全体を表すベクトルに変換する構造。

### VHRED
HREDは同じ様な会話の流れ、回答も単純ものしかできない。

VHRED = HRED + VAEの潜在変数の概念

## オートエンコーダ
教師なし学習。
入力データは訓練データのみで、教師データは利用しない。
次元削減が行える。

Encorder : 入力データから潜在変数zに変換するニューラルネットワーク
Decorder : 潜在変数zをインプットにして、元画像を復元するニューラルネットワーク

## VAE
Variational auto-encoder
オートエンコーダーだと潜在変数zにデータを押し込めているが、構造がわからない。
潜在変数zに確率分布を仮定したもの。
オートエンコーダだと、いい感じに再現するためのデータしか持たないけど、似通ったものという概念ができる。

実際にはノイズを加えて、デコーダーに入力する。

# Word2Vec
単語をベクトルで表現する。
oneHotベクトルからに通ったベクトルに変換する。
変換表を機械学習で学習する。

RNNでは、可変長の文字列を扱えない。
学習データからボキャブラリを作成する。

#Attention Mechanism
Seq2seq は長い文章への対応ができない。
(隠れ層の数が決まっているため)

一番重要な単語を見分ける様にした。
2単語でも、100単語でも固定次元ベクトルの中に入力しないといけない。

入力と出力のどの単語が関連しているか、関連度を学習する。

時系列データの関連性に重みをつける。