2016年11月3日木曜日

Tensorflow に入門してみた

概要

話題の Tensorflow に入門してみました
インストールからサンプルの実行と自分で学習データの準備から、それの学習と評価までを試してみました
とりあえずこの記事では TensorFlow の使い方の流れを理解してもらえればと思います

環境

  • Mac OS X 10.12.1
  • Python 2.7
  • pip 8.1.1
  • Tensorflow 0.11.0rc2

Tensorflow のインストール

まずはインストールします
Python のライブラリが公開されているので Mac 上にそれをインストールして Python から試してみます

  • sudo pip install --upgrade virtualenv
  • virtualenv --system-site-packages ~/tensorflow
  • cd tensorflow/
  • source bin/activate
  • pip install --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-0.11.0rc2-py2-none-any.whl

でインストールしたらインタラクティブモードで動作確認しましょう
( やらなくてもいいですが、いろんなサイトで紹介しているので何となく自分も紹介 )

$ python
Python 2.7.10 (default, Jul 30 2016, 18:31:42)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print sess.run(hello)
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print sess.run(a+b)
42
>>> print hello
Tensor("Const:0", shape=(), dtype=string)

的な感じになれば OK です

サンプル (ソフトマックス回帰) の実行

公式の一番簡単なサンプルは MNIST という手書き文字を認識するサンプルを公開しています
一応それを動作させる方法を紹介します
が、正直これだけ実行できても Tensorflow に関しては何一つ理解できないと思います

  • wget 'https://raw.githubusercontent.com/tensorflow/tensorflow/r0.11/tensorflow/examples/tutorials/mnist/input_data.py’
  • wget 'https://raw.githubusercontent.com/tensorflow/tensorflow/r0.11/tensorflow/examples/tutorials/mnist/mnist_softmax.py’
  • python mnist_softmax.py

と実行すると

Extracting /tmp/data/train-images-idx3-ubyte.gz
Extracting /tmp/data/train-labels-idx1-ubyte.gz
Extracting /tmp/data/t10k-images-idx3-ubyte.gz
Extracting /tmp/data/t10k-labels-idx1-ubyte.gz
0.9192

な感じで表示されて終了すると思います
これは学習用の MNIST データを学習したあとにテストした結果、精度が約 91 % くらいでしたという結果になります

これだけだとさっぱりだったので、別のサンプルを自分で作成して実行してみました

線形回帰のサンプル

線形回帰のサンプルを作成しました
プログラム全体は以下の通りです

# coding:utf-8                                                                                                                                 
# 1. ライブラリの呼び出し                                                                                                                      
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

# 2. 予測式の作成                                                                                                                              
x  = tf.placeholder(tf.float32, shape=(None, 2), name="x")
y_ = tf.placeholder(tf.float32, shape=(None, 1), name="y")
a = tf.Variable(tf.zeros((2, 1)), name="a")
y = tf.matmul(x, a)

# 3. 誤差関数と最適化手法の選択                                                                                                                
loss = tf.reduce_mean(tf.square(y_ - y))
train_step = tf.train.GradientDescentOptimizer(0.02).minimize(loss)

# 4. 訓練データの作成                                                                                                                          
train_x = np.array([[1., 3.], [3., 1.], [5., 7.]]).reshape(3, 2)
train_y = np.array([190., 330., 660.]).reshape(3, 1)

# 5. 学習実行 (はじめにおまじない)                                                                                                             
sess = tf.Session()
init = tf.initialize_all_variables()
sess.run(init)
# 5. 学習実行                                                                                                                                  
for i in range(100):
    _, l, a_ = sess.run([train_step, loss, a], feed_dict={x: train_x, y_: train_y})
    if (i + 1) % 10 == 0:
        print "step=%3d, a1=%6.2f, a2=%6.2f, loss=%.2f" % (i + 1, a_[0], a_[1], l)
# 5. 学習結果の表示                                                                                                                            
est_a = sess.run(a, feed_dict={x: train_x, y_: train_y})
print "Estimated: a1=%6.2f, a2=%6.2f" % (est_a[0], est_a[1])

# 6. 評価                                                                                                                                      
new_x = np.array([2., 4.]).reshape(1, 2)
new_y = sess.run(y, feed_dict={x: new_x})
print new_y

sess.close()

自分も詳細に理解できていませんが簡単にポイントを紹介します

ポイント

tf.placeholder で学習するデータや評価するデータの器を作成します
shape=(None, 2) はデータが可変長で、2 次元のデータを入れる器を用意しています
tf.zeros((2, 1)) で 2 x 1 の行列を作成します
zeros の場合、ゼロ埋めの行列を作成します

