2020年4月14日火曜日

0からごみを生み出す!素人機械設計 入門




 サークルの新歓っていつなのかわからない中の人です。今回はメカ設計未経験のド素人が、トイラジコンの設計をする話です。



1.サイズを決めよう!


作りたいサイズは道路が基準。
Jet何某が2車線使っているので、対抗して1車線分で作成。

 何を作るかは決めたので、最初はメカの設計から始めました。手元にあったレゴの道路プレート(廃盤、代替品が出てる)の1車線分を基準にサイズを決めました(50mmx95mm、車軸間62.5mm)。このサイズが後々悲劇を生むわけなのですが。

2.大まかに設計しよう!


設計の参考にしたMINI-Z AWD MA-010。
4輪駆動、ギヤデフ、4輪独立サスなどロマンもりもり。
これの最新版がMA-030で、FF版のMA-03Fがベース。

盛り込みたい機能は決まっているので、実際のラジコンを参考に設計をはじめました。参考にしたラジコンは目標サイズより一回り大きいので、各部分をスケールダウンしながら、違う設計に変えていく必要がありました(丸パクリはできないからね)。
 うだうだ設計を進めつつ(実は基板と並行して設計)、2月中頃には最初の設計が終了しました。

3.条件をよく見よう...


DMMのAgiristaは初めて使った。
最小厚み等で3Dプリント担当者には相当ご迷惑をおかけしました。

 今回はAgiristaやMJFの精度を見極めたかったので、アクリルUltraの使用は最小限にして、AgiristaやMJFを多用することにしました。(Agiristaは単価の安いアクリルだと思っていた)
 実際にDMMの3Dプリントサービスに自分で設計したデータを投げつけたところ、Agiristaで作ろうとしていたデータに厚みが足らない部分があるために作成できないとの連絡が届き、結局設計変更を行い事なきを得ました。

4.足らない強度と精度


できた部品。
届いた部品を嬉々として組み立てたが...

 数日後、部品が届いたので試しに組んでみることにしたのですが、届いた部品を見て絶句しました。あまりにも小さすぎたのです。
 これは決してDMMのせいではなく(むしろほぼ設計通り)、完全に設計段階で本当のサイズを確認していなかった私のせいでした。
 実際に組んでみたのですが、当然思ったとおりには動作しませんでした(小さく作りすぎたため、強度も精度も足らない)。

数万円のお小遣いがゴミに変わった瞬間でした。

5.再設計


再設計は辛いよ...

 ガラクタを作った事実に直面した次の日から、再設計を始めました。この時には、いろいろ妥協して既製品を使うことにしたのですが、またいろいろありました(その辺は再設計編で)。

6.次回予告

 URLのまとめは初回投稿にあるので、よかったらどうぞ。また、テクニカルな面の解説は別にしようと思っています。こちらは少々お待ちください...





©2020 shts All Right Reserved.

2020年4月13日月曜日

卒業制作(改め入学制作)(現在進行形)




 大学院に進学したものの授業開始が5月になり、就活がリアルに終活になりそうな中の人です。今回はかねてからやってはいたものの、あまり表に出してこなかった、卒業制作(改め入学制作)の話です。



1.卒業(入学)制作までの経緯


現状の"名称未設定"君。いい名前を考えてほしい。

 大学に入ってから、あまり"自分の作りたいものを作る"ことができていなかったのと、卒業研究からの逃避場所を設ける観点から、何となくCADをいじり始めたのが最初です。作るものに関しても完全に何となくで自動運転の車に決めました。

2.仕様について


ユニットごとにばらしたところ。

 仕様を固め始めたあたりにM5StickVを塩漬けにしていたことを思い出し、これを使うことに決めました。せっかくなのでいくつか試すことにしました。
  • サスペンション、デフ、ステアリングを盛り込む
  • 昇圧IC、モータの電流検知、LiPo充放電回路の搭載
  • テレメトリシステム、DeepLearningによる画像処理(Semantic Segmentation)
 ざっと書くとこの辺でしょうか。(本当はFPGAの小さいヤツを積んで、デジタルセンサのハブを作るとかも考えていました。)
 すべてにおいて専門外の中の人がやるにはとてつもなく酷野心的ではありますが、とりあえずやってみました。

3.ページまとめと次回予告


  1. 作り始めた経緯(今回)
  2. 0からごみを生み出す!素人機械設計 入門
  3. 素人でもわかる!"回 路 設 計"におけるリスケジューリング
  4. 0からごみを生み出す!素人機械設計 あげいん
  5. 基 板 が 届 か な い
  6. M5StickV触ってみた
  7. (M5StickVでセマンティックセグメンテーション)
  8. (基 板 実 装)
  9. (回路設計あげいんにならないといいな)
  10. (ESP32でテレメトリ)
  11. (動け、"名称未設定"君)
()の中身は現在進行中or予定です。おそらくうまくいかないので、あてにしないでください。

→2024/8/31更新:仕切りなおす直すことにしました。次回予告も変更になります。

次回は、"0からごみを生み出す!素人機械設計 入門"です。次の更新はいつになるのか...


©2020 shts All Right Reserved.

2020年3月26日木曜日

kmodel v4 tips




 ここ最近はFPGAに全く触れていない中の人です。kmodel v4の実装で詰まったところがあったので、まとめておきます。


