Tensorflow:tf.nn.separable_conv2d 是做什么的?
Tensorflow: What does tf.nn.separable_conv2d do?
我不太确定 tf.nn.separable_conv2d 的具体作用。似乎pointwise_filter是生成下一层的一个像素时不同特征的缩放因子。但我不确定我的解释是否正确。这种方法有什么参考吗?有什么好处?
tf.nn.separable_conv2d 生成与 tf.nn.conv2d 相同的形状。我假设我可以用 tf.nn.separable_conv2d 替换 tf.nn.conv2d。但是使用 tf.nn.separable_conv2d 时的结果似乎很糟糕。网络很早就停止了学习。对于 MNIST 数据集,准确率只是随机猜测 ~ 10%。
我想当我将 pointwise_filter 值设置为全部 1.0 并使其不可训练时,我会得到与 tf.nn.conv2d 相同的结果。但不是真的......仍然有 ~10% 的准确率。
但是当tf.nn.conv2d使用相同的超参数时,准确率可以达到99%。为什么?
此外,它需要 channel_multiplier * in_channels < out_channels。为什么?这里channel_multiplier的作用是什么?
谢谢。
编辑:
我以前使用 channel_multiplier 作为 1.0。也许这是一个糟糕的选择。我把它改成2.0后,精度就好多了。但是channel_multiplier的作用是什么?为什么 1.0 不是一个好的值?
tf.nn.separable_conv2d()
实现了 slide 26 and onwards of this talk 中描述的所谓 'separable convolution'。
这个想法是,不是在图像的所有通道上联合卷积,而是在每个通道上 运行 深度为 channel_multiplier
的单独 2D 卷积。 in_channels * channel_multiplier
中间通道连接在一起,并使用 1x1 卷积映射到 out_channels
。
这通常是降低卷积网络中早期卷积的参数复杂性的有效方法,并且可以显着加快训练速度。 channel_multiplier
控制复杂度,对于 RGB 输入通常为 4 到 8。对于灰度输入,使用它意义不大。
回答问题的最后一部分:
Also, it requires channel_multiplier * in_channels < out_channels. Why?
不知道当初为什么要加这个约束,现在TF的master分支已经去掉了,应该会到1.3版本。想法可能与 "If you are reducing the reducing the number of channels in the pointwise step, you might have as well picked a smaller channel multiplier and saved on computation" 类似。我想这个推理是有缺陷的,因为逐点步骤可以组合来自不同 depthwise_filters 的值,或者可能是因为人们可能想稍微减少维度,而不是减少一个完整因子。
在对多个输入通道执行的常规 2D 卷积中,过滤器与输入一样深,让我们可以自由混合通道以生成输出中的每个元素。 Depthwise convolutions 不这样做——每个通道都是分开的——因此得名 depthwise。这是一张图表,可帮助解释其工作原理[1]:
如果您查看官方文档,您会发现:
output[b, i, j, k] = sum_{di, dj, q, r}
input[b, strides[1] * i + di, strides[2] * j + dj, q] *
depthwise_filter[di, dj, q, r] *
pointwise_filter[0, 0, q * channel_multiplier + r, k]
以及tensorflow中的示例代码进行测试:
import tensorflow as tf
import numpy as np
width = 8
height = 8
batch_size = 100
filter_height = 3
filter_width = 3
in_channels = 3
channel_multiplier = 1
out_channels = 3
input_tensor = tf.get_variable(shape=(batch_size, height, width, in_channels), name="input")
depthwise_filter = tf.get_variable(shape=(filter_height, filter_width, in_channels, channel_multiplier), name="deptwise_filter")
pointwise_filter = tf.get_variable(shape=[1, 1, channel_multiplier * in_channels, out_channels], name="pointwise_filter")
output = tf.nn.separable_conv2d(
input_tensor,
depthwise_filter,
pointwise_filter,
strides=[1,1,1,1],
padding='SAME',
)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
output_value = sess.run(output, feed_dict={input_tensor: np.random.rand(batch_size, width, height, in_channels),
depthwise_filter: np.random.rand(filter_height, filter_width, in_channels, channel_multiplier),
pointwise_filter: np.random.rand(1, 1, channel_multiplier * in_channels, out_channels)})
print(np.shape(output_value))
信用:
[1] https://eli.thegreenplace.net/2018/depthwise-separable-convolutions-for-machine-learning/
[2]https://www.tensorflow.org/api_docs/python/tf/nn/separable_conv2d
我不太确定 tf.nn.separable_conv2d 的具体作用。似乎pointwise_filter是生成下一层的一个像素时不同特征的缩放因子。但我不确定我的解释是否正确。这种方法有什么参考吗?有什么好处?
tf.nn.separable_conv2d 生成与 tf.nn.conv2d 相同的形状。我假设我可以用 tf.nn.separable_conv2d 替换 tf.nn.conv2d。但是使用 tf.nn.separable_conv2d 时的结果似乎很糟糕。网络很早就停止了学习。对于 MNIST 数据集,准确率只是随机猜测 ~ 10%。
我想当我将 pointwise_filter 值设置为全部 1.0 并使其不可训练时,我会得到与 tf.nn.conv2d 相同的结果。但不是真的......仍然有 ~10% 的准确率。
但是当tf.nn.conv2d使用相同的超参数时,准确率可以达到99%。为什么?
此外,它需要 channel_multiplier * in_channels < out_channels。为什么?这里channel_multiplier的作用是什么?
谢谢。
编辑:
我以前使用 channel_multiplier 作为 1.0。也许这是一个糟糕的选择。我把它改成2.0后,精度就好多了。但是channel_multiplier的作用是什么?为什么 1.0 不是一个好的值?
tf.nn.separable_conv2d()
实现了 slide 26 and onwards of this talk 中描述的所谓 'separable convolution'。
这个想法是,不是在图像的所有通道上联合卷积,而是在每个通道上 运行 深度为 channel_multiplier
的单独 2D 卷积。 in_channels * channel_multiplier
中间通道连接在一起,并使用 1x1 卷积映射到 out_channels
。
这通常是降低卷积网络中早期卷积的参数复杂性的有效方法,并且可以显着加快训练速度。 channel_multiplier
控制复杂度,对于 RGB 输入通常为 4 到 8。对于灰度输入,使用它意义不大。
回答问题的最后一部分:
Also, it requires channel_multiplier * in_channels < out_channels. Why?
不知道当初为什么要加这个约束,现在TF的master分支已经去掉了,应该会到1.3版本。想法可能与 "If you are reducing the reducing the number of channels in the pointwise step, you might have as well picked a smaller channel multiplier and saved on computation" 类似。我想这个推理是有缺陷的,因为逐点步骤可以组合来自不同 depthwise_filters 的值,或者可能是因为人们可能想稍微减少维度,而不是减少一个完整因子。
在对多个输入通道执行的常规 2D 卷积中,过滤器与输入一样深,让我们可以自由混合通道以生成输出中的每个元素。 Depthwise convolutions 不这样做——每个通道都是分开的——因此得名 depthwise。这是一张图表,可帮助解释其工作原理[1]:
如果您查看官方文档,您会发现:
output[b, i, j, k] = sum_{di, dj, q, r}
input[b, strides[1] * i + di, strides[2] * j + dj, q] *
depthwise_filter[di, dj, q, r] *
pointwise_filter[0, 0, q * channel_multiplier + r, k]
以及tensorflow中的示例代码进行测试:
import tensorflow as tf
import numpy as np
width = 8
height = 8
batch_size = 100
filter_height = 3
filter_width = 3
in_channels = 3
channel_multiplier = 1
out_channels = 3
input_tensor = tf.get_variable(shape=(batch_size, height, width, in_channels), name="input")
depthwise_filter = tf.get_variable(shape=(filter_height, filter_width, in_channels, channel_multiplier), name="deptwise_filter")
pointwise_filter = tf.get_variable(shape=[1, 1, channel_multiplier * in_channels, out_channels], name="pointwise_filter")
output = tf.nn.separable_conv2d(
input_tensor,
depthwise_filter,
pointwise_filter,
strides=[1,1,1,1],
padding='SAME',
)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
output_value = sess.run(output, feed_dict={input_tensor: np.random.rand(batch_size, width, height, in_channels),
depthwise_filter: np.random.rand(filter_height, filter_width, in_channels, channel_multiplier),
pointwise_filter: np.random.rand(1, 1, channel_multiplier * in_channels, out_channels)})
print(np.shape(output_value))
信用:
[1] https://eli.thegreenplace.net/2018/depthwise-separable-convolutions-for-machine-learning/
[2]https://www.tensorflow.org/api_docs/python/tf/nn/separable_conv2d