python - 加载具有自定义层的模型时 Keras 中的形状不兼容

标签 python tensorflow keras

我正在尝试在 Keras 中实现子像素上卷积层。我可以毫无问题地训练模型并保存它。但我无法加载该模型。我总是收到尺寸错误的错误。

它的唯一工作方式是保存权重,创建一个新模型,然后加载权重。但这并不理想,因为优化器会重置,因此很难恢复训练。

import keras
import numpy as np
import tensorflow as tf

class Subpixel(keras.layers.Conv2D):

    def __init__(self,
                 filters,
                 kernel_size,
                 scale,
                 padding='valid',
                 data_format='channels_last',
                 strides=(1, 1),
                 activation=None,
                 use_bias=True,
                 kernel_initializer='he_normal',
                 bias_initializer='zeros',
                 kernel_regularizer=None,
                 bias_regularizer=None,
                 activity_regularizer=None,
                 kernel_constraint=None,
                 bias_constraint=None,
                 **kwargs):
        super().__init__(
            filters=scale * scale * filters,
            kernel_size=kernel_size,
            strides=strides,
            padding=padding,
            data_format=data_format,
            activation=activation,
            use_bias=use_bias,
            kernel_initializer=kernel_initializer,
            bias_initializer=bias_initializer,
            kernel_regularizer=kernel_regularizer,
            bias_regularizer=bias_regularizer,
            activity_regularizer=activity_regularizer,
            kernel_constraint=kernel_constraint,
            bias_constraint=bias_constraint,
            **kwargs)
        self.scale = scale
        self.data_format = data_format

    def call(self, inputs):
        return tf.depth_to_space(super().call(inputs), self.scale)

    def compute_output_shape(self, input_shape):
        if self.data_format == 'channels_first':
            b, k, r, c = super().compute_output_shape(input_shape)
            return b, k // (self.scale ** 2), r * self.scale, c * self.scale
        else:
            b, r, c, k = super().compute_output_shape(input_shape)
            return b, r * self.scale, c * self.scale, k // (self.scale ** 2)

    def get_config(self):
        config = super(keras.layers.Conv2D, self).get_config()
        config['filters'] = int(config['filters'] / self.scale * self.scale)
        config['scale'] = self.scale
        return config

X = np.random.rand(100, 2, 2, 1)
y = np.random.rand(100, 4, 4, 1)

inputs = keras.layers.Input(shape=(2, 2, 1))
x = Subpixel(4, 4, 2, padding='same')(inputs)
output = keras.layers.Dense(1, activation='sigmoid')(x)
model = keras.models.Model(inputs, output)
model.compile(optimizer='sgd',
                          loss='mean_absolute_error',
                          metrics=[])

model.fit(X, y)
model.save('foo.h5')
foo = keras.models.load_model('foo.h5', custom_objects={'Subpixel': Subpixel})

看来权重文件中的形状与加载的体系结构之间存在冲突。加载模型上的内核形状不正确。应该是 4,4,1,16 时却是 4,4,1,64。输出结果如下:

self = TensorShape([Dimension(4), Dimension(4), Dimension(1), Dimension(64)])
other = TensorShape([Dimension(4), Dimension(4), Dimension(1), Dimension(16)])

    def assert_is_compatible_with(self, other):
      """Raises exception if `self` and `other` do not represent the same shape.

      This method can be used to assert that there exists a shape that both
      `self` and `other` represent.

      Args:
        other: Another TensorShape.

      Raises:
        ValueError: If `self` and `other` do not represent the same shape.
      """
      if not self.is_compatible_with(other):
>       raise ValueError("Shapes %s and %s are incompatible" % (self, other))
E       ValueError: Shapes (4, 4, 1, 64) and (4, 4, 1, 16) are incompatible

最佳答案

极其愚蠢的错误。该行:

config['filters'] = int(config['filters'] / self.scale * self.scale)

应该是:

config['filters'] = int(config['filters'] / (self.scale * self.scale))

否则在序列化层时,会保存错误的过滤器输入参数。基本上我被运算符优先级搞混了。

关于python - 加载具有自定义层的模型时 Keras 中的形状不兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56169945/

相关文章:

python - sqlalchemy bulk_insert_mappings 生成大量插入批处理,这是可以避免的吗?

python - 分类 : What happens if one class has 4 times as much data as the other class?

python - 使用 Keras model.fit() 显示模型验证进度

python - batch_size = 1 的 tensorflow 中的不同图像大小

python - 尝试运行 OpenMMD 时出现另一个 "h5py is running against HDF5 1.10.5 when it was built against 1.10.4"错误

python - NumPy 相当于 Keras 函数 utils.to_categorical

python - 使用不是符号张量的输入调用层 up_sampling2d_1。收到类型: <class 'numpy.ndarray' >

python - 子流程调用中的用户输入?

python - `fft` 没有返回它应该返回的内容

python - Django 管理员 : OneToOne Relation as an Inline?