ラベル MNIST の投稿を表示しています。 すべての投稿を表示
ラベル MNIST の投稿を表示しています。 すべての投稿を表示

2019年5月10日金曜日

Jetson Nano で MNISTをラズパイカメラから動かしてみる

あれから、MNIST関係色々見てました。
詳しいことはよくわからなかったけど、層をたくさん経由すると「deep」になるとのこと。
だから、前回のはディープラーニングではないようです。
とはいっても、根本的な意味はよくわかっていないので、今後の課題とします。
ざっくりとした理解だけれども、今回の教師あり学習に関して言えば、画像から分布を作って(学習)、その分布に当てはめて近い値が出たらそれが答えだ!的な感じっぽい。
ディープの部分は写経なんだけれども、学習データ保存して、読込して、カメラから画像取得して読み込んだ学習データに照らし合わせてリアルタイムに数字認識するプログラムを書いてみた。
参考にしたサイトのリンク貼っておきます。

http://blog.brainpad.co.jp/entry/2016/02/25/153000

https://qiita.com/JUN_NETWORKS/items/6514e017e89b9adbfb8d

https://qiita.com/tsutof/items/2d2248ec098c1b8d3e32

ソース見たほうが早いかな。

import tensorflow as tf
import numpy as np
import os,sys
import cv2
from PIL import Image, ImageEnhance,ImageDraw

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def conv2d(x, W):
  return tf.nn.conv2d(x,W,strides=[1, 1, 1, 1],padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='SAME')

x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])

# 画像をリシェイプ 第2引数は画像数(-1は元サイズを保存するように自動計算)、縦x横、チャネル
x_image = tf.reshape(x, [-1, 28, 28, 1])
print(x_image)

### 1層目 畳み込み層
# 畳み込み層のフィルタ重み、引数はパッチサイズ縦、パッチサイズ横、入力チャネル数、出力チャネル数
# 5x5フィルタで32チャネルを出力(入力は白黒画像なので1チャンネル)
W_conv1 = weight_variable([5, 5, 1, 32])
# 畳み込み層のバイアス
b_conv1 = bias_variable([32])
# 活性化関数ReLUでの畳み込み層を構築
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

### 2層目 プーリング層
# 2x2のマックスプーリング層を構築
h_pool1 = max_pool_2x2(h_conv1)

### 3層目 畳み込み層
# パッチサイズ縦、パッチサイズ横、入力チャネル、出力チャネル
# 5x5フィルタで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)

### 4層目 プーリング層
h_pool2 = max_pool_2x2(h_conv2)

### 5層目 全結合層
# オリジナル画像が28x28で、今回畳み込みでpadding='SAME'を指定しているため
# プーリングでのみ画像サイズが変わる。2x2プーリングで2x2でストライドも2x2なので
# 縦横ともに各層で半減する。そのため、28 / 2 / 2 = 7が現在の画像サイズ

# 全結合層にするために、1階テンソルに変形。画像サイズ縦と画像サイズ横とチャネル数の積の次元
# 出力は1024(この辺は決めです) あとはSoftmax Regressionと同じ
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

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)

### 6層目 Softmax Regression層
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)

### 訓練 ###
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))


