概要
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 件のコメント:
コメントを投稿