我想做深度可分离卷积,也就是说,同一个滤波器一次作用于一个通道,而不混合结果,因此输入通道的数量必然等于输出通道的数量。这在Keras / Tensorflow中是否可行?
答案 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_conv2d
和shown here应该是解决方案。