Stimulator

機械学習とか好きな技術話とかエンジニア的な話とかを書く

楽しいAutoEncoderと学習の世界

今回はAutoEncoderについて書きます。以前ほんのちょっとだけ紹介しましたが、少し詳しい話を研究の進捗としてまとめたいと思います。(AdventCalendarに向けて数式を入れる練習がてら)

 

まず、AutoEncoderが今注目されている理由はDeepLearningにあると言っても過言ではないでしょう。DeepLearningは様々なコンペディション、例えば、ILSVRC2012(画像認識のコンテスト)や化合物の活性予測で、従来の手法を抑えとてつもない成績を収めて注目を浴びました。今年のILSVRC2013ではその殆どがDeepLearningを取り入れているほどです。さらには、「一般紙であるNewYorkTimesにまで記事が掲載」「第一人者であるHinton先生を学生ごとかのGoogleが買収」「BaiduがシリコンバレーDeep learningの研究所を作る」等学習界隈ではかなり注目された技術の一つです。Googleが猫画像認識で結果を出し、iPhoneのSiri(ソースが不確かですが)にも使われています。

 

このものすんごいDeepLearningですが、学習器の形としては多層ニューラルネットワーク(以下、多層NN)になります。元々多層NNの研究は数多くありましたが、NN全体の学習を行う際のパラメータ更新の難しさ等の問題がありました。そこでDeepLearningでは、事前学習という形で各層毎に教師なし学習を行っておいて、少ない変数で入力情報をうまく説明できるように学習(情報圧縮)しつつ、良い初期パラメータを先に持っておいて全体の教師あり学習に挑もう、という形をとっています。こうすることでNN全体の学習における調整も楽にできるようにる(事後学習)という訳です。

 

DeepLearningの事前学習の「各層」の要素は主に

  • RBM : Restricted Boltzmann Machine (制限付きボルツマンマシン)
  • AutoEncoder

 の二種類に分類されます。どちらも情報圧縮を行う事ができるNNですが、学習の過程が大きな違いです。ここではAutoEncoderの学習について説明していきます。

 

 AutoEncoderの学習は一般的なNNとほとんど変わりません。大きく違う点は「出力が入力を再現するような学習」を行う事です。

f:id:vaaaaaanquish:20131203011213j:plain

上の図で見ると、inputとoutputをサンプルを学習させて同じに出来れば、hidden(隠れ層)では少ない素子数で情報を表現出来ている、と考える事が出来ます。ここで「学習」はエンコード式とデコード式のパラメータの調整となります。(ちなみにDeepLearningでは学習させたinputとhiddenを使ってつなげていきます。)

AutoEncoderのDecode式とencode式は入力をxとすると以下のようになります。

{encode \;\;\;\; : \;\;\;\;y = s(Wx+b)}
{decode \;\;\;\; : \;\;\;\;z = s(W^{'}y+b^{'})}

上式の{s()}シグモイド関数を表し、パラメータが{W}{b}とになります。この2式で情報xを圧縮し復元するのですが、{W}{W^{'}}は転置行列を使う(tied weightという考え方)というのがありまして、そちらを使用すれば学習で求めるパラメータは実質({W,b,b^{'}})となります。しつこいですが「学習用のデータ群から、この『パラメータ』を調整して入力を再現するような出力を出せるようにする」のがAutoEncoderの学習です。この学習はよく、入力と出力の平均2乗誤差の最小化問題や交差エントロピーの最小化問題として捉えられます(数式割愛)。

 

ではその学習(パラメータの更新)ですが、主に以下の2種類に分ける事が出来ます。

詳しく分けるともう少し分けられますが主にこの2種類となります。まず2つの大きな違いとして、「いつパラメータを更新するか」があります。最小化問題はその時点の勾配を見る事で最小点に近づいていく訳ですが、バッチアルゴリズムでは、その時点での全てのデータの全ての勾配を計算し、その平均を利用してパラメータを更新します。それに対してオンラインアルゴリズムでは、ランダムに選んだ1サンプルから勾配を計算してパラメータを更新します。勾配の計算は微分やらなんやらで計算量も多くなる訳ですから、その回数が減るオンラインアルゴリズムは計算量が少なく早いと言えます。しかしバッチアルゴリズムは多くのデータの平均というより正確な勾配を計算するので、収束率が良くなります。

(上手い表現ではなくすみません。その上実はこの関係は絶対でなかったりするので一概には言えません・・・)

 

AutoEncoderでは一般的にオンラインアルゴリズムが使われています。理由としては早さが挙げられると思います。多くの学習データを見ることや、DeepLearningのように多層に繋げる場合も考えると学習の早さはかなり重要になるからです。その中でもSGD(StochasticGradientDescent:確率的降下勾配法)というアルゴリズムがよく用いられます。SGDはデータ点の誤差の和で表現される最適化問題(AutoEncoderのような問題)に使われるアルゴリズムで、誤差の和の平均(期待値)の面倒な勾配計算をデータの実現値を用いて解決します。

 

具体的にSGDの学習をパラメータ毎に式に起こすと以下のようになります。

{W^{new} \;\;\;\; = \;\;\; W^{old}\;\;\; + \;\;\; \frac{\epsilon}{N} \displaystyle \sum_{n=1}^{N} \frac{\partial L}{\partial W}}
{b^{new} \;\;\;\; = \;\;\; b^{old}\;\;\; + \;\;\; \frac{\epsilon}{N} \displaystyle \sum_{n=1}^{N} \frac{\partial L}{\partial b}}
{b^{'new} \;\;\;\; = \;\;\; b^{'old}\;\;\; + \;\;\; \frac{\epsilon}{N} \displaystyle \sum_{n=1}^{N} \frac{\partial L}{\partial b^{'}}}

上式の{L}は目的関数(交差エントロピー等)です。第二項の\epsilonで1回の更新の幅を調整する式になります。

こちらの方のブログ↓

Denoising Autoencodersにおける確率的勾配降下法(数式の導出) - Yusuke Sugomori's Blog

に第二項の微分式の導出過程も掲載されています。 これに基づいてパラメータを更新していけば出来るAutoEncoderの学習が行える訳です。パラメータ更新の3式の実装はリンク先のブログの数式をそのまま実装する事で苦労はしないと思います。特にPython等を使えば、自動微分やnumpyの配列、外積内積計算によってより苦労する事なく短いソースコードで実現する事が出来ます。

 

さいごに、C言語等の配列でも実装すべく、配列同士の微分式を考えます。ライブラリ等を使わない場合ですね。こちらは、研究室で悩んだ挙句先生が「暇つぶしにやったよw」と言って考えてくれた資料になります。正直かなりコツコツ考えないと出来ない数式なのでかなり尊敬しています。本当にこの研究室で良かった。

https://skydrive.live.com/redir?resid=4834E9356B3DA117%21111

 

以上でAutoEnocederを実装まで持っていけると思います。(多分)

交差エントロピーを使った話は発生確率の話から入りややこしくなるので「誤差を最小にする」用の目的関数ですと割愛しました。その他不明な点や、ご指摘等はコメントでお願いします。

//----------

初学者であった自分が分かりづらかった点をなるべくわかりやすく、次の初学者の為にと書きました。「初学者の癖に文面ガー」等の意見があると思いますが、これから大学院生となってさらに向上していきたいと考えていますので熱い応援よろしくお願いします。