ファイルフォーマットコンバーター

概要

digraph { rankdir="LR" NNabla1 [label = "NNabla", style="filled, rounded", fillcolor="lime", shape="box", width=1.3, height=0.8, fontsize=16]; NNabla2 [label = "Use NNabla as\nRuntime", style="filled, rounded", fillcolor="lime", shape="box", width=1.2, height=0.6, fontsize=12]; Other [label = "Other\n(Caffe2 etc.)",style=rounded, shape="box", width=1.3, height=0.8, fontsize=12]; ONNX1 [label = "ONNX", style=filled, fillcolor="mediumslateblue", shape="box", width=0.7, height=0.2, fontsize=12]; ONNX2 [label = "ONNX", style=filled, fillcolor="mediumslateblue", shape="box", width=0.7, height=0.2, fontsize=12]; Conv1 [label = "File Format\nConverter", style="filled, rounded", fillcolor="lime", shape="box", width=1.3, height=0.8, fontsize=16]; Conv2 [label = "File Format\nConverter", style="filled, rounded", fillcolor="lime", shape="box", width=1.3, height=0.8, fontsize=16]; NNP1 [label = "NNP", style=filled, fillcolor="cyan", shape="box", width=0.7, height=0.2, fontsize=12]; NNP2 [label = "NNP", style=filled, fillcolor="cyan", shape="box", width=0.7, height=0.2, fontsize=12]; NNB [label = "NNB", style=filled, fillcolor="cyan", shape="box", width=0.7, height=0.2, fontsize=12]; CSRC [label = "C Source\ncode", style=filled, fillcolor="mediumseagreen", shape="box", fontsize=12]; TF1 [label = "Tensorflow\n(.pb,ckpt,.tflite,\nsaved_model)", shape="box", style="filled, rounded", fillcolor="yellow", width=1.3, height=0.8, fontsize=12]; TF2 [label = "SavedModel,\nPB, TFlite", style=filled, fillcolor="yellow", shape="box", width=0.8, fontsize=12]; OtherRuntime [label = "Other runtime", shape="box", style=rounded, width=1.2, fontsize=12]; NNablaCRuntime [label = "NNabla C\nRuntime", style="filled, rounded", fillcolor="lime", shape="box", width=1.2, fontsize=12]; Product [label = "Implement to\nproduct", shape="box", style=rounded, width=1.2, fontsize=12]; Tensorflow [label = "Tensorflow", shape="box", style=rounded, width=1.2, fontsize=12]; NNabla1 -> NNP1 [minlen="2"]; NNP1 -> Conv2; Other -> ONNX1 -> Conv1; Conv1 -> NNP1 [constraint="false"]; Conv2 -> ONNX2 -> OtherRuntime; Conv2 -> NNB -> NNablaCRuntime; Conv2 -> CSRC -> Product; Conv2 -> NNP2 -> NNabla2; TF1 -> Conv1; TF1 -> Conv1 [constraint="false"]; Conv2 -> TF2 -> Tensorflow; }

ファイルフォーマットコンバーターを使うと、ONNX ファイルフォーマット、および NNabla C Runtime で Neural Network Libraries (または Console) ワークフローを実現できます。

ファイルフォーマットコンバーターには次のような機能があります。

  • NNP のバリエーションを有効な NNP へ変換する

  • ONNX から NNP へ変換する

  • NNP から ONNX へ変換する

  • NNP から NNB へ変換する (NNabla C Runtime のバイナリー形式)

  • Convert NNP to Tensorflow saved_model

  • Convert Tensorflow checkpoint, frozen graph or saved_model to NNP

  • Convert NNP to Tensorflow Lite

  • Convert NNP to INT8 quantized Tensorflow Lite

  • Convert Tensorflow Lite to NNP

  • 試用段階: NNP から NNabla C Runtime の C ソースコードへ変換する

重要なお知らせ: 本ファイルフォーマットコンバーターには、いくつかの既知の問題が残っています。

  • サポートする ONNX オペレーターは制限されています。詳細は Function-Level Support Status をご覧ください。

  • サポートする Tensorflow operator は制限されています。詳細は Function-Level Support Status をご覧ください

  • NNP から C ソースコードへの変換はまだ試用段階です。動作しますが、十分にテストされていません。

