FPGA開発日記

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

TensorFlow+Kerasに入門(9. Keras2のMNISTサンプルに対応)

Keras2の簡単な例題モデルとしてこれまではCIFAR-10を使っていたが、一応MNISTも対応しておきたい。 Keras2のmnist_cnn.pyが動作するように対応を実施した。

結論から言うと機能が足りておらずすぐには動作しなかった。keras2cppにいろいろと機能を追加した。

github.com

Keras2cppの機能拡張

Keras2のmnist_cnn.pyには、keras2cppのサポートしていないいくつかの機能が使われており、これにより一部動作をしなかった。

Conv2D / DenseLayer にActivationレイヤが追加されている

mnist_cnn.py には、以下のオプションが用意されており、Conv2D / DenseでActivationの機能が必要であった。

  • examples/mnist_cnn.py
...
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
...

これによりMNSITも動作するようになった。MNISTは学習時間が短いので楽だ。

  • keras2cpp/keras_model.cc
diff --git a/keras_model.cc b/keras_model.cc
index 6b30ab2..693da0e 100644
--- a/keras_model.cc
+++ b/keras_model.cc
@@ -81,7 +81,7 @@ void keras::LayerConv2D::load_weights(std::ifstream &fin) {
   string tmp_str = "";
   float tmp_float;
   bool skip = false;
-  fin >> m_kernels_cnt >> m_depth >> m_rows >> m_cols >> m_border_mode;
+  fin >> m_kernels_cnt >> m_depth >> m_rows >> m_cols >> m_border_mode >> m_activation;
   if (m_border_mode == "[") { m_border_mode = "valid"; skip = true; }

   //cout << "LayerConv2D " << m_kernels_cnt << "x" << m_depth << "x" << m_rows <<
@@ -397,12 +384,22 @@ keras::DataChunk* keras::LayerConv2D::compute_output(keras::DataChunk* dc) {
         y_ret[j][x][y] += m_bias[j];
       }
     }
-    // if (j == 0) { printf ("After biasing y[0][0][0] = %f\n", y_ret[0][0][0]); }
+  }
+
+  // Activation
+  if (m_activation == "relu") {
+    for(unsigned int j = 0; j < m_kernels.size(); ++j) { // loop over kernels
+      for(unsigned int x = 0; x < y_ret[0].size(); ++x) {
+        for(unsigned int y = 0; y < y_ret[0][0].size(); ++y) {
+          y_ret[j][x][y] = (y_ret[j][x][y] >= 0.0) ? y_ret[j][x][y] : 0.0;
+        }
+      }
+    }
   }

   keras::DataChunk *out = new keras::DataChunk2D();

実行結果。正しく動作した。

$ ./mnist_cnn
This is simple example with Keras neural network model loading into C++.
Keras model will be used in C++ for prediction only.
DataChunk2D 1x28x28
DataChunkFlat values:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000
DataChunk2D 1x28x28
DataChunkFlat values:
0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
DataChunk2D 1x28x28
DataChunkFlat values:
0.000000 0.999988 0.000003 0.000000 0.000004 0.000000 0.000001 0.000003 0.000000 0.000000
...
f:id:msyksphinz:20180712231020p:plain