元々,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)
- TensorFlow Documentation : https://www.tensorflow.org/
- Theano Documentation : http://deeplearning.net/software/theano/index.html
- gradient-optimizers 0.0.4 : https://pypi.python.org/pypi/gradient-optimizers/0.0.4
- ニューラルネットで学習係数最適化を色々試してみる- Qiita
http://qiita.com/hogefugabar/items/1d4f6c905d0edbc71af2 - TensorFlowのMLPコードで"Wine"を分類 - Qiita
http://qiita.com/TomokIshii/items/2cab778a3192d561a1ef - Keras Documentation : http://keras.io/