忽略...在__init__中带有参数的图层必须覆盖`get_config`

时间:2020-04-23 14:48:23

标签: python tensorflow keras deep-learning conv-neural-network

我正在使用下面的类定义的残差单元训练卷积神经网络(如Aurelien Geron撰写的“使用Scikit-Learn,Keras和Tensorflow进行动手学习”中的478页)

class ResidualUnit(tf.keras.layers.Layer):

    def __init__(self, filters, strides=1, activation="relu", **kwargs):

        super().__init__(**kwargs)
        self.activation = tf.keras.activations.get(activation)

        self.main_layers = [
            tf.keras.layers.Conv2D(filters, 3, strides=strides, padding="same", use_bias=False),
            tf.keras.layers.BatchNormalization(),
            self.activation,
            tf.keras.layers.Conv2D(filters, 3, strides=1, padding="same", use_bias=False),
            tf.keras.layers.BatchNormalization()]

        self.skip_layers=[]

        if strides > 1:
            self.skip_layers = [
                tf.keras.layers.Conv2D(filters, 1, strides=strides, padding="same", use_bias=False),
                tf.keras.layers.BatchNormalization()]


    def call(self, inputs):

        Z = inputs

        for layer in self.main_layers:
            Z = layer(Z)
        skip_Z = inputs

        for layer in self.skip_layers:
            skip_Z = layer(skip_Z)

        return self.activation(Z + skip_Z)

该类的创建没有错误,并且模型架构(使用此类)的创建也没有错误:

ResNet_model = tf.keras.models.Sequential()

ResNet_model.add(tf.keras.layers.Conv2D(64, 3, strides=2, input_shape=num_pixels_and_channels,
                                       padding="same", use_bias=False))


ResNet_model.add(tf.keras.layers.BatchNormalization())

ResNet_model.add(tf.keras.layers.Activation("relu"))

ResNet_model.add(tf.keras.layers.MaxPool2D(pool_size=3, strides=2, padding="same"))

prev_filters=64

for filters in [64] * 1 + [128] * 1 + [256] * 1 + [512] * 1:
    strides = 1 if filters == prev_filters else 2
    ResNet_model.add(ResidualUnit(filters, strides=strides))
    prev_filters=filters

ResNet_model.add(tf.keras.layers.GlobalAvgPool2D())
ResNet_model.add(tf.keras.layers.Flatten())
ResNet_model.add(tf.keras.layers.Dense(257, activation="softmax"))

...但是当我训练模型时,训练开始后会显示警告:

警告:tensorflow:模型无法序列化为JSON。忽略...在__init__中带有参数的图层必须覆盖get_config

模型训练第一个纪元,然后停止。

出什么问题了,我需要在代码中进行哪些更改以解决此问题?

我正在CPU的Jupyter Notebook中运行tensorflow版本2.1.0。

1 个答案:

答案 0 :(得分:1)

我在图层类中覆盖了如下的get_config()函数,它似乎已经解决了该问题:

def get_config(self):
    cfg = super().get_config()
    return cfg    

更具体地说:

class AttentionBlock(tf.keras.layers.Layer):
def __init__(self,units = 32,**kwargs):
    super(AttentionBlock, self).__init__(**kwargs)
    self.units = units
    self.conv2d = tf.keras.layers.SeparableConv2D(self.units, 1,  padding='same',
                                  use_bias=True,
                                  kernel_initializer=tf.keras.initializers.VarianceScaling(), bias_initializer='zeros',
                                  bias_regularizer=None)
    self.relu = tf.keras.layers.Activation('swish')
    self.batchnorm = tf.keras.layers.BatchNormalization()


def get_config(self):
    cfg = super().get_config()
    return cfg    

def call(self,inputs):
  if type(inputs) is not list or len(inputs) <= 1:
        raise Exception('Merge must be called on a list of tensors '
                        '(at least 2). Got: ' + str(inputs))
  else:
      x,y = inputs
      w = self.conv2d(x)
      v = self.conv2d(y)
      out = self.relu(w + v)
      out = self.batchnorm(out)
      out = tf.nn.sigmoid(out)
      return out