アーキテクチャー

digraph { rankdir="LR" INPUT [label="<<file>>\nINPUT", style="filled", fillcolor="lime", shape="box", fontsize=12, width=1.6]; OUTPUT [label="<<file>>\nOUTPUT", style=filled, fillcolor="lime", shape="box", fontsize=12, width=1.6]; PROCESS [label="Process\n(Split, Expand, etc.)", style=rounded, shape="box", fontsize=12]; proto [label="proto", style=filled, fillcolor="cyan", shape="box", width=0.8, height=0.3, fontsize=12]; INPUT -> proto [taillabel="import"]; proto -> OUTPUT [headlabel="export"]; subgraph { rank="same" proto -> PROCESS [dir = "both", minlen="2"]; } }

本ファイルフォーマットコンバーターは、中間形式として Neural Network Libraries 内に定義された protobuf を使います。

汎用のファイルフォーマットコンバーターではありませんが、Neural Network Libraries では指定されたコンバーターです。

本コンバーターは、ONNX ファイルに対する入力および出力を指定可能ですが、ONNX ファイルに Neural Network Libraries がサポートしない機能を含んでいる場合、変換中にエラーが発生する可能性があります。

また本コンバーターは、中間プロセス機能も提供します。詳細は、 プロセス をご覧ください。

Installation

Before using this converter, please use command pip install nnabla_converter to install nnabla_converter.

Note that, flatbuffer package is necessary for TFLite export, please check Tensorflow Lite section in this page for more details.

変換

サポートするフォーマット

NNP

NNP は NNabla のファイルフォーマットです。

NNP フォーマットは データフォーマット に記述されます。

本ファイルフォーマットコンバーターでは、いくつかの NNP バリエーションでしか動作しません。

  • NNP 標準フォーマット (.nnp)

  • NNP ファイルの内容 (.nntxt, .prototxt, .h5, .protobuf)

ONNX
制限事項
  • 学習はサポートしません。

  • Support operator set 7,9,10,11.

  • すべての機能をサポートしているわけではありません。詳細は Function-Level Support Status をご覧ください。

  • 限られた Neural Network Console のプロジェクトのみサポートします。詳細は Model Support Status をご覧ください。

NNB

NNB is compact binary format for NNabla C Runtime. The file format is shown as the following diagram:

../../_images/nnb.png

There are several concepts, such as buffer, variable, function, input and output in this file. Each of them is represented as a list. Each list is recorded with 2 members: number of object, and index in memory block table. The index points to the position in a memory block index table. The index in memory block index table points to the start address of memory data block.

It is designed for nnabla-c-runtime.

C ソースコード

ファイルフォーマットコンバーターは、 nnabla-c-runtime の C ソースコード出力をサポートします。

Tensorflow
制限事項

Bridged by onnx, tensorflow import and export is supported with some limitations.

As for the importer, 4 formats tends to be supported:
  • .pb, tensorflow frozen graph フォーマット

  • .ckpt, tensorflow check point フォーマット version 1

  • .ckpt.*, tensorflow check point フォーマット version 2

  • saved_model, tensorflow saved_model format

As for the exporter, some of Neural Network Console projects are supported. See Model Support Status. The output of converter is tensorflow saved_model format.

Tensorflow Lite
制限事項
For export to tensorflow lite, please install flatbuffers package:
  • For Windows platform, download package from FlatBuffers and extract.

  • For Linux platform, use command snap install flatbuffers to install flatbuffers.

  • For MaxOS platform, use command brew install flatbuffers to install flatbuffers.

and add the executable file flatc to the system PATH.

After exporting TFLite, a json file with the same name will be generated, recording whether the input and output of the TFLite network need to be transposed to channel_last according to base_axis.

INT8 quantized Tensorflow Lite
制限事項

You should also install flatbuffers package. Please refer to the installation above. You need provide a represent dataset to the converter if you want to convert nnp to int8 quantized tflite. Represent dataset is a subset of training dataset, about 2% - 10% of training data. You can collect represent dataset in your training loop. It should be saved as numpy's .npy format. Here's an example:

