Tensorflow 张量流核的力对称性

Tensorflow 张量流核的力对称性,tensorflow,symmetry,Tensorflow,Symmetry,我希望在变量的权重中强制对称。我想要一个近似的圆对称。然而,我可以想象行或列强制对称 目标是通过减少自由变量的数量来减少训练时间。我知道我的问题需要对称数组,但我可能希望同时包含对称变量和“自由”变量。我现在正在使用conv2d,所以我相信我需要继续使用它。这里有一个函数,它创建了一个相对于中心行反射对称的内核: def SymmetricKernels(高度、宽度、输入通道、输出通道、名称=无): 半内核=tf.Variable(初始值=tf.random\u normal([(高度+1)//

我希望在变量的权重中强制对称。我想要一个近似的圆对称。然而,我可以想象行或列强制对称


目标是通过减少自由变量的数量来减少训练时间。我知道我的问题需要对称数组,但我可能希望同时包含对称变量和“自由”变量。我现在正在使用conv2d,所以我相信我需要继续使用它。

这里有一个函数,它创建了一个相对于中心行反射对称的内核:

def SymmetricKernels(高度、宽度、输入通道、输出通道、名称=无):
半内核=tf.Variable(初始值=tf.random\u normal([(高度+1)//2,宽度,输入通道,输出通道])
half_kernels_reversed=tf.reverse(half_kernels[:(高度//2),:,:,:,:,:],[0])
kernels=tf.concat([half_kernels,half_kernels_reversed],axis=0,name=name)
返回内核
用法示例:

w=SymmetricKernels(5,5,1,1)
sess=tf.InteractiveSession()
sess.run(tf.global\u variables\u initializer())
w_uz=sess.run(w)
w.[:,:,0,0]
#输出:
# [[-1.299 -1.835 -1.188  0.093 -1.736]
#  [-1.426 -2.087  0.434  0.223 -0.65 ]
#  [-0.217 -0.802 -0.892 -0.229  1.383]
#  [-1.426 -2.087  0.434  0.223 -0.65 ]
#  [-1.299 -1.835 -1.188  0.093 -1.736]]
其思想是使用
tf.Variable()
只创建内核的上半部分变量(
half_kernels
),然后形成对称内核,作为上半部分及其反射版本的串联


这个想法可以扩展到创建具有左右对称和上下对称的内核。

你可以尝试的另一件事是通过卷积两次来束缚网络,重用内核,但翻转它进行第二次卷积(未经测试的代码):


您可以根据需要添加偏差、激活等。我在过去也使用过类似的方法–
reduce\u max
将允许您的内核采用任何形式,并有效地为一个内核提供两个卷积;如果改用
reduce\u sum
,任何不对称都将很快平均化,内核将是对称的。什么最有效将取决于您的用例。

在堆栈溢出中,我们希望问题显示出相当大的工作量。在提问之前您尝试过什么?2D高斯滤波器是否满足您对圆形滤波器的定义?但圆对称滤波器并不能捕获输入中的所有变化,从而成为一个好的分类器。例如,我们在特征提取任务中使用了不同方向和尺度的gabor滤波器。您是否希望这可以像
tf.nn.conv2d
kernel\u初始值设定项那样使用?@siimphh抱歉,我不是Keras用户,所以我不知道什么有趣的想法。不过,我不太理解你关于两个有效卷积的评论,一个卷积的代价是一个卷积。根据我的经验,
reduce\u sum
导致
kernel
lr\u fliped\u kernel
变得相同(和对称),因为梯度对两者的传播方式相同。另一方面,
reduce_max
将学习检测一些不对称特征,其翻转的翻拍器将检测镜像版本,而
max
每次选择更活跃的一个。我希望这有意义?
def symmetric_convolution(input_tensor, n_filters, size, name, dilations=[1,1,1,1]):
    with tf.variable_scope("", reuse=tf.AUTO_REUSE):
        kernel = tf.get_variable(shape=[*size, input_tensor.shape[-1], n_filters], name='conv_kernel_' + name, ...)
        lr_flipped_kernel = tf.reverse(kernel, axis=[1], name='conv_kernel_flipped_lr_' + name)

    conv_l = tf.nn.conv2d(input=input_tensor, filter=kernel, strides=[1, 1, 1, 1], padding='SAME', dilations=dilations)
    conv_r = tf.nn.conv2d(input=input_tensor, filter=lr_flipped_kernel, strides=[1, 1, 1, 1], padding='SAME', dilations=dilations)

    return tf.reduce_max(tf.concat([conv_l, conv_r], axis=-1), keepdims=True, axis=[-1])