概要
TensorFlow は、TheanoやChainerのように計算グラフを定義・構築し、実行するという素敵な仕組みを持っています。なにより、これらに共通する仕組みである自動微分がすばらしい。詳細は、TensorFlow の White Paper に譲りますが、個人的には、Theanoよりもわかりやすい印象を受けています。 一方で、TensorFlow は、Chainer に比べると、基本的なニューラルネットワーク(MLP)を構築するのにも、手間がかかる印象です。そこで、TensorFlowを使ってライブラリ風に作成したMLPモジュールを、実行方法含め、紹介したいと思います。
準備
- 実行環境(例)
- OS: Ubuntu 15.10 64bit (Over ESXi)
- 言語: Python (Over virtualenv)
- virtualenvでの構築方法は、Virtualenv installation を参照ください。
- TensorFlow: tensorflow-0.5.0-cp27-none-linux_x86_64.whl
- ソースファイル
- mlp.py - MLP をライブラリ風にまとめたファイル
- run.py - mlp.py をライブラリ風に実行するファイル
- input_data.py - TensorFlow の examples 配下の input_data.py
実行例
上記ソースファイルをダウンロードしたら、以下のように実行します。(初回実行時は、MNISTデータセットのダウンロードを行うため、少なからず待つことになります。)
(tensorflow)$ ls input_data.py mlp.py run.py (tensorflow)$ python run.py
tensorboard で可視化します。
(tensorflow)$ ls -F data/ input_data.py input_data.pyc log/ mlp.py mlp.pyc run.py (tensorflow)$ tensorboard --logdir=`pwd`/log Starting TensorBoard on port 6006 (You can navigate to http://localhost:6006)
可視化
- MLP構成
今回は、多層化を前提として、中間層を6層で構築しました。入力層に近いほど、勾配が残るようにReLUを配置し、出力層の前段では勾配がサチりやすいsigmoidを配置してみました。(実は、ここまで多層化しなくても、1層のみでも同程度の精度がでたりしますが・・・^-^;)
ソースコードでは、以下のように定義します。(run.py)
layers = [ # - input and hidden layers Layer("input", i_dim, activate=None, o=nh.X), Layer("01_relu", 512, activate=tf.nn.relu), Layer("02_relu6", 256, activate=tf.nn.relu6), Layer("03_tanh", 128, activate=tf.nn.tanh), Layer("04_linear", 256, activate=None), Layer("05_sigmoid", 128, activate=tf.nn.sigmoid), Layer("06_linear", o_dim, activate=None) ]
- 実行結果
- 認識精度
- 目的関数
run.py を実行した結果の認識精度です。約98%の精度が出ました。評価方法は、TensorFlowのexamplesのfully_connected_feed.pyと同じです。TensorFlowの畳み込みニューラルネットワーク(サンプル)の99.2%には、及ばずながら、そこそこの精度が出たと思います。(約7000ステップあたりから、認識精度が頭打ちになります。)- ヒストグラム
発展
- チューニング
今回は、主に、learning_rate, momentum, 各層のユニット数を変更して認識精度の違いを検証しました。試した限りでは、learning_rate を0.2~0.25の辺りにするのが、比較的良い結果になりました。momentumは、learning_rateと同程度に設定し、各層のユニット数は、MNISTデータセットの画像のサイズ(28x28=784)を参考に、512以下で設定しました。run.pyの以下のコードを変更すれば、独自にチューニングできます。
parameter.DEFINE_float('learning_rate', 0.25, 'Learning rate.') parameter.DEFINE_float('momentum', 0.25, 'Momentum rate.') parameter.DEFINE_float('regular_rate', 5e-5, 'Regularization rate. 0.0 means no regularization.') parameter.DEFINE_integer('batch_size', 100, 'Batch size. Must divide evenly into the dataset sizes.') parameter.DEFINE_integer('n_steps', 10000, 'Training steps.') parameter.DEFINE_float('dropout', 0.25, 'dropout rate.')
また、今回は、オプティマイザとして、MomentumOptimizerを使いましたが、以下のようにrun.pyのコメントを変更することで、異なるオプティマイザを利用することができます。試した限りでは、どのオプティマイザを使っても、認識精度には大きな差はでませんでした。
#optimizer = tf.train.GradientDescentOptimizer(PARAM.learning_rate) optimizer = tf.train.MomentumOptimizer(PARAM.learning_rate, PARAM.momentum) #optimizer = tf.train.AdagradOptimizer(PARAM.learning_rate) #optimizer = tf.train.AdamOptimizer()
- 考察
今後は、AutoencoderやRBM等の多層化について、でき次第、載せたいと思っています。
参考
- run.py
#!/usr/bin/env python # ===== # - main if __name__ == '__main__': # ----- class NodeHolder(object): pass # ----- import tensorflow as tf import input_data # - from current dir from mlp import MLP, Layer, LossCrossEntropy, Trainer, Evaluator parameter = tf.app.flags parameter.DEFINE_float('learning_rate', 0.25, 'Learning rate.') parameter.DEFINE_float('momentum', 0.25, 'Momentum rate.') parameter.DEFINE_float('regular_rate', 5e-5, 'Regularization rate. 0.0 means no regularization.') parameter.DEFINE_integer('batch_size', 100, 'Batch size. Must divide evenly into the dataset sizes.') parameter.DEFINE_integer('n_steps', 10000, 'Training steps.') parameter.DEFINE_float('dropout', 0.25, 'dropout rate.') PARAM = tf.app.flags.FLAGS data_sets = input_data.read_data_sets(train_dir='./data') i_dim = data_sets.train.images.shape[1] o_dim = len(set(data_sets.train.labels)) nh = NodeHolder() with tf.Graph().as_default(): nh.X = tf.placeholder(tf.float32, shape=(None, i_dim)) layers = [ # - input and hidden layers Layer("input", i_dim, activate=None, o=nh.X), Layer("01_relu", 512, activate=tf.nn.relu), Layer("02_relu6", 256, activate=tf.nn.relu6), Layer("03_tanh", 128, activate=tf.nn.tanh), Layer("04_linear", 256, activate=None), Layer("05_sigmoid", 128, activate=tf.nn.sigmoid), Layer("06_linear", o_dim, activate=None) ] nh.y = tf.placeholder(tf.int32, shape=(PARAM.batch_size)) nh.kp = tf.placeholder(tf.float32) # - build mlp mlp = MLP('mlp', layers, node_holder=nh) regularizer = PARAM.regular_rate * mlp.regularizer loss = LossCrossEntropy(nh, regularizer) #loss = LossCrossEntropy(nh) #optimizer = tf.train.GradientDescentOptimizer(PARAM.learning_rate) optimizer = tf.train.MomentumOptimizer(PARAM.learning_rate, PARAM.momentum) #optimizer = tf.train.AdagradOptimizer(PARAM.learning_rate) #optimizer = tf.train.AdamOptimizer() trainer = Trainer(loss, optimizer) init = tf.initialize_all_variables() # - create session sess = tf.Session() sess.run(init) # - setup summary trainer.setup(nh, sess, evaluator=Evaluator(nh)) # - run train mlp.run(sess, trainer, data_sets, PARAM)
0 件のコメント:
コメントを投稿