StatsFragments

Python, R, Rust, 統計, 機械学習とか

Theano で Deep Learning <5> : 多層 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

多層オートエンコーダ (Stacked Autoencoders)

この章はオートエンコーダを利用して 目的のニューラルネットワークの各層を事前学習させる方法について。この章では新しい数式は出てこないし、処理自体もこれまでのクラスの組み合わせで実現されている。Theano の使い方でも 新しい内容はないので安心して読める感じだ。

多層オートエンコーダを用いた学習は以下の 2 ステップで行われる。

まず 全体を管理する SdA クラスを作っている。重要なのは以下3つのプロパティで、

  • SdA.sigmoid_layers: 隠れ層 HiddenLayer インスタンスのリスト (長さは隠れ層の数)。
  • SdA.dA_layers: オートエンコーダ dA インスタンスのリスト (長さは隠れ層の数)。
  • SdA.params: 学習するパラメータ (各層の係数行列、バイアスベクトルを入れる)

i 番目のオートエンコーダである dA インスタンスは、同じ番号 ( i 番目) の隠れ層 HiddenLayer インスタンスと係数行列 W, バイアスベクトル b をプロパティとして共有する。そのため、dA インスタンスに対して事前学習した後の係数行列 / バイアスベクトルは HiddenLayer からも参照できる。

SdA インスタンスは 初期化の際に 隠れ層の数 n_layers 分だけループを回して隠れ層 HiddenLayer とそれに対応するオートエンコーダ dA を作る。

    for i in xrange(self.n_layers):
        # 各層への入力の次元
        if i == 0:
            # 隠れ層 1 層目では 入力層のユニット数
            input_size = n_ins
        else:
            # 以降では 直前の層のユニット数
            input_size = hidden_layers_sizes[i - 1]

        # 各層への入力        
        if i == 0:
            # 隠れ層 1 層目では 入力層への入力
            layer_input = self.x
        else:
            # 以降では 直前の層の出力
            layer_input = self.sigmoid_layers[-1].output

        # 隠れ層を作成
        sigmoid_layer = HiddenLayer(rng=numpy_rng,
                                    input=layer_input,
                                    n_in=input_size,
                                    n_out=hidden_layers_sizes[i],
                                    activation=T.nnet.sigmoid)
        # 隠れ層のリストに追加
        self.sigmoid_layers.append(sigmoid_layer)

        # 学習するパラメータ (隠れ層の係数行列, バイアスベクトル を追加)
        self.params.extend(sigmoid_layer.params)

        # 隠れ層の係数行列 W, バイアスベクトル b を参照して オートエンコーダを作成
        dA_layer = dA(numpy_rng=numpy_rng,
                      theano_rng=theano_rng,
                      input=layer_input,
                      n_visible=input_size,
                      n_hidden=hidden_layers_sizes[i],
                      W=sigmoid_layer.W,
                      bhid=sigmoid_layer.b)
        # オートエンコーダのリストに追加
        self.dA_layers.append(dA_layer)

で、ネットワーク全体の判別をロジスティック回帰で行うための LogisticRegression インスタンスを追加している。ネットワーク全体の微調整 (fine-tuning) に使う損失関数 / 判別誤差は 出力層である LogisticRegression のものを使う。これも 多層パーセプトロン の場合と同じ。

1 点 異なるのは損失関数に正則化項が含まれていないこと。元文書には特に言及ないが、汎化性能のある Denoising オートエンコーダで事前学習しているので、同じく汎化性能を高めるための正則化項を使う必要はない、ということだろう。

この後、以下 2 つのメソッドの定義が続く。処理内容は以下の記載そのままなので元文書参照。

  • SdA.pretraining_functions: SdA.dA_layers に含まれる オートエンコーダ それぞれの学習関数 ( 入力に対する損失をもとに、勾配計算してパラメータ更新する theano.function ) のリスト (長さは隠れ層の数)。
  • SdA.build_finetune_functions: ネットワーク全体について、学習データに対する学習関数、検証データの判別誤差関数、テストデータの判別誤差関数 3 つの要素をもつタプル ( 要素はいずれも theano.function )。

全部まとめて

ネットワークへの事前学習、微調整 (fine-tuning) は test_SdA 関数の中で行われている。ここもそのままなのだが、

  • 入力層のユニット数 = 入力の次元は 28 x 28 = 784 個
  • 隠れ層は 3 層で、それぞれのユニット数は [1000, 1000, 1000] 個
  • 出力層のユニット数 = 出力のクラス数は 10 個
    sda = SdA(
        numpy_rng=numpy_rng,
        n_ins=28 * 28,
        hidden_layers_sizes=[1000, 1000, 1000],
        n_outs=10
    )

オートエンコーダを用いての事前学習部分は以下。corruption_levels を指定しているので Denoising オートエンコーダになっている。 このとき、後ろの層に行くほど強いノイズ ( 10%, 20%, 30% ) を与えている。

事前学習の際には、 1 層ずつ処理をまわしてその層の事前学習を終わらせる -> 次の層を事前学習する、という動きになる。でないと後続層のオートエンコーダに対する (事前学習用の) 入力データが確定しないので。余計な出力を除いて必要な箇所だけ抜き出すと、

    # PRETRAINING THE MODEL #
    corruption_levels = [.1, .2, .3]
    for i in xrange(sda.n_layers):
        for epoch in xrange(pretraining_epochs):
            for batch_index in xrange(n_train_batches):
                # pretraining_fns[i]() が実行されるたびにパラメータ更新
                pretraining_fns[i](index=batch_index,
                                   corruption=corruption_levels[i],
                                   lr=pretrain_lr))

全体をイメージにしてみた (クリックで拡大)。事前学習の際は 対象の層に対してオートエンコーダを構成して学習させる。各オートエンコーダで学習対象となっている係数行列とバイアスベクトルをピンク色、目的のニューラルネットワークに含まれない要素 ( 各オートエンコーダの出力層 ) を破線にした。

f:id:sinhrks:20141221222540p:plain

事前学習高速化のポイント

多層オートエンコーダの学習の際には、各層への入力データは都度 計算せずにキャッシュしておくといいよ!と言っている。

まとめ

これで 任意の大きさのニューラルネットワークに対して オートエンコーダで事前学習ができるようになった。

続く2章はまたトピックが変わって、オートエンコーダとは別の事前学習法である 制約付きボルツマンマシン (RBM) と、それらから作られるディープビリーフネットワーク (DBN) について。この 2 章で元文書の入門部分はおわりだ。

01/12追記 つづき。

深層学習 (機械学習プロフェッショナルシリーズ)

深層学習 (機械学習プロフェッショナルシリーズ)