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 V0.2.0の記事のまとめです。


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


kmodelを作るときのtips


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




©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.

2020年2月16日日曜日

MTOF171000C0使ってみた




 卒論も提出し終わったにもかかわらず,研究室にこもって何かしている中の人です.研究室ので使っているマシンでデータセット作成とかをやっているのですが,メモリを大量に使い果たすのでVPNでつなげず,結局来ないといけなくなっています.OTL

 さて,今回は秋月で売っているToFセンサの話です.ToFセンサといえばSTMicroelectronicsのこちらが有名?ですが,少しお高めかつ情報が出回っているのでパスです.(レジスタマップは果たして公開されたのだろうか)

1.仕様的なもの

センサ裏面


 今回使用するモジュールはFOXCONNが製造しており,SHARP製GP2AP01VT10F ToFセンサと謎マイコンが載っています.Arduino UNO向けサンプルコードモジュールのアプリケーションノートが公開されています.
 アプリケーションノートによれば,距離レンジ10cm-120cm(白壁),10cm-70cm(灰色壁)で,120cm±4%,70cm±7%となっています.
 通信方式は,UART/I2Cですが,I2Cで通信する際には電源,SCL,SDAのほかにCS代わりにTXDピン(センサ側の)を使用します(アプリケーションノートだと,RXDにつなげって書いてあるが,マイコン側って意味なのか?).今回はI2Cの方のみテストしました.
モジュール付属のケーブル.一回装着すると取りにくいらしい

 モジュールのピンアサインは,

  1. VDD(赤)
  2. GND(黒)
  3. TXD(白)
  4. RXD(茶)
  5. SCL(緑)
  6. SDA(黄色)

となっています.注意点として,付属のケーブルをモジュールにつけると抜けにくいらしく,無理やり抜こうとしてモジュールごと破損する可能性があるらしいです.

2.I2Cでおしゃべり

距離測定の図.M5StickVはただの壁

 ESP32でMTOF171000C0を使ってみましょう.何も考えずにピンを割り当てました.
  • VDD(赤) <-> 3V3
  • GND(黒) <-> GND
  • TXD(白) <-> IO25
  • RXD(茶) <-> 未接続
  • SCL(緑) <-> IO21
  • SDA(黄) <-> IO22
最初,TXDをIO12につないでいたのですが,うまく書き込めなくなりました(ESP32の仕様で,ブート時のモード決めとかで使うらしいです).IO25であれば問題なく動きました.
 アプリケーションノートに従うと,通信の流れは以下のようになります.

  1. TXD(CS)をLowにする
  2. センサのアドレスを送る(0x52)
  3. 距離データのはいっているレジスタを指定する(0xD3)
  4. センサのアドレスからデータが送られてくるのを待つ(2Bytes,上位8bitから送信)
  5. CSをHighにする

 距離が測定できない場合には,出力結果が"8888"になります.そうでない場合は,レジスタの値がそのまま距離(mm)になります.コードはこちらに上げておきました.

3.まとめ


 モジュール内でmmに直してくれるのはありがたい...のだろうか.マイナス点はSTMicroelectronicsのToFシリーズより性能が低いこととセンサ自体のデータシートが出回っていないことでしょうか.(未公開コマンドで精度や速度に関する設定ができるのかも)
 VL53L0Xに対しては,秋月価格で\2-300安いので少しお手軽です.(\1080->\780)
何も考えずにcmオーダで正確に測れることを考えると,こっちでもいいかもしれないです.

4.その他

  • データシートが英語・中国語(繁体字)併記.繁体字なので,雰囲気はつかめる.
  • SHARPからではなくFOXCONNから出ているのはなんでだろ(親会社一緒だけど)
  • UARTではオフセットの設定もできるらしい.I2Cは知らないけど,同じレジスタにアクセスすれば設定できる気がする.
  • 精度はまあまあ.20cmぐらいなら±3mm切ってくるレベル.
  • 距離が8888になる現象は,距離が遠すぎる場合にもなる.
  • センサ自体のレジスタマップはこちらも未公開.公開してほしい.

