ソフトウェアエンジニアの勉強ログ

興味があるのは、computer vision, three.js, python, 深層学習, emacs

深層学習の超基礎知識を勉強した(ニューラルネットワークの学習)

  • 「ゼロから作るDeep Learning」の4章「ニューラルネットワークの学習」を読んで勉強したときの自分用メモです
    • 実際にPythonを走らせて、手を動かす勉強はまだ
  • 認識の大雑把な変遷
    1. 昔は人が全て設計
    2. 一時期は、SIFT + SVMなどが流行った
    3. 全てニューラルネットで行うのが現在流行っている
      • 深層学習の真骨頂は、「end-to-end」な学習
      • 生データから目的の結果を得るということ
      • とはいえ、データの前処理の重要性はかなりのウェイトを占めている印象
  • 機械学習は、汎化能力が大事で、訓練データではないテストデータで、性能を評価する
  • 基本的には損失関数で学習を行う
    • 例えば、正解率が80%のような「認識精度」を直接上げるようにしない理由
      • 認識精度が改善されたとしても、(テストデータが整数なので)離散値になってしまう
        • 連続値でないと微分を使って学習を行う、機械学習の枠組みと相性が良くない
      • 私見だが、明らかに、一回一回のテストデータでフィードバックが入ったほうが、効率が良い
    • 個人的には、強化学習の枠組みでは、どちらかという「認識精度」を上げるように学習するイメージに近い
      • どのように性能を上げるかについては、今は不明なので将来的に勉強する
  • 損失関数は主に、2乗和誤差と交差エントロピー誤差がある

    • 多分、出力層がソフトマックスなため、総和が1.0に正規化されていることが重要?
    • 2乗和誤差  \displaystyle E = \frac{1}{2}\sum_{k}(y_k - t_k)^2
    • 交差エントロピー誤差  \displaystyle E = - \sum_{k}t_k log y_k
      • tが0 or 1で、0 <= y <= 1なので、-∞ < logy <= 0であることがポイント。正解ラベルに対する結果yが0に近いと、損失が非常に大きいという特徴がある
      • 正解ラベル以外は気にしなくて良いので、多分こっちの方が好まれているのではないか?と思う
  • ミニバッチ処理

    • ある程度まとめた訓練データ、例えば100個にまとめたデータを基に学習を行うという話
    • 詳しくは書かれていないが、多分 n^2とかそういう指数オーダーで、計算量が増えてしまうので、全ての訓練データをまとめて計算するのは現実的でないため
  • ただし、個人的な見解では、ミニバッチは小さすぎてはいけない
  • 以下、そう思う理由

    • 後述するが、結局微分をといて学習をといている、つまりある訓練データあったときに、(嘘を恐れずいえば)
      1. まず現在のパラメータ(重み)を使って損失計算をする
      2. 暫定的にあるパラメータに着目して、ちょっとだけ値を変える(+h)
      3. 損失計算を再計算
      4. 損失関数の変化からそのパラメータ(重み)を大きくしたほうが良いのか小さくした方が良いのか判断する
    • という流れになるが、ここで、(パラメータがかなり多く冗長であるので)あるデータ1に対しては大きくしたほうが良いが、他のデータ2〜10に対しては小さくした方が良いということが多発する。
    • ミニバッチをある程度大きさのデータとすることで、全体としてはパラメータを小さくしたほうが良いという見解が得られる
    • 機械学習の常識はわからないが、少なくともLM法などで数値的に非線形問題を解くときに、冗長性は敵である(解が見つからない!)
  • 勾配法で学習する話

    • 学習が深層学習のコアだが、多分、数学的には深層学習のことを知らない人が想像しているよりも遥かに簡単だと思う
    • 層の設計とかいろいろ難しいことはあるのだろうが、この初期導入および深層学習を始める際の最初の数学的敷居の低さは、今の深層学習ブームに一役買っていると思う
    • 特に、この「ゼロから作るDeep Learning」は本当に解りやすい!おすすめ!
      • 「やってみた」がしやすい←まさに数学が得意でないのに、できそうな気がしてほいほいやっています
    • 大まかにいうと、関数の各パラメータに対する微分偏微分)を計算して、損失関数が小さくなる方にパラメータを更新する。さらに、関数の正解は不明で、解析的な微分はできないので、数値的な微分値を使用する
    • 要するに局所的にf(x + h)を実際に計算しみて、各パラメータの変化にたいするf(損失関数)の変化からどのようにパラメータを変えたら良いか決定する
    • 勾配法なので、更新量を決定する学習率ηが存在する
      • 上の話は、一次近似なのでどこまで更新したらよいかわからないため
      • ガウス・ニュートン的な)2次近似して、学習率ηをなくすというな方法を聞いたことがないのが疑問だが、パラメータが多すぎて解けないため、という理解で良いのだろうか?
  • 理解が正しければ、収束計算なので、一通り訓練データを学習ステップにいれただけでは全然最適解にたどり着いていない

    • 1次近似なのでその効率も全く不明?
    • そこで、ミニバッチの組み合わせを変えながら何回も訓練データを学習の際に使用する
    • 一通りデータを使い終えた(とみなせる)時点で、1エポックという単位が使われる
    • 数エポックで、学習がうまく行っているかどうかちゃんとチェックするのが、実用上は大事
  • 誤差逆伝播

    • 今度またしっかり読むが、読み飛ばした感じでは、深層学習は理論的には勾配法(確率的勾配効果法、SGD)なのは変わらない
    • それを(ほとんど結果を変えずに)高速に算出するのが誤差伝播法