Keras2cppを使ってKerasのモデルをC++のコードに変換したのだが、まだ問題がある。デフォルトの画像データフォーマットである image_data_format = channels_last
に対応していないことだ。
これにより、画像データをデフォルトの並び(縦方向, 横方向, channel)に一度変換して処理をしないといけない。これは面倒なので、channels_first
に対応させることにした。
と言っても、画像データを入力するときに、DataChunk
構造体にchannel_first
なのかchannel_last
なのかを指定して格納するだけだ。
keras2cpp/keras_model.cc
void keras::DataChunk2D::read_from_file(const std::string &fname, keras::ImageDataFormat_t image_data_format ) { ... if (image_data_format == keras::ImageDataFormat_t::First) { fin >> m_depth >> m_rows >> m_cols; // [Depth, Rows, Cols] } else { fin >> m_rows >> m_cols >> m_depth; // [Rows, Cols, Depth] } ... if (image_data_format == keras::ImageDataFormat_t::First) { for(int d = 0; d < m_depth; ++d) { for(int r = 0; r < m_rows; ++r) { char tmp_char; float tmp_float; fin >> tmp_char; // for '[' for(int c = 0; c < m_cols; ++c) { fin >> tmp_float; data[d][r][c] = tmp_float; } fin >> tmp_char; // for ']' } } } else { for(int r = 0; r < m_rows; ++r) { for(int c = 0; c < m_cols; ++c) { char tmp_char; float tmp_float; fin >> tmp_char; // for '[' for(int d = 0; d < m_depth; ++d) { fin >> tmp_float; data[d][r][c] = tmp_float; } fin >> tmp_char; // for ']' } } } ...
ついでに、CIFAR10の入力データを100個用意してそれぞれ推論を実行してみるように変更した。正しく動作しているようだ。
image_data_format = channels_first
, image_data_format = channels_last
の両方で動かしてみたが、正しく動作しているようだ。
ちゃんと整理してPull-Requestを出してみようかしら。
keras2cpp/example_main.cc
int main() { cout << "This is simple example with Keras neural network model loading into C++.\n" << "Keras model will be used in C++ for prediction only." << endl; KerasModel m("./dumped.nnet", ImageDataFormat_t::Last, false); for (int idx = 0; idx < 100; idx++) { std::stringstream filename; filename << "test_data/cifar10_test_data_" << std::setfill('0') << std::setw(2) << idx << ".txt"; DataChunk *sample = new DataChunk2D(); sample->read_from_file(filename.str().c_str(), ImageDataFormat_t::Last); m.compute_output(sample); delete sample; } return 0; }
おまけ: 使用したCIFAR-10のCNN。