tf.square(y_ - y) は誤差関数で予想と実際の合計金額の差の二乗を計算しています
そしてその値が小さければ小さいほど正解となるように GradientDescentOptimizer (最急降下法) を使っています

次に numpy を使って学習データを作成します
train_x が入力データで train_y がそれに対応した出力データになります
train_x が 3 行 2 列のデータで、train_y が 3 行 1 列のデータになります
上記の場合だと

  • 1, 3 というパターンなら -> 190
  • 3, 1 というパターンなら -> 330
  • 5, 7 というパターンなら -> 660

という感じのデータになります

あとはそれらのデータを最適化手法と誤差関数と結果を格納する行列を使って学習させます
sess.run([train_step, loss, a], feed_dict={x: train_x, y_: train_y})
feed_dict は学習させるデータになります
placeholder で事前に作製した器に設定します
終了したら学習結果を表示します

その後で学習したモデルを評価します
numpy で評価するデータを再度作成して sess.run で評価をしています

ざっと説明すると学習の流れはこんな感じです
最後に sess.close() で終了します

ロジスティクス回帰のサンプル

続けてロジスティクス回帰を使った 2 値判定のサンプルを紹介します
基本的な学習の流れは線形回帰の場合と同じです

# coding:utf-8                                                                                                                                                
# 1. ライブラリの呼び出し                                                                                                                                     
import numpy as np
import matplotlib.pyplot as plt                                                                                                                               
import tensorflow as tf

# 2. 予測式の作成                                                                                                                                             
x  = tf.placeholder(tf.float32, shape=(None, 2), name="x")
y_ = tf.placeholder(tf.float32, shape=(None, 1), name="y")
a = tf.Variable(-10 * tf.ones((2, 1)), name="a")
b = tf.Variable(200., name="b")
u = tf.matmul(x, a) + b
y = tf.sigmoid(u)

# 3. 誤差関数と最適化手法の選択                                                                                                                               
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(u, y_))
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

# 4. 訓練データの作成                                                                                                                                         
train_x = np.array([[2., 3.], [0., 16.], [3., 1.], [2., 8.]])
train_y = np.array([1., 1., 0., 0.]).reshape(4, 1)

# 5. 学習実行 (はじめにおまじない)                                                                                                                            
sess = tf.Session()
init = tf.initialize_all_variables()
sess.run(init)
# 5. 学習実行                                                                                                                                                 
for i in range(1000):
    _, l, a_, b_ = sess.run([train_step, loss, a, b], feed_dict={x: train_x, y_: train_y})
    if (i + 1) % 10 == 0:
        print "step=%3d, a1=%6.2f, a2=%6.2f, b=%6.2f, loss=%.2f" % (i + 1, a_[0], a_[1], b_, l)
# 5. 学習結果の表示                                                                                                                                           
est_a, est_b = sess.run([a, b], feed_dict={x: train_x, y_: train_y})
print "Estimated: a1=%6.2f, a2=%6.2f, b=%6.2f" % (est_a[0], est_a[1], est_b)

# 6. 評価                                                                                                                                                     
new_x = np.array([1., 11.]).reshape(1, 2)
new_y = sess.run(y, feed_dict={x: new_x})
print new_y

sess.close()

ポイント

入力は 2 次元 (x = tf.placeholder(tf.float32, shape=(None, 2), name="x"))、出力は 1 次元 (y_ = tf.placeholder(tf.float32, shape=(None, 1), name="y")) になります
シグモイド曲線のロジットを予測式に使っています
パラメータ b を追加しています
誤差関数にはクロスエントロピーを使用しています (この辺りは自分もあまり理解できていません、、、)

あとは学習させて評価するだけですが、パラメータ b に関する学習も追加しています

最後に

TensorFlow を使ってみました
写経でもいいので、自分で予測式の作成から誤差関数の作成と最適化手法の決定、データの学習、評価と一連の流れをやってみると TensorFlow の理解も少しは理解できると思います

自分はこれで、簡単な使い方とフローはだいぶ理解できたので、あとは今回の手法を実際に適用できそうなケースを探して試してみたいなと思っています

ただ、やはり予測式を出したり、誤差関数や最適化手法を決定したりするフローは経験と数学的知識がかなり必要だと思うので、本格的に TensorFlow を使いたいのであれば結構な学習が必要になると思います

また、冒頭に紹介した MNIST のサンプルも結局、線形回帰やロジスティクス回帰と同じ方法で学習から評価まで行っているので、あとでサンプルのコードを見直してみると中身を理解できるかもしれません

とりあえずは、今回の例とそのまま別のケースに横流しできるようなユースケースを見つけて試してみたいと思います

参考サイト

0 件のコメント:

コメントを投稿