9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TensorFlow向けに書いたコードをTheanoに移植してみた

Last updated at Posted at 2015-12-15

元々,Deep Learning用フレームワーク"Theano"の学習を進めていたが,先月(2015/11)公開された"TensorFlow"に興味を惹かれ最近はそちらをメインで使っていた.TensorFlowを触りながら,「ここは"Theano"に近い,ここはかなり違う」と感じていたが,両者の違いを確認するために簡単なコードを"TensorFlow"から”Theano"に移植してみた.(普通,方向が逆かと思いますが.)

概要: "Theano" vs. "TensorFlow"

まず2つのフレームワークの概要を比較する.

項目 Theano TensorFlow
開発主体 アカデミック (University of Montreal)  企業 (Google)
公開年度 2010年ぐらい(?) 2015年
Tensor operation support support
numpy 'basic' level 機能 support support
自動微分 (Graph Transformation) support support
GPU演算 support support
Graph Visualization support (一応あります) support (ご存知 Tensorboard)
Optimizer not support (built-inではないという意味) いろいろsupport
Neural Network系の関数 support (いろいろ) support

機能面では,上の表の最後の部分に違いが見られる.Theanoでは細かい部分を自前で用意しなければならないのに対し,ThensorFlowにはライブラリ関数として初めからいろいろ準備されている,といった印象である.
(Theanoで詳細部からプログラムしたくない方には,Theanoベースの高機能ライブラリ,例えば Pylearn2 があります.)

コードで比較(Neural Networkのモデル化)

ここでは,"Theano"と”ThensorFlow"ではほとんど同じようにコードを書くことができる.前回の記事で紹介した多クラス分類を行うMLP(Multi-layer Perceptron)のコードから抜粋する.

TensorFlow版

# Hidden Layer
class HiddenLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input
    
        w_h = tf.Variable(tf.random_normal([n_in,n_out],mean=0.0,stddev=0.05))
        b_h = tf.Variable(tf.zeros([n_out]))
     
        self.w = w_h
        self.b = b_h
        self.params = [self.w, self.b]
    
    def output(self):
        linarg = tf.matmul(self.input, self.w) + self.b
        self.output = tf.nn.relu(linarg)  # switch sigmoid() to relu()
        
        return self.output

# Read-out Layer
class ReadOutLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input
        
        w_o = tf.Variable(tf.random_normal([n_in,n_out],mean=0.0,stddev=0.05))
        b_o = tf.Variable(tf.zeros([n_out]))
       
        self.w = w_o
        self.b = b_o
        self.params = [self.w, self.b]
    
    def output(self):
        linarg = tf.matmul(self.input, self.w) + self.b
        self.output = tf.nn.softmax(linarg)  

        return self.output

Theano版

# Hidden Layer
class HiddenLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input
    
        w_h = theano.shared(floatX(np.random.standard_normal([n_in, n_out])) 
                             * 0.05) 
        b_h = theano.shared(floatX(np.zeros(n_out)))
   
        self.w = w_h
        self.b = b_h
        self.params = [self.w, self.b]
    
    def output(self):
        linarg = T.dot(self.input, self.w) + self.b
        # self.output = T.nnet.relu(linarg)
        self.output = T.nnet.sigmoid(linarg)
        
        return self.output

# Read-out Layer
class ReadOutLayer(object):
    def __init__(self, input, n_in, n_out):
        self.input = input
        
        w_o = theano.shared(floatX(np.random.standard_normal([n_in,n_out]))
                             * 0.05)
        b_o = theano.shared(floatX(np.zeros(n_out)))
       
        self.w = w_o
        self.b = b_o
        self.params = [self.w, self.b]
    
    def output(self):
        linarg = T.dot(self.input, self.w) + self.b
        self.output = T.nnet.softmax(linarg)  

        return self.output

細かく見なければ「"tf." を"T."に変えただけ」の違いである.活性化関数については後発のTenfsorFlowの方が "tf.nn.relu()"等もあって便利と思っていたが,Theanoでも ver.0.7.1からrelu() (Rectified Linear Unit) をサポートするようである.(本記事で使用したプログラムは,Python ver.2.7.10, TensorFlow ver.0.5.0, Theano ver.0.7.0 になります.)

また,Softmax関数も当然のことながら両者でサポートされている.

コードの比較(最適化プロセス)

ここでは両者(TensorFlow vs. Theano)で違いがみられる.TensorFlowでは,Optimizerのクラス・ライブラリが充実している一方,TheanoではOptimizerのクラス・ライブラリは自分で用意する必要がある.