1.KPUのメモリとモデル圧縮


推定されるKPUのメモリ空間の割り当て(中の人の想像)。
コンパイル時にWeightsとDataの境界を決定しているらしい。

NNCaseでは、KPUのメモリ空間を6MBのメインメモリと2MBの入出力データ用メモリに分けており、重みやバイアス、中間生成データはメインメモリに載せているようです。
 このため、大きなモデルを載せるためにはメインメモリ側と入出力専用メモリ側の両方でモデルを圧縮する必要があります。今回作成したモデルの場合、入出力専用メモリは足りるのですが、メインメモリ側でサイズ超過が発生しました。

1-1.カーネルサイズ、チャンネル数


 CNN系のレイヤでは、カーネルサイズと入出力のチャンネル数が重みパラメータ数を決めるのですが、大半のモデルでは チャンネル数 >> カーネルサイズなので、チャンネル数削減の方がよりモデルの圧縮に効いてくるようです。

1-2.レイヤ数


レイヤ数の削減は、パラメータ数の削減以外にもネットワーク全体の高速化に効いてきます。ですが精度を落ちてしまうのでそこのバランスはしっかり見ておく必要があります(チャンネル数の削減も同じ)。

1-3.入力データサイズ


 中間生成データの削減には、入力データのサイズを落とすことも有効です。入力のサイズを落とすことで、レイヤ通過後の中間生成データも小さくしようというわけです。


 NNCaseの仕様的にパラメータを載せる領域と中間生成データを載せる領域も分けているようです。中間生成データ領域の量は、モデル内で最も中間データが大きくなった時の値で固定なので、ここを小さくするのが最も効果的でした。

2.アクセラレーション


 完全な形でKPUのアクセラレーションをしようとした場合、いくつかの制限があります。
  • 各レイヤの入力フィーチャーマップが320x240以下かつ出力フィーチャーマップが4x4
  • どの辺も同じパディング幅であること
  • Conv2DやDepthwiseConv2Dのカーネルサイズは1x1または3x3、かつストライド幅が1または2
  • MaxpoolとAveragepoolは2x2または4x4
  • 要素ごとの活性化関数がReLU, ReLU6, LeakyRelu, Sigmoidで、PReLUは未対応(FAQ上だと使える関数に...ってなってたけど、実際はよくわからん)
 部分的なアクセラレーションになるのは

  • 畳み込み系のレイヤで非対称なパディング、パディングされていない場合
  • ストライドが1、2以外(KPUConv2D+StrideSliceに置き換え)
  • MatMul(Pad(to 4x4)+KPUConv2D(1x1kernel)+Crop(to 1x1)に置き換え)->Beta 3でKPU matmulが追加されたので、もしかしたら専用の命令に置き換わってるかも。
  • TransposeConv2D(SpaceToBatch+KPUConv2D+BatchToSpaceに置き換え)
らしいです。これ以外にも置き換えはあるかもしれないのですが、公開はされていないです(NNCaseのオプションに--dump-irをつければレイヤの変換過程が見られる)。
意外とFakeKPUConv2DとかIgnoreが多かったです。

参考:https://github.com/kendryte/nncase/blob/master/docs/FAQ_EN.md

3.入出力データの扱い


この辺は情報が特に出回っていないので、苦労しました。

3-1.データの正規化


 トレーニング時に入力データの正規化を行いますが、M5StickV上で動かすことを考えると[0, 1]に正規化したほうが扱いやすかったです。どうやらNNCaseが勝手に、画像データの入力の場合は[0, 1]に正規化しているようです。[0, 255]とかでもやったのですが、うまくいかなかったです。

3-2.出力データフォーマット


 入力が画像の場合、image.Image()にすればいいので問題ないのですが、出力は画像出力でも1次元のtupleなので変換する必要があります。いろいろ探した結果、NCHWだったことが判明し、実際に変換してみても同じだったので安心しました。
 ただ、tuple->Imageの変換の際には、画素ごとに色を割り当てたいのでNCHWよりもNHWCの方がより便利です。NNCaseのオプションで変えられればいいのですが。

4.その他

4-1.Maix_Toolbox


 Maix_Toolboxにはtflite2kmodel.shという変換用のshellスクリプトが用意されています。中身はNNCaseでコンパイルを実行しているだけなのですが、コンパイルオプションから推定するとNNCase V0.1.0向けであることがわかります。
 なので、NNCase V0.2.0系を入れてしまうと動かなくなります。また、V0.1.0は対応するレイヤが少ないので、個人的にはV0.2.0をお勧めします。

参考:

4-2.Beta2とBeta3


 いつの間にやらNNCase v0.2.0 Beta3がリリースされたようなので、そちらのテストをしました。
 コンパイルのオプションは、Beta 2で使えたものはすべて使えました。Beta 3で追加されたオプションはあるかどうかがわかりませんでした。
 コンパイル結果を見ると、同じモデルでもBeta3の方がメインメモリの使用量が増えているようです。また、"Optimize Pass 3"という工程が増えていました。実行速度はあまり変わっていませんでした。もう少しコンパイラの気持ちになってモデルを作れば、速くなるかもしれません。

4-2(2020/5/21追記).Beta4


 Beta3が出たと思ったら,NNCase v0.2.0 Beta4がリリースされたようなので、そちらのテストをしました。
 リリースの内容を見ると,オプションとして,--weights-quantize-threshold,--output-quantize-threshold,--no-quantized-binaryが追加されているようです.(実は,--dump-weights-rangeなんていうオプションも追加されてる)