saver = tf.train.Saver()

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
config.gpu_options.visible_device_list="0"
with  tf.Session(config=config) as sess:
  sess.run(tf.initialize_all_variables())

  os.makedirs("./model_2",exist_ok=True)

  ckpt = tf.train.get_checkpoint_state('./model_2')
  if ckpt:
    saver.restore(sess, ckpt.model_checkpoint_path)
  else:
    for i in range(1500):
      batch = mnist.train.next_batch(50)
      if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1],keep_prob: 1.0})
        print("step %d, training accuracy %g"%(i, train_accuracy))
      train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

    saver.save(sess, "./model_2/model.ckpt")

  num_test = len(mnist.test.labels)
  sum_accuracy = 0
  for i in range(0, num_test, 50):
    sum_accuracy = sum_accuracy + accuracy.eval(feed_dict={x: mnist.test.images[i:i+50], y_: mnist.test.labels[i:i+50], keep_prob: 1.0})
  print("test accuracy:", sum_accuracy/(num_test/50))


  GST_STR = 'nvarguscamerasrc \
      ! video/x-raw(memory:NVMM), width=320, height=240, format=(string)NV12, framerate=(fraction)10/1 \
      ! nvvidconv ! video/x-raw, width=(int)320, height=(int)240, format=(string)BGRx \
      ! videoconvert \
      ! appsink'
  WINDOW_NAME = 'Camera Test'

  cap = cv2.VideoCapture(GST_STR, cv2.CAP_GSTREAMER)

  while True:
    ret, img = cap.read()
    if ret != True:
      break

    pilImg = Image.fromarray(np.uint8(img))
    #print(pilImg.format, pilImg.size, pilImg.mode)
    img_width, img_height = pilImg.size
    draw = ImageDraw.Draw(pilImg)
    draw.rectangle(((img_width - 150) // 2,
                         (img_height - 150) // 2,
                         (img_width + 150) // 2,
                         (img_height + 150) // 2), outline=(255, 255, 255))

    mnistImg = Image.fromarray(np.uint8(img))
    mnistImg = mnistImg.crop(((img_width - 150) // 2,
                         (img_height - 150) // 2,
                         (img_width + 150) // 2,
                         (img_height + 150) // 2))
    mnistImg = mnistImg.convert("L")
    color = ImageEnhance.Color(mnistImg)
    mnistImg = color.enhance(1.5)
    contrast = ImageEnhance.Contrast(mnistImg)
    mnistImg = contrast.enhance(1.5)
    brightness = ImageEnhance.Brightness(mnistImg)
    mnistImg = brightness.enhance(1.5)
    sharpness = ImageEnhance.Sharpness(mnistImg)
    mnistImg = sharpness.enhance(1.5)
    mnistImg = mnistImg.resize((28, 28), Image.LANCZOS)
    #print(mnistImg)
    mnistImg = map(lambda x: 255 - x, mnistImg.getdata())
    mnistImg = np.fromiter(mnistImg, dtype=np.uint8)
    mnistImg = mnistImg.reshape(1, 784)
    mnistImg = mnistImg.astype(np.float32)
    mnistImg = np.multiply(mnistImg, 1.0 / 255.0)
    # print(mnistImg)
    for i in range(len(mnistImg[0])):
      num=mnistImg[0][i]
      if num<0.4:
        print('    ', end="")
      else:
        print('%03d ' % (num*1000), end="")
      if i % 28 == 0:
        print('\n')

    #学習データと読み込んだ数値との比較を行う
    pred = sess.run(y_conv, feed_dict={x:mnistImg, y_: [[0.0] * 10], keep_prob: 1.0})[0]
    # print(pred)
    if not np.max(pred) < 0.5 :
      print(np.argmax(pred) ,np.max(pred))
      draw.text((10,10),f'{np.argmax(pred)} {round(np.max(pred)*100,2)}%')


    imgArray = np.asarray(pilImg)
    cv2.imshow(WINDOW_NAME, imgArray)

    key = cv2.waitKey(10)
    if key == 27: # ESC 
      break
起動すると、ウインドウが開いてカメラの画像が出ます。
真ん中の白枠に手書きの文字を入れると、上に値が出るってわけ。
認識率悪くて、コントラスト上げたり、明度あげたり、色々やってみてる。
コンソールに、プログラムからみたテンソルを表示しています。

色々やってて思ったのが、Jetson Nanoだと、何するにしてもメモリ不足で死にます。
これは、僕の書き方の問題なのかもしれないけど、いろいろシンドかった。
学習するにしても、バッチサイズ減らしてやらないと落ちるし、学習データの読み込みでも、ブラウザは落としておかないと死ぬ。
こういったあたりも、今後調べていきたい。
次は、自分で教師データ作って学ばせてあげたい。
できるかな?

2019年4月25日木曜日

Jetson Nano の TensorFlow で MNIST やってみる

お熱冷めないうちにやってみる。
git clone サンプル叩きマンは卒業して、一応ソースも書いてみる。
ただ、内容はさっぱりなので、見たページを覚書として残しておく。

https://www.scriptlife.jp/contents/programming/2016/10/19/post-1796/

http://domkade.hatenablog.jp/entry/2016/04/07/011016

男は黙ってチュートリアルだろと思って本家見に行ったら、Keras勧められてしまうので、参考にした情報が2016年とか、だいぶ古いけど、意味がわからないものが2つあると、そもそも理解できるところまで行かなそうなので、古いまま行きます。
なので、ソースを実行すると、ワーニング出ます。

$ cd ~/
$ mkdir mnist
$ cd mnist

mnist.pyっていうファイルを作ってみました。

import tensorflow as tf
import numpy as np

# mnistのの学習データがMNIST_dataフォルダになければダウンロードしてから読み込み
# あったらそのまま読み込み
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

# MNIST画像をランダムで1枚読み込んでみる
for listitem in mnist.train.next_batch(1)[0]:
  for i in range(len(listitem)):
    num=listitem[i]
    if num==0:
      print('    ', end="")
    else:
      print('%03d ' % (num*1000), end="")
    if i % 28 == 0:
      print('\n')
print('\n')

# 訓練画像入れ
# 訓練画像(28x28px)を1行784列の配列に格納する
# https://www.tensorflow.org/api_docs/python/tf/placeholder
x = tf.placeholder(tf.float32, shape=[None, 784])

# 重み
# 訓練画像のpx数の行、ラベル(0-9の数字の個数)数の列の行列
# 0埋めしておく(tf.zeros)
# https://www.tensorflow.org/api_docs/python/tf/Variable
# https://www.tensorflow.org/api_docs/python/tf/zeros
W = tf.Variable(tf.zeros([784,10]))

# バイアス
# ラベル数の列の行列
# 0埋めしておく(tf.zeros)
# https://www.tensorflow.org/api_docs/python/tf/Variable
# https://www.tensorflow.org/api_docs/python/tf/zeros
b = tf.Variable(tf.zeros([10]))

# ソフトマックス回帰を実行
# yは入力x(画像)に対しそれがある数字である確率の分布
# matmul関数で行列xとWの掛け算を行った後、bを加算する。
# yは[1, 10]の行列
# https://www.tensorflow.org/api_docs/python/tf/nn/softmax
# https://www.tensorflow.org/api_docs/python/tf/linalg/matmul
y = tf.nn.softmax(tf.matmul(x,W) + b)

# 正解用ラベル入れ
# https://www.tensorflow.org/api_docs/python/tf/placeholder
y_ = tf.placeholder(tf.float32, shape=[None, 10])

# 交差エントロピー
# 誤差関数の交差エントロピー誤差関数を用意
# https://www.tensorflow.org/api_docs/python/tf/math/reduce_sum
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

# 勾配硬化法を用い交差エントロピーが最小となるようyを最適化する
# 学習方法を定義 0.01は学習率
# https://www.tensorflow.org/api_docs/python/tf/train/GradientDescentOptimizer
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

# 用意した変数Veriableの初期化を実行する
# https://www.tensorflow.org/api_docs/python/tf/initialize_all_variables
init = tf.initialize_all_variables()

# Sessionを開始する
# runすることで初めて実行開始される(run(init)しないとinitが実行されない)
# https://www.tensorflow.org/api_docs/python/tf/InteractiveSession
sess = tf.InteractiveSession()
sess.run(init)

# 正しいかの予測
# 計算された画像がどの数字であるかの予測yと正解ラベルy_を比較する
# 同じ値であればTrueが返される
# argmaxは配列の中で一番値の大きい箇所のindexが返される
# 一番値が大きいindexということは、それがその数字である確率が一番大きいということhttp://blogspot.com/
# Trueが返ってくるということは訓練した結果と回答が同じということ
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

# 精度の計算
# correct_predictionはbooleanなのでfloatにキャストし、平均値を計算する
# Trueならば1、Falseならば0に変換される
# https://www.tensorflow.org/api_docs/python/tf/math/reduce_mean
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

print("before training accuracy %g"%accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

# 1000回の訓練(train_step)を実行する
# next_batch(50)で50つのランダムな訓練セット(画像と対応するラベル)を選択する
# feed_dictでplaceholderに値を入力することができる
for i in range(1000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
    train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1]})
    print("step %d, training accuracy %g"%(i, train_accuracy))
  train_step.run(feed_dict={x: batch[0], y_: batch[1]})

# モデルの評価
print("test accuracy %g"%accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

実行してみます。

$ python3 mnist.py

こんな感じの結果がでます。

python3 mnist.py 

    

                                                                                                                

                                                                                                                

                                                                                                                

                                                                                                                

                070 741 588 384 184 098     003 184 345 823 1000 564 054                                         

                682 992 992 992 992 890 607 776 992 992 992 992 992 282                                         

                713 992 992 992 992 992 992 992 992 992 992 886 419 011                                         

                247 980 992 992 992 992 992 992 792 666 435 066                                                 

                    956 992 898 078 078 078 078 031                                                             

                    839 992 964 211                                                                             

                    192 992 992 796 447 164 305 388 062 062 062 062 019                                         

                    109 929 992 992 992 992 992 992 992 992 992 992 749 164                                     

                        549 992 992 992 992 992 992 992 992 992 992 992 913 447                                 

                            356 501 788 788 780 384 384 450 788 788 937 992 890 423                             

                                                                    145 913 992 968 145                         

                                                                        498 992 992 596                         

                                                                        490 992 992 768                         

                                                                        490 992 992 768                         

                        227 278                                         490 992 992 768                         

                    070 862 984 611 490 490 149 035                 184 737 992 992 737                         

                    105 925 992 992 992 992 992 796 670 670 670 670 901 992 992 964 117                         

                        403 752 980 992 992 992 992 992 992 992 992 992 992 984 745                             

                                254 392 823 992 992 992 992 992 992 992 992 635                                 

                                        047 356 584 745 992 992 992 701 388 058                                 

                                                                                                                

                                                                                                                

                                                                                                                

                                                                                                            


2019-04-25 13:10:24.417408: W tensorflow/core/platform/profile_utils/cpu_utils.cc:98] Failed to find bogomips in /proc/cpuinfo; cannot determine CPU frequency
2019-04-25 13:10:24.419881: I tensorflow/compiler/xla/service/service.cc:161] XLA service 0x30de2ef0 executing computations on platform Host. Devices:
2019-04-25 13:10:24.419973: I tensorflow/compiler/xla/service/service.cc:168]   StreamExecutor device (0): <undefined>, <undefined>
2019-04-25 13:10:24.495340: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:965] ARM64 does not support NUMA - returning NUMA node zero
2019-04-25 13:10:24.495643: I tensorflow/compiler/xla/service/service.cc:161] XLA service 0x2f6e9ff0 executing computations on platform CUDA. Devices:
2019-04-25 13:10:24.495706: I tensorflow/compiler/xla/service/service.cc:168]   StreamExecutor device (0): NVIDIA Tegra X1, Compute Capability 5.3
2019-04-25 13:10:24.496060: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1433] Found device 0 with properties: 
name: NVIDIA Tegra X1 major: 5 minor: 3 memoryClockRate(GHz): 0.9216
pciBusID: 0000:00:00.0
totalMemory: 3.86GiB freeMemory: 742.95MiB
2019-04-25 13:10:24.496126: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1512] Adding visible gpu devices: 0
2019-04-25 13:10:25.773266: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-04-25 13:10:25.773363: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990]      0 
2019-04-25 13:10:25.773402: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0:   N 
2019-04-25 13:10:25.773596: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 273 MB memory) -> physical GPU (device: 0, name: NVIDIA Tegra X1, pci bus id: 0000:00:00.0, compute capability: 5.3)
2019-04-25 13:10:25.863593: I tensorflow/stream_executor/dso_loader.cc:153] successfully opened CUDA library libcublas.so.10.0 locally
before training accuracy 0.098
step 0, training accuracy 0.06
step 100, training accuracy 0.86
step 200, training accuracy 0.8
step 300, training accuracy 0.92
step 400, training accuracy 0.94
step 500, training accuracy 0.9
step 600, training accuracy 0.94
step 700, training accuracy 0.88
step 800, training accuracy 0.88
step 900, training accuracy 0.94
test accuracy 0.9175

動いたけど、写経っぷりにもほどがあるし、そもそもようわからんなぁ・・・
チュートリアルでコレって。。機械学習お熱下がっちゃうよ。。
悔しいから、本買って勉強しよう。