FPGA開発日記

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

TensorFlow+Kerasに入門(7. Keras2cppをimage_data_formatに対応させる)

f:id:msyksphinz:20180701195704p:plain

Keras2cppを使ってKerasのモデルをC++のコードに変換したのだが、まだ問題がある。デフォルトの画像データフォーマットである image_data_format = channels_last に対応していないことだ。

バックエンド - Keras Documentation

これにより、画像データをデフォルトの並び(縦方向, 横方向, channel)に一度変換して処理をしないといけない。これは面倒なので、channels_firstに対応させることにした。

github.com

と言っても、画像データを入力するときに、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。

f:id:msyksphinz:20180707232250p:plain