忘れそうな内容をメモしています

忘れっぽいのでメモ帳がわりに色々書いてます

M5StickVでオートエンコーダを動かしてみる①

先日作成したCNNモデルを元にオートエンコーダをM5StickVで動かしてみました。このオートエンコーダですが、設備の異常検知用途で色々使えそうだなーと気になっていました。 オートエンコーダの概要については以下が大変わかりやすかったです。 www.youtube.com

以下手順です。今回もモデルの作成はgoogle colabで行いました。

1.モデル作成

以下のブログの解説を参考にさせていただきつつ、kerasのオートエンコーダの記事のMNISTを使った「Convolutional autoencoder」のモデルをh5形式で保存しました。

elix-tech.github.io

次にtflite形式→kmodel形式と変換します。tflite形式への変換はtflite_convertコマンドで変換できましたが、kmodel形式の変換をバージョンv0.1.0-rc5のnncaseコマンドで行ったところ下記のエラーが出ました。

コマンド

#!./Maix_Toolbox/ncc/ncc -i tflite -o k210model --dataset images ConvolutionalAutoencoder.tflite ConvolutionalAutoencoder.kmodel

エラー(抜粋)

Fatal: Layer Conv2d is not supported 

エラー内容でググってみると「最新版を使いなさい」とのことだったので、最新版(v0.2.0-beta4)を入れて以下コマンドで無事kmodel形式に変換できました。
*v0.2になって引数の指定の仕方が色々と変わっているので注意が必要です。

!./Maix_Toolbox/ncc_v2/ncc compile ConvolutionalAutoencoder.tflite ConvolutionalAutoencoder.kmodel -i tflite -o kmodel --dataset images 

ただ、以前試したCNNモデル(Conv2d使用)はv0.1.0-rc5でも変換できたんですよねえ。何が違うんだろう。

2.M5StickVへの移植

以下のコードでM5StickVのLCDの左にカメラ画像、右側にオートエンコーダで復元した画像を表示しています。ちなみにmaixpyのバージョンはmaixpy_v0.5.0_38_g4c4d5b6_m5stickv.binを使いました。

また、ハマった点としてバージョンv0.2.0-beta4のnncaseで作成したモデルを読み込む際にはkpu.loadの後にkpu.set_outputsが必要になったようです。このあたりは以下記事を参考にさせていただきました。ありがとうございます。 www.shtsno24.tokyo

ちょっと崩れているように見えますが復元できているように見えます。学習していない「A」は真ん中が潰れて復元できていないことがわかります。

f:id:shintarof:20200530022006p:plainf:id:shintarof:20200530112326p:plain
import sensor,lcd,image
import KPU as kpu
lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1)
sensor.set_hmirror(1)
sensor.run(1)
task = kpu.load(0x300000) 
a=kpu.set_outputs(task, 0, 28,28,1)

while True:
    #camera image
    img1 = sensor.snapshot()
    img1 =img1.resize(28,28)
    #auto encoder image
    img2 = image.Image()
    img2 = img2.resize(28, 28)
    
    a=img1.pix_to_ai();             #generate data for ai
    fmap=kpu.forward(task,img1)

    x = 0
    y = 0
    for i in range(len(fmap[:])):
        color = image.grayscale_to_rgb(int((fmap[:][i])*255))
        img2.set_pixel(x,y,color)        
        x = x + 1
        if x > 27:
            x = 0
            y = y+1
            
    img1=img1.resize(112,112)
    lcd.display(img1,oft=(4,11))  

    img2=img2.resize(112,112)
    lcd.display(img2,oft=(116,11))

今度はオリジナルのデータセットを使って実際に異常検知にトライしてみようと思います。