はじめに
TensorFlowのチュートリアルで機械学習の初心者のためと書いてある「MNIST For ML Beginners」をやってみました。そこで機械学習のHelloWorldと書いてある、MNISTの数字認識を実装してみました。MNISTとは手書き画像のデータセットの事で、ここでは0~9の手書きの数字の画像を読み込んで、機会学習で分類をします。
TensorFlowのGithubに置いてあるサンプルコードは難しいそうに見えるのですが、必要な実装だけしてみると本当にシンプルで20行で実装できました。
環境
Cloud9
Python 2.7.6
Sample Codes : GitHub
環境構築は「クラウド統合開発環境Cloud9でTensorFlowを使う~GetStarted~ 」
TesorFlowの基本的な使い方は「クラウド統合開発環境Cloud9でTensorFlowを使う〜使い方の基本〜」
を参照
学習処理のコード
Githubに置いてありますが、以下が実装したコードになります。
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
# Download gz files to MNIST_data directory
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# Initializing
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, shape=[None, 28*28])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
W = tf.Variable(tf.zeros([28*28, 10]), name="W")
b = tf.Variable(tf.zeros([10]), name="b")
sess.run(tf.initialize_all_variables())
# Making model
y = tf.matmul(x, W) + b
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y, y_))
# Training
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
for i in range(1000):
batch = mnist.train.next_batch(100)
train_step.run(feed_dict={x: batch[0], y_: batch[1]})
# Evaluating
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
# Save train data
saver = tf.train.Saver()
saver.save(sess, 'param/softmax.param')
実行してみるとチュートリアルにも書いてあるように、92%ほどの精度が出ているようです。
コードの中身
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
データを取得しているところです。MNIST_dataというディレクトリを作成して、そこに4ファイルダウンロードしています。中身はブラックボックスなので調べてみる必要があります。
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, shape=[None, 28*28])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
W = tf.Variable(tf.zeros([28*28, 10]), name="W")
b = tf.Variable(tf.zeros([10]), name="b")
sess.run(tf.initialize_all_variables())
初期化処理です。xが画像データ(28ピクセル×28ピクセル)、y_がその画像のラベル(0~9)を保持します。placeholderなので、後で代入しています。
Wとbはパラメータで、Wが画像の各ピクセルの重みづけとbが切片と言った形でしょう。
y = tf.matmul(x, W) + b
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y, y_))
yはパラメータとxから予測値を算出している式。次の式がソフトマックス回帰。
ロジスティック回帰は0と1を予測するモデルですが、それを拡張して複数のラベル(今回だと0~9)を予測できるようにしたもの。
チュートリアルには詳しい式も記載されていたので、それも勉強する必要があると思います。
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
for i in range(1000):
batch = mnist.train.next_batch(100)
train_step.run(feed_dict={x: batch[0], y_: batch[1]})
GradientDescentOptimizerが確率的勾配降下法。mnist.train.next_batchで最初にダウンロードしたデータを順に取得して、feed_dict={x: batch[0], y_: batch[1]}で、変数に代入しています。繰り返し実行することで最適解を求めているところです。
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
テストデータを使用して、y(予測値)とy_(実際の値)の精度を確認しているところです。
saver = tf.train.Saver()
saver.save(sess, 'param/softmax.param')
学習したパラメータを保存している処理です。これで後からパラメータのみを使用して画像の分類を行えます。
自分の手書きデータの予測
上記で手書きの数値データを学習しました。そのパラメータを使って、自分で書いた手書きデータの分類を行ってみました。
自分の手書きデータは、同じようにGithubに置いてありますが、白黒のbmpです。parsebmp.py で読み込んでいます。MNISTのデータは、0~1の数値で学習しているのですが、この処理は簡単に0, 1のデータのみです。
実際に動かしてみると、60%の精度でした。92%には程遠いのですが、ある程度は判定できていると言ってよいでしょう。
⇒ 手書きデータの予測には前処理が必要でした。詳細については自分の手書きデータをTensorFlowで予測するの記事を参考にして下さい。
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import sys
import numpy as np
import parsebmp as pb
def whatisit(file, sess):
print("File name is %s" % file)
data = pb.parse_bmp(file)
# Show bmp data
for i in range(len(data)):
sys.stdout.write(str(int(data[i])))
if (i+1) % 28 == 0:
print("")
# Predicting
d = np.array([data])
result = sess.run(y, feed_dict={x: d})
# Show result
print(result)
print(np.argmax(result, 1))
if __name__ == "__main__":
# Restore parameters
x = tf.placeholder(tf.float32, shape=[None, 28*28])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
W = tf.Variable(tf.zeros([28*28, 10]), name="W")
b = tf.Variable(tf.zeros([10]), name="b")
y = tf.matmul(x, W) + b
sess = tf.InteractiveSession()
saver = tf.train.Saver()
saver.restore(sess, 'param/softmax.param')
# My data
whatisit("My_data/0.bmp", sess)
whatisit("My_data/1.bmp", sess)
whatisit("My_data/2.bmp", sess)
whatisit("My_data/3.bmp", sess)
whatisit("My_data/4.bmp", sess)
whatisit("My_data/5.bmp", sess)
whatisit("My_data/6.bmp", sess)
whatisit("My_data/7.bmp", sess)
whatisit("My_data/8.bmp", sess)
whatisit("My_data/9.bmp", sess)
おわりに
まずはコードをチュートリアルを見ながら実装してみました。本当に簡単に実装できてしまうのですが、以下の点を理解していく必要があると思います。
- 使用データの中身
- ソフトマックス回帰の詳細な計算式
また本当に理解するために、自分の手書きのデータなどをとりこんで予測させることができたらよいと思います。それが実用にも繋がると思います。
⇒ 2017/03/27に自分の手書きデータの予測をやってみました。
更新履歴
- 2018/06/12: 手書きデータの予測について追記
- 2017/03/27: パラメータの保存方法、自分の手書きデータの予測内容を追記
- 2016/10/30: 新規投稿