"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

tensorflow1.12で、model.save()が「Currently `save` requires model to be a graph network.」エラー

tensorflowを1.12にバージョンアップすると、tf.kerasのmodel.save()が使えるようになるのですが、1.10のままのソースだとエラーになる場合があります。

f:id:arakan_no_boku:20181012005050j:plain

tf.kerasのmodel.save()は、1.11ではエラーで使えませんでした。

arakan-pgm-ai.hatenablog.com

1.12の場合も、同じようなエラーに見えますが内容が違います。

 

1.12で仕様変更があったみたい

 

例えば、以下のようなソースです。

import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.sparse_categorical_crossentropy,
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=2)
model.evaluate(x_test, y_test)
model.save('my_model.h5')

これは。

1.10では問題なく動きます。

1.11ではエラーになって保存できません。(回避もできません)

1.12ではソースによっては動きますが、上記のようなソースの場合だと、以下のようなエラーメッセージでエラーになります。

NotImplementedError: Currently `save` requires model to be a graph network. Consider using `save_weights`, in order to save the weights of the model.

原因は仕様変更のようです。

どうも、1.12で仕様が厳しくなって、modelを定義する最初のレイヤーで、「input_shape」を必ず指定しないと「graph network」と認識されず、上記のエラーがでるようになったみたいです。

これを回避するための方法です。

上記のソースの場合は以下の部分を修正します。

  tf.keras.layers.Flatten(),

これを、以下のようにします。

tf.keras.layers.Flatten(input_shape=(28,28)),

このように、modelを定義する最初のレイヤーで、「input_shape」を指定してあれば、エラーがでずに保存できるようになります。

ちょっと したことですし、「input_shape」を指定する方が正しい書き方なのは間違いないのですが、1.10まで普通に動いていたソースがいきなり動かなくなって、上記のようなエラーメッセージをはくと、かなり焦ります。

自分もそうでした。

それにしても。

tensorflowをバージョンアップすると毎回、ドキドキさせられますねえ。

最後に。

1.12で正常動作するソース全文です。

import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28,28)),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.sparse_categorical_crossentropy,
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=2)
model.evaluate(x_test, y_test)
model.save('my_model.h5')

ではでは。

 

2018/12/09追記

上記例では、input_shapeで(28,28)などと固定で書いてます。

でも、毎回こうはいきません。

全結合だけのネットワークの場合は、データ量によって違ったりします。

そういう場合の書き方を補足しておきます。

model.add(tf.keras.layers.Flatten(input_shape=x_train.shape[1:]))

これだと、データ量が変動してもOKです。