©2020 shts All Right Reserved.

2020年1月31日金曜日

DRV8830をESP32-DevKitCで動かした話




 卒論発表が終わった日にモータ回してる中の人です.発表自体は特に問題なく終わったので,あとは卒論を提出するのみです.ヤッタネ.
 今回はESP32でDRV8830を動かした話です.I2Cで制御できるMDとしては一番ポピュラーなICで中の人も何度か使っていますが,ESP32と一緒に使ったことがありませんでした.復習もかねて動かしてみましょう.



1.回路回り

 IC自体は絶対最大定格が7Vとなっていますが,実際は5Vあたりが上限になります(実はDACの関係で5V一択になります).ICの裏面にはGNDパッドがあるため,回路設計やはんだ付けの際には十分気を付けてください.
 VCCが1つだけなので,ロジック電圧とモータ電源電圧が一致するはず(と思いたい)です.ロジック電圧とモータ電源電圧が違う場合は,レベル変換のICや回路をロジック側に追加します.
 モータにかける電圧はDACで生成しており,0.48[V]から5.06[V]のまで57段階で調整できます.昇圧回路などはないので,この範囲をフルに使う場合は電源電圧を5V以上になります.フルにしないとあまり使えないので,結局モータ電源電圧は5V一択になります.(6Vとかを生成しても結局5.06Vで頭打ちになる)
 パスコンは0.1uFが最低になっていますが,10uFを突っ込んだ方が安定します.あとはモータの端子にセラコン直付けがでどうにかなります.
 I2C線のプルアップは様子を見つつやってください.単体で動かすならSCL/SDAともに10kで動きました.
 ISENSEの抵抗は適宜付けますが,電流制限がいらない場合はGNDに落としておきましょう.
A0/A1はアドレスの設定に使います.各ピンをGND/未接続/VCCのどれかに設定することで変えられます.
 FAULTnはレジスタ1(FAULT)と同期する形で,障害を通知します.使わないときは未接続にするか,抵抗を介してVCCにつないでおきましょう.障害が発生したときにはLowになるので,LED(と電流制限抵抗)をつけておくことでレジスタを読まなくても障害発生がわかります.

参考:シリアル・インターフェイス内蔵、低電圧モータ・ドライバ 日本TI

2.I2C

 ユーザが叩くI2Cのレジスタはわずか2本と,わかりやすい構造です.

2.1アドレス

 A1/A0ピンでアドレスを指定するのですが,データシート上ではアドレス(書き込み)とアドレス(読み込み)とありますが,DRV8830は7bitアドレスのはずです.
 これは,I2Cの仕様として,7bitのアドレスの後に読み込みか書き込みかを示すビットを付与する仕組みになっているためです.よくよく見てみると,同じピンの状態における読み込み/書き込みアドレスは1つ違いになっています.
 ArduinoのWire.hでは,最後の1bitを自動付与するので,アドレスはデータシートにあるものの上位7bitを書き込むことになります.(A1=A0=0だと0xC0>>1 = 0x60)

2.2レジスタ0(0x00)

 出力電圧や回転方向の指定はここで行います.
 ┌────┬──┬──┐
|D7- D2  |D1 | D0 |
 ├────┼──┼──┤
 |VSET    |IN2 |IN1|
 └────┴──┴──┘
 VSETがモータの電圧,D1/D0で回転の仕方を決めます.
 VSETは0x06から0x3Fまでの整数を設定します.もし電源電圧が0x3F(=5.06[V])より低い場合は,電源電圧以上の電圧を指定しても出力されません.
 D1/D0=0で惰性,1で逆転,2で正転,3でブレーキと,普通のMDの方向指定とあまり変わりません.

2.3レジスタ1(0x01)

 障害通知用です.
 ┌────┬────┬───┬──┬───┬──┬────┐
|D7        | D6-D5 | D4    | D3 | D2   | D1 | D0       |
 ├────┼────┼───┼──┼───┼──┼────┤
 | CLEAR |未使用 |ILIMIT|OTS|UVLO|OCP| FAULT  |
 └────┴────┴───┴──┴───┴──┴────┘
 D7に1を書き込むときは,D0が0になっていることを確認しましょう.障害が発生している状態でやっても意味ないですからね.

