Theano で Deep Learning <4> : Denoising オートエンコーダ
Python Theano
を使って Deep Learning の理論とアルゴリズムを学ぶ会、第四回。
目次
DeepLearning 0.1 について、対応する記事のリンクを記載。
第一回 MNIST データをロジスティック回帰で判別する | 英 |
第二回 多層パーセプトロン | 英 |
第三回 畳み込みニューラルネットワーク | 英 |
第四回 Denoising オートエンコーダ (今回) | 英 |
第五回 多層 Denoising オートエンコーダ | 英 |
第六回の準備1 networkx でマルコフ確率場 / 確率伝搬法を実装する | - |
第六回の準備2 ホップフィールドネットワーク | - |
第六回 制約付きボルツマンマシン | 英 |
Deep Belief Networks | 英 |
Hybrid Monte-Carlo Sampling | 英 |
Recurrent Neural Networks with Word Embeddings | 英 |
LSTM Networks for Sentiment Analysis | 英 |
Modeling and generating sequences of polyphonic music with the RNN-RBM | 英 |
オートエンコーダ (Autoencoders)
まずは ( Denoisingでない ) ふつうのオートエンコーダについて。
オートエンコーダを使う目的
ニューラルネットワークの層が深くなっていくと、誤差逆伝播でネットワーク全体を学習させるのは時間がかかるし、過学習もしやすくなっていく。全体を誤差逆伝播で学習させることが難しいなら、各層をそれぞれ事前に学習 (pretraining) させて、あらかじめ特徴抽出しやすい初期値をもたせておけばいいよね!というのがオートエンコーダの考え方。オートエンコーダは、最終的につくりたい多層ニューラルネットワークの各層を効率的に事前学習させるための仕組みであって、この構造がそのまま多層ニューラルネットワークに含まれるわけではない。
多層ニューラルネットワークの各層がそれぞれどういった特徴抽出をすればよいか?というのは 事前学習の時点ではわからない。そのためオートエンコーダは教師なし学習になる。オートエンコーダで仮定されるのは、"隠れ層の出力から入力が復元できる (隠れ層で情報が失われていない) なら よい初期値といえそう" ということ。オートエンコーダは構造としては多層パーセプトロンと同じく、入力層 - 隠れ層 - 出力層からなる 3 層ニューラルネットワークをつくる。
オートエンコーダの数式表現
オートエンコーダを DeepLearning 0.1 Denoising Autoencoders (dA) の式をベースに図示するとこんな感じになる。真ん中の隠れ層にあたる部分が事前学習させたい層。デコード部分 + 出力層 (破線) は事前学習のために追加されたダミーで、最終的につくりたいニューラルネットワークには含まれない。
- : 入力層 - 隠れ層の間 (エンコーダ) で適用される係数行列。次元は 入力データの次元 x 隠れ層のユニット数
- : 入力層 - 隠れ層の間 (エンコーダ) で適用される重みベクトル。次元は 隠れ層のユニット数
- : 隠れ層の活性化関数。シグモイド関数もしくは (ハイパボリックタンジェント) をよく使う。
- : 隠れ層 - 出力層の間 (デコーダ) で適用される係数行列。次元は 隠れ層のユニット数 x 入力データの次元 。元文書のサンプルでは としており、これを Tied weight という。
- : 隠れ層 - 出力層の間 (デコーダ) で適用される重みベクトル。次元は 入力データの次元
補足 オートエンコーダは次元圧縮として働く、つまり入力の次元 > 隠れ層のユニット数 であることが多いようだが、必須条件ではない。
オートエンコーダの動きを要約すると、
もの。本当に事前学習させたいものは だが、損失関数の評価のために も (Tied weight でない場合 も ) 事前学習することになる。
補足 元文書では 入力ベクトルの各値が [0, 1] からなる 2 値データの場合について記載している。より一般化したものは Generalized Denoising Auto-Encoders as Generative Models にある。
オートエンコーダの損失関数
多層パーセプトロン では 負の対数尤度 + 正則化項 ( L2ノルム )を使っていたが、オートエンコーダでは交差エントロピー関数 を使っている。
ここからのスクリプトで、オートエンコーダをあらわすクラス dA
が定義されている。多層パーセプトロン は HiddenLayer
クラスと LogisticRegression
クラスの 2 つで表現されていたが、 dA
クラスは それ自体で オートエンコーダ (上図) の全体を表現している。使っている Theano
の機能 / 内部的な処理は 多層パーセプトロンの場合と 同じなので概要だけ。
get_corrupted_input
メソッド: Denoising オートエンコーダで使うメソッド。ふつうのオートエンコーダでは、入力x
と同じデータをそのまま返す。get_hidden_values
メソッド: 隠れ層からの出力 を計算するメソッド。get_reconstructed_input
メソッド: 出力層からの出力 を計算するメソッド。
これらを使って、損失関数 (交差エントロピー関数) は以下のように計算される。
tilde_x = self.get_corrupted_input(self.x, corruption_level) y = self.get_hidden_values(tilde_x) z = self.get_reconstructed_input(y) L = - T.sum(self.x * T.log(z) + (1 - self.x) * T.log(1 - z), axis=1)
元文書ではこの後、損失関数に正則化項入れなくていいのか?という話が続いている。特に 隠れ層のユニット数が入力層のユニット数以上の場合には 入力層 - 隠れ層 で恒等変換が学習されてしまうと隠れ層の存在意義がない。が、参照されている論文 によると、確率的勾配降下法 (SGD) で学習させた場合は L2 正則化に似た動きになり、ある程度はうまいこといくらしい。
ほか、オートエンコーダが恒等関数を学習してしまうのを防ぐ方法はいくつか提案されている。
- 入力層のユニット数 > 隠れ層のユニット数 とする ( サンプルスクリプトでは 入力 784次元に対し 隠れ層 500次元 )
- 損失関数に正則化項を入れる (スパースオートエンコーダ)
- 学習データにランダムなノイズを入れる (Denoising オートエンコーダ : 次セクション)
Denoising オートエンコーダ
入力に対して学習のたびにランダムなノイズを付与し、それらについて事前学習を行うことで より汎化能力の高い初期値を与えるための仕組み。損失関数はノイズの入っていない入力に対して評価されるため、Denoising オートエンコーダでは以下 2 つを学習していることになる。
- 入力された情報を維持したまま、よい特徴を抽出する
- 入力に含まれるノイズを除去する
入力にノイズを与えているのは、上述の get_corrupted_input
メソッド。具体的な処理は、
corruption_level
で与えられた比率で 0 を含む二項分布の乱数を生成- 生成した乱数を入力画像の対応する要素にかける (行列積ではなく、各要素の積)
例えば 10 x 10 の入力があったとき、ノイズ 30% ( corruption_level=0.3
) で二項分布の乱数を生成すると、
corruption_level = 0.3 rng = numpy.random.RandomState(123) theano_rng = RandomStreams(rng.randint(2 ** 30)) theano_rng.binomial(size=(10, 10), n=1, p=1 - corruption_level, dtype=theano.config.floatX).eval()) # [[ 1. 1. 1. 1. 1. 0. 1. 0. 1. 1.] # [ 1. 1. 1. 1. 0. 0. 1. 1. 1. 1.] # [ 1. 1. 0. 1. 1. 0. 1. 1. 0. 1.] # [ 1. 0. 0. 0. 1. 1. 1. 0. 1. 1.] # [ 1. 1. 0. 1. 1. 0. 0. 0. 0. 1.] # [ 1. 1. 0. 1. 0. 0. 1. 0. 1. 1.] # [ 1. 1. 0. 1. 1. 1. 1. 1. 1. 1.] # [ 1. 1. 1. 1. 0. 1. 1. 1. 0. 1.] # [ 1. 1. 1. 0. 0. 1. 1. 1. 0. 1.] # [ 1. 0. 1. 0. 1. 0. 1. 1. 1. 1.]]
普通の画像について 同じロジックで作成したノイズを適用すると以下のような結果になる。ガウシアンノイズではなく 2値のノイズなので画像が欠損するような感じだ。
付与するノイズが 0% ( corruption_level=0
) ならふつうのオートエンコーダになる。このノイズ付与が事前学習にどのように作用するのか、次のセクションで比較されている。
全部まとめて
これまでと同じく、最後にあるスクリプトを保存して実行すればよい。実行結果 に添付されている以下2つの画像が "dA_plots" フォルダ内に出力される
filters_corruption_0.png
: ふつうのオートエンコーダで事前学習した特徴 ( によって学習されたもののうち 100個分 )filters_corruption_30.png
: Denoising オートエンコーダ ( ノイズ30% ) で事前学習した特徴 (同上)
また、実行には、以下に添付されている util.py
が必要。
Miscellaneous — DeepLearning 0.1 documentation
どんな感じで学習していくのかをみるため、Epoch の経過ごとにアニメーションさせてみた。
- 左側 : ふつうのオートエンコーダで事前学習した特徴
- 右側 : Denoising オートエンコーダ ( ノイズ30% ) で事前学習した特徴
ふつうのオートエンコーダでもいくつかは意味がありそうな特徴 (スパースな特徴 = 白/黒がはっきりわかれるもの) を抽出できている。が、Denoising オートエンコーダのほうが より多くのセルで はっきりとした特徴を早く抽出できているように見える。
※ Denoising オートエンコーダはノイズが乗ったデータから学習しているため、損失関数の値 (cost) は大きい。
アニメーション部分のプログラム
※ Epoch 計算に時間がかかるため計算のたびにプロット出力し、手動でアニメーションGIFとして結合した。
まとめ
オートエンコーダでの事前学習により、多層ニューラルネットワークによりよい初期値を持たせることができる。このとき、入力にノイズをのせる (Denoising オートエンコーダ) ことで より特徴らしい特徴が抽出できる。
12/21追記 続きはこちら。
- 作者: 岡谷貴之
- 出版社/メーカー: 講談社
- 発売日: 2015/04/08
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る