離島プログラマの雑記

島根県の離島、隠岐・西ノ島に移住して子育て中のフリープログラマです。

ディープラーニングことはじめ

最近はやりの人工知能で注目されているディープラーニングですが、どんなものか良く知らなかったので本を一冊読んでみました。

TensorFlowなどのフレームワークをいきなり触るのはなんだか難しそうだなー、と思っていたところに「ゼロから作る」というコンセプトの本を見つけたので手に取りました。結論から言うとわかりやすくて良い本だったので、入門にはおすすめです。

読んでみて理解したことを備忘録として羅列しておきます。

必要な前提知識

数学

数学の知識としては行列と微分が分かればOKという感じです。行列や微分の定義についてもちゃんと説明されているので、なんとなく分かってる程度でも読み進めることはできます。そこそこ数式も出てきますが、Python のコードを動かしながら進んでいくのでそんなに躓くことはありませんでした。

プログラミング言語(Python)

Python はほとんど使ったことないですが、演算や関数の定義などから説明があるので、他の言語をかじっていれば問題ないレベルです。 多次元配列や行列の計算には NumPy という数値計算ライブラリを使うので、ややこしい演算などはライブラリ側でやってくれます。

理解できたこと

自分が理解した内容の覚書なので、間違っているところもあるかもしれません。 本ではもう少しアルゴリズムの実装寄りの話が詳細に説明されており、実際にコードを動かして手元で確認しながら進みます。

パーセプトロン

ニューラルネットワークのもととなるアルゴリズム。 以下の特徴がある。

  • 複数の信号を入力として受け取り1つの信号を出力する
  • 信号の総和がある閾値を超えると発火(=1を出力)
  • 入力信号に重みバイアスというパラメータを設定
    重み
    各入力信号の重要性をコントロールするパラメータで。各入力信号にそれぞれの重みを乗算する。
    バイアス
    ニューロンの発火しやすさをコントロールするパラメータ。重みを乗算した入力信号の総和にバイアスを加算する。
  • 重みとバイアスを調整することで AND、NAND、ORのような単純な論理回路を表現できる

単層のパーセプトロンでは非線形な表現(XORゲートなど)ができない。
パーセプトロンを重ねることで非線形表現ができる

ニューラルネットワーク = 多層パーセプトロン

パーセプトロンの出力を次のパーセプトロンの入力信号とすることで、多層化することができる(多層パーセプトロン)。 多層化により、XORゲートなどの非線形表現が可能になる。 ニューラルネットワークは多層パーセプトロンとほぼ同じで、以下の特徴を持つ。

  • 入力層、中間層(隠れ層)、出力層に分類される層からなるニューロンのネットワーク
  • 各層には複数のニューロンが存在し、入力層〜中間層(1層以上)〜出力層の順に信号を伝達する(順方向伝播)
  • ある層の各ニューロンが出力する信号は、次の層の各ニューロンの入力となる
    • 例えば、ある層に存在する2つのニューロンの各出力(x1, x2)と重み(w)の和にバイアス(b)を足した値が、次層の3つのニューロン(y1, y2, y3)にそれぞれ伝播する
    • ニューロンから次層のニューロンへの各経路には、それぞれ異なる重みを設定する
    • 重み付き入力信号とバイアスの総和には活性化関数(h)を適用する
    • x1 → y1、x1 → y2 などの経路ごとに重みが違うため、y1, y2, y3 のニューロンへの入力はそれぞれ異なった値となる
      • y1 = h(x1 * (x1 → y1の重み) + x2 * (x2 → y1の重み) + b)
      • y2 = h(x1 * (x1 → y2の重み) + x2 * (x2 → y2の重み) + b)
      • y3 = h(x1 * (x1 → y3の重み) + x2 * (x2 → y3の重み) + b)
  • 活性化関数 入力信号の総和を出力信号に変換する関数 = 活性化関数 → 閾値を境にして出力が切り替わる性質を持ち、非線形関数である必要がある

出力層の設計

機械学習は分類問題と回帰問題に大別されるが、ニューラルネットワークはどちらにも使える。 出力層の活性化関数は問題に合わせて使い分ける必要がある。

  • 出力層の活性化関数
    • 恒等関数 → 回帰問題
    • シグモイド関数 → 2クラス分類問題
    • ソフトマックス関数 → 多クラス分類問題
      • 出力の総和が1になる = 確率として解釈可能
      • 出力層のニューロン数 = 分類したいクラスの数

ニューラルネットワークの推論(順方向伝播)

MNIST データセットを例に推論処理を実装する。

  • MNIST データセット
    • 0ら9までの手書きの数字画像
    • 訓練画像60000枚、テスト画像10000枚を含む
    • 画像データは 28 x 28 のグレー画像(256階調)
    • 各画像には対応するラベルが与えられている

ニューラルネットワークの設計は以下のようにする。

  • 前処理
    • ピクセルの値を 255 で除算(0.0〜1.0の範囲に正規化)
  • 入力層
  • 中間層(隠れ層)
    • 層の数やニューロン数は任意
      • 2つの隠れ層で、1層目が50個、2層目が100個、など
  • 出力層
    • ニューロン数 = 分類するクラス数
      • 10クラス(数字の0から9)に分類 = 10個
  • バッチ処理
    • NumPyなどの数値計算ライブラリは配列の計算を効率良く処理できるように最適化されている
      • 入力データをまとめて処理(バッチ処理)すると効率が良い
      • 入力データから100枚ずつ取り出してNumPy配列として処理する(NumPy配列の演算は配列のすべての値に適用される)