TensorFlow版(AdagradOptimzer使用例)

    # Train
    optimizer = tf.train.AdagradOptimizer(0.01)
    train_op = optimizer.minimize(loss)
    
    init = tf.initialize_all_variables()

    with tf.Session() as sess:
        sess.run(init)
        print('Training...')
        for i in range(10001):
            train_op.run({x: train_x, y_: train_y})
            if i % 1000 == 0:                # echo status on screen
                train_accuracy = accuracy.eval({x: train_x, y_: train_y})
                print(' step, accurary = %6d: %8.3f' % (i, train_accuracy))

TensorFlowでは,optimizerを指定して,Sessionを動かす.Seesionの中でTrain DataをFeed_dictの形で供給するという流れ.

Theano版(Adagradを実装した例)
できるだけ関数のcallの仕方をTensorFlowのコードに近づけるように書いたつもりだが,以下のようになった.

# Optimizers - (GradientDescent), AdaGrad
class Optimizer(object):
    def __init__(self, params, learning_rate=0.01):
        self.lr = learning_rate
        self.params = params
       
    def minimize(self, loss):
        self.gradparams = [T.grad(loss, param) for param in params]
        
class AdagradOptimizer(Optimizer):
    def __init__(self, params, learning_rate=0.01, eps=1.e-6):
        super(AdagradOptimizer, self).__init__(params, learning_rate)
        self.eps = eps
        self.accugrads = [theano.shared(floatX(np.zeros(t.shape.eval())),
                          'accugrad') for t in self.params
                         ]
    def minimize(self, loss):
        super(AdagradOptimizer, self).minimize(loss)
        self.updates = OrderedDict()    # for Theano's rule

        for accugrad, param, gparam in zip(
                              self.accugrads, self.params, self.gradparams):
            agrad = accugrad + gparam * gparam
            dx = - (self.lr / T.sqrt(agrad + self.eps)) * gparam
            self.updates[param] = param + dx
            self.updates[accugrad] = agrad

        return self.updates

これらを使って最適化プロセス(学習)を走らせる.

    # Train
    myoptimizer = AdagradOptimizer(params, learning_rate=0.01, eps=1.e-8)
    one_update = myoptimizer.minimize(loss)
    
    # Compile ... define theano.function
    train_model = theano.function(
        inputs=[],
        outputs=[loss, accuracy],
        updates=one_update,
        givens=[(x, strain_x), (y_, strain_y)],
        allow_input_downcast=True
    )

    n_epochs = 10001
    epoch = 0
    
    while (epoch < n_epochs):
        epoch += 1
        loss, accu = train_model()
        if epoch % 1000 == 0:
            print('epoch[%5d] : cost =%8.4f, accyracy =%8.4f' % (epoch, loss, accu))

このように最適化プロセスの部分において,
TensorFlowでは...
変数を初期化した後,Sessionを走らせる.訓練データは,セッション中に op.run( {Feed_dict})のような形で与える.
Theanoでは...
theano.function()のところで(訓練データの供給を含め)学習プロセスの流れを定義する.定義した関数(theano.function)を用いて,反復学習計算を実行する,
という違いが見られる.

”Theano"の学習を始めた当初は,この theano.function() の使い方に悩んだ記憶があるが,上記のように"TensorFlow"と比較することで,theano.function() への理解が深まった.(違う見方をすれば,theano.function() についてきちんと理解していれば,Theanoをうまく使いこなせると思います.)

まとめと感想

同じ目的で使用されるフレームワークですので,似ているところがたくさんあります.機能面では,TensorFlowの方が充実しているので,ThenoコードをThensorFlow向けに移植するのは容易ではないかと思われます.但し,Optimizerや新しい関数も一度,実装していればそれを使いまわすことができるので,Theanoが不利というわけではありません.(先人のコードも参考になりますし,アドオンのライブラリもたくさんあります.)

まだMLPのコードを見ただけで,より複雑なネットワークモデルを試していませんが,どちらも非常に可能性のあるツールと思われます.(Chainerもインストールしたのですがなかなか手がつがず... )

(追記)Keras についての情報

本記事を書くにあたりNeural Network Library "Keras"についてサイトを確認したところ,”Theano"と組み合わせて使用するライブラリに加えて, ”TensorFlow"との組み合わせで使うものもリリースされているようです.(後で調べてみたいと思います.)

Keras: Deep Learning library for Theano and TensorFlow

参考文献 (web site)

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?