rdataset = []
# suppose this is your training loop
for step in range(max_step):
    image, label = dataset.next()
    x.d = image
    rdataset.append(image)
    # your code
    # ...
rdataset = np.array(rdataset).astype(np.float32)
np.save('represent_dataset.npy', rdataset)

Of course, you can create represent dataset by any way you like, but please ensure the shape of each item is equal with the shape of network's input and you have finished the necessary preprocess.

プロセス

繰り返しの拡張と循環

Neural Network Console は LoopControl 擬似関数である RepeatStart, RepeatEnd, RecurrentInput, RecurrentOutput または Delay をサポートしています。

現在、Neural Network Library ではこれらの関数を直接的にはサポートしていません。

ファイルフォーマットコンバーターは、ネットワークを拡張し、デフォルトでこれらの擬似関数を削除します。

これらの関数を保持したい場合、ファイル変換時にコマンドラインオプション --nnp-no-expand-network を指定してください。

ネットワークを分割する

--split オプションを使ってネットワークを分割できます。

この機能を使用する場合、 分割ネットワーク をご覧ください。

使い方

NNP 操作

NNP から NNP への変換

NNP から NNP への変換が必要な場合があります。

たいていの場合、繰り返しの拡張、あるいは循環ネットワークは Neural Network Console ではサポートしていますが、C++ API ではサポートしていません。

$ nnabla_cli convert input.nnp output.nnp

console 出力から単一の NNP ファイルへ変換する

Neural Network Console の現在のバージョンは .nntxt と .h5 を学習結果として出力します。

続いて、分離したファイルを単一の NNP に変換し、パラメータを protobuf 形式で格納する必要があります。

$ nnabla_cli convert net.nntxt parameters.h5 output.nnp

console 出力から単一の NNP ファイルへ 繰り返しの拡張や循環なしに変換する

$ nnabla_cli convert --nnp-no-expand-network net.nntxt parameters.h5 output.nnp

パラメータ形式を hdf5 で保持する

$ nnabla_cli convert --nnp-no-expand-network --nnp-parameter-h5 net.nntxt parameters.h5 output.nnp

すべてを単一の nntxt に入れる

$ nnabla_cli convert --nnp-parameter-nntxt net.nntxt parameters.h5 output.nntxt

ONNX 操作

NNP から ONNX へ変換する

$ nnabla_cli convert input.nnp output.onnx

onnx opset 9 出力を指定する場合、次のように指定してください (デフォルトは opset 7):

$ nnabla_cli convert input.nnp output.onnx -d opset_9

ONNX から NNP へ変換する

$ nnabla_cli convert input.onnx output.nnp

Currently, opset 7,9,10,11 are supported to import.

C Runtime 操作

一般的に、ファイルから C Runtime に変換するときは、バッチサイズを 1 に指定する方がよいとされています。バッチサイズが 1 より大きい場合、バッチサイズを 1 にするためにまとめて処理する必要があります。コマンドラインオプションで -b 1 を追加してください。

NNP から NNB へ変換する

$ nnabla_cli convert -b 1 input.nnp output.nnb

NNP から C ソースコードへ変換する

$ nnabla_cli convert -b 1 -O CSRC input.onnx output-dir

量子化

C-runtime ライブラリは、バイナリ (または固定小数点) の重みをサポートしており、モデル (およびフットプリント) のサイズを劇的に縮小できます。モデルを量子化する方法については、 固定小数点量子化によるネットワークの圧縮 を参照してください。

Tensorflow 操作

Convert NNP to Tensorflow saved_model

$ nnabla_cli convert input.nnp output_saved_model --export-format SAVED_MODEL

NNP から Tensorflow frozen graph へ変換する

$ nnabla_cli convert input.nnp output.pb

NNP から Tensorflow frozen graph へ変換する

$ nnabla_cli convert input.pb output.nnp

Tensorflow checkpoint から NNP へ変換する

checkpoint version 1 の場合:

$ nnabla_cli convert input.ckpt output.nnp --inputs x0,x1 --outputs y0,y1

