2020年3月16日月曜日

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.

0 件のコメント:

コメントを投稿