我正在查看有关tf.nn.conv2d
的tensorflow文档here 。但我无法理解它的作用或它想要实现的目标。它在文档上说,
#1 : Flattens the filter to a 2-D matrix with shape
[filter_height * filter_width * in_channels, output_channels]
.
现在它有什么作用?是逐元素乘法还是简单的矩阵乘法?我也无法理解文档中提到的其他两点。我把它们写在下面:
# 2: Extracts image patches from the the input tensor to form a virtual tensor of shape
[batch, out_height, out_width, filter_height * filter_width * in_channels]
.# 3: For each patch, right-multiplies the filter matrix and the image patch vector.
如果有人能给出一个例子,一段代码(非常有帮助),并解释那里发生了什么以及为什么操作是这样的,那将非常有帮助。
我尝试编写一小部分代码并打印出操作的形状。不过还是看不懂。
我尝试过这样的事情:
op = tf.shape(tf.nn.conv2d(tf.random_normal([1,10,10,10]),
tf.random_normal([2,10,10,10]),
strides=[1, 2, 2, 1], padding='SAME'))
with tf.Session() as sess:
result = sess.run(op)
print(result)
我了解卷积神经网络的一些细节。我研究了它们here 。但在tensorflow上的实现并不是我所期望的。所以就提出了这个问题。
编辑: 因此,我实现了一个更简单的代码。但我不知道发生了什么事。我的意思是结果是这样的。如果有人能告诉我什么过程产生了这个输出,那将非常有帮助。
input = tf.Variable(tf.random_normal([1,2,2,1]))
filter = tf.Variable(tf.random_normal([1,1,1,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
print("input")
print(input.eval())
print("filter")
print(filter.eval())
print("result")
result = sess.run(op)
print(result)
输出
input
[[[[ 1.60314465]
[-0.55022103]]
[[ 0.00595062]
[-0.69889867]]]]
filter
[[[[-0.59594476]]]]
result
[[[[-0.95538563]
[ 0.32790133]]
[[-0.00354624]
[ 0.41650501]]]]
最佳答案
好吧,我认为这是解释这一切的最简单方法。
<小时/>您的示例是 1 张图像,大小为 2x2,具有 1 个 channel 。您有 1 个过滤器,尺寸为 1x1,以及 1 个 channel (尺寸为高度 x 宽度 x channel x 过滤器数量)。
对于这个简单的情况,生成的 2x2、1 channel 图像(大小 1x2x2x1、图像数量 x 高度 x 宽度 x x channel )是将滤镜值乘以图像的每个像素的结果。
<小时/>现在让我们尝试更多 channel :
input = tf.Variable(tf.random_normal([1,3,3,5]))
filter = tf.Variable(tf.random_normal([1,1,5,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
此处 3x3 图像和 1x1 滤波器各有 5 个 channel 。生成的图像将为 3x3、1 个 channel (大小为 1x3x3x1),其中每个像素的值是滤波器 channel 与输入图像中相应像素的点积。
<小时/>现在使用 3x3 过滤器
input = tf.Variable(tf.random_normal([1,3,3,5]))
filter = tf.Variable(tf.random_normal([3,3,5,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
这里我们得到一个 1x1 图像,具有 1 个 channel (大小 1x1x1x1)。该值是 9 个 5 元素点积的总和。但您可以将其称为 45 元素点积。
<小时/>现在有更大的图像
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
输出是 3x3 1 channel 图像(大小 1x3x3x1)。 每个值都是 9 个 5 元素点积的总和。
每个输出都是通过将滤镜集中在输入图像的 9 个中心像素之一上来实现的,这样滤镜就不会突出。下面的 x 代表每个输出像素的滤波器中心。
.....
.xxx.
.xxx.
.xxx.
.....
<小时/>
现在使用“相同”填充:
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
这给出了 5x5 的输出图像(大小 1x5x5x1)。这是通过将滤镜集中在图像上的每个位置来完成的。
过滤器超出图像边缘的任何 5 元素点积的值均为零。
所以角点只是 4、5 元素点积的总和。
<小时/>现在有多个过滤器。
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,7]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
这仍然给出 5x5 的输出图像,但有 7 个 channel (大小 1x5x5x7)。其中每个 channel 均由该组中的一个滤波器产生。
<小时/>现在步幅为 2,2:
input = tf.Variable(tf.random_normal([1,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,7]))
op = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
现在结果仍然有 7 个 channel ,但只有 3x3(大小 1x3x3x7)。
这是因为滤镜不是在图像上的每个点居中,而是在图像上的每隔一个点居中,步长为 2。x
的下面代表输入图像上每个输出像素的滤波器中心。
x.x.x
.....
x.x.x
.....
x.x.x
<小时/>
当然,输入的第一个维度是图像数量,因此您可以将其应用于一批 10 个图像,例如:
input = tf.Variable(tf.random_normal([10,5,5,5]))
filter = tf.Variable(tf.random_normal([3,3,5,7]))
op = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
这对每个图像独立执行相同的操作,给出一堆 10 个图像作为结果(大小 10x3x3x7)
关于neural-network - tf.nn.conv2d 在 tensorflow 中做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34619177/