反射填充 Conv2D
Posted
技术标签:
【中文标题】反射填充 Conv2D【英文标题】:Reflection padding Conv2D 【发布时间】:2018-11-13 14:38:02 【问题描述】:我正在使用 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模型中?
【问题讨论】:
【参考方案1】:上面接受的答案在当前的 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')
【讨论】:
jeevaa_v,你能解释一下你写的东西吗?即使是解释反射层作用的参考文章也会很棒 我刚刚使用 tensorflow 的反射填充在 Keras 中创建了一个自定义层。关于反射填充或其他类型的填充,请参见此处:www-cs.engr.ccny.cuny.edu/~wolberg/cs470/hw/hw2_pad.txt 这个实现既有用又干净,感谢分享! 如果使用大于 (1,1) 的 padding 并保存模型,这里会出现一个大问题。当您加载它时,它会尝试进行 (1,1) 填充,因为它在 init 中以这种方式初始化,并且模型将无法加载。我想不出办法,所以如果你有这个问题,我会使用下面的 Lambda 解决方案。 machinecurve.com/index.php/2020/02/10/…【参考方案2】:找到了解决方案!我们只需要创建一个以层为输入的新类,并使用 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)
【讨论】:
但是在demo中padding不应该在卷积之前吗? 这对我有用。之后还是一样的形状 @ChristofHenkel 在下面查看我的答案。您应该将函数名称 get_output_shape_for 更改为 compute_output_shape。【参考方案3】: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 版本,所以我想出了自己的解决方案。 sn-p 将一批 202x202x3 的图像填充为 256x256x3
【讨论】:
真正简单有效的解决方案【参考方案4】:正如您可以在documentation 中查看的那样,没有这样的“反射”填充。 keras 中只实现了“相同”和“有效”。
您可能会尝试自己实现或查找是否有人已经这样做了。你应该以Conv2D
类为基础,并检查self.padding
成员变量的使用位置。
【讨论】:
我知道这在 keras 中还没有实现。但是,如何实现反射层并将其添加到 keras 模型中? 那你应该澄清你的问题,说你想通过反射来实现填充。【参考方案5】:如果我们有未定义的尺寸,则接受的答案不起作用!调用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
【讨论】:
以上是关于反射填充 Conv2D的主要内容,如果未能解决你的问题,请参考以下文章
Android mancj.MaterialSearchBar:使用反射覆盖和更改一些 API 布局和小部件、字体系列、粗体和填充
Angular4 core.es5.js 使用类装饰器时需要未捕获的反射元数据填充程序