可分离的深度卷绕而不混合

时间:2018-03-27 21:43:09

标签: python tensorflow keras

我想做深度可分离卷积,也就是说,同一个滤波器一次作用于一个通道,而不混合结果,因此输入通道的数量必然等于输出通道的数量。这在Keras / Tensorflow中是否可行?

2 个答案:

答案 0 :(得分:1)

请注意,根据定义,深度可分离卷积会混合通道;你想要的东西有点不同。也就是说,在这里你将如何将相同的卷积应用于不同的通道,而不会在它们之间混合。

如果事先知道通道大小,可以使用tf.split沿通道维分割,对每个通道应用相同的卷积,然后将结果连接在一起。下面是两个方法,一个使用NAMED tf.layers.conv2d和一个变量范围来强制每个通道重用内核,另一个使用tf.nn.conv2d和一个声明的内核来实现相同的结果(通过简单地传递每次都使用相同的过滤器)。

您可以通过更改“过滤器”将其扩展到多个过滤器/频道。参数或内核的最后一个维度'变量,分别。但是,如果要将输出减少到每1个输入通道的1个输出通道,则需要跟进1x1卷积(与3x3卷积相同的设置,置于for循环内)。激活函数可以在for循环内部或外部应用,而输出没有任何差异。

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

def rescale(arr):
    #Quick method to fit output into plotting range
    arr=arr-np.min(arr,(0,1))
    return arr/np.max(arr,(0,1))

def main():
    channels=3
    feed=np.asarray(np.round(np.random.random((1,10,10,channels)),1),np.float32)
    #Feed of shape [batch,height,width,channels]

    individual_channels=tf.split(feed,channels,-1)
    print(individual_channels)

    #With variable scope and tf.layers.conv2d
    results=[]
    with tf.variable_scope('channel_conv',reuse=tf.AUTO_REUSE):
        for channel in individual_channels:
            #Change conv parameters, add bias, add activation, etc. as desired
            #NAME IS REQUIRED, OTHERWISE A DEFAULT WILL BE ASSIGNED WHICH DIFFERS BY CHANNEL
            #THIS NAME *MUST NOT VARY* THROUGHOUT THE LOOP OR NEW FILTERS WILL BE CREATED
            conv=tf.layers.conv2d(channel,filters=1,kernel_size=[3,3],padding='VALID',use_bias=False,name='conv')
            results.append(conv)

    output=tf.concat(results,-1)

    #With tf.nn.conv2d
    #kernel=tf.get_variable('var', (3,3,1,1),tf.float32)
    #Grabbing previous kernel to show equivalent results, commented out line is how you would create kernel otherwise
    kernel=tf.get_default_graph().get_tensor_by_name('channel_conv/conv2d/kernel:0')

    results=[]

    for channel in individual_channels:
        #Change conv parameters, add bias, add activation, etc. as desired
        conv=tf.nn.conv2d(channel,kernel,[1,1,1,1],'VALID')
        results.append(conv)

    output2=tf.concat(results,-1)

    #Demonstrate the same output from both methods
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        out,out2=sess.run((output[0],output2[0]))

        fig,axs=plt.subplots(2,1,True,True)
        axs[0].imshow(rescale(out))
        axs[1].imshow(rescale(out2))
        plt.show(fig)

答案 1 :(得分:-1)

看来tf.nn.depthwise_conv2dshown here应该是解决方案。