【发布时间】:2018-08-12 07:53:41
【问题描述】:
受tf.keras.Model subclassing 的启发,我创建了自定义模型。
我可以训练它并获得成功的结果,但是我无法保存它。
我使用 python3.6 和 tensorflow v1.10(或 v1.9)
这里是最小的完整代码示例:
import tensorflow as tf
from tensorflow.keras.datasets import mnist
class Classifier(tf.keras.Model):
def __init__(self):
super().__init__(name="custom_model")
self.batch_norm1 = tf.layers.BatchNormalization()
self.conv1 = tf.layers.Conv2D(32, (7, 7))
self.pool1 = tf.layers.MaxPooling2D((2, 2), (2, 2))
self.batch_norm2 = tf.layers.BatchNormalization()
self.conv2 = tf.layers.Conv2D(64, (5, 5))
self.pool2 = tf.layers.MaxPooling2D((2, 2), (2, 2))
def call(self, inputs, training=None, mask=None):
x = self.batch_norm1(inputs)
x = self.conv1(x)
x = tf.nn.relu(x)
x = self.pool1(x)
x = self.batch_norm2(x)
x = self.conv2(x)
x = tf.nn.relu(x)
x = self.pool2(x)
return x
if __name__ == '__main__':
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(*x_train.shape, 1)[:1000]
y_train = y_train.reshape(*y_train.shape, 1)[:1000]
x_test = x_test.reshape(*x_test.shape, 1)
y_test = y_test.reshape(*y_test.shape, 1)
y_train = tf.keras.utils.to_categorical(y_train)
y_test = tf.keras.utils.to_categorical(y_test)
model = Classifier()
inputs = tf.keras.Input((28, 28, 1))
x = model(inputs)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(10, activation="sigmoid")(x)
model = tf.keras.Model(inputs=inputs, outputs=x)
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
model.fit(x_train, y_train, epochs=1, shuffle=True)
model.save("./my_model")
错误信息:
1000/1000 [==============================] - 1s 1ms/step - loss: 4.6037 - acc: 0.7025
Traceback (most recent call last):
File "/home/user/Data/test/python/mnist/mnist_run.py", line 62, in <module>
model.save("./my_model")
File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py", line 1278, in save
save_model(self, filepath, overwrite, include_optimizer)
File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/saving.py", line 101, in save_model
'config': model.get_config()
File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py", line 1049, in get_config
layer_config = layer.get_config()
File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py", line 1028, in get_config
raise NotImplementedError
NotImplementedError
Process finished with exit code 1
我查看了错误行,发现 get_config 方法检查 self._is_graph_network
有人处理这个问题吗?
谢谢!
更新 1:
在 keras 2.2.2 上(不是 tf.keras)
找到评论(用于模型保存)
文件:keras/engine/network.py
函数:get_config
# 子类网络不可序列化
# (除非序列化由
实现 # 子类网络的作者)。
所以,显然它不会工作......
我想知道,他们为什么不在documentation 中指出这一点(例如:“使用没有保存能力的子类!”)
更新 2:
发现于keras documentation:
在子类模型中,模型的拓扑定义为 Python 代码
(而不是作为图层的静态图)。这意味着模型的
无法检查或序列化拓扑。结果,以下
方法和属性不适用于子类模型:model.inputs 和 model.outputs。
model.to_yaml() 和 model.to_json()
model.get_config() 和 model.save()。
因此,没有办法通过使用子类来保存模型。
只能使用Model.save_weights()
【问题讨论】:
-
子类模型不能序列化的原因是keras需要跟踪每个张量的历史以确定图的结构,每个张量应该输出
tf.keras.layers.Layer,但是,子类化模型在其call方法中包含像tf.nn.relu这样的幼稚tensorflow 操作,因此无法序列化 -
那么,如果我在里面只使用
tf.keras呢?答:不行 -
我的建议是,如果你真的想要子类模型,那么忘记
Model.save,使用Model.save_weights只保存模型的权重,用Model.load_weights加载权重,否则如果你仍然想要保存整个模型而不是只保存权重,你必须遵循 keras 的功能 api 指南 -
哦,真的很有帮助。
Model.save_weights工作正常。非常感谢!
标签: python-3.x tensorflow keras