6

我正在使用 keras 构建用于图像分割的卷积神经网络,我想使用“反射填充”而不是填充“相同”,但我找不到在 keras 中执行此操作的方法。

inputs = Input((num_channels, img_rows, img_cols))
conv1=Conv2D(32,3,padding='same',kernel_initializer='he_uniform',data_format='channels_first')(inputs)

有没有办法实现反射层并将其插入到 keras 模型中?

4

5 回答 5

7

上面接受的答案在当前的 Keras 版本中不起作用。这是正在运行的版本:

class ReflectionPadding2D(Layer):
    def __init__(self, padding=(1, 1), **kwargs):
        self.padding = tuple(padding)
        self.input_spec = [InputSpec(ndim=4)]
        super(ReflectionPadding2D, self).__init__(**kwargs)

    def compute_output_shape(self, s):
        """ If you are using "channels_last" configuration"""
        return (s[0], s[1] + 2 * self.padding[0], s[2] + 2 * self.padding[1], s[3])

    def call(self, x, mask=None):
        w_pad,h_pad = self.padding
        return tf.pad(x, [[0,0], [h_pad,h_pad], [w_pad,w_pad], [0,0] ], 'REFLECT')
于 2018-11-17T09:41:34.020 回答
3

找到了解决方案!我们只需要创建一个以层为输入的新类,并使用 tensorflow 预定义函数来完成。

import tensorflow as tf
from keras.engine.topology import Layer
from keras.engine import InputSpec

class ReflectionPadding2D(Layer):
    def __init__(self, padding=(1, 1), **kwargs):
        self.padding = tuple(padding)
        self.input_spec = [InputSpec(ndim=4)]
        super(ReflectionPadding2D, self).__init__(**kwargs)

    def get_output_shape_for(self, s):
        """ If you are using "channels_last" configuration"""
        return (s[0], s[1] + 2 * self.padding[0], s[2] + 2 * self.padding[1], s[3])

    def call(self, x, mask=None):
        w_pad,h_pad = self.padding
        return tf.pad(x, [[0,0], [h_pad,h_pad], [w_pad,w_pad], [0,0] ], 'REFLECT')

# a little Demo
inputs = Input((img_rows, img_cols, num_channels))
padded_inputs= ReflectionPadding2D(padding=(1,1))(inputs)
conv1 = Conv2D(32, 3, padding='valid', kernel_initializer='he_uniform',
               data_format='channels_last')(padded_inputs)
于 2018-06-04T11:27:05.307 回答
2
import tensorflow as tf
from keras.layers import Lambda

inp_padded = Lambda(lambda x: tf.pad(x, [[0,0], [27,27], [27,27], [0,0]], 'REFLECT'))(inp)

Akihiko 的解决方案不适用于新的 keras 版本,所以我想出了自己的解决方案。该片段将一批 202x202x3 图像填充到 256x256x3

于 2018-08-24T17:51:34.150 回答
0

正如您可以在文档中查看的那样,没有这样的“反射”填充。keras 中只实现了“相同”和“有效”。

您可能会尝试自己实施或查找是否有人已经这样做了。您应该将自己置于Conv2D类中并检查self.padding成员变量的使用位置。

于 2018-06-04T09:44:20.997 回答
0

如果我们有未定义的尺寸,则接受的答案不起作用!调用compute_output_shape函数时会报错。这是解决此问题的简单方法。

class ReflectionPadding2D(Layer):
    def __init__(self, padding=(1, 1), **kwargs):
        self.padding = tuple(padding)
        self.input_spec = [InputSpec(ndim=4)]
        super(ReflectionPadding2D, self).__init__(**kwargs)

    def compute_output_shape(self, s):
        if s[1] == None:
            return (None, None, None, s[3])
        return (s[0], s[1] + 2 * self.padding[0], s[2] + 2 * self.padding[1], s[3])

    def call(self, x, mask=None):
        w_pad, h_pad = self.padding
        return tf.pad(x, [[0, 0], [h_pad, h_pad], [w_pad, w_pad], [0, 0]], 'REFLECT')

    def get_config(self):
        config = super(ReflectionPadding2D, self).get_config()
        print(config)
        return config
于 2020-02-07T15:18:06.293 回答