Translate

2019年9月10日火曜日

Donkeycar3.1.0上の機械学習モデルを調べてみた


Donkeycar がVersion3になり、実装されているモデルのタイプ(DEFAULT_MODEL_TYPE)が増えた。

しかし、どのモデルが何者なのか、ドキュメントには一切書かれていない。

デフォルトで動作するlinear以外はどうなっているのか、
そもそも既存のTubデータで動作するのかといった情報がないのだ。

結局 donkeycar パッケージリポジトリを自分で読むしか無いのだ。

<2019/09/11追記>
Facebook側にコメントが有り、公式ドキュメントにも
記載があるそうです。よく読めって話ですよね..
http://docs.donkeycar.com/parts/keras/
まずこちら(Google Chromeの翻訳かけても十分読めます)を
参照していただいたほうがいいでしょう。

と、いうことでざっと読んで概要をまとめてみた。

ちなみにdonkeycarのモデルの呼び出しはFactoryパターンで実装されていて、
myconfig.py上にDEFAULT_MODEL_TYPEを指定すると、
(デフォルトはconfig.py上のDEFAULT_MODEL_TYPE="linear"が有効になる)
Abstract Factory関数はutil.pyのget_model_by_typeの引数にわたり
該当するモデルパーツクラスがインスタンス化される仕組みだ。

Donkeycar3.1.0には以下のモデルタイプ(引数model_type)が存在する。


model_typeクラス概要
lineardonkeycar.parts.keras.KerasLineardonkeycarデフォルトのモデル。中間層は、Conv2D×5層。出力層でステアリング値、スロットル値を直接出力。
tflite_lineardonkeycar.parts.tflite.TFLitePilotTensorFlow Lite モデルファイルをロードして実行するためのパーツクラス。トレーニングを実行するための`compile`メソッドが実装されていないのでモデル作成およびトレーニングはdonkeycarアプリケーション外で各自で作成・実行しなくてはならない。linearで作成したモデルファイルをコンバートするなどして使用する(h5ファイルのコンバート処理はkeras_model_to_tfliteメソッドが提供されている)。使用可能なモデルは、入力はイメージ(120x160x3)、出力はアングル値・ステアリング値(ともにfloat値)が前提となる。
localizerdonkeycar.parts.KerasLocalizerほぼcategoricalのモデルと同じだが、出力層がスロットル、アングルにロケーション分類値が加わっている。ロケーション分類値は、LED表示に使用されるのみなので、自動運転動作には全く影響しない。LEDを搭載していない標準DonkeyCarの場合はcategoricalを指定した場合と何ら変わらない。 しかしTubデータにロケーション分類値を格納する処理が実装されていないので、学習処理が動かないかもしれない。
behaviordonkeycar.parts.keras.KerasBehavioral入力層がイメージと車線状態を取り込むモデル。車線状態(左車線・右車線のどちらか)をL1キーでトグル入力させそれをone hotな動作ベクトルに変換し、イメージと一緒に入力層に与えている。入力層以外はイメージ側は`categorical`と同様、状態ベクトル側は全結合層×3、最後に両方の結果を連結している。ソースコードコメントを読むと昔はlinearベースだったようだ。ジョイスティックがない場合、あってもL1というラベルが使用しているJoystickクラスに定義されていない場合はこのモデルを選択しても意味がない。しかも手動運転時の運転者が走行操作と並行してただしく状態を入力しなければならない。
imudonkeycar.parts.keras.KerasIMUMPU6050(I2C)から角速度3軸、加速度3軸がTubデータに書かれていることが前提。入力層はイメージとIMU値、中間層はイメージがConv×5層・IMUが全結×3層を結合したもの、出力層でステアリング値、スロットル値を直接出力。
tensorrt_lineardonkeycar.parts.tensorrt.TensorRTLinearTensorRTを使ったクラス、このためTelsa/Jetson/Nvidia Driveがない場合は使用できない(GeForceも実行できない)。`compile`メソッドは存在するが処理が実装されていないため、学習済みモデルをロードし推論するのみの機能提供となるコンバート方法は公式ドキュメントを参照のこと。なお、コードのコメントにtesnorflow-gpuでのトレーニングは非推奨との記述がある(なぜかは不明)。
coral_tflite_lineardonkeycar.parts.coral.CoralLinearPilotEdgeTPU搭載した環境を前提としたクラス。Tensorflow Liteモデルファイルを読み込み、推論を実行するのみ。モデルファイルは別途作成する必要がある。コンバート方法は..知っている人はコメント欄にお願いします..
3ddonkeycar.parts.keras.Keras3D_CNN畳み込み層を時系列データを扱うためConv2DではなくConv3Dを使ったモデル。直近一定数(デフォルトは20)のイメージを入力し、Conv3D×4層の中間層にかけ、アングル値・スロットル値を出力する(分類ではなくfloat値で返却)。
rnndonkeycar.parts.keras.KerasRNN_LSTM時系列データが扱えるRNN/LSTMをベースとしたモデル。直近一定件数(デフォルトは3)のイメージを入力し、各イメージにConvolution2D×5層にかけ各々をベクトル化したものを作成しLSTM(RNN実装の一つ)にかけ、出力層はアングル値、スロットル値を出力する(分類ではなくfloat値で返却)。
categoricaldonkeycar.parts.keras.KerasCategorical画像分類を使ったモデル。入力層はイメージ、中間層はイメージサイズによりConv2D×4or5層、出力層はスロットル15分割、アングル20分割の各1値を選定する。CNNの画像分類精度の高さを使っているためlinearより精度が高いという人もいる。細やかな動作を行いたい場合は出力層の分割数を増やせば良い。
latentdonkeycar.parts.keras.KerasLatentConv2D×8層を中間層に持つモデル。入力はイメージ、出力はアングル値・スロットル値(ともにfloat値を直接出力)以外にCNNを掛けた直後Deconvolution(Transposed Convolution/up-convolutionともいうDC-GANによく使用される)層を6層かけてイメージも生成している。しかし出力ではアングル値・スロットル値のみを使っているだけで生成したイメージは`KerasLatent`クラス内で捨てているため、そのまま使用する場合は、単にCNN8層のモデルでしかない。
fastaidonkeycar.parts.fastai.FastAiPilotfastaiパッケージのモデルファイルを読み込み実行するための推論のみのパーツクラス。クラス上にcompileメソッドがなくpython manage.py trainを実行できない(donkeycarアプリケーションを使ったトレーニングができない)。よってモデルはdonkeycarアプリケーション外部で定義されていることが前提となる。fastaiパッケージがtoachパッケージベースで記述されているためtensorflowベースではない。なおfastaiパッケージはディープラーニングのeラーニングコースである course.fast.ai 内で使用されている。

標準Donkeycarで有効に動作しそうなモデルタイプは
  • linear
  • categorical
  • rnn
  • 3d
の4種類。
ただ..rnnと3dは複数のイメージデータ(rnnはデフォルト3件、3dはデフォルト10件)
を入力にしないといけないが、
manage.py上のVehicle上のメモリ領域に最近N件のイメージデータを
確保するような処理がない..
なのでまともに動作するのは
  • linear
  • categorical
の2つだけだ。

<2019/09/11修正>
rnn、3dのrun関数内で最近N件をインスタンス変数にためて
いる実装がありました。推論も実行できそうです。
コメントご指摘、ありがとうございました。

linearでうまく行かない人はcategoricalでうまくいくことが多い。
これはCNNが画像分類で世に出たわけでもともと得意なケース
ということなのだとおもう。



  • behavior
は、ゲームパッドでの手動運転(学習データ収集)が必須となっており、
かつゲームパッド上に(joystick具現クラス上に)ラベル"L1"が定義されていること
が前提となり、
手動運転中Donkeycarが車線を変更するたびにL1ボタンを押さなくてはならない。
behaviorモードで手動運転したTubデータは項目が増えるが、
そのまま先の4つのモードでもトレーニングさせることができる(拡張項目は無視されるが、ファイルロードに時間がかかる)。
ゲームパッドとしてPS3/PS4をつかっているならこのまま動作すると思うが
F710とかだとmanage.pyの1行を書き換える(L1をLTなどに書き換える)必要がある
(厄介なことにmyconfig.pyではなくmanage.py上に直書きされているのだ)。


