Python ラッパーの利用 - DigitalMediaProfessionals/dv-sdk GitHub Wiki
この節ではネットワークのPython ラッパの使い方を、MobileNet を例にして説明します。
この例では、ネットワーク変換ツールに与えられた.ini ファイルで python_module == gnet_wrap と指定されているとします。
必要なもの
- Boost.Python(libboost-python-dev), Boost.Numpy(libboost-numpy-dev)
- libpython3.6-dev (お使いのPython のバージョンに合わせてご変更ください)
- jinja2
ビルド方法
ネットワークのPython ラッパーモジュールを作成するには次のステップに従ってください。 (なお、サンプルコードはAI FPGA モジュール上で実行されるものとします。)
- python_module オプションを指定して、DMP ツールからPython ラッパーのC++ ソースコードを生成してください。
- 位置独立コード(PIC)のオプション(gcc であれば
-fPIC
)とともに、ネットワークのソースコードをコンパイルしてください。コンパイル方法についてはアプリケーションのビルドをご覧ください。 - Python ラッパーのソースコードをPIC オプションとともにコンパイルしてください。そのソースコードではPython ライブラリを用いているので、Python のインクルードディレクトリを適切にコンパイラに渡してください。
# AI FPGA モジュール上にて
$ g++ -std=c++11 -O3 -fPIC -c -I/usr/include/python3.6 -o gnet_wrap.o gnet_wrap.cpp
- コンパイルしてできたオブジェクトファイルを
-ldmpdv -lboost_python3 -lboost_numpy3
オプションとともにリンクして、Python ラッパーとなる動的共有ライブラリを作成してください。 そのファイル名はgnet_wrap.so でなくてはなりません。 ほかのネットワークについては、gnet_wrap の部分をDMP ツール使用時に python_module で指定した名前に置き換えてください。
# AI FPGA モジュール上にて
$ g++ -std=c++11 -shared -fPIC gnet_wrap.o CaffeMobileNet_gen.o dmp_network.o -o gnet_wrap.so -L/path/to/dv-user-driver -ldmpdv -lboost_python3 -lboost_numpy3
この共有ライブラリがPython モジュールとして扱われます。
シンプルサンプル
ここでは作成したPython モジュールを用いてネットワークの利用方法を、サンプルコードを用いて紹介します。 なお簡便のためエラーチェックはしません。
注: Python は作成した共有ライブラリを、通常のPython モジュールのように名前を指定してimport できます。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import gnet_wrap as gnw
net = gnw.create()
try:
# initialize
gnw.initialize(net)
gnw.load_weights(net, "path/to/network_weight.bin/")
gnw.commit(net)
# get image
img = cv2.imread("path/to/image_file")
## Manipulate image according to network rule
...
## Be sure to call np.ascontiguousarray() before put_input()
img = np.ascontiguousarray(img)
# run network
gnw.put_input(net, img)
gnw.run_network(net)
output = gnw.get_final_output(net)
# after processing
...
finally:
gnw.destroy(net)
API リファレンス
ここではgnet_wrap
Python モジュールのAPI を紹介します。
これらのAPI はほかのネットワークにおいても同様です。
create()
def create() -> int:
対象のネットワークのオブジェクトを作成します。
返値はそのオブジェクトのID 番号です。
destroy()
def destroy(id: int) -> None:
ネットワークオブジェクトを破棄します。
id
ネットワークオブジェクトのID 番号です。
initialize()
def initialize(id: int) -> bool:
ネットワークオブジェクトを初期化します。
id
ネットワークオブジェクトのID 番号です。
関数の成功時にはTrue
が、そうでなければFalse
が返されます。
load_weights()
def load_weights(id: int, weight_file: str) -> bool:
ネットワークの重みを読み込みます。
id
ネットワークオブジェクトのID 番号です。weight_file
重みファイルへのパスです。
関数の成功時にはTrue
が、そうでなければFalse
が返されます。
commit()
def commit(id: int) -> bool:
ネットワークオブジェクトをコミットします。
id
ネットワークオブジェクトのID 番号です。
関数の成功時にはTrue
が、そうでなければFalse
が返されます。
run_network()
def run_network(id: int) -> bool:
ネットワークを実行します。
id
ネットワークオブジェクトのID 番号です。
関数の成功時にはTrue
が、そうでなければFalse
が返されます。
put_input()
def put_input(id: int, input: numpy.ndarray) -> None:
ネットワークに入力を与えます。
-
id
ID number of a network object -
input
Input to the network.input.dtype
must benumpy.float16
. Please be sure to callnp.ascontiguousarray(input)
just before calling this function. -
id
ネットワークオブジェクトのID 番号です。 -
input
ネットワークへの入力です。input.dtype
はnumpy.float16
でなくてはなりません。 またこの関数の前にnp.ascontiguousarray(input)
を必ず呼び出してください。
get_final_output()
def put_input(id: int, index: int) -> numpy.ndarray:
id
ネットワークオブジェクトのID 番号です。index
ネットワークのオブジェクトのインデックスです。
ネットワークの出力を返します。
get_conv_usec()
def get_conv_usec(id: int) -> int:
id
ネットワークオブジェクトのID 番号です。
最後に畳み込み層の実行にかけた時間をマイクロ秒単位で返します。
get_fc_usec()
def get_fc_usec(id: int) -> int:
id
ネットワークオブジェクトのID 番号です。
最後に全結合層の実行にかけた時間をマイクロ秒単位で返します。
get_cpu_usec()
def get_cpu_usec(id: int) -> int:
id
ネットワークオブジェクトのID 番号です。
最後にCPU 層の実行にかけた時間をマイクロ秒単位で返します。