量子化周りの設定のようで,しきい値の設定をできるようです.(後でいろいろ書きます.)
 出力されるモデルサイズはBeta3とBeta4で違いはないようです.オプション次第で変わるかもしれないです.

4-3.ファームウェア


カスタムファームウェアの_boot.pyをいじった。
中央右の得体のしれないものは猫。

 フラッシュに焼く際に、モデルが大きすぎると載せられない問題が発生します。その対策として、自分でファームウェアをビルドする方法があります。


 やり方は、上のURLを参考にしてもらうとして、私の場合は_threadとulab、MaixPy IDEのみを有効化し、あとは無効化しました。


©2020 shts All Right Reserved.

2020年3月21日土曜日

NNCase on Windows 10



 NNCaseのV0.2.0がWindows 10に対応しているとのことなので、使ってみました。
"tf.kerasの自作モデルをNNCase  v0.2.0 (kmodel V4)に対応させ、M5StickV(K210)上で動かす(2)" のWindows 10版だと思ってください。





2-1.NNCaseのダウンロード


 今回使用する kmodel V4に対応するNNCaseはV0.2.0以降なので、最新版(2020/3/16現在)であるNNCase v0.2.0 から各OS版の圧縮ファイルをダウンロードします。Windows 10の場合は、ncc_win_x86_64.zip を選択しましょう、

2-2.NNCaseのインストール(?)

 落としてきたファイルをどこでもいいので解凍します。解凍した中にncc.exeが存在するはずです。
 このexeファイルをトレーニング済みの.tfliteがあるフォルダに投げ込みましょう。これでインストール(?)は終わりです。

2-3.コンパイルオプション

2-4.コンパイルの例

 コンパイル例です。


.\ncc.exe compile Model.tflite Model.kmodel -i tflite -o kmodel --dataset ./Img/ -- dataset-format image --inference-type uint8 --input-mean 0 --input-std 1 --dump-ir --input-type uint8 --max-allocator-solve-secs 120 --calibrate-method l2

 中の人は、PowerShellで動作確認しました。

2-5.その他

 一応動いたので、よし。
 (Macを持っていないので、そちらの動作確認はほかの方に投げたい所存です。)


©2020 shts All Right Reserved.

NNCase 記事まとめ




 NNCaseの記事のまとめです。


tf.kerasの自作モデルをNNCase v0.2.0 (kmodel V4)に対応させ、M5StickV(K210)上で動かす


kmodelを作るときのtips


セマンティックセグメンテーションやってみた


NNCase V1.7を試す




©2020 shts All Right Reserved.

2020年3月18日水曜日

tf.kerasの自作モデルをNNCase v0.2.0 (kmodel V4)に対応させ、M5StickV(K210)上で動かす(3)



 この前研究室に行ったら、学位記って書かれた紙を受け取った中の人です。概略(0)モデル構築(1)kmodelの生成(2)に引き続きkmodel v4をM5StickVで動かす話です。


3-1.MaixPyのファームウェア

 M5StickV向けのプログラミングにはいくつかの方法がありますが、今回はkmodel v4(NNCase v0.2.0)対応のMaixPyを使います。MaixPyを使う場合は、Sipeedが配布しているファームウェアを焼く必要があります。最新版はv0.5.0_31のようです(2020/3/18現在)。M5StickV向けのファームウェアは、maixpy_v0.5.0_31_gd3e71c0_m5stickv.bin です。


3-2.ファームウェアを焼く

ファームウェアの書き込み。中の人は独自ビルドのファームウェアを使用するため、
ファイル名が異なっている
 先ほど紹介したファームウェアと、前回生成したkmodelをKflash GUIを用いて焼きました。ファームウェアは0x00000番地(デフォルト)、kmodelは0x500000番地を先頭に設定しました。

3-3.KPUライブラリ

 MaixPyはMicroPythonをベースにK210向けにライブラリを追加・改変したもので、Python-likeな書き方ができます。K210に搭載されているKPU向けのライブラリも追加されており、比較的容易に扱うことができます、

3-4.関数解説

 Kmodel V4からマルチアウトプットに対応した関係で、V3(NNCase v0.1.0)のころとは書き方が変わっています。

3-4-1. KPU.load(addr)

引数
  • addr : kmodelの先頭アドレス
戻り値
  • task : kpu_netオブジェクト
 最初に実行するのが KPU.load(addr) です。addrはkmodelを焼いた際に指定した先頭アドレス(今回なら0x500000)を指定します。task = KPU.load(0x500000) のようにし、kpu_netオブジェクトを保持しておきましょう。

3-4-2. KPU.set_outputs(task, index, width, height, depth)

引数
  • task : kpu_netオブジェクト
  • index : 何番目のモデル出力かを指定
  • width、height、depth : 出力の横、縦、深さ形状
戻り値
 いまいちわかっていません。どなたか情報をください。
 2020/3/26追記:ただのboolでした。確保できればTrueが返ってきます。

 Kmodel V4になってから必要になった関数です。V4からは複数出力に対応したので、このようなものが必要になったようです。タプル等を使って複数同時指定皆体なことはできないので、各モデル出力に対して実行する必要があるようです。