また
  • imu
は、MPU6050をI2C経由で接続しておかなくてはならず、
Tubデータも増える。
MPU6050は日本のAmazonでも購入可能だ。
IMUデータはCNNではなく全結合層の結果をCNNの結果と
コンカチしているだけなので
素人目にも精度が悪そうだ。
角速度と加速度なので、
機械学習の入力として使用するのではなく、
ルールベースの剰余項補正などに使用したほうが良いとおもう。


  • localizer 
はよくわからない実装だ。
3色LEDを搭載しているDonkeycarでないと意味がないし、
そもそもどう点灯してほしいかの学習データ入力方法がないので
学習は無法地帯になっている。
コードを読む上でなにか見落としがあるのかもしれない。
3色LEDの想定はKY-009という基板実装モジュールで
日本のAmazonにもあるにはあるが品切れ状態で
国内で入手するのは難しそうである。
3色LED自体は販売されているので、
ブレッドボード上でカソード側の抵抗を見繕えば
自前基板実装の難易度は高くない。
(..Donkeycarを菅原文太が乗っていたデコトラみたいにしたかったのかもしれない..)

よくわからない実装といえば
  • latent
もそうだ。
DC-GANで使用されているDeconvolution層を使って画像データを生成
させているが、3.1.0ではつくりっぱなしで、
Tubやメモリ上に格納していない、使用していないのだ。
想像するに、学習データを増やそうとしているのだろうが、
もしかしたら後続バージョンでなにかかわるのかもしれない。
入力・出力ともデフォルトのTubデータで操作しそうだから
このモデルも動くとは思うが、deconv結果を使用しない以上
単なるCNN8層モデルでしかないため、
トレーニングや自動運転処理が重いだけでおわるかもしれない。


以下の4つのモデル
  • tflite_linear
  • coral_tflite_linear
  • tensorrt_linear
  • fastai
は、クラス上にモデルファイルのロードと自動運転実行機能しか
実装されていない。
fastai以外はlinearとついているのでlinearモデルのTF Lite/TF Lite TPU版/TensorRT
実装(モデル定義、トレーニング処理)があってもいいとおもうのだけど
みあたらない..

ただ
  • tflite_linear
  • coral_tflite_linear
は、デフォルトのlinearで学習したモデルファイルをコンバートするだけ
で使用できそうだ。coralはUSB接続するGoogle Coralアクセラレータ
(旧Mobidius)かEdge TPU実装ボード(Google Coral Dev Board JP Version)が
ないと動作しない。
  • tensorrt_linear
は、Tesla(Google ColabでもOK)、Jetson、NVIDIA Driveシリーズでのみ
動作する。
TeslaをDonkeycarに乗せるのはコストが見合わないし、
NVIDIA Driveはトヨタとかホンダとか本気で自律走行を載せようとしている
メーカ向けらしいので無理。
ほぼJetson Nano向けということになる。
持っていないので詳しくないが、Jetson Nano上のTensorflow は
バックエンドでTensorRTを使うようになっているのだと思う
(モデルファイルはどう作るのかは不明)

<2019/09/11追記>
tensorrt_linearのモデルファイルの作り方は公式ドキュメント
http://docs.donkeycar.com/guide/robot_sbc/tensorrt_jetson_nano/
に記載されています。
コメントご指摘、ありがとうございました。



p.s.

ちなみにdonkey makemovie --tub <tubデータディレクトリパス> --type < model_type値 > --out < 出力mp4ファイルパス >--salient --start 1 --end <画像にしたいtubデータ通し番号(最後)>を実行することで、
モデルがexciteした箇所を可視化してくれる。
さらにモデルが推論した値も可視化してくれるので
ぜひためしてほしい。

..のだけど、処理はとても重い。
linear で start=1 end=2400を指定して
仮想マシン2コア8GBRAM(FloydHub cpu)で動かしたら
8時間たったころにメモリが足りなくて落ちた..
しかも生成したmp4は途中で切れている状態で
再生できなかった..

以下、FloydHub実行例。
#Tubデータはデータセットとして先に格納済みで
#モデルファイルmodels/20190910/mypilot_linear.h5も作成済みが前提。
#Tawn氏のkeras-visだと動かなかったので1行だけ修正した版を独自リポジトリ
#に格納している

floyd run --cpu --env tensorflow-1.13 --data user_id/datasets/dataset_name/1:data 'git clone https://github.com/autorope/donkeycar.git&&cd donkeycar&&git checkout master&&cd ..&&pip install -e donkeycar[pc]&&pip install keras-vis&&git clone https://github.com/coolerking/keras-vis&&pip install -e keras-vis&&donkey createcar --path mycar&&cd mycar&&donkey makemovie --tub /floyd/input/data --out linear.mp4 --type linear --model ../models/20190910/mypilot_linear.h5 --start 1 --end 2400 --salient'



Google Colaboratory (Python3/GPU)で
linear で start=1 end=2400を指定して実行すると
5時間23分かかって1分の動画を生成した..
ただ..実はGoogle Colabratoryの90分問題・120分問題というのがあり、
(モデルファイル作成のトレーニング処理は長くても20分なので問題ない)
手動で対処していたためほとんど他の作業ができなかった..
この記事に書いてあるChromeプラグインを入れたのだが、
#ダイアログが出て自動更新されなかった

タダだから、文句言えないけど..

p.s.2

ちなみにrnnや3dモデルでdonkey makemovieすると大量のエラーがでた。
generatorやrunの入力が複数件対応していないためだ。

<2019/09/11追記>
エラーの原因はrnnと3dで異なっているので、もう少し掘り起こしてみます..

p.s.3

tensorflow liteはRaspberry Pi Zero上では
トレーニングだけでなく推論実行できない。
armv6ベースのwheelファイルがPyPIにないので
自分でwheelファイルがつくれないと、
すなわちソースコードからwheelファイルを
Raspberry Pi Zero上もしくはDockerコンテナなどのクロスコンパイル環境上で
ビルドできないと、
使用できない。

あるいはTawn氏が作ったtflite_serverというOSSで
クラサバ形態をとるかだが、
これだと"自律"走行とは言えないかもしれない..

2019年8月14日水曜日

Windows10上でRaspberry Pi Zero用Tensorflow Lite 静的ライブラリのコンパイル方法

Donkeycarのバージョンが3.1.0にあがってしまいました..
3.1.0の目玉はTensorRT対応とTensorflow Lite対応です。
TensorRTはGPUがそもそもないのでどうでもいいですがLiteのほうは..Zeroで自動走行にすると内部エラーで落ちる問題が解決できるかもしれない..ということでRaspberry Pi ZeroにTensorflow Liteをインストールしなくてはなりません。

でもそんなwheelファイル誰も公開していない..TawnさんにSlackできいても知らないとの答え..

しょうがないので公式ドキュメントに従ってコンパイルをすることになったわけです。

----

Tensorflow LiteドキュメントにはDockerコンテナ上でクロスコンパイルする手順がかかれていますが、あくまでarmv7l(3B/3B+)用であり、get started に whlファイルのダウンロード元URLがかかれているので、正直コンパイルするひつようがありません。

でもなぜかZero用のarmv6用は置かれていないので、自分でコンパイルするしかありません。

以下、手順を紹介しますが、すべての機能のテストをしていませんので、動かなくてもごめんなさい。
Tensorflow本体のビルドは40時間以上かかるというブログ記事情報もあったりしますが、ここに書かれている手順はLiteの静的ライブラリ作成だけなので、Lenovo T470で20分くらいだったとおもいます。

----

Docker Desktopのインストール

  • Windows10上にDocker Desktopをインストール
  • Docker Desktop>Settings>Shared Drives
  • Cドライブをシェア

クロスコンパイル環境コンテナの起動

  • コマンドプロンプトを管理者として起動
  • cd c:/Users/ユーザ名
  • mkdir tmp
  • docker run -it -v c:/Users/ユーザ名/tmp:/projects tensorflow/tensorflow:nightly-devel /bin/bash
