我正在使用下面的类定义的残差单元训练卷积神经网络(如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。
答案 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