input.ckpt と同じディレクトリには、 その関連ファイルである checkpoint、input.ckpt.meta などがあることが必要です。 inputs では、モデルの入力名がコンマで区切られていることが必要です。 outputs も同様です。checkpoint 形式の解析では、入力と出力があることが必要です。

checkpoint version 2 の場合:

$ nnabla_cli convert input.ckpt.meta output.nnp --inputs x0,x1 --outputs y0,y1

input.ckpt.meta と同じディレクトリには、その関連ファイルである checkpoint、 *.ckpt.index などがあることが必要です。

Convert Tensorflow saved_model to NNP

$ nnabla_cli convert input_saved_model output.nnp

Convert NNP to Tensorflow Lite

$ nnabla_cli convert -b 1 input.nnp output.tflite

Convert NNP to INT8 quantized Tensorflow Lite

$ nnabla_cli convert -b 1 input.nnp output.tflite --quantization --dataset represent_dataset.npy

Convert Tensorflow Lite to NNP

$ nnabla_cli convert input.tflite output.nnp

分割ネットワーク

分割ネットワークは少し複雑で面倒な場合があります。

NNP ファイルは複数の Executor ネットワークを持つことがありますが、Split は単一ネットワークを分割することしかサポートしません。

まず、NNP の中に executor がいくつあるかを確認し、どの executor を nnabla_cli dump で分割するのか指定してください。

