2016年2月1日月曜日

自分の手描き文字を判定させた履歴

はじめに

Googleがオープンソースとして公開したTensorFlow、こいつは機械学習に興味を持ちながらもまったく勉強したことがない私の心をくすぐった。
さっそく仮想環境へTensorFlowを入れていろいろ調べて半日かけてMNISTの簡素版を動かすことができた。

もう一歩進めて、自分で用意した画像を判定できるようにしたいと思うのは普通のことで、実際にそれを公開されている方もいらっしゃる。
>すぎゃーんメモ

現在はほぼ手順を把握しているので大体理解できるが、当初は何が書かれているか分からず読むのを諦めた。

とりあえず、簡素版MNISTに何をすれば自分の手描き数字を認識してくれるようになるか手順のメモ。環境はUbuntu14.04。

学習内容の保存

今よりさらに無知だった頃、パソコン一台(一つの環境)に一つの人工知能的なものが用意されて、それに対して学習させていくようなイメージを持っていたがそんなことはなく、プログラム終了と同時に学習内容は消えてしまう。

...
init = tf.initialize_all_variables()

#学習前に追加
saver = tf.train.Saver()

sess = tf.Session()
...

#学習後(今回は最後の行)に追加、FILE_PATHは'/tmp/model.ckpt'等適当に
save_path = saver.save(sess, FILE_PATH)

この二行を追加することで、今回の学習内容を保存して置くことが可能となる。

元のファイルはチュートリアルをそのままコピペすれば作れるし、どこかその辺に転がっているので省略。

初めは手描き文字判定プログラムも同じファイルに書いていたため、デバッグの度に再学習させてしまいとても効率が悪かった。

ちなみに出来上がるファイルサイズは30k程度。スタンドアローンではないので一般的なプログラムとのサイズ比較はできない。

学習内容の読み込み・再利用

...

#呪文
saver = tf.train.Saver()

...

with tf.Session() as sess:
  #保存した学習内容を指定
  saver.restore(sess, FILE_PATH)
  ...

これは簡単。

OpenCvのインストール

いくつかのサイトではmakeする手順が書かれていたり、いっぱいいろんなファイルの導入をしろとかあったけど、

> sudo apt-get install python-opencv

これ一発で今回必要なものは入りました。なお環境によってはupdateが必要かもしれません。メッセージが出るので分かると思います。

リンクを貼りたいけど元サイトを見失ってしまいました。海外のサイトでシンプルに上記一行だけが表示されていました。

完成品

#
import tensorflow as tf

#画像処理のためのライブラリ
import cv2
import numpy as np

#
x = tf.placeholder(tf.float32, [None, 784])

W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)

#学習内容の読み書き用
saver = tf.train.Saver()

with tf.Session() as sess:
  #学習内容の読み込み
  saver.restore(sess, 'model.ckpt')

  #画像の読み込みと判定前処理、画像ファイルはIMAGE_PATHで指定
  images = np.zeros((1, 784))

  gray = cv2.imread(IMAGE_PATH, cv2.CV_LOAD_IMAGE_GRAYSCALE)
  gray = cv2.resize(255 - gray, (28, 28))

  images[0] = gray.flatten() / 255.0

  #判定処理。
  #argmaxだと画像の数字が戻ってくる。
  #こちらで数字を指定しないのでfeed_dictの引数y_は削除。
  prediction = tf.argmax(y, 1)
  print sess.run(prediction, feed_dict = {x: images})

以上で一応の手順(学習>評価)は確認できた。あとは必要に応じて適宜変更すればよろしいかと。

その他

触ってみたが、一般的なプログラミングと異なり、100パーセント正しい答えが出ない点がとても面白いと感じた。ただ、データの準備から評価方法の選定など、素人が簡単に手を出せるようなものではないという評判を痛感させられた。

あと、簡易版MNISTは数字を画面いっぱいに書いたり端のほうに寄せて書いたりするとでたらめな判定が返ってきた。90パーセントの正解率となっているが、入力側が気配りを十分にして90パーセント、ということか。もしそうなら使い勝手が悪く対策が必要。
この辺りは上位版MNISTをやってみて検証する必要がありそう。

機械学習自体はとても興味深い分野であるが、相当の量と高い質の勉強が必要になりそう。他にも同じようなライブラリがあり、どれがより正確に学習してくれるのかとか、どれがどの分野に強いライブラリなのかとか、向き不向きのようなものがあるのか?

知識が不足しているので様々な疑問が湧いてくるが、きりがないのでここまで。

参考