深層学習の自己符号化器を4行で記述できるライブラリを作りました

深層学習(DeepLeanring)の事前学習や特徴抽出に使われる積層自己符号化器(stacked auto-encoder)を簡単に記述するためのライブラリ(Chainerインターフェイス)を作りました。名前はzChainerです。

zChainer - scikit-learn like interface and stacked autoencoder for chainer

なぜ作ったか

ニューラルネットワークを簡単に実装することができるライブラリとしてChainerが多くの方に利用されていますが、ほぼ同じ記述を繰り返し書く必要があったり、学習器の定義・評価の記述が煩雑になりがちであるという課題があります。そこでインターフェイスとなるライブラリがあれば便利だと思って開発しました。scikt-learn likeに使うためにscikit-chainerとxchainerを参考にさせていただきました。

作ってみると積層自己符号化器の実装も共通なコードが多いことに気付いたので、本ライブラリは積層自己符号化器を管理するところまでインターフェイスに含めてみました。後述のサンプルコードのとおり、少ない行数(整形のための改行を除けばわずか4行)で記述することができます。

機能

インストール方法

$ pip install zChainer

サンプルコード

import numpy as np
import chainer.functions as F
import chainer.links as L
from chainer import ChainList, optimizers
from zChainer import NNAutoEncoder, utility

data = (..).astype(np.float32)

# encoderの定義
# 例)ノード数784-200-100のネットワーク
# 学習後に出力層(MNISTの場合はノード数10)をadd_linkする
encoder = ChainList(
    L.Linear(784, 200),
    L.Linear(200, 100))

# decoderの定義
# encoderとノード数を反対にしたLinkをChainする
decoder =ChainList(
    L.Linear(200, 784),
    L.Linear(100, 200))

# NNAutoEncoderインスタンスの作成
ae = NNAutoEncoder(encoder, decoder, optimizers.Adam(), epoch=100, batch_size=100,
    log_path="./ae_"+utility.now()+"_log.csv", export_path="./ae_"+utility.now()+".model")

# 学習
ae.fit(data)

forward関数にはdropoutありのreluを登録していますが、好みのforward関数をセットすることもできます。詳しくはgithubのexampleをご確認ください。

実装

class NNAutoEncoder ():
    def __init__(self, encoder, decoder, optimizer,
        epoch=20, batch_size=100, log_path="", export_path=""):
        self.encoder = encoder
        self.decoder = decoder
        self.optimizer = optimizer
        self.epoch = epoch
        self.batch_size = batch_size
        self.log_path = log_path
        self.export_path = export_path
        self.autoencoded = ChainList()

    def fit(self, x_train):
        for layer in range(0, len(self.encoder)):
            # Creating model
            self.model = ChainList(self.encoder[layer].copy(), self.decoder[layer].copy())
            NNManager.forward = self.forward
            nn = NNManager(self.model, self.optimizer, F.mean_squared_error,
                self.epoch, self.batch_size, self.log_path)

            # Training
            x_data = self.encode(x_train, layer).data
            nn.fit(x_data, x_data)
            self.autoencoded.add_link(nn.model[0].copy())

        if self.export_path != "":
            pickle.dump(self.autoencoded, open(self.export_path, 'wb'), -1)
        return self

    def predict(self, x_test):
        raise Exception("Prediction for AutoEncoder is not implemented.")

    def encode(self, x, n):
        if n == 0:
            return Variable(x)
        else:
            h = self.encode(x, n-1)
            return F.relu(self.autoencoded[n-1](h))

    def forward(self, x):
        h = F.dropout(F.relu(self.model[0](x)))
        return F.dropout(F.relu(self.model[1](h)))

Chainer1.5のLink and Chainを使用しています。ネットワークの構造をChainではなくChainListとして管理することで各層に添字でアクセスできるようにして、学習が済んだものをself.autoencodedにコピーしています。学習済みモデル最先端の層からの出力はencoded関数を再帰的に呼ぶことで得ています。(層が深くなるにつれて遅くなるかも?時間ができれば改良したい)

まとめ

積層自己符号化器を含めたChainerのインターフェイスとなるライブラリを作成しました。時間の都合で十分検証ができていないので、不具合などあるかもしれません。おかしいところがあれば連絡いただけると嬉しいです。バージョン1.0になるまで使用は自己責任でお願いします。

https://github.com/shoya140/zChainer

#release #engineering

関連記事

前後の記事