3-4-3.  KPU.forward(task, data, [layer)

引数
  • task : kpu_netオブジェクト
  • data : モデル入力。imageオブジェクトのみかも。
  • layer : 実行するレイヤ番号。
戻り値
  • fmap : フィーチャーマップ 
 KPUで実際にモデルを実行する関数です。layerは省略すると、モデル全体の計算を行います。fmapはNCHWフォーマットで、単一出力の場合は、1次元化されたタプルが返ってきます。

3-4-4. KPU.memtest()

 メモリの確保状況を取得します。

3-4-5. KPU.deinit(task)

引数
  • task : kpu_netオブジェクト
 メモリの開放などを行います。

3-5.動作

動作の様子。もっさりしている。


とりあえず動作しました。画面描画を含め3FPSを少し超える程度ですが、動いているのでよしとしましょう(KPU単体なら7FPS程度)。より高速に動作させる場合は、モデルのレイヤ数の低減や入出力サイズの縮小を行うべきです。

 ソースコードはこちら:https://github.com/shtsno24/DAE_for_M5StickV/blob/master/M5StickV/KPU_Test.py

3-6. まとめ

 全4回でM5StickV上でKmodel V4を動かす話をしてきました。日本語情報がほぼない中で完全手探りでしたが、簡易的に動かすことができました。まだ試していない関数があるので、今後の課題にしておきます。
 今後はセマンティックセグメンテーションなどの応用にチャレンジしていきたいと思います。

参考:KPU - MaixPy DOC https://maixpy.sipeed.com/en/libs/Maix/kpu.html
   MaixPy support new nncase & Kmodel V4 Now~ - MAIX - Sipeed bbs
   https://en.bbs.sipeed.com/t/topic/1790


©2020 shts All Right Reserved.

2020年3月16日月曜日

唐突に学部4年間を振り返る



 あまりにも唐突に始まりました、学部4年間の振り返りです。おそらく地球上でこの記事を 黒歴史認定して消し去ろうとする 熱心に読むのは未来の私一人なのですが、まあやっていきましょう。



0.高校時代

 高校時代はLEGO(特にTechnic)が大好きで、WROに友人とともに出てました。最初は機械系を志望していたのですが、途中で電気電子系の学科に変更しました。
 アキバでRaspberry Pi Model Bが発売された当時、Make:とかを読んでいた当時の中の人は、"回路系も面白そうだな"という単純な思考で変更していた気がします。

暇なときに作ったロボットアーム。プログラムを書いてくれた友人には圧倒的感謝。

 Raspberry Piとの出会いは結構衝撃的で、まともにPC(?)でプログラミングしたのはこれが最初でした。なんだかんだ縁あって、最初のラズパイコンテストで学生賞になりました。

当時作成した動画。スマホでいいじゃんとかは言っちゃダメ

 当時は金工木工室をほとんど貸し切りで使っており、動画中のアクリルケースはここで加工しました。モノづくりの環境としては木の切りくずに悩まされた以外、非常に良いものでした。

 大学進学に当たり、もともとは国立の大学を狙っていたのですが、おもに本人の実力不足と努力不足により、滑り止めで受けた東京にある私大に進むことになりました。
 DNNを組込み分野に応用したいって話を考え始めたのが高校を卒業したあたりで、今考えれば、今の研究をやり始める遠因だったかもしれません。

当時の投稿はこの辺:https://www.shtsno24.tokyo/2014/10/

1年生

 期待に胸膨らませ入学式に来たわけですが、式の第一部が終わるころには北の大地に島流しされました。寮生活ではクラスターのメンバーに恵まれ、さらにうまいこと機材とかを持ち込めたので、趣味の開発を続けることができました。ラズパイコンテスト用のHW作成は5-6月ごろからはじめていました。

 このころは、授業の成績が 控えめに言ってクソ 目を覆うほどひどいもので、力学でC、実験でBが付いていました。2Qの試験が終わり、実家に帰省するときには気分がどんよりしていたことを覚えています。
 実家に帰省した後は、ラズパイコンテストのSW開発をずっとしていました。当時は20年物のクーラーを動かす勇気がなく、27℃の部屋でGPU付きのノートを全開にしてサウナ状態でAIのトレーニングをしていました(2016年当時Donkey Carなんて知らず、SWもほとんど自前で作成していました)。

2度目の学生賞。動画作るの難しい。


 苦労した甲斐あって学生賞をいただきました(2度目)。授賞式的なものには授業の関係で参加できず、そこが心残りでした。

 3Q開始後は授業終了後から22:00まで図書館に残って勉強・レポート作成をするような生活で、土日も図書館にこもっていました。大学に入って最初につらかったのがこの時期でした。しかも成績は少ししか上がらず、絶望感に襲われていた記憶があります。

 いまのバイト先に拾われたのが、4Q終わってこちらに帰ってきた直後でした。高校時代にWROに出ていた友人の紹介で入りました。ロボット教室だったのですが、個人経営の小さいところだったので、入って1か月たたずして教材開発に参加するなど、相当ハードでした。

当時の投稿はこの辺:https://www.shtsno24.tokyo/2016/09/

2・3年生

 北の大地での刑期も終わり、東京でのキャンパスライフスタートです。ですが期待に胸膨らませることはあまりなかった気がします。それもそのはずで、実家から片道2h以上かかるため、1限の授業に出るためには6:00前に家を出るのが確定していたからです。別に電車通学にはさほど抵抗感はありませんでしたが、この通学時間(帯)は健康面で相当なハンディになりました(今もだけど)。

 とはいえ、授業にはほとんど出席し成績も少しは良くなったので、精神的には少し良くなった...と言いいたいところですが、絶望感から焦りに変わっただけでした。所属しているどのコミュニティ(大学・サークル・バイト)にも、私よりできる人が多かったので、取り残されまいと必死こいてその場でじたばたしてました。(結局何も進まない)

 このころ、毎週出される実験レポートが結構な重荷になっていました。2年次は手書き、3年次がPCだったのですが、要領よくやることが相当苦手だったので、毎日図書館にこもり、どのレポートも期限ぎりぎりまで作成していました。

初代Camellia。モータが両面テープで止まってる。

 サークルではマウスを2年がかりで作り、公式大会での完走にこぎつけました。この時期趣味は通学時間以外でのプログラミング以外ほとんどやっていなかった気がします。

 キャンパスの近くで一人暮らしをするためのお金が欲しかったので給付型の奨学金に応募しましたが、学内選考でことごとく落とされました。(親が無職になりかけ、金銭的な不安が増してきたのもこのころ)

とあるインターンに行って、無能感に打ちひしがれたこともあったっけ?

4年生

研究室配属ガチャに当選し、第一希望の研究室に入ることができました。研究テーマは組込み向けFPGAにCNNのアクセラレータを載せて高速化するものを考えており、9月ぐらいの進捗報告会で初めて研究室向けに話してOKをもらいました。
 10月から本格的な開発が始まり、HLSツールのバグに悩まされながらも12月末には開発が終了、1月末の発表までには論文もほぼ仕上げられました。このころには13:00ラボ着->23:00ラボ発->25:30自宅着の健康を害する以外何もないルーティンが出来上がっていました。

 バイトの方は2月からのコース再編の関係で、ほぼゼロからコースの立ち上げを行いました。数人のチームを組み、その中のリーダー的な役回りをしていました。このころに他人にタスクを振ることを覚え始めました。(その流れで、3月の対応や5月以降のコース再再編のPMをやる羽目に)

 サークルにはほとんど顔を出していないので、非常に申し訳なく思っていますが、肝心のマウス(もどき)の進捗は虚無なので、これからもガラクタ作ってる影の薄いおじさんになりそうです。

 趣味の方は、いわゆる勉強会的なものに顔を出すようになりました。誰からの紹介もなく一人で行ったのですが、大きい勉強会になればなるほどいろいろなバックグラウンドの方がいるので結構刺激的です(自分の知らない分野の情報が入ってくるのが一番大きい)。

 

4年間で得たこと

  • 体重
  • 焦り
  • 処分に困るガラクタ、ごみ屋敷と化した自分の部屋
  • 両親からの心配
  • 将来の心配
  • 学位
  • 大学院進学


4年間で失ったもの

  • 健康
  • やる気
  • 記憶力
  • アイデア
  • 自尊心
  • 精神の安定感(小中の頃に失ってたかも)
  • 両親からの信頼
  • 将来への希望

4年間で学んだこと

  • 全力で取り組んでも、ほとんど上手くいかない。ごく稀に上手くいく。
  • カネは余裕。あったらあった分だけよい。
  • 長距離通学は、健康で金を買っている。
  • 予備を買うと予備がいらなくなる。
  • 進捗には実軸と虚軸があり、虚軸上で単振動していることがわかると非常に虚しい。
  • 大体のコミュニティには自分の上位互換がいる。
  • 要領の悪さは一生もの。
  • みんなすごい! 自分?無能。

まとめ

 4年間で精神と健康、金を使って、学位を錬成しました。両親や関係者の皆様には頭が上がりません。これから先も無能らしく皆様に媚びて生きるので、何卒よろしくお願いします。



©2020 shts All Right Reserved.

tf.kerasの自作モデルをNNCase v0.2.0 (kmodel V4)に対応させ、M5StickV(K210)上で動かす(2)



 卒業式が吹き飛んだ中の人です。今回も前回前々回に引き続き、NNCaseの話です。前回まででモデルの作成が終了し、変換の話になります。
2020/3/21 追記:Windows 10でもNNCaseが動きました!





2-1.NNCaseのダウンロード


 前回作成した.tfliteのモデルの変換には、kendryte提供のNNCaseを使用します。というわけでまずはダウンロードしましょう。
 今回使用する kmodel V4に対応するNNCaseはV0.2.0以降なので、最新版(2020/3/26現在)であるNNCase v0.2.0から各OS版の圧縮ファイルをダウンロードします。中の人はUbuntuを使用しているので、ncc_linux_x86_64.tar.xzを落としてきました。

2-2.NNCaseのインストール(?)

 落としてきたファイルをどこでもいいので解凍します。解凍した中にnccという名前のフォルダnccという名前のファイルが存在するはずです(おそらく./ncc/nccという形)。
 このフォルダごとトレーニング済みの.tfliteがあるフォルダに投げ込みましょう。これでインストール(?)は終わりです。

2-2-1.(補足)

 実はフォルダを移動させることなく、tfliteのパスと出力先のパスをファイル名とともにに指定してあげれば問題なく動きます(Linuxなら相対パスでも動作確認済み)。

2-3.コンパイルオプション

 モデルを変換する際のオプションは、以下のようになっています。(2020/5/31更新)

DESCRIPTION
NNCASE model compiler and inference tool.

SYNOPSIS
    ncc compile <input file> <output file> -i <input format> [-o <output
        format>] [-t <target>] [--dataset <dataset path>] [--dataset-format
        <dataset format>] [--inference-type <inference type>] [--input-mean
        <input mean>] [--input-std <input std>] [--dump-ir] [--input-type <input
        type>] [--max-allocator-solve-secs <max allocator solve secs>]
        [--calibrate-method <calibrate method>] [-v]

    ncc infer <input file> <output path> --dataset <dataset path>
        [--dataset-format <dataset format>] [--input-mean <input mean>]
        [--input-std <input std>] [-v]

OPTIONS
    ncc compile <input file> <output file> -i <input format> [-o <output
        format>] [-t <target>] [--dataset <dataset path>] [--dataset-format
        <dataset format>] [--inference-type <inference type>] [--input-mean
        <input mean>] [--input-std <input std>] [--dump-ir]
        [--dump-weights-range] [--input-type <input type>]
        [--max-allocator-solve-secs <max allocator solve secs>]
        [--calibrate-method <calibrate method>] [--weights-quantize-threshold
        <weights quantize threshold>] [--no-quantized-binary] [-v]

    ncc infer <input file> <output path> --dataset <dataset path>
        [--dataset-format <dataset format>] [--input-mean <input mean>]
        [--input-std <input std>] [-v]

    ncc -h [-v]

OPTIONS
    compile
        <input file>        input file
        <output file>       output file
        -i, --input-format  input file format: e.g. tflite, caffe, onnx
        -o, --output-format output file format: e.g. kmodel, default is kmodel
        -t, --target        target arch: e.g. cpu, k210, default is k210
        --dataset           calibration dataset, used in post quantization
        --dataset-format    datset format: e.g. image, raw default is image
        --inference-type    inference type: e.g. float, uint8 default is uint8
        --input-mean        input mean, default is 0.000000
        --input-std         input std, default is 1.000000
        --dump-ir           dump nncase ir to .dot files
        --dump-weights-range
                            dump weights range

        --input-type        input type: e.g. default, float, uint8, default
                            means equal to inference type

        --max-allocator-solve-secs
                            max optimal layout solve time in secs used by
                            allocators, 0 means don't use solver, default is 60

        --calibrate-method  calibrate method: e.g. no_clip, l2, default is
                            no_clip

        --weights-quantize-threshold
                            the threshold to control quantizing op or not
                            according to it's weigths range, default is
                            32.000000

        --output-quantize-threshold
                            the threshold to control quantizing op or not
                            according to it's output size, default is 1024

        --no-quantized-binary
                            don't quantize binary ops

    infer
        <input file>        input kmodel
        <output path>       inference result output directory
        --dataset           input dataset to inference
        --dataset-format    datset format: e.g. image, raw default is image
        --input-mean        input mean, default is 0.000000
        --input-std         input std, default is 1.000000

    -h, --help              show help
    -v, --version           show version
(https://github.com/kendryte/nncase/blob/master/docs/USAGE_EN.mdより引用)

 V0.1.0の頃とは異なり、compileとinferを指定する必要があります。inferはコンパイル済みのkmodelを実行するモードなので今回はパス。

2-3-1.ファイル・ファイルフォーマット・ターゲット

コンパイルオプションの<input flie>は入力ファイルなので、(入力ファイル名).tflite、<output file>は出力ファイルなので、(出力ファイル名).kmodelと入れておきます。
 同様に、-i(--input-format)には tflite、-o(--output-format)には kmodel としておきます。V0.1.0では-oには k210model と指定していたので注意してください。
 -t(--target)は指定しなくても大丈夫です。勝手にK210向けになります。(cpuに指定したときの挙動は未確認)

2-3-2.データセット・データセットフォーマット

--datasetは、データセット内の画像の入ったフォルダを指定しておきます。特には解説していなかったのですが、モデルのテスト用コードとtfliteへの変換用コード内で、テスト画像と出力画像を指定のフォルダ(./Img)に吐き出すようにしていました。今回はここを指定しておきます。これはパラメータの量子化で使っているようです。データ数が増えるほどよい性能になるかもしれませんが、コンパイルに時間がかかります。
 --dataset-formatは入力データがどのようなデータなのかを指定します。といっても、画像orその他の選択肢しかないです。今回は画像が入力なので image を選択しました。音声などの信号データや、2dデータだけどチャンネル数が3(もしかしたらor 1)ではないデータを使う際は raw にしてください。

2-3-3.インターフェース・入力データ

 --interface-typeは内部処理のデータ型を指定します。精度重視の場合には float を選択しますが、メモリの使用率が上がりKPUのアクセラレーションが受けられなくなります。
KPUを使用する場合は、uint8 一択になります。
 --input-meanと--input-stdは入力データの範囲調整に使われます。トレーニング時の入力データと同じ範囲になるようにしましょう。変換式は
y = (x - mean) / std
となっています。
(参考:https://github.com/kendryte/nncase/blob/master/docs/USAGE_EN.md)
NNCaseでは、最初に入力データを[0, 1]に変換してから上記の変換式を使うそうです。
0~1、-1~1、0~255の場合については、上記の参考URL内に値が出ています。

2-3-4.中間生成データ

 --dump-irはNNCase IRが生成する中間生成データを.dot形式でファイルにするかどうかのオプションです。

2-3-5.入力データ型

 --input-typeは入力データのデータ型を指定します。MaixPyで画像データを使う場合は、デフォルトの uint8 にしておきましょう。もし浮動小数点型の場合は float を指定しましょう。

2-3-6.その他

--max-allocator-solve-secsは最適な量子化のレンジの探索にかかる時間を指定します。デフォルトは60sですが、個人的に120sにしています(特に意味はない)。
 --calibrate-methodは最適な量子化のレンジの探索方法を指定します。デフォルトだと全レンジを使う no_clip になっていますが、 l2 を指定すると、時間はかかりますがよい量子化レンジを得られるようです。

2-3-7.2020/05/31追記

NNCase V0.2.0 Beta4の登場により,オプションが追加されています.
--dump-weights-rangeは,conv2dの重みパラメータの範囲を表示します.
--weights-quantize-thresholdは,conv2dとmatmulの重みパラメータの量子化をするための重みパラメータのしきい値を指定します.デフォルトは32です.これよりも大きい場合は,量子化しません.
--output-quantize-thresholdは,conv2dとmatmulの重みパラメータの量子化をするための出力要素数の閾値を指定します.デフォルトは1024です.これより小さい場合量子化しません.
--no-quantize-binaryは,すべての計算を量子化せずにfloatで行うオプションです.

2-4.コンパイルの例

 コンパイル例です(解説文書くの疲れた)。


./ncc/ncc compile Model.tflite Model.kmodel -i tflite -o kmodel --dataset ./Img/ -- dataset-format image --inference-type uint8 --input-mean 0 --input-std 1 --dump-ir --input-type uint8 --max-allocator-solve-secs 120 --calibrate-method l2

 Tensorflowでトレーニング・変換したModel.tfliteをModel.kmodelに変換しています。
 --dataset用のデータを./Imgに入れて置きました。.jpgや.pngのファイルをそのまま./Imgに入れるだけでよく、データセットの画像は0-1に正規化する必要はないです。
 トレーニング時には0-1に正規化していたので、--input-meanと--input-stdを合わせておきます。

2-5.次回予告

 次回は本編最終回で、M5StickVに実装していきます。
 MaixPyやKflashGUIのインストール・使い方は飛ばすので、ほかのところで探しておいてください。
ついに手に入れた、精密ナットドライバー
アキバとかではお目にかかれず、新宿のハンズで購入


©2020 shts All Right Reserved.

2020年3月12日木曜日

tf.kerasの自作モデルをNNCase v0.2.0 (kmodel V4)に対応させ、M5StickV(K210)上で動かす(1)



 最近は特に何もない中の人です。前回からの続きで、今回はM5StickV向けのモデルを作っていきます。
 コードについてはこちらから:https://github.com/shtsno24/DAE_for_M5StickV



1-1.ターゲットモデル

M5Stack+KPUの作例で多く出ているのがYOLOなどを使用した物体検出です。まあ同じものをやっても面白みに欠けるので、今回はCNNを用いたDeep Autoencoderを作成していきます。Autoencoderを端的に言えば、入力データと同じ出力データを得られるようにトレーニングしたモデルです。一見無駄に見えますが、モデル構造を工夫することで、画像圧縮・復元ができるようになります(特に意味はない)(セマンティックセグメンテーションや超解像のモデルに結構近いので応用重視で選んだ側面が大きい)。

 もう少し話すと、tf.kerasで容易にデータセットが構築できるCIFAR-10の入力画像をそのまま復元することにしました。モデルの入出力は32x32x3(トレーニング時は1x32x32x3)の画像になります(入出力のデータは0-1に正規化する)。

1-2.ライブラリ

 M5StickV向けのモデル作成にはTensorflowまたはCaffeが対応しているようです。今回は対応しているレイヤの多いTensorflowを使います。Tensorflowによる開発の場合、Tensorflow ->Tensorflow Lite -> Kmodelとなるので、Tensorflow Liteへの対応がカギになります。

NNCaseのアーキテクチャ。
資料は見当たらないが、ONNX・PaddlePaddle(百度のDLフレームワーク)も対応しているらしい。
(NNCase/README.mdより)

1-3.モデル作成前の準備

 Tensorflowをpipでインストールすればモデルの作成・推論はできます。トレーニングに関してはGPUが欲しいので、Google Colabを使うか、自前でGPU付きのマシンを準備したほうがよいでしょう。中の人は、ラボのUbuntuマシンにDocker環境を作りました。

1-4.モデル

 今回作成するCNNベースのDeep Autoencoderは、全層CNNで構成します。これはKPU
がCNN向けに最適化されているためであり(もっと言えば1x1 or 3x3カーネル、ストライド=1 or 2)、また全結合を使うよりもパラメータ数を削減し、小メモリ化を図るためです。(参考:NNCase/FAQ_EN.md)

今回作成したモデル全体図(tflite)。レイヤが確認できないほど長くてもメモリに載るのはありがたい。

今回のモデルはほぼオリジナルでNNCase/KPUのテストもかねて、必要以上に分岐・結合させたり、レイヤを増やしたりしています(そもそも無意味なタスクなので関係なし)。
 モデルを確認する際にはnetronを使いました。tf.kerasの.h5や.tfliteを読み込めるので、レイヤの種類の確認にはうってつけでした。

 モデルの作成で注意したいのが、使用できるレイヤの種類です。今回はtf.kerasを使用したので、kerasのレイヤからTensorflow Liteのレイヤに変換できるかが第一関門となります。このページを参考にしながら、対応するkerasのレイヤと紐づけていくのが楽でした。YOLO、UNetあたりなら、ほぼそのまま変換ができそうです。
 第二関門はTensorflow Liteのレイヤからkmodelのレイヤに変換できるかです。こちらはNNCaseのGitHubに一覧があるので、そこから対応するレイヤを確認しましょう。

コード:https://github.com/shtsno24/DAE_for_M5StickV/blob/master/Model.py

1-5.トレーニング

入力画像。実際は32x32の画像なのでものすごく小さい

 トレーニングは通常のtf.kerasを使った場合と同じです。今回は、訓練データ50000枚、検証データ10000枚で、100epoch回しました。バッチサイズは100枚とし、lossはMSE、OptimizerはAdamを使用しました。

tf.kerasモデルのトレーニング結果。輪郭がぼやけているが、雰囲気はとらえられている。

コード:https://github.com/shtsno24/DAE_for_M5StickV/blob/master/Train.py

1-6.TFLiteへの変換

 tf.kerasに変換したモデルを今度は.tfliteに変換します。このやり方は、ここを参考にするとわかりやすいです。参考例ではkeras付属のMobilenetを読み出して変換していますが、今回は自作のモデルを読み込んだうえで変換するので、書き方が少し変わってきます。

.tfliteの推論結果。tf.kerasの結果と大差ない。

コード:https://github.com/shtsno24/DAE_for_M5StickV/blob/master/Convert_to_tflite.py

1-7.次回予告

 .tfliteまで変換できたので、次回はkmodelへの変換となります(前回と今回でまだ本題に入っていない...)。



©2020 shts All Right Reserved.

2020年3月9日月曜日

tf.kerasの自作モデルをNNCase v0.2.0 (kmodel V4)に対応させ、M5StickV(K210)上で動かす(0)




 卒業も決定し、無事週5で研究室にこもっている中の人です。3月に予定されていた各種イベントが軒並み流れたため、研究もバイトもそっちのけでM5StickVで遊んでいました。(教授からオーバーワークかもよって言われました)。
 M5StickVで何をしていたかといえば、独自に作成したDNNモデルをK210内のKPU上で動かそうと悪戦苦闘していました。その時の苦労も含めて話していきたいと思います。


0-1.K210とKPU

 K210は、Kendryteが開発したデュアルコアRISC-Vチップです。内部構成はこんな感じ。

K210の概略。アクセラレータはKPU以外にもオーディオとFFT用が載る。(Image:Kendryte)

 このプロセッサの注目すべき(?)点としてKPUがあげられます。KPUはニューラルネット(おそらくCNNの演算をメインにしている)のアクセラレータであり、0.8TOPSの性能があるらしいです(参考:M5Stack - A series of modular stackable development devices)。
 今回はこいつを使っていきます。


0-2.KPUを開発する

 KPUはGPUなどと同じく、CPUのコードとは別の実行バイナリを作ってやる必要があります。そのためのツールとしてkendryteからNNCaseが提供されています。NNCase自体では学習モデルの作成は行わず、量子化とKPU向けの変換に特化しています。(PC向けのバイナリも吐き出せるようだが、今回は動作未確認)
 そのため、大元のモデルは自前で開発する必要があります。NNCaseの場合、Tensorflow/Tensorflow LiteまたはCaffeを使う必要があります(.tfliteが吐き出せればよいので、Torch->ONNX->tfliteとかでもできるはず)。


0-3.NNCase V0.1.0とV0.2.0

 NNCase V0.1.0からV0.2.0にかけての主な変更点は、GitHubのリリースを見てね(出落ち)。
 対応しているレイヤが増えたことや、コンパイルオプションが変わったことがあります。特にコンパイルオプションの違いはMaix Toolboxでのバグの原因になったりしてるようです。開発の最初、Maix Toolboxを入れていたのですが、結局tfliteの変換コードを作成し、直接NNCaseを使うことで解決しました。(一度作ればそこまで苦ではない)


0-4.開発環境

 リリースの内容的には、Win/Mac/Linuxがサポートされているようです。今回はTensorflow/Kerasによるトレーニング、Kmodelの生成をLinux(Ubuntu 18.04.3)、MaixPyによる開発をWindows 10で行いました。


0-5.次回予告?

 とりあえず導入は(中の人が力尽きたので)終わりで、次回はTensorflowによるモデル作成とTensorflow Liteへの変換の話の予定です。(ターゲットモデルは未定Deep Autoencoderになりました。)

 今回の一連の投稿は、モデル作成からM5StickVへの実装までの備忘録的なものにしていく予定です。
(V0.1.0の方は偉大なる先人のおかげで使用例や日本語資料も出ているのですが、V0.2.0の資料が少ない(日本語資料はほぼ皆無)という裏事情も。)

 この投稿ですくわれる方が一人でもいれば幸いです。
 


©2020 shts All Right Reserved.