TensorFlow2.0保存模型参数时报错的解决办法

TensorFlow2.0保存模型参数时报错的解决办法

NotImplementedError: Layers with arguments in __init__ must override get_config.

在Tensorflow2.0保存模型时,通常用model.save语句保存模型

model.save("./saver/model_mnist.h5")

有时会出现下面这样的错误,报错信息很长只截取了上下部分

Traceback (most recent call last):
  File "F:/Python_ChengXu/Pycharm Projects/Python_TF2_projects/code4-6.py", line 56, in <module>
    model.save("./saver/the_model_mnist_2.h5")
  File "D:\Program Files (x86)\Anaconda3-5.2.0\envs\tf2\lib\site-packages\tensorflow_core\python\keras\engine\network.py", line 975, in save
    signatures, options)
  File "D:\Program Files (x86)\Anaconda3-5.2.0\envs\tf2\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py", line 573, in get_config
    raise NotImplementedError('Layers with arguments in `__init__` must '
NotImplementedError: Layers with arguments in `__init__` must override `get_config`.

但有时候却可以正常保存。
究其原因,是因为如果构建的网络中有的层自己定义的网络层时,那在保存模型时就要格外注意。当然,如果神经网络各个层都是用函数直接用的层,就比如下面这样,这样就可以直接用model.save()函数保存,参数是要保存的路径,这样就是以.h5的格式保存,不仅保存了网络的模型,还有训练之后的参数。

input_xs = tf.keras.Input([28,28,1])
conv = tf.keras.layers.Conv2D(32,3,padding = "SAME",activation = tf.nn.relu)(input_xs)
conv = tf.keras.layers.BatchNormalization()(conv) 
conv = tf.keras.layers.Conv2D(64,3,padding = "SAME",activation = tf.nn.relu)(conv)
conv = tf.keras.layers.MaxPool2D(strides = [1,1])(conv)
conv = tf.keras.layers.Conv2D(128,3,padding = "SAME",activation = tf.nn.relu)(conv)

flat = tf.keras.layers.Flatten()(conv)
dense = tf.keras.layers.Dense(512,activation = tf.nn.relu)(flat)
logits = tf.keras.layers.Dense(10,activation = tf.nn.softmax)(dense)

model = tf.keras.Model(inputs = input_xs,outputs = logits)

但是,如果里面有自己定义的网络层,就像这样

class MyLayer(tf.keras.layers.Layer):
    def __init__(self,kernel_size,filter):  #设定层中参数,目前需要定义的参数是卷积核大小和卷积核数目
        self.filter = filter
        self.kernel_size = kernel_size
        super(MyLayer,self).__init__()
    def build(self,input_shape):
        self.weight = tf.Variable(tf.random.normal([self.kernel_size,self.kernel_size,input_shape[-1],self.filter]),name = 'Weight')
        self.bias = tf.Variable(tf.random.normal([self.filter]),name = 'Bias')
        super(MyLayer,self).build(input_shape)
    def call(self,input_tensor):
        conv = tf.nn.conv2d(input_tensor,self.weight,strides = [1,2,2,1],padding = "SAME")
        conv = tf.nn.bias_add(conv,self.bias)
        out = tf.nn.relu(conv) + conv
        return out
input_xs = tf.keras.Input([28,28,1])
conv = tf.keras.layers.Conv2D(32,3,padding = "SAME",activation = tf.nn.relu)(input_xs)
conv = MyLayer(32,3)(conv)
conv = tf.keras.layers.BatchNormalization()(conv)

显然网络层中的MyLayer(32,3)就是自己定义的,这时候在模型保存时会出现上面提到的错误。需要做两点

  • 重新get_config()函数。在原来的网络层定义的__init__,build,call函数下面重写get_config()函数,就像这样
    def get_config(self):  #在有自定义网络层时,需要保存模型时,重写get_config函数
        config = {"kernel_size": self.kernel_size,"filter":self.filter}
        base_config = super(MyLayer, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))
  • 自定义层中的Variable类型的参数需要命名。这个不必多说,build函数里的Variable类型的变量直接name一下就可以,注意是build函数所有Variable类型的变量都要命名,下面只是截取的其中一个
self.bias = tf.Variable(tf.random.normal([self.filter]),name = 'Bias')

完成这两步,再次运行就可以成功保存模型啦。下面运行之后的提示信息

118/118 [==============================] - 94s 799ms/step - loss: 0.3067 - accuracy: 0.9097
模型保存成功
last scaore: [0.10443486766889691, 0.9664]
totally cost 106.19307065010071

我爱小倩!

  • 12
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值