(Proxy指定が必要な場合)
  • cat >> /etc/apt/apt.conf <
  • Acquire::http::Proxy "http://proxy.server:XXXX";
  • Acquire::https::Proxy "http://proxy.server:XXXX";
  • Ctrl+D


  • apt-get update
  • apt-get install crossbuild-essential-armhf vim

リポジトリのチェックアウト

(Proxy指定が必要な場合)
  • git config --global http.proxy http://peoxy.server:XXXX
  • git config --global https.proxy http://peoxy.server:XXXX

  • cd /projects
  • git clone https://github.com/tensorflow/tensorflow
  • cd tensorflow
  • git checkout master


Raspberry Pi Zero用設定に書き換え

  • vi vi tensorflow/lite/tools/make/targets/rpi_makefile.inc
  • 5行目:TARGET_ARCH := armv6 に変更
  • 38行目:-fPIC の末尾に \ 追加
  • 39行目:-marc 挿入
  • 46行目:-fPIC の末尾に \ 追加
  • 47行目:-marc 挿入
  • 53行目:-Wl,--as-needed の末尾に \ 追加
  • 54行目:-latomic 挿入

コンパイル実行

  • ./tensorflow/lite/tools/make/download_dependencies.sh
  • ./tensorflow/lite/tools/make/build_rpi_lib.sh
  • exit


静的ライブラリファイルのデプロイ

  • WinSCPなどを使って以下のファイルをRaspberry Pi Zero上の/usr/local/libなどにコピー
C:\Users\89004\tmp\tensorflow\tensorflow\lite\tools\make\gen\rpi_armv6\lib\libtensorflow-lite.a

------

..公式サイトにwheelファイルリンクがないのはもしかしたらZeroでは動作しないということなのかもしれないなあ..

そのあたりは自己責任でお願いします...



ps

WinSCP後の後始末

クロスコンパイル環境コンテナの削除

  • docker container ls -a でコンテナID先頭3文字を確認
  • docker container rm コンテナID先頭3文字


イメージの削除

  • docker image rm tensorflow/tensorflow:nightly-devel


作業ディレクトリの削除

  • cd c:/Users/ユーザ名
  • del /f tmpY選択

2019年7月31日水曜日

pip install時にERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE.というエラーが発生する

pip install時にERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE.というエラーが発生する

Raspberry Pi上で以下のようにtensorflowをpip install しようとしたら、

(env) pi@nakano:/dev/input $ pip install tensorflow
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting tensorflow
  Downloading https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl (87.1MB)
     |??????                          | 13.9MB 36kB/s eta 0:33:37

ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    tensorflow from https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl#sha256=25f4ff027beec1e568baf8e90a07bad59d354560533d6b37318b9efeb70beeb1:
        Expected sha256 25f4ff027beec1e568baf8e90a07bad59d354560533d6b37318b9efeb70beeb1
             Got        3ace76e2b0ded895a4e6239a4620a1f0aaa92ad8747d5660f6b34f17d5f4c688

というエラーが出てしまい先に進めない..

--no-chache-dirをつけて実行しても同様のエラーでとまる。

ダウンロードしようとしてフィンガープリントのハッシュが合わないようなので、以下のようにwgetしてwhlファイルをpip innstallしたら..何度かエラーを出すがそのままダウンロードすることができ、うまくいった。

env) pi@nakano:~/tmp $ wget https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl
--2019-07-31 00:03:14--  https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Resolving www.piwheels.org (www.piwheels.org)... 93.93.129.174, 46.235.225.189, 2a00:1098:0:82:1000:3b:1:1, ...
Connecting to www.piwheels.org (www.piwheels.org)|93.93.129.174|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 87138952 (83M)
Saving to: ‘tensorflow-1.13.1-cp37-none-linux_armv6l.whl’

tensorflow-1.13.1-c  16%[== >                  ]  13.39M  29.1KB/s    in 8m 16s

2019-07-31 00:11:35 (27.6 KB/s) - Read error at byte 14041088/87138952 (Error decoding the received TLS packet.). Retrying.

--2019-07-31 00:11:36--  (try: 2)  https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Connecting to www.piwheels.org (www.piwheels.org)|93.93.129.174|:443... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 87138952 (83M), 73097864 (70M) remaining
Saving to: ‘tensorflow-1.13.1-cp37-none-linux_armv6l.whl’

tensorflow-1.13.1-c  34%[+++== >               ]  28.31M  27.8KB/s    in 9m 11s

2019-07-31 00:20:51 (27.7 KB/s) - Read error at byte 29687808/87138952 (Error decoding the received TLS packet.). Retrying.

--2019-07-31 00:20:53--  (try: 3)  https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Connecting to www.piwheels.org (www.piwheels.org)|93.93.129.174|:443... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 87138952 (83M), 57451144 (55M) remaining
Saving to: ‘tensorflow-1.13.1-cp37-none-linux_armv6l.whl’

tensorflow-1.13.1-c  51%[++++++=== >           ]  43.02M  30.3KB/s    in 8m 56s

2019-07-31 00:29:52 (28.1 KB/s) - Read error at byte 45105152/87138952 (Error decoding the received TLS packet.). Retrying.

--2019-07-31 00:29:55--  (try: 4)  https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Connecting to www.piwheels.org (www.piwheels.org)|93.93.129.174|:443... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 87138952 (83M), 42033800 (40M) remaining
Saving to: ‘tensorflow-1.13.1-cp37-none-linux_armv6l.whl’

tensorflow-1.13.1-c  68%[++++++++++== >        ]  56.80M  27.9KB/s    in 8m 22s

2019-07-31 00:38:21 (28.1 KB/s) - Read error at byte 59555840/87138952 (Error decoding the received TLS packet.). Retrying.

--2019-07-31 00:38:25--  (try: 5)  https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Connecting to www.piwheels.org (www.piwheels.org)|93.93.129.174|:443... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 87138952 (83M), 27583112 (26M) remaining
Saving to: ‘tensorflow-1.13.1-cp37-none-linux_armv6l.whl’

tensorflow-1.13.1-c  84%[+++++++++++++== >     ]  70.11M  27.2KB/s    in 8m 7s

2019-07-31 00:46:36 (28.0 KB/s) - Read error at byte 73515008/87138952 (Error decoding the received TLS packet.). Retrying.

--2019-07-31 00:46:41--  (try: 6)  https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Connecting to www.piwheels.org (www.piwheels.org)|93.93.129.174|:443... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 87138952 (83M), 13623944 (13M) remaining
Saving to: ‘tensorflow-1.13.1-cp37-none-linux_armv6l.whl’

tensorflow-1.13.1-c 100%[++++++++++++++++=== > ]  83.10M  28.1KB/s    in 7m 56s

2019-07-31 00:54:39 (28.0 KB/s) - ‘tensorflow-1.13.1-cp37-none-linux_armv6l.whl’ saved [87138952/87138952]

(env) pi@nakano:~/tmp $ ls
tensorflow-1.13.1-cp37-none-linux_armv6l.whl
(env) pi@nakano:~/tmp $ pip install tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Processing ./tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Collecting termcolor > =1.1.0 (from tensorflow==1.13.1)
  Downloading https://www.piwheels.org/simple/termcolor/termcolor-1.1.0-py3-none-any.whl
Collecting absl-py > =0.7.0 (from tensorflow==1.13.1)
  Downloading https://www.piwheels.org/simple/absl-py/absl_py-0.7.1-py3-none-any.whl (117kB)
     |????????????????????????????????| 122kB 52kB/s
