Edited at

ABEJA Platformからエッジデバイス(NVIDIA Jetson)にモデルデプロイをする


はじめに

はじめまして。おおたぐろです。ABEJAのエンジニアです。

これは、ABEJA Platform AdventCalendar 2018 12日目の記事です。

(ごめんなさい。遅くなりました

)

今回は、ABEJA Platformからエッジデバイス(Jetson TX2)にモデルをデプロイする方法をお話したいと思います。どうぞよろしくお願いいたしますmm


手順

流れ


  1. 本体(Jetson)の設定

  2. Platformへのデバイス登録作業

  3. Device Agentのインストール・設定

  4. モデルの作成

  5. デバイス上にモデルデプロイ

  6. テスト


本体(Jetson)の設定


L4Tのインストール

Jetson に L4T 28.2 をインストールします。 L4T 28.2 は JetPack 3.2 に含まれています。

https://developer.nvidia.com/embedded/downloads#?search=jetpack%203.2


Dockerのインストール


# Update libs, install prereqs for commands
nvidia@tegra-ubuntu:~$ sudo apt-get update && sudo apt-get upgrade && sudo apt-get -y install curl apt-transport-https

# Install Docker-CE
nvidia@tegra-ubuntu:~$ echo "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu xenial edge" >/etc/apt/sources.list.d/docker.list
nvidia@tegra-ubuntu:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -qq - >/dev/null
nvidia@tegra-ubuntu:~$ sudo apt-get update && sudo apt-get install docker-ce
nvidia@tegra-ubuntu:~$ sudo systemctl enable docker

# Test Docker install
nvidia@tegra-ubuntu:~$ sudo docker run --rm -it arm64v8/ubuntu:16.04 cat /etc/issue
Ubuntu 16.04.5 LTS \n \l


PlatformとJetsonの接続


デバイス登録

ここからは、JetsonのターミナルではなくPlatformの画面上での操作になりますm

まずはじめにデバイスに名前・説明を付けて、デバイス認証用のキー

を発行します。





ここで表示されるDevice ID及び鍵は、は、次のステップでデバイス側に埋め込みます。

Device IDはあとから参照できますが、鍵はこのページでしか表示されないので注意が必要です。

Downloadボタンを押すことで、zip圧縮された鍵ファイルを直接ダウンロードする事ができます。

ダウンロードしたzipは次の工程で使うので、Jetson側のファイルシステムに転送しておきます。

筆者はscpを使ってzipファイルを移動しました( ̄ー ̄)

taguro@main:~/Download$ scp device_XXXXXXXXXXXXX_certifications.zip nvidia@172.16.XXX.XXX:~/device_XXXXXXXXXXXXX_certifications.zip

ここまでの作業が終わると、Edge Devicesに登録したデバイスが表示されます。


ABEJA Device Agentのインストール

ABEJA Device Agentは、ABEJA Platformと接続してデプロイを担ったり&メトリクス・ログをクラウド上に送信してくれるデーモンです。これを入れる事によって、ユーザーはクラウド上のモデルをデバイスに直接デプロイしたり、デバイス本体のモニタリングをする事ができます。(要するに大事なヤツです)


nvidia@tegra-ubuntu:~$ wget https://s3-ap-northeast-1.amazonaws.com/abeja-device-resources/0.7.1/abeja-device-agent.deb
nvidia@tegra-ubuntu:~$ sudo dpkg -i abeja-device-agent.deb

エッジデバイスがABEJA Platformが接続して認証する為に、/etc/abeja/keysを作ってそこに鍵を配置します。

ここで先程生成した鍵(zipファイル)を使います。


nvidia@tegra-ubuntu:~$ sudo mkdir /etc/abeja
nvidia@tegra-ubuntu:~$ sudo unzip device_xxxxxxxxxxxxx_certifications.zip -d /etc/abeja/keys

鍵の配置が完了したら、次にデバイスの情報を /etc/default/abeja-device-agentに設定します。

先程Platform上で払い出されたDevice IDを、DEVICE_NAMEという所に入れておきます。

Device IDは、Edge Devices一覧から確認できます。


nvidia@tegra-ubuntu:~$ sudo vim /etc/default/abeja-device-agent
DEVICE_NAME=XXXXXXXXXXXX
DEVICE_TYPE=jetson_tx2
LOCAL_LOGGING=1

最後に、これらの設定を反映させる為にデーモン再起動をします。


nvidia@tegra-ubuntu:~$ sudo systemctl restart abeja-device-agent.service
nvidia@tegra-ubuntu:~$ sudo systemctl status abeja-device-agent.service


デバイス連携確認

Edge DevicesページにあるMetricsボタンを押すと、下記のようなメトリクス情報が表示されます。

これが表示されていれば、デバイスとPlatformが正しく通信できており、初期設定は全て完了です。


余談

ABEJA Device Agentのインストール・設定が正しく完了すると、下記のようにコンテナが立ち始めます。

合計で3つのシステムコンテナが立ち上がれば成功です。


nvidia@tegra-ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9069eb198afe xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/device-logger-fluentd:0.6.4-aarch64 "/bin/entrypoint.sh …" 3 hours ago Up 3 hours 0.0.0.0:5140->5140/tcp, 0.0.0.0:24224->24224/tcp device-logger
d1541745ea3a abeja/docker-dd-agent:latest-arm64v8 "/entrypoint.sh supe…" 3 hours ago Up 3 hours (healthy) 8125/udp, 8126/tcp dd-agent
9fd99a29f77d abeja/abeja-device-agent:latest-aarch64 "/bin/sh -c abeja-de…" 3 hours ago Up 3 hours


