FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

TensorFlow+Kerasに入門(2. Keras2cppを試行)

FPGAの部屋のmarseeさんの記事を見て、TensorFlow+Kerasに入門してみた。 というかmarseeさんの記事で掲載されているソースコードをほとんどCopy & Pasteして実行してみているだけだが...

前回でKerasでMNISTの学習ができるようになったので、次はモデルをJSONで出力、重みパラメータをh5で保存して、C++のプログラムに変換してみたい。 というか、Pythonで実行するのが面倒なので基本的にC++で実行できるようになりたいという話だけなのだが...

メンテナンスはされていないのかもしれない?が、keras2cppというツールを試行してみた。

一点注意なのは、keras2cppは推論の部分のみをC++に変換するらしい。学習済みのモデルとパラメータを使ってC++に変換するようだ。

Keras2cppを使うためには、Kerasで生成したモデルとパラメータを出力する。Jupyter Notebook上で以下を実行した。

from keras.models import load_model

model.save('mnist_cnn10_model.h5') # creates a HDF5 file 'my_model.h5'
with open('mnist_cnn10_model.json', 'w') as fout:
    fout.write(model.to_json())

これで、JSONとh5ファイルが保存されるので、Keras2cppでC++のファイルに変換する。 ただし、keras2cppはPython2.x系で動作するようで、とりあえずKerasを動かすためにPython 2.xのTensorFlowとKerasをインストールした。

$ pip2 install tensorflow keras

これで変換を行う。以下のコマンドを実行する。

$ python ./dump_to_simple_cpp.py -a ../machine-learning/keras/keras-introduction/mnist_cnn10_model.json -w ../machine-learning/keras/keras-introduction/mnist_cnn10_model.h5 -o dumped.nnet

dumped.nnetが生成されたので確認する。単なるテキストファイルのようだ。

layers 8
layer 0 Conv2D
layer 1 Activation
relu
layer 2 MaxPooling2D
2 2
layer 3 Flatten
layer 4 Dense
1440 100
[-0.00869748 -0.03056295  0.02002885  0.05073868 -0.02439169 -0.01678224
 -0.00400479 -0.05224665  0.00741209  0.06284878  0.02699389  0.05822603
 -0.02994106 -0.030139    0.03076001 -0.05264932  0.00020877 -0.0064121
  0.03952856 -0.03737402  0.04069051  0.05051897  0.05892574  0.06181276
 -0.00088991 -0.01981324 -0.0137962  -0.03498058  0.03866504  0.02167791
...

これを使ってC++のコードをコンパイルする。以下のコードを実行する。随分とシンプルだが、内部のソースコードを見ると、テスト用の入力として./example/sample_mnist.datをロードしていた。

g++ -std=c++11 keras_model.cc example_main.cc
  • example_main.cc
  DataChunk *sample = new DataChunk2D();
  sample->read_from_file("./example/sample_mnist.dat");
  std::cout << sample->get_3d().size() << std::endl;
  KerasModel m("./example/dumped.nnet", true);
  m.compute_output(sample);

sample_mnist.dat の入力画像で、Excelでプロットしてみると'5'だった。なるほど。

f:id:msyksphinz:20180701135331p:plain

さて、コンパイルしたa.outを実行してみよう。最後に最終レイヤの値一覧が表示されている。

$ ./a.out
This is simple example with Keras neural network model loading into C++.
Keras model will be used in C++ for prediction only.
1
Reading model from ./example/dumped.nnet
Layers 12
Layer 0 Convolution2D
Layer 1 Activation
Layer 2 Convolution2D
Layer 3 Activation
Layer 4 MaxPooling2D
Layer 5 Dropout
Layer 6 Flatten
Layer 7 Dense
Layer 8 Activation
Layer 9 Dropout
Layer 10 Dense
Layer 11 Activation
DataChunk2D 1x28x28
DataChunkFlat values:
0.037296 0.00783805 0.0658804 0.217285 0.0109373 0.34731 0.0135039 0.0217452 0.266247 0.0119571

というわけで、5に相当する値が0.34731 で最も大きい。正しく推論ができているようだ。

f:id:msyksphinz:20180701135833p:plain