ラビッドチャレンジで勉強したことを残します。
はい。
深層学習を入力・出力の目的で分類
大きく2つに分類できる。
- 識別モデル
確率的にどれに分類できるか
(高次元->低次元)
- 生成モデル
学習したデータをもとに、データを作り出す。
(低次元->高次元)
画像の高解像度化、テキスト生成
識別器の開発アプローチ
3つに分けられる。
-
生成モデル
計算量が多い。現実のデータを推定する。 -
識別モデル
識別結果の確率を得る。
間違いの程度を測ることができる。 -
識別関数
入力データから識別結果を一気に得る。
間違いの程度はわからない。
深層学習
中間層が4つ以上のNNを深層ニューラルネットワークと呼んでいる。
入力層〜中間層
(1)要点
入力層:入力(x), 切片(b)
入力(x),重み(w),切片(b) を使って出力した結果が中間層の入力になる。
中間層:中間層への入力を活性化関数を使って出力する。
下記のようなデータは入力層として取るべきでないデータ。
- 欠損値が多い
- 誤差が大きい
- 出力地そのもの、出力を加工した情報
- 連続性のないデータ
- 無意味な数が割り当てられているデータ
データが不足しているときに、人工的にデータを作って水増しする。(データ拡張)
例えば、フィルタをかけた画像(元データに加工を加えた画像)を学習データとして使う。
データ拡張すると、しばしば、劇的に汎化性能が向上する。
(2)サマリと考察
中間層を複数いれることで、入力から分類する確率を計算することができる。
重み、切片(バイアス)がやはり大切。
活性化関数
(1)要点
線形な関数と非線形な関数に分けられる。
また、中間層用と出力層用に分けられる。
- 中間層用の活性化関数
入力値をいい感じの値に変換する。
ReLU関数
シグモイド(ロジスティック)関数
ステップ関数
(2)サマリと考察
使用する関数の特性により、問題点がある。
ReLu関数使うと良さそう。
出力層
(1)要点
中間層の出力値に対して、活性化関数と誤差関数を使う。
- 誤差関数
NNで計算した値と訓練データ(人間がつけた値)で学習した値と比較して誤差を出して一致する確率を出す。
最も確率が高いものに分類する。
その誤差を算出する関数の事。
回帰問題は「二乗誤差」を使う。
分類問題は「クロス(交差)エントロピー誤差」を使う。
クロスエントロビー誤差は本当によく使う。
クロスエントロピー誤差
E_n(w) = -\sum_{i=1}^Id_ilogy_i
- 出力層用の活性化関数
抽出した値を扱いやすい値に変換するために使う。
0〜1の確率として扱えるようにする。
ソフトマックス関数 (3種類以上の分類をするときに使用する)
恒等写像
シグモイド(ロジスティック)関数
(2)サマリと考察
回帰・分類で使用する定番の誤差関数がある。
活性化関数も、実施したい分類により、定番の関数がある。
どの方式を使っても、定番関数を使えばそれなりの結果が得られるというのは、少し意外だった。
勾配降下法
(1)要点
w, b を最適な値にする方法。
誤差関数の出力値を元に重み、バイアスを繰り返し調整していく。
【勾配降下法】
全サンプルを使って学習する。
(バッチ学習)
w^{(t+1)} = w^{(t)} -\epsilon \nabla E
$\epsilon$ は学習率と呼ぶ。
【確率的勾配降下法】
全データのうち、ランダムにデータを選択して学習する。
(オンライン学習)
w^{(t+1)} = w^{(t)} -\epsilon \nabla E_n
実際のアルゴリズムは Adam がよく使われる。
【ミニバッチ勾配降下法】
全サンプルをランダムに分割して、分割したかたまりごとに、学習する。
確率的勾配降下法のメリットを損なわず、計算資源を有効利用できる。
スレッド並行化や、GPUを使ったSIMD並行化ができる。
w^{(t+1)} = w^{(t)} -\epsilon \nabla E_t
(2)サマリと考察
機械学習の章で学習したことが、ようやく繋がった。
手計算をする分には確率的勾配降下法が感覚を掴むためには良いと思う。
実際に実装するときは、ミニバッチ勾配降下法がいいんだろうなと。
誤差伝搬法
(1)要点
- 誤差逆伝播法
算出された誤差を前の層に伝搬させる。
不要な再帰的計算を避けて効率的に計算ができる。
重みとバイアス(切片)に反映していく。
(2)サマリと考察
誤差逆伝播法を使用する理由がわかった。
効率的なのね。。。
勾配消失問題
(1)要点
学習の過程で誤差逆伝播が階層に進んでいくと、勾配がどんどん緩やかになって、パラメータがほとんど変わらなくなってしまう事象のこと。
結果、最適値に収束しなくなる。
シグモイド関数使っていると発生することがある。
【対策】
-
活性化関数の選択
ReLu関数を使う。
後輩消失問題の回避と、スパース化に貢献する関数。 -
重みの初期値設定
-
Xavier の初期値
重みの要素を前の層のノード数の平方根で除算した値を使う。
下記関数向け。- Relu関数
- シグモイド関数
- 双極線正接関数。
-
He の初期値
重みの要素を、前の層のノード数の平方根で除算した値に対し、$\sqrt{2}$ を掛け合わせた値。
Relu関数むけ。
-
<Heの初期値> = <Xavier の初期値> \times \sqrt{2}
- バッチ正規化
データを塊(ミニバッチ単位)に分けて、入力値のデータの偏りを抑制する。
活性化関数に値を渡す前後で適用する。
必要な機材はCPU, GPU, TPU(AI専用)を使って実施する。
画像の場合、一般的には1バッチあたり、下記の枚数。
HW制限で2の倍数または8の倍数を適用することが多い。
GPU : 1〜64枚
TPU : 1〜256枚
【メリット】
中間層での学習が安定する。
過学習が起きづらくなる。
【数学的記述】
最終目標は $y_{ni}$ を求めたい。
(1) ミニバッチの平均を求める
\mu_t = \frac{1}{N_t} \sum_{i=1}^{N_t}x_ni
(2) ミニバッチの分散を求める
\sigma_t^2 = \frac{1}{N_t} \sum_{i=1}^{N_t}(x_ni -\mu_t)^2
(3) ミニバッチの正規化をする
\hat{x}_{ni} = \frac {x_{ni} - \mu_t} {\sqrt{\sigma_t^2 + \theta}}
(1)〜(3)は通常の統計的な計算ですよ。
(4) 変倍・移動する。(処理しやすいようにする)
y_{ni} = \gamma {x_{ni}} + \beta
(2)サマリと考察
活性化関数によって、適切な初期値が異なるようだ。
自分でやるときは、ReLu関数を使用するようにしようと思う。
学習率最適化手法
(1)要点
学習率は大きくても小さくても良くなく、ちょうどいい感じが必要。
大きいと発散する。
小さいと収束に時間がかかる。または、局所解にトラップされてしまう。
職人技ですね。。。ではなく、最適化手法がちゃんとあります。
最初は学習率を大きくし、徐々に小さくする感じでやっていきたい。
Adamが最近、よく使われる。
次のページがわかりやすく説明されている。
モメンタム
「慣性」という概念が出てくる。
前回の重みを考慮した計算をする。
過去の勾配の指数関数的減衰平均。
- 大域的最適解を求めたい。
- 谷間についてから最適解に行くまでの時間が短い
- 勾配降下法よりなめらかに収束していく。
V_t = \mu V_{t-1} - \epsilon \nabla E \\
w^{(t+1)} = w^{(t)} + V_t
勾配降下法の式に、$\mu V_{t-1}$を足したもの。
$\epsilon$ : 学習率
$\mu$ : 慣性。事前に決めておく。
$V_t$ : 前回の重み
AdaGrad
- 勾配の緩やかな斜面に対して、最適値に近づける。
要するに勾配が大きいときは学習率を大きくし、勾配が小さくなるにつれて学習率を小さくする。 - 学習率が徐々に小さくなるので、鞍点問題を引き起こすことがある。
w^{(t+1)} = w^{(t)} - \eta \frac{1}{\epsilon + \sqrt{h_t}} \nabla E\\
h_0 = \theta \\
h_t = h_{t-1} + (\nabla E)^2 \\
$\epsilon$は発散を防ぐ微少量
$\theta$ をうまく調整してあげる必要がある。
RMSProp
AdaGrad の進化系。鞍点問題を解決したロジック。
AdaGradの欠点である、単調な学習低下を改善。
過去の勾配の2乗の指数関数的減衰平均
- 大域的最適解になる。
- ハイパーパラメータの調整が必要な場合が少ない。
w^{(t+1)} = w^{(t)} - \eta \frac{1}{\epsilon + \sqrt{h_t}} \nabla E\\
h_t = \alpha h_{t-1} + (1 - \alpha) (\nabla E)^2 \\
$\alpha$は過去の勾配による影響を抑え、$h_t$を優先させて反映させる効果を狙っている。
過去の全ての勾配の平均ではなく、指数移動平均を採用している。
Adam
- モメンタムとRMSPropのメリットを持つ。
(2)サマリと考察
Adam を適用するのが一番良さそう。
でも、場合によるのかなぁ。。。
学習率最適化法をまとめてみた
過学習
(1)要点
学習済みデータだと正確な結果が出せるけど、未知のデータに対しては正しい結果が出せない。
小さなデータ - 巨大なネットワークだと起きやすい。
自由度が大きいと発生しやすい。
テスト誤差と学習誤差を比較することで過学習しているか否かわかる。
正則化する。(自由度を制限する。)
過学習が発生する状況】
Weight decay (荷重減衰)
重みが大きい値になると、過学習が発生することがある。
$\rightarrow$ 誤差に対して正則化項を加算して、重みを抑制する。
過学習が起こりそうな重みの大きさ以下にコントロールして、重みの大きさにばらつきを出す必要がある。
【過学習を防ぐ具体的な方法】
L1, L2正則化
誤差関数に、pノルムを加える。
E_n(w) + \frac{1}{p}\lambda ||x||_p\\
||x||_p = (|x_1|^p + ... + |x_n|^p)^{\frac{1}{P}})
$\lambda$はハイパーパラメータ。
p=1 : L1正則化 (Lasso推定量, スパース推定)マンハッタン距離を使う。
ReLu関数に近い効果が得られる。よくある図の四角の方。
グラフで横方向が 0 になる点を求める。
p=2 : L2正則化 (Rige推定量, 縮小推定)ユークリッド距離(2乗)を使う。
よくある図の丸い方。
ドロップアウト
ノードの数を減らす方法。
ランダムにノードを削除して学習させる。
シンプルな割に効果が高い。
(2)サマリと考察
過学習を起こさないように、学習させるデータセットに何を使うか、学習の仕方の工夫が必要。
それ以外にも、正則化という方法がある。
何にでも解決方法があるわけです。はい。
畳み込みニューラルネットワークの概念
(1)要点
非常に汎用性の高いNN。
- 次元間で繋がりのあるデータを扱える。
畳み込み層は、3次元の空間情報も学習できる層。
入力画像にフィルタ(重み)をかけて出力値とする。
-
畳み込み層
4x4の画像に対して、3x3を読み込む(3x3 のフィルタをかけて1つの出力を得る)。
→ 4x4 の出力になる。
少しずつずらして出力を研鑽するので、隣のデータを考慮した出力にできる。- バイアス
<入力画像> * <フィルタ> + <バイアス> = <出力値> - パディング
畳み込みをしていくと、画像サイズが小さくなる。出力が適切なサイズになるように事前に、入力画像の周囲にデータをパディングしておく。 - ストライド
ストライドの値だけ、ずらしていく。 - チャンネル
- バイアス
-
プーリング層
畳み込み層と組み合わせて使われる。
重みは使わな。
ずらしながら画像を読み出す。
対象領域のMax値または平均値を出力値とする。
(2)サマリと考察
フィルタとスライド、値の計算方法がポイント。
CNNが次元や時系列を考慮できる理由がわかった。
なるほど。
最新のCNN
(1)要点
最新とは言えないけど。。。AlexNet
5層の畳み込み層とプーリング層、それに続く3層の全結合層から構成される。
入力:[13x13]x256
Fratten : 13x13x256 のデータをそのままデータとして使う。
Global Max Pooling:[13x13]から最大の値を256個選ぶ
Global Average Pooling:[13x13]の平均の値を256個選ぶ
(2)サマリと考察
CNNについて、理解ができた。
総括
実際にプログラムを動作させると、感覚が掴めていい!