- 投稿日:2019-04-13T21:20:40+09:00
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (プロキシ版)
概要
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)を会社等のプロキシ環境で使う際の設定になります。
環境
Ubuntu 18.04
目指す環境
- python==3.5
- tensorflow==1.12.0
- docker内でグラフプロット等のGUI使用可能
- プロキシ環境で動作するコンテナ
下準備
1. dockerのインストール
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の1を参照
2. ホスト側のGUI表示用設定
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の2を参照
3. NVIDIAドライバーとnvidia-docker2のインストール(GPU使用の場合)
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の3を参照
4. dockerのプロキシ設定とsudoなし設定
docker pull等を実行できるようにdockerのプロキシ設定を行います。
あとsudoも使わなくていいように設定しておきます。参考記事 : Ubuntu Docker インストールとproxyとsudo無し実行
5. DNSの設定
Ubuntuの場合、dockerコンテナのDNS設定はホスト側のDNS設定を引き継ぎます。
具体的にはホストの「/etc/resolve.conf」がコンテナ内にコピーされます。
この際にGUIの設定画面等で設定したホスト側のDNS設定やDHCPから配布された設定が「/etc/resolve.conf」に反映されていない場合があります。
以下のページを参考に、nameserverが自分自身を指定している場合(127.0.0.1など)の場合は設定を変更して下さい。参考記事 : Ubuntu 16.10: /etc/resolv.confのnameserver 127.0.0.1を防ぐ
dockerの設定
6. Dockerfile
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)と比べて②環境変数設定, ③apt.confの作成 を追加しています。これでコンテナ内のプロキシ環境変数とaptのプロキシを設定しています。
使用する際は「PROXY_ID」, 「PROXY_PASS」, 「PROXY_HOST」, 「PROXY_PORT」のoooを自分のプロキシの「認証ID」, 「認証パスワード」, 「サーバー名」, 「ポート番号」に変更します。Dockerfile# GPUの場合 #FROM tensorflow/tensorflow:1.12.0-gpu-py3 # ①CPUの場合 FROM tensorflow/tensorflow:1.12.0-py3 COPY into_container/requirements.txt /root/ # ②環境変数設定 ENV PROXY_ID ooo ENV PROXY_PASS ooo ENV PROXY_HOST ooo ENV PROXY_PORT ooo ENV PROXY_SERVER http://"$PROXY_ID":"$PROXY_PASS"@"PROXY_HOST":"PROXY_PORT" ENV http_proxy "$PROXY_SERVER" ENV https_proxy "$PROXY_SERVER" ENV ftp_proxy "$PROXY_SERVER" ENV HTTP_PROXY "$PROXY_SERVER" ENV HTTPS_PROXY "$PROXY_SERVER" ENV FTP_PROXY "$PROXY_SERVER" # ③apt.confの作成 RUN echo "Acquire::ftp::proxy \"""$PROXY_SERVER""\";" > /etc/apt/apt.conf \ && echo "Acquire::fttp::proxy \"""$PROXY_SERVER""\";" >> /etc/apt/apt.conf \ && echo "Acquire::fttps::proxy \"""$PROXY_SERVER""\";" >> /etc/apt/apt.conf # ④パッケージインストール RUN add-apt-repository -y ppa:jonathonf/vim \ && apt-get update \ && apt-get install -y git vim xterm sudo python3-tk \ && pip3 install --upgrade pip \ && pip3 install -r /root/requirements.txt # ⑤ユーザーの切り替え RUN groupadd -g 1000 developer && \ useradd -u 1000 -g 1000 --groups sudo --create-home --shell /bin/bash developer && \ echo 'developer:P@ssw0rd' | chpasswd USER developer WORKDIR /home/developer7. ビルド
普通にビルドすればOKです。
build.shdocker build -t baby-steps-env .8. コンテナ起動
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の5を参照
9. 実行
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の6を参照
7. 動作確認
コンテナ内のbashコンソールで
書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)の7を参照
8. Gitリポジトリ
Gitに今回紹介したソースをあげていますのでよければご利用ください。
Ubuntu用 : kinziro/baby-steps-ubuntu-env_on_docker_in_proxy参考にさせて頂いたサイト
Ubuntu Docker インストールとproxyとsudo無し実行
Ubuntu 16.10: /etc/resolv.confのnameserver 127.0.0.1を防ぐ
- 投稿日:2019-04-13T12:22:07+09:00
Deep Learningアプリケーション開発 (7) TensorFlow Lite with Python on Raspberry Pi and Edge TPU
この記事について
機械学習、Deep Learningの専門家ではない人が、Deep Learningを応用したアプリケーションを作れるようになるのが目的です。MNIST数字識別する簡単なアプリケーションを、色々な方法で作ってみます。特に、組み込み向けアプリケーション(Edge AI)を意識しています。
モデルそのものには言及しません。数学的な話も出てきません。Deep Learningモデルをどうやって使うか(エッジ推論)、ということに重点を置いています。
- Kerasで簡単にMNIST数字識別モデルを作り、Pythonで確認
- TensorFlowモデルに変換してPythonで使用してみる (Windows, Linux)
- TensorFlowモデルに変換してCで使用してみる (Windows, Linux)
- TensorFlow Liteモデルに変換してPythonで使用してみる (Windows, Linux)
- TensorFlow Liteモデルに変換してCで使用してみる (Linux)
- TensorFlow Liteモデルに変換してC++で使用してみる (Raspberry Pi)
- TensorFlow LiteモデルをEdge TPU上で動かしてみる (Raspberry Pi) <--- 今回の内容
今回の内容
- Kerasモデル(h5)を、Edge TPU用に変換する
- Raspberry Pi上でのEdge TPU環境を用意する
- Raspberry Piに接続されたEdge TPU上でモデルを動作させてMNIST数字識別をする
TensorFLow Lite用モデルはKerasで簡単にMNIST数字識別モデルを作り、Pythonで確認で作成した
conv_mnist.h5を使います
ソースコードとサンプル入力画像: https://github.com/take-iwiw/CNN_NumberDetector/tree/master/07_TensorflowLite_TPU環境
- OS: Windows 10 (64-bt)
- CPU = Intel Core i7-6700@3.4GHz (物理コア=4、論理プロセッサ数=8)
- Raspberry Pi 2 Model B (2018-11-13-raspbian-stretch)
- その他: Google Edge TPU
Keras用モデルをEdge TPU用モデルに変換する
量子化したTensorFlow Liteモデルに変換する
Edge TPU上で動作可能なモデルは、いくつかの制約を満たしたTensorFlow Liteモデル(tflite)になります。(https://coral.withgoogle.com/web-compiler/ のRequirementsセクションを参照)
そのため、まずはKerasで作成したモデル(h5)をTensorFlow Liteモデル(tflite)に変換します。その際に、上記制約を満たすために、量子化オプションも付けます。
変換ツール (tflite_convert)の使い方は、https://www.tensorflow.org/lite/convert/cmdline_examples を参考にしてください。これによって、conv_mnist.tfliteというファイルが出来上がります。
Kerasモデルから量子化済みTensorFlowLiteモデルに変換tflite_convert ^ --output_file=conv_mnist.tflite --keras_model_file=conv_mnist.h5 ^ --inference_type=QUANTIZED_UINT8 ^ --default_ranges_min=0 ^ --default_ranges_max=255 ^ --mean_values=128 ^ --std_dev_values=127変換はWindows上のAnaconda環境(python=3.6.8, tf-nightly-gpu=1.14.1.dev20190403)で行いました。
TensorFlowをpipインストールすると、自動的にtflite_convertもインストールされます。Edge TPU用モデルに変換する
次に、作成したTensorFlow Liteモデルを、Edge TPU用に変換します。これには、Googleが提供しているWebコンパイラを使用します。
https://coral.withgoogle.com/web-compiler/
Drag and drop your model file hereの所に、先ほど作成したconv_mnist.tfliteをドラッグ&ドロップし、使用許諾的な2つのチェックボックスにチェックを付けると、自動的にコンパイルが始まります。成功したら下記画面のようになるので、
Download modelで、ダウンロードします。
conv_mnist_123456789_edgetpu.tfliteというファイルがダウンロードされます。扱いやすいように、数字部分は消してconv_mnist_edgetpu.tfliteとしておきます。備考:
2019年4月11日まではベータ版ということで、MobileNetなど、限られたモデルしか対応していませんでした。4月12日(この記事を書いている前日)から、カスタムモデルにも対応されるようになりました!!Raspberry Pi上でのEdge TPU環境を用意する
基本的には、https://coral.withgoogle.com/docs/accelerator/get-started/ の通りに進めれば大丈夫です。
ラズパイ上の端末で以下コマンドでインストールします。EdgeTPUインストールonラズパイcd ~/ wget https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz -O edgetpu_api.tar.gz --trust-server-names tar xzf edgetpu_api.tar.gz cd edgetpu_api bash ./install.shが、僕の環境はRaspberry Pi 2のため、Edge TPUは未対応のためインストールに失敗しました。また、virtualenv上ではうまくインストールできませんでした。
以下方法で回避しましたので、同じ状況の人は参考にしてください。(自己責任でお願いします)Raspberry Pi 2にインストールする(optional)
install.sh でプラットフォームチェックしている部分を以下のように変更します。
ラズパイ3でも32bitモードで動いているので、バイナリ互換性はあるはず、と思いチェック処理だけ変えたら出来ました。install.sh~略~ elif [[ "${CPU_ARCH}" == "armv7l" ]]; then MODEL=$(cat /proc/device-tree/model) # if [[ "${MODEL}" == "Raspberry Pi 3 Model B Rev"* ]]; then if [[ "${MODEL}" == "Raspberry Pi "* ]]; then info "Recognized as Raspberry Pi 3 B." LIBEDGETPU_SUFFIX=arm32 HOST_GNU_TYPE=arm-linux-gnueabihf # elif [[ "${MODEL}" == "Raspberry Pi 3 Model B Plus Rev"* ]]; then elif [[ "${MODEL}" == "Raspberry Pi "* ]]; then info "Recognized as Raspberry Pi 3 B+." LIBEDGETPU_SUFFIX=arm32 HOST_GNU_TYPE=arm-linux-gnueabihf fi ~略~virtualenv上にインストールする(optional)
単にinstall.sh を実行すると、パッケージはグローバル環境にインストールされるようです。(virtualenvをactivate/workonしていても)。
そのため、自分の仮想環境に入っている状態で、別途pip installする必要がありました。
これをやらないと、No module named 'edgetpu'エラーが出ます。まとめると以下のようになります。
EdgeTPUインストールfor仮想環境onラズパイ2cd ~/ workon py3_tpu wget https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz -O edgetpu_api.tar.gz --trust-server-names tar xzf edgetpu_api.tar.gz cd edgetpu_api nano ./install.sh # 編集する bash ./install.sh pip install edgetpu-1.9.2-py3-none-any.whlEdge TPU上でモデルを動作させてMNIST数字識別をする
Edge TPUのインストールを完了すると、デモコードが
/usr/local/lib/python3.5/dist-packages/edgetpu/(通常インストールの場合)、/home/pi/.virtualenvs/py3_tpu/lib/python3.5/site-packages/edgetpu(virtualenvの場合)にインストールされます。デモコードを動かす
xxx/site-packages/edgetpu/demo/classify_image.pyが識別用のサンプルコードです。
本当なら、以下のようにすることでデモコードで、今回作成したモデルを試すことが出来ます。
が、これは動きません。
デモコード(というか、画像識別用Wrapper)が、3chカラー入力を前提としているため、今回作成した1chグレースケールのMNIST識別モデルはパラメータチェックではじかれてエラーになります。
MobileNet等のちゃんとしたモデルなら、これで確認出来ます。デモコードを動かすpython3 /home/pi/.virtualenvs/py3_tpu/lib/python3.5/site-packages/edgetpu/demo/classify_image.py \ --model conv_mnist_edgetpu.tflite \ --label mnist_labels.txt \ --image resource/3.jpgちなみに、mnist_labels.txtには識別結果と表示ラベルのペアを記載します。
mnist_labels.txt0 num0 1 num1 2 num2 ~略~識別用コードを実装する
edgetpu/demo/classify_image.pyをベースに、自分で実装します。classify_image_mnist.pyとします。classify_image_mnist.pyimport argparse import re from edgetpu.classification.engine import ClassificationEngine from PIL import Image, ImageOps import numpy # Function to read labels from text files. def ReadLabelFile(file_path): """Reads labels from text file and store it in a dict. Each line in the file contains id and description separted by colon or space. Example: '0:cat' or '0 cat'. Args: file_path: String, path to the label file. Returns: Dict of (int, string) which maps label id to description. """ with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines() ret = {} for line in lines: pair = re.split(r'[:\s]+', line.strip(), maxsplit=1) ret[int(pair[0])] = pair[1].strip() return ret def main(): parser = argparse.ArgumentParser() parser.add_argument( '--model', help='File path of Tflite model.', required=True) parser.add_argument( '--label', help='File path of label file.', required=True) parser.add_argument( '--image', help='File path of the image to be recognized.', required=True) args = parser.parse_args() # Prepare labels. labels = ReadLabelFile(args.label) # Initialize engine. engine = ClassificationEngine(args.model) # Read input image and convert to tensor img = Image.open(args.image) img = img.convert('L') img = ImageOps.invert(img) input_tensor_shape = engine.get_input_tensor_shape() if (input_tensor_shape.size != 4 or input_tensor_shape[3] != 1 or input_tensor_shape[0] != 1): raise RuntimeError( 'Invalid input tensor shape! Expected: [1, height, width, 3]') _, height, width, _ = input_tensor_shape img = img.resize((width, height), Image.NEAREST) input_tensor = numpy.asarray(img).flatten() # Run inference. for result in engine.ClassifyWithInputTensor(input_tensor=input_tensor, threshold=0.1, top_k=3): print('---------------------------') print(labels[result[0]]) print('Score : ', result[1]) # for time measurement for i in range(5000): for result in engine.ClassifyWithInputTensor(input_tensor=input_tensor, threshold=0.1, top_k=3): pass if __name__ == '__main__': main()オリジナルのデモコードでは、読み込んだ画像をそのまま入力として、ClassificationEngine.ClassifyWithImageをコールしていました。
この関数は画像を入れるだけで推論処理が出来て便利なのですが、グレースケール(1ch)画像には対応していないです。
ClassificationEngine.ClassifyWithImageは、内部でリサイズなどを行ったあと、ClassificationEngine.ClassifyWithInputTensor を呼んでいます。こちらの関数の入力は文字通りTensorになります。
ですので、今回は自分で画像->Tensorへの変換を行い、直接ClassificationEngine.ClassifyWithInputTensor を呼ぶことにしました。また、処理時間測定のために無駄に5000回くらい呼んでいます。
実行してみる
以下コマンドで実行できます。
実行コマンドpython3 classify_image_mnist.py \ --model ~/CNN_NumberDetector/07_TensorflowLite_TPU/conv_mnist_edgetpu.tflite \ --label ~/CNN_NumberDetector/07_TensorflowLite_TPU/mnist_labels.txt \ --image ~/CNN_NumberDetector/07_TensorflowLite_TPU/resource/5.jpg「5」が書かれたJPEG画像を入力しました。結果、以下のように正しく5だと識別できました。
また、実行中はEdgeTPUドングルの白LEDが強く光っていたので、ちゃんとTPU側で処理しているのだと思います。結果num5 Score : 0.99609375処理時間を比較してみる
使用するモデルを差し替えるだけで、CPU動作かEdge TPU動作かを切り替えられるようです。
timeコマンドを付けて処理時間を比較してみました。処理時間比較実行コマンド# for Edge TPU time python3 classify_image_mnist.py \ --model ~/CNN_NumberDetector/07_TensorflowLite_TPU/conv_mnist_edgetpu.tflite \ --label ~/CNN_NumberDetector/07_TensorflowLite_TPU/mnist_labels.txt \ --image ~/CNN_NumberDetector/07_TensorflowLite_TPU/resource/5.jpg # for CPU time python3 classify_image_mnist.py \ --model ~/CNN_NumberDetector/07_TensorflowLite_TPU/conv_mnist.tflite \ --label ~/CNN_NumberDetector/07_TensorflowLite_TPU/mnist_labels.txt \ --image ~/CNN_NumberDetector/07_TensorflowLite_TPU/resource/5.jpg結果Edge TPU: real 0m18.596s user 0m9.698s sys 0m3.427s CPU: real 0m12.852s user 0m9.446s sys 0m0.233s結果、Edge TPU実行はトータルで18.6秒、CPU実行はトータルで12.9秒という、CPUの方が速いという残念な結果になってしまいました。
sys時間を見ると、TPU側の方は3.5秒もかかっていました。おそらく、EdgeTPUデバイス制御関係のオーバーヘッドによるものだと思います。
今回使用したような非常に小さいモデルではディープラーニング計算時間そのものよりも、こういったオーバーヘッドの方が大きいようです。メモ: インストールコマンドまとめ
素のRaspberry Pi2に対して、Edge TPUデモコードを動作させるまでの環境設定コマンド
(virtualenv, opencvを含む(単にEdge TPUを試すだけなら不要))EdgeTPU環境設定コマンドforラズパイ2# 環境更新 sudo apt-get update sudo apt-get upgrade # OpenCV用パッケージインストール sudo apt-get install libatlas3-base libwebp6 libtiff5 libjasper1 libilmbase12 libopenexr22 libilmbase12 libgstreamer1.0-0 libavcodec57 libavformat57 libavutil55 libswscale4 libqtgui4 libqt4-test libqtcore4 # virtualenvインストールと設定 sudo pip install virtualenv sudo pip install virtualenvwrapper nano ~/.bashrc >>> 以下を追加 export LC_ALL="en_US.UTF-8" export LC_CTYPE="en_US.UTF-8" ### Virtualenvwrapper if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh fi <<< # ターミナル再起動 # 仮想環境を作る (名前をpy3_tpuとする) cd ~/ mkvirtualenv --python=python3 py3_tpu # deactivate # workon py3_tpu # 仮想環境上で必要なパッケージをpipインストール pip install --upgrade setuptools pip install opencv-python pip install numpy # Pillow は2019/4/13時点でインストール時にビルドエラーが出たので、piwheelsのprebuiltバイナリを使用 # pip install Pillow pip install https://www.piwheels.org/simple/Pillow/Pillow-5.4.1-cp35-cp35m-linux_armv7l.whl#sha256=ed4e05737ed076aed4065e05b67983650b10110f3e133444e8e87bd572e1492a # Edge TPUインストール wget https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz -O edgetpu_api.tar.gz --trust-server-names tar xzf edgetpu_api.tar.gz cd edgetpu_api # ラズパイ2の場合、編集する(https://qiita.com/take-iwiw/items/6aeab468c326ecc21563#raspberry-pi-2にインストールするoptional) nano ./install.sh bash ./install.sh # 仮想環境用に再度インストール pip install edgetpu-1.9.2-py3-none-any.whl # デモを試す cd ~/Downloads/ wget https://storage.googleapis.com/cloud-iot-edge-pretrained-models/canned_models/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite \ http://storage.googleapis.com/cloud-iot-edge-pretrained-models/canned_models/inat_bird_labels.txt \ https://coral.withgoogle.com/static/images/parrot.jpg cd /home/pi/.virtualenvs/py3_tpu/lib/python3.5/site-packages/edgetpu/demo python3 classify_image.py \ --model ~/Downloads/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite \ --label ~/Downloads/inat_bird_labels.txt \ --image ~/Downloads/parrot.jpg※たまたまかもしれないが、インストール直後にそのままデモを実行したら、RuntimeErrorが発生した。ラズパイを再起動したりEdge TPUドングルを抜き差ししたら治った。
- 投稿日:2019-04-13T09:59:58+09:00
Edge TPU Accelarator+カスタムモデルMobileNetv2-SSDLiteの.tflite生成 【やっと成功したよ】_Docker編_その4
Tensorflow-bin
TPU-MobilenetSSD
1.Introduction
TPUモデルコンパイラがカスタムモデルの変換に対応したそうですので早速試してみました。
この記事の手順では最終的に生成されたモデルの精度が極悪ですが、転移学習ではなくフル学習にしたり、パラメータを調整することで精度は改善可能です。
この記事で語るのは、あくまで独自DockerイメージによるカスタムTPUモデルの学習と生成手順のみです。
モデル性能のチューニングは実施しません。2.Procedure
学習手順は、前回記事 Edge TPU Accelaratorの動作を少しでも高速化したかったのでMobileNetv2-SSD/MobileNetv1-SSD+MS-COCOをPascal VOCで転移学習して.tfliteを生成した_Docker編_その2 あるいは Edge TPU Accelaratorの動作を少しでも高速化したかったのでMS-COCOをPascal VOCで転移学習して.tfliteを生成した_GoogleColaboratory[GPU]編_その3 をそのまま使用します。 前回記事はもともと、 TPUコンパイラ がカスタムモデルに対応することを事前に知っていたため、機能がリリースされたときに最速で検証できるよう事前準備をしていたのです。
私独自のDockerは公式のDockerイメージとは異なり、NVIDIA Docker を使用します。
公式のDockerがGPUトレーニングに対応していないため、自力でシーケンスを大幅に組み直しています。なお、対応可能なレイヤと変換アルゴリズムは、 公式の TensorFlow models on the Edge TPU に記載されていますので参考にしてください。
3.Results
前回記事 の手順により生成した MobileNetv2-SSDLite の .tflite ファイルをコンパイラに投入してみます。
https://coral.withgoogle.com/web-compiler/
あっさり成功しました。 しかも、アップデートが入る前までは一切表示されなかった変換ログが表示されるようになっています。 さらに、TPU側で非対応のレイヤーは自動的にCPUへオフロードされる仕様に改善されています。
最高です。 OpenVINOに欲しい機能です。
ある程度自由にレイヤを組み合わせて推論させることができるため、対応モデルの幅が大幅に広がりましたね。今回は、各種公式ドキュメントを一切見ずに独自の軽量トレーニングとコンバートを実施しました。
4.Finally
おいおいフルトレーニングをし直して推論精度を向上した .tflite モデルを生成して遊びたいと思います。