Collecting tensorflow-estimator < 1.15.0rc0, > =1.14.0rc0 (from tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/3c/d5/21860a5b11caf0678fbc8319341b0ae21a07156911132e0e71bffed0510d/tensorflow_estimator-1.14.0-py2.py3-none-any.whl (488kB)
     |????????????????????????????????| 491kB 21kB/s
Collecting astor > =0.6.0 (from tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/d1/4f/950dfae467b384fc96bc6469de25d832534f6b4441033c39f914efd13418/astor-0.8.0-py2.py3-none-any.whl
Collecting google-pasta > =0.1.6 (from tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/d0/33/376510eb8d6246f3c30545f416b2263eee461e40940c2a4413c711bdf62d/google_pasta-0.1.7-py3-none-any.whl (52kB)
     |????????????????????????????????| 61kB 56kB/s
Collecting wrapt > =1.11.1 (from tensorflow==1.13.1)
  Downloading https://www.piwheels.org/simple/wrapt/wrapt-1.11.2-cp37-cp37m-linux_armv6l.whl (68kB)
     |????????????????????????????????| 71kB 51kB/s
Requirement already satisfied: six > =1.10.0 in /usr/lib/python3/dist-packages (from tensorflow==1.13.1) (1.12.0)
Requirement already satisfied: wheel > =0.26 in /home/pi/env/lib/python3.7/site-packages (from tensorflow==1.13.1) (0.33.4)
Requirement already satisfied: numpy < 2.0, > =1.14.5 in /usr/lib/python3/dist-packages (from tensorflow==1.13.1) (1.16.2)
Collecting keras-applications > =1.0.8 (from tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/71/e3/19762fdfc62877ae9102edf6342d71b28fbfd9dea3d2f96a882ce099b03f/Keras_Applications-1.0.8-py3-none-any.whl (50kB)
     |????????????????????????????????| 51kB 30kB/s
Collecting tensorboard < 1.14.0, > =1.13.0 (from tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/0f/39/bdd75b08a6fba41f098b6cb091b9e8c7a80e1b4d679a581a0ccd17b10373/tensorboard-1.13.1-py3-none-any.whl (3.2MB)
     |????????????????????????????????| 3.2MB 24kB/s
Collecting grpcio > =1.8.6 (from tensorflow==1.13.1)
  Downloading https://www.piwheels.org/simple/grpcio/grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl (13.0MB)
     |???????????????????????????     | 10.7MB 27kB/s eta 0:01:25
Collecting keras-preprocessing > =1.0.5 (from tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/28/6a/8c1f62c37212d9fc441a7e26736df51ce6f0e38455816445471f10da4f0a/Keras_Preprocessing-1.1.0-py2.py3-none-any.whl (41kB)
     |????????????????????????????????| 51kB 36kB/s
Collecting gast > =0.2.0 (from tensorflow==1.13.1)
  Downloading https://www.piwheels.org/simple/gast/gast-0.2.2-py3-none-any.whl
Collecting protobuf > =3.6.1 (from tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/34/58/a8230dcd36e5db75c1084f4fc32b18cc217bb2806143597df625dc628a5d/protobuf-3.9.0-py2.py3-none-any.whl (432kB)
     |????????????????????????????????| 440kB 29kB/s
Requirement already satisfied: h5py in /home/pi/env/lib/python3.7/site-packages (from keras-applications > =1.0.8- > tensorflow==1.13.1) (2.9.0)
Collecting markdown > =2.6.8 (from tensorboard < 1.14.0, > =1.13.0- > tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/c0/4e/fd492e91abdc2d2fcb70ef453064d980688762079397f779758e055f6575/Markdown-3.1.1-py2.py3-none-any.whl (87kB)
     |????????????????????????????????| 92kB 30kB/s
Collecting werkzeug > =0.11.15 (from tensorboard < 1.14.0, > =1.13.0- > tensorflow==1.13.1)
  Downloading https://files.pythonhosted.org/packages/d1/ab/d3bed6b92042622d24decc7aadc8877badf18aeca1571045840ad4956d3f/Werkzeug-0.15.5-py2.py3-none-any.whl (328kB)
     |????????????????????????????????| 337kB 26kB/s
Requirement already satisfied: setuptools in /home/pi/env/lib/python3.7/site-packages (from protobuf > =3.6.1- > tensorflow==1.13.1) (41.0.1)
ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    grpcio > =1.8.6 from https://www.piwheels.org/simple/grpcio/grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl#sha256=6f92b984a746341529b8f82f7c6e101d36d70764f232505949828af7dca27e06 (from tensorflow==1.13.1):
        Expected sha256 6f92b984a746341529b8f82f7c6e101d36d70764f232505949828af7dca27e06
             Got        e3c32a594668a3aa59f190f0a768e11b81710d91b1fa9ae2918d414ba204f2b5


(env) pi@nakano:~/tmp $ wget https://www.piwheels.org/simple/grpcio/grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl
--2019-07-31 01:09:05--  https://www.piwheels.org/simple/grpcio/grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl
Resolving www.piwheels.org (www.piwheels.org)... 46.235.225.189, 93.93.129.174, 2a00:1098:0:80:1000:3b:1:1, ...
Connecting to www.piwheels.org (www.piwheels.org)|46.235.225.189|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 12990873 (12M)
Saving to: ‘grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl’

grpcio-1.22.0-cp37-  69%[============ >        ]   8.56M  26.5KB/s    in 5m 9s

2019-07-31 01:14:19 (28.4 KB/s) - Read error at byte 8978432/12990873 (Error decoding the received TLS packet.). Retrying.

--2019-07-31 01:14:20--  (try: 2)  https://www.piwheels.org/simple/grpcio/grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl
Connecting to www.piwheels.org (www.piwheels.org)|46.235.225.189|:443... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 12990873 (12M), 4012441 (3.8M) remaining
Saving to: ‘grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl’

grpcio-1.22.0-cp37- 100%[+++++++++++++====== > ]  12.39M  30.1KB/s    in 2m 20s

2019-07-31 01:16:42 (28.1 KB/s) - ‘grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl’ saved [12990873/12990873]

(env) pi@nakano:~/tmp $ ls
grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl
tensorflow-1.13.1-cp37-none-linux_armv6l.whl
(env) pi@nakano:~/tmp $ pip install grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Processing ./grpcio-1.22.0-cp37-cp37m-linux_armv6l.whl
Requirement already satisfied: six > =1.5.2 in /usr/lib/python3/dist-packages (from grpcio==1.22.0) (1.12.0)
Installing collected packages: grpcio
Successfully installed grpcio-1.22.0
(env) pi@nakano:~/tmp $ pip install tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Processing ./tensorflow-1.13.1-cp37-none-linux_armv6l.whl
Collecting keras-applications > =1.0.8 (from tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/71/e3/19762fdfc62877ae9102edf6342d71b28fbfd9dea3d2f96a882ce099b03f/Keras_Applications-1.0.8-py3-none-any.whl
Requirement already satisfied: six > =1.10.0 in /usr/lib/python3/dist-packages (from tensorflow==1.13.1) (1.12.0)
Requirement already satisfied: numpy < 2.0, > =1.14.5 in /usr/lib/python3/dist-packages (from tensorflow==1.13.1) (1.16.2)
Collecting astor > =0.6.0 (from tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/d1/4f/950dfae467b384fc96bc6469de25d832534f6b4441033c39f914efd13418/astor-0.8.0-py2.py3-none-any.whl
Collecting wrapt > =1.11.1 (from tensorflow==1.13.1)
  Using cached https://www.piwheels.org/simple/wrapt/wrapt-1.11.2-cp37-cp37m-linux_armv6l.whl
Collecting protobuf > =3.6.1 (from tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/34/58/a8230dcd36e5db75c1084f4fc32b18cc217bb2806143597df625dc628a5d/protobuf-3.9.0-py2.py3-none-any.whl
Collecting gast > =0.2.0 (from tensorflow==1.13.1)
  Using cached https://www.piwheels.org/simple/gast/gast-0.2.2-py3-none-any.whl
Requirement already satisfied: grpcio > =1.8.6 in /home/pi/env/lib/python3.7/site-packages (from tensorflow==1.13.1) (1.22.0)
Collecting tensorflow-estimator < 1.15.0rc0, > =1.14.0rc0 (from tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/3c/d5/21860a5b11caf0678fbc8319341b0ae21a07156911132e0e71bffed0510d/tensorflow_estimator-1.14.0-py2.py3-none-any.whl
Collecting tensorboard < 1.14.0, > =1.13.0 (from tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/0f/39/bdd75b08a6fba41f098b6cb091b9e8c7a80e1b4d679a581a0ccd17b10373/tensorboard-1.13.1-py3-none-any.whl
Collecting termcolor > =1.1.0 (from tensorflow==1.13.1)
  Using cached https://www.piwheels.org/simple/termcolor/termcolor-1.1.0-py3-none-any.whl
Collecting absl-py > =0.7.0 (from tensorflow==1.13.1)
  WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))': /simple/absl-py/
  Using cached https://www.piwheels.org/simple/absl-py/absl_py-0.7.1-py3-none-any.whl
Collecting google-pasta > =0.1.6 (from tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/d0/33/376510eb8d6246f3c30545f416b2263eee461e40940c2a4413c711bdf62d/google_pasta-0.1.7-py3-none-any.whl
Collecting keras-preprocessing > =1.0.5 (from tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/28/6a/8c1f62c37212d9fc441a7e26736df51ce6f0e38455816445471f10da4f0a/Keras_Preprocessing-1.1.0-py2.py3-none-any.whl
Requirement already satisfied: wheel > =0.26 in /home/pi/env/lib/python3.7/site-packages (from tensorflow==1.13.1) (0.33.4)
Requirement already satisfied: h5py in /home/pi/env/lib/python3.7/site-packages (from keras-applications > =1.0.8- > tensorflow==1.13.1) (2.9.0)
Requirement already satisfied: setuptools in /home/pi/env/lib/python3.7/site-packages (from protobuf > =3.6.1- > tensorflow==1.13.1) (41.0.1)
Collecting markdown > =2.6.8 (from tensorboard < 1.14.0, > =1.13.0- > tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/c0/4e/fd492e91abdc2d2fcb70ef453064d980688762079397f779758e055f6575/Markdown-3.1.1-py2.py3-none-any.whl
Collecting werkzeug > =0.11.15 (from tensorboard < 1.14.0, > =1.13.0- > tensorflow==1.13.1)
  Using cached https://files.pythonhosted.org/packages/d1/ab/d3bed6b92042622d24decc7aadc8877badf18aeca1571045840ad4956d3f/Werkzeug-0.15.5-py2.py3-none-any.whl
Installing collected packages: keras-applications, astor, wrapt, protobuf, gast, tensorflow-estimator, markdown, absl-py, werkzeug, tensorboard, termcolor, google-pasta, keras-preprocessing, tensorflow
Successfully installed absl-py-0.7.1 astor-0.8.0 gast-0.2.2 google-pasta-0.1.7 keras-applications-1.0.8 keras-preprocessing-1.1.0 markdown-3.1.1 protobuf-3.9.0 tensorboard-1.13.1 tensorflow-1.13.1 tensorflow-estimator-1.14.0 termcolor-1.1.0 werkzeug-0.15.5 wrapt-1.11.2
(env) pi@nakano:~/tmp $ pip list


tensorboard          1.13.1
tensorflow           1.13.1
tensorflow-estimator 1.14.0


(env) pi@nakano:~/tmp $

関連パッケージも同様のエラーがでたのでwgetしてpip installして再実行してやっとこさtensorflowをインストールできた。

Raspberry Pi上だったのでLinuxコマンドのwgetを使ったが、WindowsならWSLのwgetcurlを使うか、ためしてないがブラウザでダウンロードしても多分動くはずだ。



..おかげで今月のギガ3GB全部使ってしまったよ..とほほ..

2019年7月30日火曜日

Raspbian OS 初回起動時からSSH接続したい




Raspbean OS をSDカードに書き込み、
Raspberry Piにさして最初に起動する際、
SSHが無効になっているので
どうしてもモニタやキーボードが必要になります。

Xを使う人はそれでもいいですが、
DonkeyCarやロボット、IoTゲートウェイとして
Xの入っていないRaspbean Liteをつかう人は
初回以外モニタなどは使用しない。

なので初回起動時からSSH接続したいはず。

とくにRaspberry Pi Zeroを使う場合
HDMIがミニHDMIコネクタでないと接続できない。

わざわざコネクタ買っても初回しか使わないし..

と、いうことで調べてみたら、
SDカードへイメージを書き込んだ直後、
SDカードカードのbootパーティション(wpa_supplicant.confと同じ場所)
に"ssh"という空のファイルを作成しておけば初回起動時にSSH接続できるようになるようだ。

情報元: http://downloads.raspberrypi.org/raspbian/release_notes.txt

sshというファイルを書き込んだSDカードをRaspberry Piに挿して
起動すると..うまくいった。デフォルトユーザでSSH経由でログインできた。

これは便利だ。

2019年5月7日火曜日

映画「アベンジャーズ エンドゲーム」前提パッケージ

※今回は、ITの話ではありません。

GWの最終週の日曜、たまたま岡田斗司夫氏のニコ生をみていたら、いまやってる映画「アベンジャーズ エンドゲーム」を見るための必要最低限の前提マーベル映画リストを上げていた。

ので、列挙してみた。

  • アイアンマンの1
  • マイティ・ソーのどれかひとつ (1だと浅野忠信がでてる)
  • キャプテン・アメリカの1
  • アベンジャーズの1
  • ガーディアンズ・オブ・ギャラクシーの1
  • アベンジャーズの2(エイジ・オブ・ウルトロン)
  • キャプテン・アメリカの3(シビル・ウォー)
  • アベンジャーズの3(インフィニティ・ウォー) 

GW 開始早々エンドゲームを見てしまった自分から見ても、いいリストだと思う。

端から端まで全部楽しむなら、ハルクとかアントマンとか、ひげマントの魔術師とかも全部見ているといいのだけど、そんなにマーベルに年貢を納めなくてもエンドゲームの本筋だけ追うのなら上記の8本で十分だ。


Pythonで例えるなら、エンドゲームリポジトリのsetup.pyinstall_requiresには上記の8本は最低でもいれておけば、全機能は実行できないけどコア機能は動作するはずだ。


..といっても、必要最小限のこれらのタイトル全部見ると17時間を超えるらしいけど..


2019年4月11日木曜日

AWS IoT Core にQoS=2でLast Willメッセージを設定したら例外が出た件

AWS IoT CoreへアクセスするPythonプログラムを書いた。
ライブラリはpahoではなくAWSIoTPythonSDKを使った。



ちなみにMQTTブローカへ接続するプログラムを書く場合、
ベンダ提供ライブラリを素直に使うのが生産性を上げるコツだ。
ベンダ固有の機能の有無を関数やメソッドのコード上ドキュメントで
確認できるし、
一番困るのがベンダ固有のpayloadやtopicフォーマットを持っている
場合だ。
ドキュメントをイチから読むより、関数やメソッドのドキュメントを
見るほうが圧倒的に速い..と私はおもっている。
..Eclipse Mosquitto、IBM Watson IoT PlatformとAWS IoT Coreしか
まだ触ったことがないのだけど..

話をもどすが、どうも AWS IoT に Will

つまりデバイスが死んだ際に
特定のメッセージを指定トピックへ送信してくれる
MQTTベースのメッセージブローカに標準搭載される機能

がないと思っている人が意外と多い。

AWS IoT に Will がないと書かれたブログ記事もすくなくなく
これを鵜呑みにした人がおおいのだろう。

ベータ版の頃はそうらしかったのだけど、
今のバージョンでは存在している。
#この先、消えるかはわからないけど ;-p

AWSIoTPythonSDK の AWSIoTMQTTClient クラスには

configureLastWill(topic, payload, QoS, retain=False)
というインスタンスメソッドが存在する。

なのでQoS=2にしてWillメッセージをセットすると..

Traceback (most recent call last):
  File "test_dev.py", line 45, in
    test_dev()
  File "test_dev.py", line 31, in test_dev
    client = Client('conf/aws/xxxx/xxxx.yml', 'xxxx_test')
  File "C:\Users\xxxxx\projects\xxxx\aws\broker.py", line 354, in __init__
    client.connect()
  File "C:\Users\xxxxx\AppData\Local\Continuum\anaconda3\envs\xxxx\lib\site-packages\AWSIoTPythonSDK\MQTTLib.py", line 486, in connect
    return self._mqtt_core.connect(keepAliveIntervalSecond)
  File "C:\Users\xxxxx\AppData\Local\Continuum\anaconda3\envs\xxxx\lib\site-packages\AWSIoTPythonSDK\core\protocol\mqtt_core.py", line 195, in connect
    raise connectTimeoutException()
AWSIoTPythonSDK.exception.AWSIoTExceptions.connectTimeoutException


というエラーになってconnectできない状態になってしまった。

どうも Will はサポートされたけど、
AWS IoT はあくまで QoS は 0 か 1 までで
QoS=2は未だにサポートしていないらしい..
というより、今サポートしてないなら、やる気なしでしょ..


ということでQoS=1にしたら正常に動作した


ちなみに引数にretainがあり、
AWSIoTPythonSDKのコードをおっていくとpahoのクライアントクラスに
そのまま値を渡しているので、
もしかしたら..とおもって retain=True で実行してみた。

..結果は、QoS=2のときと全く同じ例外が発生してしまった..

retain とは、
最後にpublishされたメッセージをブローカで保持し、
新規Subscriberにそのメッセージを渡す
MQTTベースのメッセージブローカに標準提供される機能のひとつ。

AWS IoTベータのころからサポートされておらず、
こちらもQoS=2同様
現時点でもサポートされていない
ということらしい..


そのかわりにシャドウを使えってことなのだろうけど..
この機能AWS IoT Coreにしか存在しない独自機能なんだよなあ..

..日本のSIerは、こういったベンダ依存をきらうからねえ..

2019年4月3日水曜日

AWS IoT Core へバイナリデータが送れない件(AWS IoT CoreをDonkey Carで使う)

Donkeycar のAI処理が重くなりすぎたので、サーバ側で処理させようとMQTTブローカ経由で画像データをおくっていたのだけど、AWS環境でもやってみたいということで試してみた。

AWS IoT Coreをセットアップして、paho-mqttを使って画像データを送信しようとしたのだけどうまくいかない..

AWS IoT Python SDK を使ってもうまく送れない..


Eclipse Mosquitto や IBM Watson IoT Platform だとうまくいったのに..



..と、いろいろ調べていると以下の記事


Python AWS IoT SDK - MQTT publish with binary payload fails
https://forums.aws.amazon.com/thread.jspa?threadID=237466


にこのような記述があった。

The AWS IoT Python SDK uses Eclipse Paho Python MQTT Client as the dependency underneath. It supports the following payload type in Python:
1. str
2. bytearray
3. unicode string

(日本語訳)
AWS IoT Python SDKは、その下の依存関係としてEclipse Paho Python MQTTクライアントを使用します。 Pythonでは次のペイロードタイプをサポートしています。
1. str
2. bytearray
3. Unicode文字列

..ん?
bytesがサポートされていない?!


仕様かよ!!






bytearray(message) したら..動いた..

マジかよ..subscribe側でbytesに戻さないと..


p.s.1

AWS IoT CoreはWatson IoT Platformより画面が整理されていて使いやすい。
..のだけど、パラメータが多いし、Raspberry Pi側にプライベートキーファイルとcertificateファイル、サーバ側のルートCAファイルをおいてやらないといけないのが面倒だ..

モノのシャドウはいわゆるMQTTブローカのWill機能。AWS IoTCore上でドキュメントを定義して、これをMQTT通信経由でget/delete/update/deltaイベントコールバックで操作する。
便利そうではあるのだけど、ドキュメントがJSONデータ1つなんだよなあ..

まあキューにすればMQの悪名高きデッドレターキュー管理シないといけなくなるしなあ..



p.s.2

にしても..各ベンダのMQTTブローカって独自色を出そうと付加機能つけすぎ..
正直 paho-mqtt ライブラリで疎通取るより各ベンダ独自のSDK使ったほうが、生産性がとっても高くなることがよくわかった..
#SDKで方言対応してくれるからね

このあたり、基盤屋が対応してくれればいいのだけど、堅モノから一歩たりとも出てくれない..

せめて..死んで^H^H^H python覚えてくれないかなあ..

2019年3月14日木曜日

超音波センサHC-SR04をDonkey Carで使う


前方障害物との距離をはかりたくて、HC-SR04をRaspberry Piに接続し、Donkey Carのパーツクラス化してみた。

[GitHub] coolerking/donkeypart_hc_sr40
※インストール方法や使い方は上記リポジトリのREADME.mdを参照のこと。

このセンサ、5VとGND以外は、デジタルピンのままで使用できるのが良いのだけど、以下の仕様通りにGPIOを操作してやらないといけない。以下の記述は、購入元のスイッチサイエンス社サイトに掲載されていた。以下、引用する。

  • トリガ端子を10 us以上Highにしてください。
  • このセンサモジュールが40 kHzのパルスを8回送信して受信します。
  • 受信すると、出力端子がHighになります。
  • 出力端子がHighになっている時間がパルスを送信してから受信するまでの時間です。
  • 出力端子がHighになっている時間の半分を音速で割った数値が距離です。

トリガはTrigピン、出力端子というのがEchoピンです。

引用を要約すると、Trigピンに所定の値でOUTPUTして、Echo受信状態(HIGH)になったらLOWになるまでの時間を計測して、往復しているので2で割り、最後音速を使って自分で距離にしてね、ということ。

このような場合こそpigpioパッケージの指定ピンに対するコールバック関数機能が有効です。

最初に記述したリポジトリのコードは
pigpio python サンプルコードの「SonarRanger」をもとに書いたものです。

この超音波距離計即センサ、pigpioパッケージでコールバック関数をどう使うかを学習するのに最適。





この系統の処理なら、pigpioのほうがコード数が少ないと思いますよ。

2019年3月12日火曜日

DCモータをDonkey Carで使う

■DCモータを Donkey Carで使う


模型などでよく使用される マブチモータFC130RA-2270 をDonkey Carの駆動輪用に使用する際のパーツクラスをつくってみました。

Donkey Carを知らない人でも、Raspberry PiにDCモータを接続し、動作をPythonプログラムで操作したい人も参考になると思います。


■TA7291P DCモータドライバ



DCモータをRaspberry Piに直接つないでも操作することはできません。3.3VとGNDにつないで一定速度で回す事はできますが、速度を変えたり、逆転したりすることはできません。

このような場合、モータドライバというICを間にはさむ方法が一般的です。
このICにもいろんな種類があって、用途に合わせて選定しなくてはなりません。

・モータの種類(DCモータ、ステッピングモータ、サーボモータ)
・モータの個数
・モータ以外にGPIOピンをどのくらい使用するか

GPIOピンをほかのセンサやデバイスに使用する場合、26本もあるとはいえ、できるだけ使用ピンをへらしたいと考えるはずです。なれていない回路設計も1ピンへるだけでバグ発生原因が減るわけですし..

モータ数が多数などGPIOが足りない場合は、I2CやSPI対応しているICやマルチチャネルをもつICを選択します。

今回ここで使用するDCモータドライバ TA7291P は、I2CやSPIを使用しない、PWMピンを併用して回転速度調整をおこなう仕様となっています。

以下の図は、単一のDCモータの場合の結線例です。

 
GPIO番号接続先備考
5VTA7291P 7pin(Vcc), 10kΩ経由でTA7291P 4pin(Vref) 
GNDTA7291P 1pin(GND), DCモータGND
GPIO19TA7291P 5pin(IN1)PWM OUTPUT
GPIO26TA7291P 6pin(IN2)PWM OUTPUT

実は、Raspberry PiのハードウェアPWMピンもGPIO15/GPIO12か、GPIO13を使用しなくてはなりませんが、上図のGPIO19とGPIO26は通常のGPIOピンです。ハードウェアPWMではないGPIOピンをPWM化させると疑似PWMという品質の低いPWMになってしまいます。

しかし、これをハードウェアPWM並みの性能に上げる方法があります。

■ pigpio


pigpioはPythonパッケージの一つで、GPIOを操作することのできるライブラリを提供します。このライブラリをつかうと、疑似PWMの性能を向上させてくれる機能をもっているそうです。


pigpioはPythonプログラムからGPIOを操作するライブラリとしては後発で、実行前提としてpigpiodというデーモンプロセスをあらかじめRaspberry Pi上であげておかなくてはなりません。

デーモンが常時存在している恩恵もあります。別のノードからコマンドでGPIOを操作することができますし、疎結合となっているためテスト時にモッククラスを比較的簡単に実現することができます。


pigpioを使用可能にするには、以下のコマンドをRaspberry Pi上で実行します。

   $ sudo apt install -y pigpio
   $ sudo pigpiod
パーツクラスは以下のGitHubリポジトリにあります。

coolerking/donkeypart_dcmotor
https://github.com/coolerking/donkeypart_dcmotor

   $ cd ~/
   $ git clone https://github.com/coolerking/donkeypart_dcmotor.git
   $ cd donkeypart_dcmotor
   $ pip install -e .

■Donkey Carアプリの修正

まず~/mycar/config.pyに以下の設定値を記述します。

変数名設定する変数値
MOTOR_IN1_GPIOIN1と接続されているGPIOの番号
MOTOR_IN2_GPIOIN2と接続されているGPIOの番号

~/mycar/manage.pyを編集して、DCMotorパーツを追加します。
以下修正サンプルです。

:
# ダミーデータ
V.mem['user/motor/value'] = 0.5
V.mem['user/motor/status'] = 'move'
:

:
from pigpio
pi = pigpio.pi()

from donkeypart_dcmotor import DCMotor
motor = DCMotor(pi, cfg.MONITOR_IN1_GPIO, cfg.MOTOR_IN2_GPIO)
V.add(motor, inputs=['user/motor/value', 'user/motor/status'])
:
上記の通り、出力値がvalue(float型)とstatus(string型)の2種類に増えているので、Tubデータフォーマットも変わってきます。

引数名範囲説明推奨キー名
motor_value[-1.0, 1.0]のfloat値正値:正転、負値:逆転となる。最大値は、モータにVsピンと同等の電圧が加わる。本リポジトリのコードではアナログパッドなどの遊びを鑑み、(-0.1, 0.1)の範囲はゼロとして扱っている。user/motor/value
motor_statusmove/free/brakeのいずれか'move':モータ駆動、 'free':モータ駆動なし、'brake':制動停止user/motor/brake

このためmanage.pyTubWriter引数も合わせて変更する必要があります。以下は一例です。

    :
    # recording ダミー入力
    V.mem['recording'] = True
    :
    # Tubデータ・フォーマットも変更しなくてはならない
    inputs = ['cam/image_array', 'user/motor/value', 'user/motor/status', 'timestamp']
    types = ['image_array', 'float', 'str', 'str']

    # single tub
    tub = TubWriter(path=cfg.TUB_PATH, inputs=inputs, types=types)
    V.add(tub, inputs=inputs, run_condition='recording')
    :
donkeycar パッケージのデフォルトmanage.pyではdonkeycar.partモジュールにデフォルトのオートパイロットパーツクラスKerasLinearが格納されていますが、Tubデータの項目を変更したので、デフォルトのオートパイロットでは動作しなくなってしまいました。

このため、以下のようにKerasLinearの代替となるクラスを作成する必要があります。

MOTOR_STATUS = ['move', 'free', 'brake']
class MyPilot(KerasPilot):
    def __init__(self, model=None, num_outputs=None, *args, **kwargs):
        super(KerasLinear, self).__init__(*args, **kwargs)
        if model:
            self.model = model
        elif num_outputs is not None:
            self.model = my_default_linear()
        else:
            self.model = my_default_linear()

    def run(self, img_arr):
        img_arr = img_arr.reshape((1,) + img_arr.shape)
        outputs = self.model.predict(img_arr)
        # モータ値:回帰
        left_value = outputs[0][0][0]
        # モータステータス:分類
        left_status = MOTOR_STATUS[np.argmax(outputs[1][0][0])]

        # 操作データを返却
        return motor_value, motor_status


def my_default_linear():
    img_in = Input(shape=(120, 160, 3), name='img_in')
    x = img_in

    # Convolution2D class name is an alias for Conv2D
    x = Convolution2D(filters=24, kernel_size=(5, 5), strides=(2, 2), activation='relu')(x)
    x = Convolution2D(filters=32, kernel_size=(5, 5), strides=(2, 2), activation='relu')(x)
    x = Convolution2D(filters=64, kernel_size=(5, 5), strides=(2, 2), activation='relu')(x)
    x = Convolution2D(filters=64, kernel_size=(3, 3), strides=(2, 2), activation='relu')(x)
    x = Convolution2D(filters=64, kernel_size=(3, 3), strides=(1, 1), activation='relu')(x)

    x = Flatten(name='flattened')(x)
    x = Dense(units=100, activation='linear')(x)
    x = Dropout(rate=.1)(x)
    x = Dense(units=50, activation='linear')(x)
    x = Dropout(rate=.1)(x)

    # 最終全結合層と活性化関数のみ差し替え
    # categorical output of the angle
    #angle_out = Dense(units=1, activation='linear', name='angle_out')(x)

    # continous output of throttle
    #throttle_out = Dense(units=1, activation='linear', name='throttle_out')(x)
   
    # モータ値(回帰)
    value_out  = Dense(units=1, activation='linear', name='value_out')(x)
    # モータ値(分類)
    status_out = Dense(units=len(MOTOR_STATUS), activation='softmax', name='left_status_out')(x)


    #model = Model(inputs=[img_in], outputs=[angle_out, #throttle_out])
    model = Model(inputs=[img_in], outputs=[value_out, status_out])

    #model.compile(optimizer='adam',
    #              loss={'angle_out': 'mean_squared_error',
    #                    'throttle_out': 'mean_squared_error'},
    #              loss_weights={'angle_out': 0.5, 'throttle_out': .5})
    # 回帰、分類別に最適化関数を使い分け
    model.compile(optimizer='adam',
                  loss={'value_out': 'mean_squared_error',
                        'status_out':  'categorical_crossentropy'},
                  loss_weights={'value_out': 0.5,
                        'status_out': 0.5})

    return model

上記モデルのアウトプット層は以下の通り。


変数名範囲説明
value_out[-1.0, 1.0]の範囲のfloat値DCモータの電圧値をあらしており、1.0/-1.0の場合、用意されたDCモータ用電圧の最大値が投入される。
status_out0,1,2のいずれかのint値配列MOTOR_STATUSのindex値に相当。

manage.pyのトレーニング関数train()も修正する必要があります。

まず先頭部分のTubデータのキーを修正します。

    :
    X_keys = ['cam/image_array']
    y_keys = ['user/motor/value', 'user/motor/status']
    :
そして、Tubデータのmotor_statusが文字列であるのに対し、モデルのアウトプット層の所定の変数は0,1,2のint値となっているため、このあたりの変更にも対応し無くてはならない。本来は大改修が必要なのだけど、donkeycarパッケージはその点うまいかんじにできている(これに気づいているユーザは少ないと思うけど..)。

TubGroup のトレーニングバッチと評価用バッチデータを取得するための関数TubGroup.get_traun_val_genの引数train_record_transformval_record_transformに修正する関数motor_status_transformを与えることで対応できてしまうのだ。

    :
    tubgroup = TubGroup(tub_names)
    train_gen, val_gen = tubgroup.get_train_val_gen(
        X_keys, y_keys,
        batch_size=cfg.BATCH_SIZE,
        train_frac=cfg.TRAIN_TEST_SPLIT,
        train_record_transform=motor_status_transform,
        val_record_transform=motor_status_transform)
    :
関数`motor_status_transform`の定義例は、以下の通り。

MOTOR_STATUS = ['move', 'free', 'brake']
:
def agent_record_transform(record_dict):
    """
    TubGroupクラスのメソッドget_train_val_genの引数として渡し、
    Agent用Tubデータ仕様のものでも学習データ化できるようにする
    マッピング関数。

    引数
        record_dict     もとのレコードデータ(Agent用Tubデータ、辞書型)
    戻り値
        record_dict     AIのinput/output層にあったマッピングが終わったレコードデータ(辞書型)
    例外
        ValueError      モータステータスキーが1件も存在しない場合
    """
    status_val = record_dict['user/motor/status']
    if status_val is not None:
        record_dict['user/motor/status'] = motor_status_to_list(status_val)
    else:
        raise ValueError('no value of key=\"user/motor/status\" in loaded record')
    return record_dict

def motor_status_to_list(val):
    """
    モータステータス値を数値リスト化する。

    引数
        モータステータス値
    戻り値
        数値リスト
    """
    classes = np.zeros(len(MOTOR_STATUS)).tolist()
    classes[MOTOR_STATUS.index(val)] = 1
    return classes

■まとめ

・pigpioパッケージで実装すれば疑似PWMはハードウェアPWMに近い性能になる
・I2C/SPIによる回路短縮をえらぶと、コードが増えるし、データシートが読めないと難しい
・PWMのみの場合はコードは簡単だが、ピン数は複雑になる


ちなみに、I2Cを使う場合はDRV8830があります。SPI化は更にADC/DACをつかうことで実現できます。


<後日追記>
実はこのTA7291P、現在では使用していません。
理由はモータ電源の電圧と実際にモータへ割り当てられる電圧差が大きいこと。
一度実測した値だと、2.6Vの入力に対して2.1~1.8Vくらい。

今はTB6612(実際は秋月のモータ不ドライブキット)を使っている。
こちらだと実測2.4Vが2.3V~2.0Vくらい。
キットの足とPiをジャンパ線でつないで使ってます。


はんだでジャンパするとピン1本管理しなくていいのだが、
手が滑ってこてをチップにあててしまい1個無駄にしてしまった。
不器用な方はご注意を。


2019年2月25日月曜日

ブログ記事「Lingvo: A TensorFlow Framework for Sequence Modeling for Sequence Modeling」を勝手に翻訳してみた

今朝のタイムラインに流れていたブログ記事 Lingvo: A TensorFlow Framework for Sequence Modeling for Sequence Modeling を勝手に翻訳したものです。

--------

Lingvo: シーケンスモデリングのための TensorFlow フレームワーク

  • 2019年2月23日
  • Jonathan Shen

Lingvo とは、 国際語エスペラント語 で「言語」を表します。Lingvo と命名したことは、まさにLingvoフレームワークのルーツを暗示しています - Lingvoは、機械翻訳、音声認識、そして音声合成のような言語関連タスクのためのシーケンスモデルに焦点を合わせてTensorFlowを使った一般的なディープラーニングフレームワークとして開発されました。
内部的には、Lingvoフレームワークは勢いを増し、Lingvoを使用している研究者の数はバルーンのように膨らんでいます。その結果、Lingvoを使用して作成された最先端の結果を含む出版済みの 論文 が今では多数あります。サポートされているアーキテクチャは、従来のRNNシーケンスモデルからTransformerモデルおよびVAEコンポーネントを含むモデルまで多岐にわたります。私たちの研究コミュニティの支持を示し、再現可能な研究努力を奨励するために、私たちはフレームワークをオープンソース化し、私たちの論文で使われているモデルを公開し始めています。

図1:Lingvoフレームワークの概要。評価と提供のためにモデルをインスタンス化、トレーニング、およびエクスポートする方法を概説しています。

Lingvo は共同研究を念頭に置いて構築されており、さまざまなタスクで共通のレイヤの実装を共有することでコードの再利用を促進しています。さらに、すべてのレイヤが同じ共通のインタフェースを実装し、同じ方法でレイアウトされています。これにより、よりクリーンでわかりやすいコードが生成されるだけでなく、他の人が別のタスクに対して行った改善を自分のタスクに適用することが非常に簡単になります。この一貫性を強化するには、より多くの規律 (dicipline) と共通語 (boilerplate) が必要になりますが、 Lingvo では、これを最小限に抑えて研究中の反復時間を短縮することを試みています。

コラボレーションのもう1つの側面は、再現可能な結果を共有することです。Lingvoは、チェックインモデルのハイパーパラメータ設定を集中管理する場所を提供します。これは重要な実験を文書化するのに役立つだけでなく、同一のモデルを訓練することによってあなたの結果を簡単に再現する方法を他の人に与えることになります。

def Task(cls):
  p = model.AsrModel.Params()
  p.name = 'librispeech'

  # encoder パラメータの初期化
  ep = p.encoder
  # データは240次元フレーム(80x3フレーム)で構成されており、
  # それらを個々に80次元フレームとして再解釈します。
  # 詳細は LibrispeechCommonAsrInputParams も参照のこと。
  ep.input_shape = [None, None, 80, 1]
  ep.lstm_cell_size = 1024
  ep.num_lstm_layers = 4
  ep.conv_filter_shapes = [(3, 3, 1, 32), (3, 3, 32, 32)]
  ep.conv_filter_strides = [(2, 2), (2, 2)]
  ep.cnn_tpl.params_init = py_utils.WeightInit.Gaussian(0.001)
  # Conv LSTM レイヤを無効化
  ep.num_conv_lstm_layers = 0

  # decoder パラメータの初期化
  dp = p.decoder
  dp.rnn_cell_dim = 1024
  dp.rnn_layers = 2
  dp.source_dim = 2048
  # unrolling ベースに基づく間、機能を使用する。
  dp.use_while_loop_based_unrolling = False

  tp = p.train
  tp.learning_rate = 2.5e-4
  tp.lr_schedule = lr_schedule.ContinuousLearningRateSchedule.Params().Set(
      start_step=50000, half_life_steps=100000, min=0.01)

  # Setting p.eval.samples_per_summary を大きな値に設定すると、
  # dev, devother, test, testother は完全に評価され(これらの各セットの
  # num_samplesは5000未満なので)、トレーニングサマリは5000サンプルで計算される
  p.eval.samples_per_summary = 5000
  p.eval.decoder_samples_per_summary = 0

  # オーバーフィットを防ぐために、可変重量ノイズを使用
  p.vn.global_vn = True
  p.train.vn_std = 0.075
  p.train.vn_start_step = 20000

  return p


Lingvo は NLP に焦点を当てることから始めましたが、それは本質的に非常に柔軟性があり、画像セグメンテーションや点群分類などのタスクのためのモデルはフレームワークを使ってうまく実装されています。Distillation、GAN、およびマルチタスクモデルもサポートされています。同時に、このフレームワークはスピードを犠牲にすることはなく、最適化された入力パイプラインと高速分散トレーニングを特徴としています。最後に、Lingvoはプロダクションの容易さを目指してまとめられており、モバイル推論のためのモデルの移植への明確な道筋さえあります。

コードに直接ジャンプするには、GitHubページcodelab を調べてください。Lingvoまたはそれがサポートする高度な機能の詳細については、私たちの 論文 を参照してください。
-----

個々に乗ってるコードを読む限りでは、自然言語処理系DLは基本エンコーダデコーダで、それぞれのレイヤ群をあらわすオブジェクトにパラメータをセットするだけでモデル構築ができるフレームワークのようだ。

でもね..機械学習やディープラーニングで苦労するのはモデルよりもデータの口金(くちがね)にあわせることであって、特に日本語などの分かち書きから始めないとだめな言語はとっても面倒になるのよ..そのあたりをカバーするフレームワークが本当はほしいんだけどなあ..

 

2019年2月6日水曜日

pip install mpi4py したら mpi.h がないと怒られた件

Ubuntu 18.04 LTS 環境下のPython3(python3-dev)で


pip install mpi4py

したら、

    _configtest.c:2:10: fatal error: mpi.h: No such file or directory
     #include
              ^~~~~~~
    compilation terminated.
    failure.
    removing: _configtest.c _configtest.o
    error: Cannot compile MPI programs. Check your configuration!!!
   
    ----------------------------------------

Command "/home/tasuku_hori/env/bin/python3 -u -c "import setuptools, tokeni
ze;__file__='/tmp/pip-install-8php8m1j/mpi4py/setup.py';f=getattr(tokenize,
 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec
(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-xt1ud26
w/install-record.txt --single-version-externally-managed --compile --instal
l-headers /home/tasuku_hori/env/include/site/python3.6/mpi4py" failed with
error code 1 in /tmp/pip-install-8php8m1j/mpi4py/


というエラーが出た。

いろいろ調べてみたら、

sudo apt install -y libopenmpi-dev

を実行後再度実行すると成功した。


調べている間、openmpi-binだとかmpichだとかをapt install しろ書いてあったが
私の環境では libopenmpi-dev だった。

ご参考まで。

Google Colab相当の環境をローカルPC上のDocker Composeで実現する

 Docker Composeの有料版に、お金を払いたくない ^H^Hが使えない ため古いゲーミングPC(GeForce3080)にDocker Composeを入れてその上のコンテナでGoogle Colab相当のノート操作ができないかためしてみた: コンテナイメージとして a...