モデル作成

次にモデルの作成に移ります。基本的にはモデル名・バージョン・Runtime設定といった基本情報設定と・動かすモデル(ファイル)をアップロードする事で完了します。今回は、Runtimeにabeja-inc/mxnet:0.1.0-arm64v8を利用し、モデルのソースコードとしてABEJAで用意しているResnet50のサンプルを使いました。

※FYIですが、Deploy after creatingにチェックを入れておくと、エッジデプロイをする為のリソースが自動でつくられます。


余談

今回モデルとして動かすのは下記のコードです。モデルのコードを変更する事で、細かいふるまいや後述するAPIのResponseの変更が可能です。


import numpy as np
import cv2
import mxnet as mx
import argparse
import os

def ch_dev(arg_params, aux_params, ctx):
new_args = dict()
new_auxs = dict()
for k, v in arg_params.items():
new_args[k] = v.as_in_context(ctx)
for k, v in aux_params.items():
new_auxs[k] = v.as_in_context(ctx)
return new_args, new_auxs

synset = [l.strip() for l in open('synset.txt').readlines()]
if os.environ.get('USE_CPU', 1):
ctx = mx.cpu()
else:
ctx = mx.gpu(0)
sym, arg_params, aux_params = mx.model.load_checkpoint('resnet-50', 0)
arg_params, aux_params = ch_dev(arg_params, aux_params, ctx)

def handler(iter, _ctx):
for img in iter:
img = cv2.resize(img, (224, 224)) # resize to 224*224 to fit model
img = np.swapaxes(img, 0, 2)
img = np.swapaxes(img, 1, 2) # change to (c, h,w) order
img = img[np.newaxis, :] # extend to (n, c, h, w)
arg_params["data"] = mx.nd.array(img, ctx)
arg_params["softmax_label"] = mx.nd.empty((1,), ctx)
exe = sym.bind(ctx, arg_params ,args_grad=None, grad_req="null", aux_states=aux_params)
exe.forward(is_train=False)

prob = np.squeeze(exe.outputs[0].asnumpy())
pred = np.argsort(prob)[::-1]
yield {'result': [synset[pred[i]] for i in range(5)]}


デバイス上にモデルデプロイ

ABEJA Platformでは、ユーザーが用意(学習)したモデルを使って推論APIを展開する事ができます。

クラウド上にもエッジ上にもAPIを作成する事ができるのですが、今回はエッジ上にAPIを作成してみます。

(エッジデバイスに対してAPI作成すると、クラウド上に置かれているモデル等が勝手にダウンロードされます

)

まず、Modelに紐づくDeploymentというページにいきます。

(Deploy after creatingという所にチェックをいれると、自動でDeploymentが作られるはずです)

Create HTTP Serviceをクリックすると、下記の様なWizardが表示されます。

Edge側のタブを選択すると、デプロイ先のデバイス・APIのポート設定等が表示されるので、入力します。

※今回はポート8000でResnet50を使った推論APIを展開します

設定が完了すると下記のように、HTTP Serviceの一覧に新たな項目が増えます。

あとは放置でOKです。

ABEJA Device AgentとABEJA Platformがよしなに通信してくれて、先程作ったモデルが自動ダウンロード&自動でAPIが作成されます。

簡単すぎて、あまりエッジデプロイした気にならないかもしれませんが、内部のメトリクス・コンテナ数を見ると動いてる感を肌で感じることができます。

下記はデプロイ前後のメトリクスの様子です。

デプロイが終わるとモデル作成時に指定したコンテナイメージabeja-inc/mxnet:0.1.0-arm64v8が立ち上がっている事が確認できます。ここまで確認できればシステム的にも全く問題なしです。


root@tegra-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
46da842d25cc xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/abeja-inc/mxnet:0.1.0-arm64v8 "/bin/bash -l -c 'cd…" 23 minutes ago Up 23 minutes 0.0.0.0:8000->8000/tcp edge-xxxx
9069eb198afe xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/device-logger-fluentd:0.6.4-aarch64 "/bin/entrypoint.sh …" 3 hours ago Up 3 hours 0.0.0.0:5140->5140/tcp, 0.0.0.0:24224->24224/tcp device-logger
d1541745ea3a abeja/docker-dd-agent:latest-arm64v8 "/entrypoint.sh supe…" 3 hours ago Up 3 hours (healthy) 8125/udp, 8126/tcp dd-agent
9fd99a29f77d abeja/abeja-device-agent:latest-aarch64 "/bin/sh -c abeja-de…" 3 hours ago Up 3 hours abeja-device-agent


テスト

テスト用の画像をJetsonにダウンロードします。

nvidia@tegra-ubuntu:~$ wget https://console.abeja.io/images/cat_thumb.jpg

localhost:8000に下記のように画像を投げると、JSONで推論結果が帰ってくる事が確認できます。

あとはビジネスロジックの乗ったコードを作り推論APIと結合する事によって、やりたい事を自由に叶える事ができます

nvidia@tegra-ubuntu:~$ curl -X POST -H 'Content-Type:image/jpeg' --data-binary @cat_thumb.jpg -XPOST http://localhost:8000

{"result": ["n02123045 tabby, tabby cat", "n02123159 tiger cat", "n02124075 Egyptian cat", "n02127052 lynx, catamount", "n03958227 plastic bag"]}


最後に

今回はABEJA Platformを使って、エッジデバイスに対してモデルデプロイをする流れについて解説させていただきました



ハンズオンイベントも来年1月に企画しておりますので、ご興味がアレばぜひご参加いただければと思います。

ありがとうございました