2016/05/21 機械学習 名古屋 第4回勉強会
以下の環境を前提とします。
インストールの詳細省略。
インストールが成功していれば、Python のインタラクティブシェル(もしくは ipython, Jupyter 等)で↓以下のようにすれば利用開始。
import tensorflow as tf
※ 今回は TensorBoard は不使用。
TensorFlow では、以下のようにすると MNIST データセット(訓練データおよびテストデータ)を扱えるようになる:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
※↑データが存在しなければネットワーク経由でダウンロードから開始。
ダウンロード後(or ダウンロード済のデータが存在する場合)そのデータを読み込んでくれる。
※⇒既にダウンロード済のデータ(4つの.gzファイル)を持っていたらそれを所定の場所に置いておくだけでもOK。
# 訓練データ:長さ784のベクトルデータ(=28x28 の画像データ)
x = tf.placeholder(tf.float32, [None, 784])
# 正解データ:長さ10のベクトルデータ(0,1,…,9 の対応する要素のみ 1、他は 0)
d = tf.placeholder(tf.float32, [None, 10])
shape(行列の行数と列数、もしくはベクトルの要素数)を指定して、重み(およびバイアス)を返すユーティリティ関数を用意しておく。
# 重み(フィルター)は tf.truncated_normal() で初期化(tf.random_normal() でも大体同じ)
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
# バイアスは固定値 0.1 で初期化
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
同様、畳み込み層とプーリング層も定型のものを返すユーティリティ関数定義。
# 畳み込み層は、tf.nn.conv2d() を利用。
# ストライドは (1, 1)、パディングあり(=入力と出力の画像サイズが同じ)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
# プーリング層は、tf.nn.max_pool() を利用(最大プーリング)。
# プーリングサイズ・ストライドはいずれも (2, 2)、パディングあり(=出力の画像サイズは入力の1/2)
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1], padding='SAME')
# 1件分のデータ(長さ784)を 28x28x1(W=28, K=1)に変換
x_image = tf.reshape(x, [-1,28,28,1])
# フィルターは 5x5x1x32(H=5, K=1, M=32)
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
# 畳み込み層・プーリング層を定義(活性化関数は正規化線形関数)
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
# フィルターは 5x5x32x64(H=5, K=32, M=64)
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
# 畳み込み層・プーリング層を定義(活性化関数は正規化線形関数)
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
# 入力サイズ 3136(=7x7x64)、出力サイズ 1024
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
# 前層(プーリング層2)の出力(7x7x64 の 3-D)を 1-D に変換してから適用
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
# ドロップアウトの定義
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
# 入力1024、出力10
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
# ソフトマックス出力
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
x_entropy = tf.reduce_mean(-tf.reduce_sum(d * tf.log(y_conv), reduction_indices=[1]))
# Tensorflow v0.7 以前の場合は↓
# x_entropy = -tf.reduce_sum(d * tf.log(y_conv))
tf.train.AdamOptimizer
を利用した例を示す。tf.train.GradientDescentOptimizer
、tf.train.MomentumOptimizer
等を利用しても良い。optimizer = tf.train.AdamOptimizer(1e-4)
train_step = optimizer.minimize(x_entropy)
init = tf.initialize_all_variables()
※↑これも「変数を初期化する」という命令を宣言しているだけ。
この後 sess.run(init)
することで(そのセッション内で実際に)変数の初期化が実行される。
sess = tf.Session()
sess.run(init)
# ↑実際にはここで始めて各変数が初期化される
今回は分かりやすくするため、ループ中にも随時精度を確認してみる。
そのため先に精度を確認する各種準備。
# y(=学習結果の出力)と d(正解データ)で一致しているかどうかを確認
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(d, 1))
# 平均(=一致している個数÷全データ数)を計算
accuracy = tf.reduce_mean(tf.cast(correct_prediction,
tf.float32))
# ループ回数は 5000回
# バッチサイズは 50
# 200イテレーションごとに現在の精度を算出し出力
for i in range(1, 5001):
batch_xs, batch_ys = mnist.train.next_batch(50)
sess.run(train_step, feed_dict={x: batch_xs, d: batch_ys, keep_prob: 0.5})
if i % 200 == 0:
train_accuracy = sess.run(accuracy, feed_dict={x: batch_xs, d: batch_ys, keep_prob: 1.0})
print(' step, accurary = %6d: %6.3f' % (i, train_accuracy))
※注意:けっこう時間がかかります。
テストデータを利用して精度の確認。
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
d: mnist.test.labels,
keep_prob: 1.0}))
↑だいたい0.98前後になる(と思われます)。
matplotlib が入っている場合、以下を実行して実際のデータと推測結果を確認してみる。
%matplotlib inline
# ↑Jupyter 上で実行するときに必要
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import random
n = len(mnist.test.images)
i = random.randrange(n)
imageData = mnist.test.images[i]
label = mnist.test.labels[i]
result = sess.run(y_conv, feed_dict={x: [imageData], d: [label], keep_prob: 1.0})
print("Classified as: %d" % np.argmax(result))
image = np.reshape(imageData, [28, 28])
plt.imshow(image, cmap = cm.Greys)
# plt.show()
# ↑Jupyter 以外では必要
tf.train.AdagradOptimizer
の代わりに tf.train.MomentumOptimizer
を試してみる。optimizer = tf.train.MomentumOptimizer(0.001, 0.9)
等