参考:シリアル・インターフェイス内蔵、低電圧モータ・ドライバ 日本TI
   I2Cの基本データフォーマット 電子工作室

3.動かしてみた


 とりあえず動かしてみました.昔作った基板にたまたまDRV8830が載っていたので,使いまわしてます.秋月で売っているDRV8830のブレークアウトボードレベル変換IC10uFセラミックコンデンサ10k抵抗x2,5Vレギュレータ9V電池あたりで代用ができそうです.
ソースコードはこちらから.

4.まとめ

 ロジック電源とモータ電源が分離していないなど電源回りに癖がありますが,それを除けば扱いやすいMDです.



©2020 shts All Right Reserved.

2020年1月25日土曜日

GS1502動かしてみた


 卒論発表の資料作っているはずの中の人です.最近はスライドの作成に手間取っております,はい. 今回は自宅で熟成を重ねたサーボモータの話です.

 サーボモータでよく使われているのはRCサーボ(SG90とその無限回転Ver.)とかだと思います.ですが,今回使ったサーボモータはリニアサーボモータという,別の種類のサーボモータになります.RCサーボモータは回転運動をしますが,リニアサーボモータは直線方向の運動をするものです.

1.とりあえずGS1502を眺める


GS1502.1円玉はデカいだけ(すっとぼけ)
 この手のサーボは2010年ごろには存在したようで,小さなRC飛行機やRCヘリ向けなようです.
 パットコネクタ周りを見た感じだと,SG90あたりとあまり変わらない制御ができるのではないかなぁと思いました.赤が+Vcc,黒がGND,白がPWMだと考え,動かしてみることにしました.


2.眺めたので端子を交換する

 一通り眺めたので,ここから作業開始です.手始めに,ESP32-DevKitCには使いにくそうなコネクタをQiに交換しましょう(2550とQiってどっちがメジャーな呼び方なんだろうか).
とりあえずぶった切る
Qi圧着して終わり
 交換自体はさほど時間はかかりませんでした.PA-09いいね.

3.動かす

 交換も終わったのでマイコン(ESP32を使用)とつないで動作確認です...

仕様一切知らんのだが

 ええ,仕様が全く分かりません.とりあえずCR1630ってICが乗っていたので調べたのですが,データシートが見当たらない...
 まあ最初の方でSG90と同じ制御だろって考えたので,そのままの方法で動かしてみました.とりあえずコードの方はこちらから.


なんもしてないのに

動きました


 これはブログを書けとの思し召しなのだろうかって思いましたが,おそらくRCサーボと同じ規格で使うことを想定しているため動いたと思います.あくまで推測ですが.
 となると,パルス幅は700[us]-2300[us]で,1500[us]に設定すると真ん中で停止する感じですね.ArduinoのServoライブラリでいえば700[us]が0[deg],2300[us]が180[deg],1500[us]は90[deg]に相当するので,今回作ったコードよりもライブラリを使った方が楽に動作確認できそうです.

4.最後に

 意外とすんなり動きました.やっぱり(仕様ががっちり決まってる)共通規格は偉大.あと,ホビーラジコン系の部品は精度がいい上に小さい部品もあるので,物理的に動くものを作るときは有力な選択肢になりそうです.

©2020 shts All Right Reserved.

2019年12月31日火曜日

M5StickVとESP32-DevKitC-32Dで双方向UARTやってみた



 大晦日も自宅にこもって高位合成している中の人です.PYNQ-Z2からUltra96 V2に乗り換えれば,簡単に速くなりそうなんですけどねぇ. さて,今回は積み基板になっていたM5StickVESP32-DevKitC-32Dを使って,UART通信してみた話です.



配線的なもの

 とりあえずピンアサイン的なもの.
────────────
 ESP32  M5StickV
━━━━━━━━━━━━
 GPIO16  GPIO35
────────────
 GPIO17  GPIO34
────────────
 GND    GND
