卷积层的任意形状滤波器(与矩形滤波器相对)

3

我在处理由2D图像组成的数据样本时使用卷积层。滤波器的形状之一是1x2,它作用于由两个相邻像素组成的1x2连续块。如果我想要一个同时作用于2个像素的滤波器,但这两个像素之间隔了另外一个像素怎么办?在神经网络中是否可能对这样的卷积滤波器进行编码?


1
你可以创建一个由零和一组成的“掩码”,然后将其应用于权重并进行正常卷积吗? - Vijay Mariappan
3个回答

7

让它正常工作的代码

您也可以观看使用Keras使其正常工作的视频

这里有一些示例代码,它定义了Conv2d的内核和一个5x5的掩码,只允许中心和外部值通过。

image = np.array( range(25) ).reshape([1,5,5,1] ).astype( float )

kern = tf.Variable( tf.ones( [5,5,1,1] , dtype=tf.float32) )

mask = np.array([[ 1,  1,  1,  1,  1],
                 [ 1,  0,  0,  0,  1],
                 [ 1,  0,  1,  0,  1],
                 [ 1,  0,  0,  0,  1],
                 [ 1,  1,  1,  1,  1]]).reshape( [5,5,1,1] )

mask_variable = tf.constant( mask , dtype=tf.float32 )

output           = tf.nn.conv2d( image , kern        , strides=[1,1,1,1] , padding="VALID" )
output_with_mask = tf.nn.conv2d( image , kern * mask , strides=[1,1,1,1] , padding="VALID" )

print("Using whole kernal :",output.numpy())
print("Using kernal with a mask :",output_with_mask.numpy())

输出结果

Using whole kernal : [[[[ 300.]]]]
Using kernal with a mask : [[[[ 204.]]]]

此外,反向传播不会改变掩码,因为掩码被包含在tf.stop_gradient中。祝好!

2
我正在尝试使用卷积网络来处理六边形网格游戏。这似乎是该技术的一个有效应用。 - Marc
这是一个很酷的应用程序,而且完全合适!我没有想到过。 - Anton Codes
为什么在只作用于常量时需要使用stop_gradient()操作? - Marc
1
我也看到了。虽然这不是必须的,但如果它是一个变量就会需要。我更新了代码以展示你可以使用tf.Variable并且它能够工作。 - Anton Codes
该项目不是公开的,因为它是为了一个编程竞赛,我想今年再次参加。我将在下面的答案中放置一段代码片段。 - Marc
显示剩余3条评论

1
这不是一个答案,而是一个代码片段,展示了我如何使用Panchishin的答案编写六边形游戏的代码(版主:如果有更好的扩展评论或向某人发送私信的方法,请告诉我)
注意:我是深度学习的初学者。
该游戏是Blackhole,用于2018年CodeCup比赛:http://archive.codecup.nl/2018/60/rules_blackhole.html。它是在三角形中玩的六边形游戏。下面的代码定义了卷积和relu层。
def conv_weight_variable(w, h, in_ch, out_ch, learn):
    d = 1.0 / np.sqrt(in_ch * w * h)
    initial = tf.truncated_normal([w, h, in_ch, out_ch], stddev=d)
    return tf.Variable(initial, trainable=learn), iEnd

def conv_bias_variable(w, h, in_ch, out_ch, learn):
    d = 1.0 / np.sqrt(in_ch * w * h)
    initial = tf.constant([0.1*d]*out_ch, dtype=tf.float32)
    return tf.Variable(initial, trainable=learn), iEnd

def relu_conv_layer(input, in_ch, out_ch, learn):
    W, iEnd = conv_weight_variable(3, 3, in_ch, out_ch, learn)
    o = np.zeros((in_ch, out_ch), np.float32)
    i = np.ones((in_ch, out_ch), np.float32)
    maskW = np.array([[ o, i, i],
                      [ i, i, i],
                      [ i, i, o]])
    maskW = tf.constant(maskW, dtype=tf.float32)
    b, iEnd = conv_bias_variable(3, 3, in_ch, out_ch, learn)
    conv = tf.nn.conv2d(input, W * maskW, strides=[1, 1, 1, 1], padding='SAME')

    o = np.zeros(out_ch, np.float32)
    i = np.ones(out_ch, np.float32)
    maskO = np.array([[ i, i, i, i, i, i, i, i],
                      [ i, i, i, i, i, i, i, o],
                      [ i, i, i, i, i, i, o, o],
                      [ i, i, i, i, i, o, o, o],
                      [ i, i, i, i, o, o, o, o],
                      [ i, i, i, o, o, o, o, o],
                      [ i, i, o, o, o, o, o, o],
                      [ i, o, o, o, o, o, o, o]])
    maskO = tf.constant(maskO, dtype=tf.float32)
    return tf.nn.relu(conv + b)*maskO, W, b, iEnd

0

任意过滤器(权重放置在任何位置)不可用,但存在一种称为空洞卷积的有限但有用的版本,它将权重放置在稀疏网格上,可以处理您的特定示例。

例如,在您的情况下,您可以尝试

W = tf.Variable(tf.random_uniform((1, 2, n_in, n_out))
tf.nn.atrous_conv2d(value, W, (1, 2), 'SAME')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接