改变喀拉拉邦卷积层内核的形状

时间:2020-04-29 13:50:16

标签: tensorflow keras deep-learning conv-neural-network

如果我的内核大小为3X3,它将在它关注的像素周围看一个像素。 例如,对于内核:

1  2  3
4  5  6
7  8  9

它将使用1-9在要素图的位置5处生成一个值。 有没有一种方法可以使它在位置9产生一个值?因此对于要素地图上的每个位置,它只会“看到”其顶部和左侧的像素?

在keras中,张量流后端。

编辑: 根据我得到的答案,我使用以下代码:

from keras.layers import Layer
class CornerConv2D(Layer):
    def __init__(self, filters, **kwargs):
        self.filters = filters
        self.kernel_size = (3,3)
        super(CornerConv2D, self).__init__(**kwargs)

    def build(self, input_shape):
        shape = self.kernel_size + (input_shape[-1], self.filters)
        self.kernel = self.add_weight(name='kernel', shape=shape,
                                  initializer='glorot_uniform')
        super(CornerConv2D, self).build(input_shape)

    def call(self, layer_input):

        custom_kernel = K.get_value(self.kernel)
        # set the bottom right corner as zero
        custom_kernel[-1,-1,:,:] = np.zeros_like(custom_kernel[-1,-1,:,:])

        return K.conv2d(layer_input,  custom_kernel)

    def compute_output_shape(self, input_shape):
        return (input_shape[0], input_shape[1]-2, input_shape[1]-2) + (self.filters,)


inp = Input(shape=(64,64,1))
x = ZeroPadding2D(1)(inp)
x = CornerConv2D(30)(x)
x = ZeroPadding2D(1)(x)
x = CornerConv2D(30)(x)
x = ZeroPadding2D(1)(x)
x = CornerConv2D(1)(x)


m = Model(inputs=[inp], outputs=[x])

m.compile(loss='mse', optimizer="adam")

m.summary()

这仍然有问题。当我尝试训练模型时,模型创建没有问题,并且可以预测没有任何错误:

m.fit(imgs, imgs, batch_size=32, epochs=2)

它给出了错误:

An operation has `None` for gradient. Please make sure that all of your ops have a gradient defined (i.e. are differentiable). Common ops without gradient: K.argmax, K.round, K.eval.

1 个答案:

答案 0 :(得分:1)

在您自己的层上操作内核并在左侧和顶部应用零填充应该可以实现您想要的:

             0  0  0  0 
1  2  3      0  1  2  3
4  5  6  ->  0  4  5  6 
7  8  9      0  7  8  9

内核将考虑:

f  f
f  0

对于位置4,它将仅考虑1,对于位置5,将考虑1,2,4,而对于位置9,其将考虑5,6,8。您可以根据需要修改填充。

from tensorflow.keras.layers import ZeroPadding2D
from tensorflow.keras.models import Sequential
from tensorflow.keras import backend as K
import numpy as np

class CornerConv2D(Layer):
    def __init__(self, filters, **kwargs):
        self.filters = filters
        self.kernel_size = (2,2)
        super(CornerConv2D, self).__init__(**kwargs)

    def build(self, input_shape):
        shape = self.kernel_size + (input_shape[-1], self.filters)
        self.kernel = self.add_weight(name='kernel', shape=shape,
                                  initializer='glorot_uniform')
        super(CornerConv2D, self).build(input_shape)


    def call(self, layer_input):

        custom_kernel = K.get_value(self.kernel)
        # set the bottom right corner as zero
        custom_kernel[-1,-1,:,:] = np.zeros_like(custom_kernel[-1,-1,:,:])

        K.set_value(self.kernel, custom_kernel)
        return K.conv2d(layer_input,  self.kernel)


    def compute_output_shape(self, input_shape):
        return input_shape[:-1] + (self.filters,)


m = Sequential()
m.add(ZeroPadding2D(((1, 0), (1, 0) ), input_shape=(9,9,3))) # (1, 0), (1, 0) adds zeros to top and left
m.add(CornerConv2D(5)) # Valid padding as default

m.compile(loss='mse', optimizer="adam")

m.summary()
input_test = np.random.random((9,9,3))
pred = m.predict(input_test.reshape(1,9,9,3))

print(pred.shape)