我有一个具有常数的自定义层,但是,我无法保存显示以下错误的模型。任何人都知道如何使用自定义tf.keras图层中具有tf.Variable的自定义图层保存tf.keras模型吗?我希望将模糊内核应用于我的卷积神经网络,该网络试图使卷积层从this paper
开始再次保持平移不变# This is the layer
class MaxBlurPooling2D(Layer):
def __init__(self, pool_size: int = 2, kernel_size: int = 3, **kwargs):
self.pool_size = pool_size
self.blur_kernel = None
self.kernel_size = kernel_size
super(MaxBlurPooling2D, self).__init__(**kwargs)
def get_config(self):
config = {
'pool_size': self.pool_size,
'blur_kernel': self.blur_kernel,
"kernel_size": self.kernel_size
}
base_config = super(MaxBlurPooling2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
def build(self, input_shape):
if self.kernel_size == 3:
bk = tf.constant([[1, 2, 1],
[2, 4, 2],
[1, 2, 1]])
bk = bk / tf.math.reduce_sum(bk)
elif self.kernel_size == 5:
bk = tf.constant([[1, 4, 6, 4, 1],
[4, 16, 24, 16, 4],
[6, 24, 36, 24, 6],
[4, 16, 24, 16, 4],
[1, 4, 6, 4, 1]])
bk = bk / tf.math.reduce_sum(bk)
else:
raise ValueError
bk = tf.cast(bk,tf.float32)
bk = tf.repeat(bk, input_shape[3])
bk = tf.reshape(bk, (self.kernel_size, self.kernel_size, input_shape[3], 1))
# blur_init = tf.keras.initializers.constant(bk)
self.blur_kernel = self.add_weight(name='blur_kernel',
shape=(self.kernel_size, self.kernel_size, input_shape[3], 1),
initializer=tf.keras.initializers.constant(bk),
trainable=False)
super(MaxBlurPooling2D, self).build(input_shape) # Be sure to call this at the end
def call(self, x):
x = tf.nn.pool(x, (self.pool_size, self.pool_size),
strides=(1, 1), padding='SAME', pooling_type='MAX', data_format='NHWC')
x = K.depthwise_conv2d(x, self.blur_kernel, padding='same', strides=(self.pool_size, self.pool_size))
return x
def compute_output_shape(self, input_shape):
return input_shape[0], int(tf.math.ceil(input_shape[1] / 2)), int(tf.math.ceil(input_shape[2] / 2)), input_shape[3]
'Not JSON Serializable:', <tf.Variable 'max_blur_pooling2d_3/blur_kernel:0' shape=(3, 3, 64, 1) dtype=float32, numpy=
array([[[[0.0625],
[0.0625],
[0.0625],
...,
]]]
答案 0 :(得分:0)
似乎自定义层get_config不应包含 self.add_weight
的变量这应该解决了问题
class MaxBlurPooling2D(L.Layer):
def __init__(self, pool_size: int = 2, kernel_size: int = 3, **kwargs):
self.pool_size = pool_size
self.kernel_size = kernel_size
super(MaxBlurPooling2D, self).__init__(**kwargs)
def get_config(self):
config = {
'pool_size': self.pool_size,
'kernel_size': self.kernel_size
# in this config should not include the variable from add_weight but only the variables in __init__
}
base_config = super(MaxBlurPooling2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
def build(self, input_shape):
if self.kernel_size == 3:
bk = tf.constant([[1, 2, 1],
[2, 4, 2],
[1, 2, 1]])
bk = bk / tf.math.reduce_sum(bk)
elif self.kernel_size == 5:
bk = tf.constant([[1, 4, 6, 4, 1],
[4, 16, 24, 16, 4],
[6, 24, 36, 24, 6],
[4, 16, 24, 16, 4],
[1, 4, 6, 4, 1]])
bk = bk / tf.math.reduce_sum(bk)
else:
raise ValueError
bk = tf.cast(bk,tf.float32)
bk = tf.repeat(bk, input_shape[3])
bk = tf.reshape(bk, (self.kernel_size, self.kernel_size, input_shape[3], 1))
self.blur_kernel = self.add_weight(name='blur_kernel',
shape=(self.kernel_size, self.kernel_size, input_shape[3], 1),
initializer=tf.keras.initializers.constant(bk),
trainable=False)
super(MaxBlurPooling2D, self).build(input_shape) # Be sure to call this at the end
def call(self, x):
x = tf.nn.pool(x, (self.pool_size, self.pool_size),
strides=(1, 1), padding='SAME', pooling_type='MAX', data_format='NHWC')
x = K.backend.depthwise_conv2d(x, self.blur_kernel, padding='same', strides=(self.pool_size, self.pool_size))
return x
def compute_output_shape(self, input_shape):
return input_shape[0], int(tf.math.ceil(input_shape[1] / 2)), int(tf.math.ceil(input_shape[2] / 2)), input_shape[3]