────────────
 M5StickVの方はFPIOAの仕組みがあるので,UARTピンのアサインを間違えても入れ替えれば動くのですが,とりあえずこんな感じにしておきます.
 ESP32の方はUART2を使っていますが,UART0やUART1でも設定すれば使える気がします.

参考:SwitchScience ESP32-WROOM-32に関するTIPS


プログラム的なもの

 今回,ESP32はArduino IDE,M5StickVはMaixPyを使いました.まあUARTのテストだけなのでこれでいいかなって感じです.

コード全体はGitHubに上げておきます.最新版のArduinoでESP32のUART2を使うときは,何も宣言することなくSerial2を使うだけで,OKなようです.

 

結果

 115200bpsで動いた.
左:M5StickV,右:ESP32
参考:Wi-FiがないM5StickVを、M5StickCと繋ぎLINEに投稿してみるまでの手順

今年最後の投稿がこんな感じでいいものなのだろうか...

©2018 shts All Right Reserved.

2019年12月8日日曜日

にゃーん(異常検知しようとしてできたのか出来なかったのかよくわからない話)


0.初めに

 この投稿はMice Advent Calendar 2019の8日目の記事です.7日目はコヒロさんの2019年全日本大会で人権を取り戻した話でした.人権...僕も欲しい....



卒論のファイルの存在が虚無な中の人です.こんな時期にブログを書くなんて思っていなかったのですが,現役からの熱い圧力強い要望により書いています.今回は異常検知したかった話です.

1.異常検知とは

 異常検知(anomaly detection)は,"通常の動作として明確に定義された概念に準拠しないデータパターン"(wikiより)を検出することで,いろいろな分野で使われています.
 まあいつもの動き(狙った動き)と違うぞってことを見つけるって話です.

2.PID制御ぶるぶる問題

  マウスに限らず,限界感度法とかでPID制御のパラメータを決めている場合,パラメータを上げすぎると出力が発散(振動)することがあります.
見事に発散

別に適切なパラメータであれば問題はないのですが,どんな環境でも動くパラメータを見つけ出すのは至難の業.なので少し高めのパラメータをデフォルトに設定し,出力が発振しかかったらパラメータを下げるようにしてみました.

3.そうだ,検出しよう

さて,出力の発振を検出して...ってどうやって?ここで出力データをよーく見てみましょう.

出力とにらめっこ

何となくですが,比例制御で使う偏差の絶対値をとって,その値をテキトーな区間(半周期あたり)で積分すればいい気がしてきました.制御が荒ぶっているときは値が大きくなって,安定しているときは値が小さくなりそうです.あとはしきい値決めてぶった切れば勝ち確かな?

検出できた???

4.わたし,(誤検知)気になります!

3.で考えた検出方法にはある問題があります.アンダーシュート/オーバーシュートして安定している場合です.元データでは,加速度がノンゼロの区間の遅れが誤検知されています.勝ち確#とは.(※実はこの方法でもどうにか検出することもできたりできなかったり)

やっぱり駄目だったよ


 となると方針変更です.偏差を何か,入力データの変動のみを表すものに置き換えてやればできそうです.
 ある関数の変動を見るとすれば...ああ,微分なんてあったなぁ.まあ厳密に数値微分なんてする必要はないので,もういっそ引き算だけすればいいでしょう(やけくそ).

5.そして,よくわからないものへ

 さて,結果です.

さっきよりイケそう

差分だけならよさげなので,最初のデータと合わせて確認してみましょう.

イケたのでは
 
   とりあえず,誤検知が無くなりました.めでたしめでたし...なんてことにはならない.
実機にぶち込んで動いたら完全なる勝利です.さて,やってみましょう.

 
 あれ,思ったよりも誤検知多いのでは?とりあえずは安定して動いているので,良しとします.

結論.

 異常検知は難しい...が,マウス君はちょっとだけ安定するようになった.このやり方であってるかどうかは知らないです.もっといい方法があったら教えてください.

 Mice Advent Calendar 2019の9日目はべし先輩の未定です.""未定""です.(大事なことなので2回言いました)