ニューラルネットワークの学習

特徴量 + 機械学習のアプローチでは問題に応じた(人力での)特徴量の設定が必要だが、ニューラルネットワークでは特徴量も機械が学習する。 ニューラルネットワークでは損失関数の値が小さくなるように最適なパラメータ(重みとバイアス)を探索する。

ニューラルネットワークでは、パラメータ解空間の探索方法として勾配法(確率的勾配降下法 = SGD)がよく用いられる。

  • 勾配法
    1. 偏微分により現在のパラメータにおける損失関数の勾配を求めて、最小値の方向を予測する
    2. 勾配から予測した最小値の方向へパラメータを更新する(移動する量 = 学習率)
    3. 1と2を繰り返して最小値へ向かって降下しながら、最小値を探索する

ただし、勾配が指す方向に必ず最小値があるとは限らない(極小値の可能性が高い)。 また、数値微分による勾配の計算は非常に時間がかかる。
誤差逆伝播(バックプロパゲーション)による勾配算出の高速化

誤差逆伝播法については、簡潔に説明するのが難しいので省略しますが、数値微分より大幅に少ない計算で勾配を算出できます。
本では一章丸々使って、計算グラフという表現方法で説明されています。

学習のテクニック
  • パラメータの更新方法
    パラメータの更新方法は学習の効率に大きく影響する。
    • SGD
      • シンプルだが関数の形状によっては探索が非効率
    • Momentum
      • 物理法則に従ってパラメータの移動場所を決める(お椀にボールを転がすイメージ)
    • AdaGrad
      • 学習率を徐々に減衰させる
    • Adam
      • Momentum + AdaGrad
  • 重みパラメータの初期値
    重みパラメータの初期値はモデルの表現力や学習の効率に大きく影響する。
    • Xavier の初期値
    • He の初期値
      • 活性化関数が ReLU の場合に特化した初期値
  • 過学習対策(正則化)
    • Weight decay(荷重減衰)
      • 大きな重みに対してペナルティを課す
    • Dropout
      • 訓練時に隠れ層のニューロンをランダムに消去しながら学習する
      • 実質的に複数のモデルに個別に学習させた平均をとることと同義なので、アンサンブル学習に類似
  • Batch Normalization
    • 2015年に提案された新しい手法
      • 学習の効率が良い
      • 初期値に依存しにくい
      • 過学習の抑制
    • 重みのパラメータの分布を強制的に分散させる
      • 活性化関数の前か後にデータ分布の正規化処理を行う
  • ハイパーパラメータの検証と最適化
    • 自動で学習できない(手動で設定する必要がある)パラメータ = ハイパーパラメータ
      • 各層のニューロン
      • バッチサイズ
      • パラメータ更新の学習率
      • Weight decay 係数
      • その他手法に応じて設定が必要なもの
    • 検証方法
      • ハイパーパラメータがテストデータに対して過学習を起こさないように、ハイパーパラメータ調整用の検証データを用意して検証
        • 訓練データから一部分離するなどして検証データを用意しておく
    • 最適化方法
      • ハイパーパラメータはモデルの認識精度で評価する
      • 試行を繰り返しながら良い値の範囲を絞り込んでいく
畳み込みニューラルネットワーク(CNN)

前述のニューラルネットワークでは全結合層を用いていたため、データの形状は無視されていた。 CNN ではデータの形状を維持する畳み込み層とプーリング層が追加される。 多段の畳み込み層では、前層の情報を元に段階的に高度な情報を認識することができるため、画像認識等の精度が向上する。

  • 畳み込み層

    • 入力データに対してフィルターを適用する
      • 入力データとフィルターの要素を乗算して和を求める(積和演算)
      • 3次元データ(奥行き = チャンネル方向が存在する)の場合、チャンネル毎に畳み込み演算した後、結果を合算して1つの出力を得る(チャンネルは1つになる)
    • パディング
      • 入力データの周囲に固定データを埋め込むことで、出力サイズを調整する
      • パディングを大きくすると出力サイズは大きくなる
    • ストライド
      • フィルターを適用する位置の間隔
      • ストライドを大きくすると出力サイズは小さくなる
  • プーリング層

    • 学習するパラメータがない
    • チャンネル数が変化しない

ディープラーニング(= 多層構造のニューラルネットワーク)

層を深くした多層構造のニューラルネットワークディープラーニングと呼ばれている。

  • 層を深くする意味
    • 理論的にはあまり分かっていないが、実践的には意味のある結果が出ている
      • (コンペティションの結果から)層が深まるほど認識精度が向上している
      • 層を深くすることで、パラメータ数を少なくできる
      • 層を深くすることで、学習データを少なくできる(=学習が高速化する)  
  • ディープラーニングの実装

  • 高速化

  • 実用例

    • 物体検出
      • R-CNN
    • セグメンテーション
      • FCN (Fully Convolutional Network)
    • 画像キャプション生成
      • NIC (Neural Image Caption) = Deep CNN + RNN (Recurrent Neural Network)
    • 画像スタイル変換
    • 画像生成
      • DCGAN (Deep Convolutional Generative Adversarial Network)
    • 自動運転
      • SegNet
    • Deep Q-Network (強化学習)