14
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Movidius NCS + Raspberrypi で自作DNNモデルを動かす

Posted at

概要

エッジでAIが流行っている昨今、ラズパイでdeeplearningというフレーズに踊らされ、tensorflowもcaffeも触ったことないのに勢いで買ってしまったMovidius NCSで、ようやく自作モデルを動かせたのでまとめておきます。

Movidius™ Neural Compute Stickとは

  • https://developer.movidius.com/
  • DNNの推論をやってくれるUSB型VPU
  • TensorFlow、Caffeのモデルを動かせる
  • Raspberrypiでも動く
  • 1万円くらい

使い方

ざっくりとこんな感じで動かします。

  • PC
  1. tensorflowでモデル作成
  2. SDKでモデルをNCS用にコンパイル
  • ラズパイ(+NCS)
  1. APIを叩いて、コンパイル済みモデルを読み込み、推論

コード

githubに置いておきます。
https://github.com/watanabeyyy/NCS_test

  • train.py
    • tensorflowで学習させたスクリプトです。
    • MNISTベースで作ってますが、MS Pゴシックの数字を学習させてます。
  • create_pred_model.py
    • 学習済みモデルを、SDKでコンパイルできるように変換するスクリプトです。
    • 学習した重みを読み込み、推論用モデルとして新たに保存します。
  • prediction.py
    • NCS用にコンパイルされたモデルを読み込み、推論を行うスクリプトです。

導入

環境は

  • Ubuntu PC (VirtualBox on Windows)
  • Raspberry Pi 3 Model B

PC

###1. SDKをインストール
Ubuntu 16.04にしか入らないみたいです。

$ git clone http://github.com/Movidius/ncsdk
$ cd ncsdk
$ make install

###2. 自作モデルをコンパイル
ここでだいぶ苦戦しました。サンプル動かす以上の情報がなかなか得られず・・・
とりあえず、サンプル通りmvNCCompileコマンドにtensorflowのmetaファイル渡してやって、このエラー

$ mvNCCompile -s 12 model.meta -in=input -on=softmax
.....
[Error 34] Setup Error: Values for input contain placeholder. Pass an absolute value.

tensorflowでinputがplaceholderなのは当たり前だろと思って、別の要因を探していたのですが、改めて難解なサンプルをよくよく見てみると

inception_v1.py
import numpy as np
import tensorflow as tf

from tensorflow.contrib.slim.nets import inception

slim = tf.contrib.slim

def run(name, image_size, num_classes):
  with tf.Graph().as_default():
        image = tf.placeholder("float", [1, image_size, image_size, 3], name="input")
        with slim.arg_scope(inception.inception_v1_arg_scope()):
        logits, _ = inception.inception_v1(image, num_classes, is_training=False, spatial_squeeze=False)
    probabilities = tf.nn.softmax(logits)
    init_fn = slim.assign_from_checkpoint_fn('inception_v1.ckpt', slim.get_model_variables('InceptionV1'))

    with tf.Session() as sess:
        init_fn(sess)
        saver = tf.train.Saver(tf.global_variables())
        saver.save(sess, "output/"+name)

run('inception-v1', 224, 1001)
  • inputのtensor.shapeでNoneは使わず定数を指定してる(入力のテンソルサイズは固定)
  • 学習済みモデルのckptファイルを読み込んで、推論用のsessを新たにsaveしてる
    ていうのが大事そうです。
    (確かにhttps://movidius.github.io/ncsdk/TensorFlow.html に、Save Session with Graph and Checkpoint Informationと記述があります)

ということで改めて

2.1 推論用モデルを作成

推論用のモデルを保存します。

create_pred_model.py
import tensorflow as tf

def predict(x):
    #
    #計算グラフを書く
    #
    y = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2,name="output")

    return y

def run(name):
  with tf.Graph().as_default():
    input = tf.placeholder("float", [1, 108, 108, 1], name="input")
    output  = predict(input)

    with tf.Session() as sess:
        saver = tf.train.Saver(tf.global_variables())
        last_model = "./model/cnn-model-99"
        saver.restore(sess, last_model)
        saver.save(sess, name)

run('./model/pred_model')

入出力にnameを明示しておくのが無難です。
pred_model.metaとしてモデルが保存されます。

2.2 推論用モデルをコンパイル

pred_model.metaに対してコマンドを叩けば、コンパイルが通りました。

$ mvNCCompile -s 12 pred_model.meta -in=input -on=output

NCS用モデルがgraphとして保存されます。

ラズパイ

1. APIをインストール

Debian 9 Stretchにしか入らないみたいです。

$ git clone http://github.com/Movidius/ncsdk
$ cd ncsdk
$ make install

2. 推論

https://github.com/movidius/ncappzoo/tree/master/apps/image-classifier を参考にこんな感じで作成。

prediction.py
import mvnc.mvncapi as mvnc
import numpy as np


def predict(input):
    devices = mvnc.EnumerateDevices()
    device = mvnc.Device(devices[0])
    device.OpenDevice()

    with open('./model/graph', 'rb') as f:
        blob = f.read()
    graph = device.AllocateGraph(blob)

    for i in range(4):
        graph.LoadTensor(input[i], 'user object')
        output, userobj = graph.GetResult()
        print(np.argmax(output))

    graph.DeallocateGraph()
    device.CloseDevice()

    return output


if __name__ == "__main__":
    input = np.load("test_data.npy")
    predict(input.astype(np.float16))
  • LoadTensor()にはfloat16で渡さないとダメっぽいです

3. 動作確認

ラズパイにNCSを挿して、スクリプトを実行してみます。
テストデータとして使ったのは下の4枚の画像です。
Figure_1.png

$ python prediction.py
7
1
9
5

うまく動いているみたいです。
NCSの性能については追々評価したいと思います。

まとめ

  • raspi+NCS+webcamの格安画像認識システム、ありかも
  • tensorflow、意外と楽しい
14
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?