おまけ : 偏差だけで異常検知はできるのか?

 3.で作った偏差だけを使うやり方では誤検知が多いという話をしました.が,実はそこで議論していないことがありました.しきい値です.
 具体的な値を言えば,3.の場合0.1をしきい値としていました.ここでしきい値を0.5に上げて比べてみましょう.

あれ,こっちもできてる

 どうやらうまく検出出来ているようです.ですが,4.の方法のほうがパラメータがテキトーでも成功しやすいと感じました.この辺の話はリソースとかの問題もあるので,一概にどちらのアルゴリズムがいいかを決めることはできませんが,まあ好きな方を選んでください.

おまけ2 : タイトルと内容について

タイトルと内容の決定のながれはこちらのツイート及びコヒロさんの2019年全日本大会で人権を取り戻した話の最後のほうを参照のこと.


©2019 shts All Right Reserved.

2019年9月17日火曜日

TinyFPGA BXをVSCode(+PowerShell)で開発する



 ブログのネタを探してさまよっていた中の人です。夏休みはマウスのコーディングやらバイトやらで忙しい毎日を送ってました。(今夏はアキバへ2桁回買い出しに行ってました。定期がなかったらヤバかった)
 今はこの記事を書きながら環境構築研究を始めています。圧倒的進捗のNASA。



 さて、今回のネタはちっちゃいFPGAをVSCode上で開発する話です。タイトルには(+PowerShell)って入ってますが、pipが入ってる(入る)ターミナルなら何でも大丈夫です。

0.TinyFPGA BXについて&開発の動機

 TinyFPGA BXはLattice Semiconductor Corporation製ICE40LP8Kを使ったFPGAボードで、その名の通り小さいのが特徴です。(AX2っていうもっと小さいのもある)

 サイズ感はArduino nanoやNucleo F303に近いです。
 このボードGUI環境でも開発ができるのですが、なんとPython2.xを使用しているのです!(インストールしようとしたら2.7.11を突っ込もうとしてきた)
 よって今回はPython3.x系で開発環境を整えようとした感じです。

1.今回の環境及び使うもの

  • VSCode 1.38.1
  • Python 3.7.4
  • pip 19.2.3
  • TinyFPGA BX
  • USB micro B ケーブル
今回はVHDLではなくverilogを使用します。(ビルドツールがVHDL未対応らしい)

2.インストール

最初は、TinyFPGA BX User Guideに従ってインストールを進めましょう。私が環境構築をしていて詰まったところは、

apio drivers --serial-enable

の前に

apio install drivers

をすることでしょうか。この辺りはそこまで難しくないはずです。
この時、一緒にverilogのExtensionをVSCodeに入れておくと.vが読みやすくなります。

Atomを入れろとなっていますが、今回は無視します。


3.実機実装

 FPGAの開発では、大体の場合シミュレーションを走らせてから実機実装しますが、面倒なので飛ばします。
とりあえず、サンプルコードを使いたいので、TinyFPGA BXのリポジトリをどうにかこうにかして落としましょう。落として来たら、apio_templateをフォルダコピーしておきます。(書き換えると面倒なので)

 コピーしたフォルダをVSCodeで開いたら、ターミナルを出して、

apio build

と打ちましょう。.vが間違っていなければビルドが通り、hardware.binが生成されているはずです。(ほかのファイルも同時に生成)



 ボードへの書き込みは、ケーブルでPCとつなぎ、リセットボタンを一回押した状態で、

tinyprog -p .\hardware.bin

と打てば書き込まれます。


書き込みがうまくいかないときは、User Guideの下の方に書いてあるブートローダのアップデートをやってみましょう。

参考:tinyFPGA-BX boardにTerminalのみでbuildとボードへの書き込みを行った




©2018 shts All Right Reserved.

2019年7月23日火曜日

matplotlibでマウスやらキーボードのイベントを取得する


 ブログ更新をさぼりにサボっていた中の人です.研究室とバイトとマウスに明け暮れたら,いつの間にか金と時間が溶けていました.
 私事ではございますが,大学院に進学することが決まりもう少しだけ学生でいられそうです.やったね(白目)

 それはさておき,今回はmatplotlibでマウスやらキーボードのイベントを取得する話です.

