在默认的Conv2D
图层中,kernel_size=3
其中一个过滤器切片的权重可以命名如下:
A B C
D E F
G H I
有了这样的kernel_size=5
:
A B C D E
F G H I J
K L M N O
P Q R S T
U V W X Y
现在我想构建(和训练/测试)一个基于 conv 层的模型,其中包含如下内核:
A A B C C
A A B C C
D D E F F
G G H I I
G G H I I
这种自定义层的实现是什么样的?
也许是这样的?
class CustomConv2D(Layer):
def __init__(self, filters, **kwargs):
self.filters = filters
self.kernel_size = (3, 3)
super(CustomConv2D, self).__init__(**kwargs)
def build(self, input_shape):
# only have a 3x3 kernel
shape = self.kernel_size + (input_shape[-1], self.filters)
self.kernel = self.add_weight(name='kernel', shape=shape,
initializer='glorot_uniform')
super(CustomConv2D, self).build(input_shape)
def call(self, x):
# duplicate rows 0 and 2
dup_rows = K.stack([self.kernel[0]]*2 + [self.kernel[1]] + [self.kernel[2]]*2, axis=0)
# duplicate cols 0 and 2
dup_cols = K.stack([dup_rows[:,0]]*2 + [dup_rows[:,1]] + [dup_rows[:,2]]*2, axis=1)
# having a 5x5 kernel now
return K.conv2d(x, dup_cols)
def compute_output_shape(self, input_shape):
return input_shape[:-1] + (self.filters,)
诀窍是简单地在 3x3 内核中为每个过滤器存储 9 个权重(硬编码,您可能想要概括它),并复制第一行和最后一行和列,使其成为您想要的 5x5 内核。然后,此内核将传递给K.conv2d()
就像在原始 Conv2d 实现中一样。
我测试了它,它似乎正在工作。您可能需要添加其他参数,如填充、偏差等。
我认为这是您想要的基本版本:
from keras import backend as K
class Conv2DTiledKernel(Layer):
def __init__(self, filters, kernel_size, multiplies, **kwargs):
self.filters = filters
self.kernel_size = kernel_size
self.multiplies = multiplies
super(Conv2DTiledKernel, self).__init__(**kwargs)
def build(self, input_shape):
shape = list(self.kernel_size) + [input_shape[-1], self.filters]
self.kernel = self.add_weight(name='kernel', shape=shape,
initializer='glorot_uniform')
super(Conv2DTiledKernel, self).build(input_shape)
def call(self, x):
mult = list(self.multiplies) + [1, 1]
kernel_tiled = K.tile(self.kernel, mult)
return K.conv2d(x, kernel_tiled)
def compute_output_shape(self, input_shape):
return input_shape[:-1] + (self.filters,)
fitlers
是输出通道的数量,kernel_size
每个内核通道的大小,multiplies
切片因子。你会像这样使用它:
from keras.models import Model
from keras.layers import Input, Layer
img = Input(shape=(64, 64, 3))
output = Conv2DTiledKernel(10, [1, 5], [5, 1])(img)
model = Model(inputs=img, outputs=output)
不过,这是一个非常基本的版本。您稍后可以添加偏差、正则化、起始化、填充、步幅、膨胀等选项。您可以查看源代码以了解卷积层是如何在 Keras 中实现的。如果您可以只对其中一个类进行子类化,以便免费获得所有其他选项,那将是理想的选择,但我不确定是否可以以当前代码的实际方式完成。