$ nnabla_cli dump squeezenet11.files/SqueezeNet-1.1/*.{nntxt,h5}
2018-08-27 15:02:40,006 [nnabla][INFO]: Initializing CPU extension...
Importing squeezenet11.files/SqueezeNet-1.1/net.nntxt
Importing squeezenet11.files/SqueezeNet-1.1/parameters.h5
 Expanding Training.
 Expanding Top5Error.
 Expanding Top1Error.
 Expanding Runtime.
  Optimizer[0]: Optimizer
  Optimizer[0]:  (In) Data      variable[0]: Name:TrainingInput                  Shape:[-1, 3, 480, 480]
  Optimizer[0]:  (In) Data      variable[1]: Name:SoftmaxCrossEntropy_T          Shape:[-1, 1]
  Optimizer[0]:  (Out)Loss      variable[0]: Name:SoftmaxCrossEntropy            Shape:[-1, 1]
  Monitor  [0]: train_error
  Monitor  [0]:  (In) Data      variable[0]: Name:Input                          Shape:[-1, 3, 320, 320]
  Monitor  [0]:  (In) Data      variable[1]: Name:Top5Error_T                    Shape:[-1, 1]
  Monitor  [0]:  (Out)Monitor   variable[0]: Name:Top5Error                      Shape:[-1, 1]
  Monitor  [1]: valid_error
  Monitor  [1]:  (In) Data      variable[0]: Name:Input                          Shape:[-1, 3, 320, 320]
  Monitor  [1]:  (In) Data      variable[1]: Name:Top1rror_T                     Shape:[-1, 1]
  Monitor  [1]:  (Out)Monitor   variable[0]: Name:Top1rror                       Shape:[-1, 1]
  Executor [0]: Executor
  Executor [0]:  (In) Data      variable[0]: Name:Input                          Shape:[-1, 3, 320, 320]
  Executor [0]:  (Out)Output    variable[0]: Name:y'                             Shape:[-1, 1000]

上記の出力結果によって、1 つの executor のみがあることが分かります。

続いて nnabla_cli dump -E0 で executor の詳細情報を見ることができます。

$ nnabla_cli dump -E0 squeezenet11.files/SqueezeNet-1.1/*.{nntxt,h5}
2018-08-27 15:03:26,547 [nnabla][INFO]: Initializing CPU extension...
Importing squeezenet11.files/SqueezeNet-1.1/net.nntxt
Importing squeezenet11.files/SqueezeNet-1.1/parameters.h5
 Try to leave only executor[Executor].
 Expanding Runtime.
  Executor [0]: Executor
  Executor [0]:  (In) Data      variable[0]: Name:Input                          Shape:[-1, 3, 320, 320]
  Executor [0]:  (Out)Output    variable[0]: Name:y'                             Shape:[-1, 1000]

-F オプションにより、関数リストを取得できます。

$ nnabla_cli dump -FE0 squeezenet11.files/SqueezeNet-1.1/*.{nntxt,h5}
2018-08-27 15:04:10,954 [nnabla][INFO]: Initializing CPU extension...
Importing squeezenet11.files/SqueezeNet-1.1/net.nntxt
Importing squeezenet11.files/SqueezeNet-1.1/parameters.h5
 Try to leave only executor[Executor].
 Expanding Runtime.
  Executor [0]: Executor
  Executor [0]:  (In) Data      variable[0]: Name:Input                          Shape:[-1, 3, 320, 320]
  Executor [0]:  (Out)Output    variable[0]: Name:y'                             Shape:[-1, 1000]
  Executor [0]:   Function[  0  ]: Type: Slice                Name: Slice
  Executor [0]:   Function[  1  ]: Type: ImageAugmentation    Name: ImageAugmentation
  Executor [0]:   Function[  2  ]: Type: MulScalar            Name: SqueezeNet/MulScalar
  Executor [0]:   Function[  3  ]: Type: AddScalar            Name: SqueezeNet/AddScalar
  Executor [0]:   Function[  4  ]: Type: Convolution          Name: SqueezeNet/Convolution
  Executor [0]:   Function[  5  ]: Type: ReLU                 Name: SqueezeNet/ReLU
  Executor [0]:   Function[  6  ]: Type: MaxPooling           Name: SqueezeNet/MaxPooling

    SNIP...

  Executor [0]:   Function[ 63  ]: Type: ReLU                 Name: SqueezeNet/FireModule_8/Expand1x1ReLU
  Executor [0]:   Function[ 64  ]: Type: Concatenate          Name: SqueezeNet/FireModule_8/Concatenate
  Executor [0]:   Function[ 65  ]: Type: Dropout              Name: SqueezeNet/Dropout
  Executor [0]:   Function[ 66  ]: Type: Convolution          Name: SqueezeNet/Convolution_2
  Executor [0]:   Function[ 67  ]: Type: ReLU                 Name: SqueezeNet/ReLU_2
  Executor [0]:   Function[ 68  ]: Type: AveragePooling       Name: SqueezeNet/AveragePooling
  Executor [0]:   Function[ 69  ]: Type: Reshape              Name: SqueezeNet/Reshape
  Executor [0]:   Function[ 70  ]: Type: Identity             Name: y'

ImageAugmentation を除いたネットワークを取得したい場合、上記の出力結果によれば、ImageAugmentation は index 2 に配置されます。index 3 に分割した後、 ImageAugmentation を除いたネットワークを取得できます。 nnabla_cli 変換-E0 -S 3- オプションを指定する必要があります。このコマンドで出力を XXX_S_E.nnp という名前に変更します。 XXX は元の名前で、S は開始関数の index、E は終了関数の index です。

$ nnabla_cli convert -E0 -S 3- squeezenet11.files/SqueezeNet-1.1/*.{nntxt,h5} splitted.nnp
2018-08-27 15:20:21,950 [nnabla][INFO]: Initializing CPU extension...
Importing squeezenet11.files/SqueezeNet-1.1/net.nntxt
Importing squeezenet11.files/SqueezeNet-1.1/parameters.h5
 Try to leave only executor[Executor].
 Expanding Runtime.
   Shrink 3 to 70.
    Output to [splitted_3_70.nnp]

Finally you got splitted_3_70.nnp as split output. You can check split NNP with nnabla_cli dump

注意: Input shape は元のネットワークから変更されました。新しい input shape は開始関数の入力と同じです。

$ nnabla_cli dump splitted_3_70.nnp
2018-08-27 15:20:28,021 [nnabla][INFO]: Initializing CPU extension...
Importing splitted_3_70.nnp
 Expanding Runtime.
  Executor [0]: Executor
  Executor [0]:  (In) Data      variable[0]: Name:SqueezeNet/MulScalar           Shape:[-1, 3, 227, 227]
  Executor [0]:  (Out)Output    variable[0]: Name:y'                             Shape:[-1, 1000]

以上で終了です。