概略
 みんな大好きmatplotlibなのですが,実はマウスやキーボード,その他もろもろのイベントを拾うことができます.これによってグラフに表示されているデータをいじったりすることが可能です.

イベントの種類
 トリガとして扱えるイベントは以下の通り.
  1. button_press_event       : マウスのボタンが押されたら
  2. button_release_event    : マウスのボタンが離されたら
  3. draw_event                   : キャンバスが更新されたら
  4. key_press_event           : キーボードのボタンが押されたら
  5. key_press_event           : キーボードのボタンが離されたら
  6. motion_notify_event      : カーソルが動いたら
  7. pick_event                    : キャンバス内のオブジェクトが選択されたら
  8. resize_event                 : figureキャンバスがリサイズされたら
  9. scroll_event                  : マウスホイールが回ったら
  10. figure_enter_event        : カーソルがfigureの中に入ったら
  11. figure_leave_event        : カーソルがfigureの中から出たら
  12. axis_enter_event           : カーソルがaxisの中に入ったら
  13. axis_leave_event           : カーソルがaxisの中から出たら
参考:https://matplotlib.org/users/event_handling.html?highlight=event%20handling%20picking

使い方
 イベント発生時に動かしたい関数を事前に準備しておき,canvasに紐づける感じです.

#クリック時にカーソルの座標を取得する
def Click(event):
    print("x=%d, y=%d" % (event.x, event.y))

#紐づける
fig.canvas.mpl_connect("button_press_event", Click)

2020/8/17 追記:上記のmplの部分がmlpだったのを修正

eventはマウスカーソルの位置や選択したデータの値,マウスやキーボードの押したボタンなどを取得するために使うやつです.取得できるのは以下の通り

  1. x, y : canvas内のピクセル
  2. inaxis : カーネルがaxisを超えたかどうか(True/False)
  3. xdata, ydata : 選択されたデータ
  4. button : 押されていたマウスのボタン(None, 1, 2, 3, 'up', 'down')
  5. key : 押されていたキーボードのボタン(None, すべての文字,'shift', 'win', 'ctrl')


最後に
 便利機能が結構仕込まれているmatplotlibです.公式のサンプル等もあるので,そちらも参考にするといいと思います.


©2018 shts All Right Reserved.

2019年6月11日火曜日

Raspberry Pi 2とZero WでFCNを走らせてみた




れぽーよなんて大嫌いな中の人です.
今回は秋月で安売りしてたことを知ってわざわざ学校を抜け出して入手した
たまたま入手できたRaspberry Pi 2とZero Wを比較する話です.



今回この二つのボードを使っていくわけですが,その前にスペック比較を
Pi Zero
  • 1GHz, single-core CPU
  • 512MB RAM
Raspberry Pi 2
  • A 900MHz quad-core ARM Cortex-A7 CPU
  • 1GB RAM

シングルコアの性能はZeroのほうがいいかも.ただ4コアのPi 2のほうがトータルで速そうだけどどうなんだろう?

というわけで実際にプログラムを実行して比べてみましょう.実行するのは最近いじってきたFCNの最新版です.(レイヤーを4層に減らしたらなぜか精度が上がったのはなんででしょうか...)

Pi 2 : 0.020[s/frame]
Pi Zero W : 0.060[s/frame]
(それぞれ100回平均)

Pi 2の速さが圧倒的すぎる.(目標の30fps超えちゃってるヨ...)
個人的にはPi 2がもう少し遅いと思ったんですが,予想を超えてきましたね.Pi Zero Wはレイヤー数を落とした関係で15%ぐらい速くなったのはうれしいです.

まあ今更Pi 2かよって話ですが,予想以上に高速化できたのでよかったです.(Pi 3Bとかだともっと速くなりそう)


参考
https://www.raspberrypi.org/products/raspberry-pi-zero-w/
https://www.raspberrypi.org/products/raspberry-pi-2-model-b/