tf.nn.conv2d() 对输入张量形状的影响是什么?

what is the effect of tf.nn.conv2d() on an input tensor shape?

我正在专门研究 Dandelion Mane 的 tensorboard 代码:https://github.com/dandelionmane/tf-dev-summit-tensorboard-tutorial/blob/master/mnist.py

他的卷积层具体定义为:

def conv_layer(input, size_in, size_out, name="conv"):
  with tf.name_scope(name):
    w = tf.Variable(tf.truncated_normal([5, 5, size_in, size_out], stddev=0.1), name="W")
    b = tf.Variable(tf.constant(0.1, shape=[size_out]), name="B")
    conv = tf.nn.conv2d(input, w, strides=[1, 1, 1, 1], padding="SAME")
    act = tf.nn.relu(conv + b)
    tf.summary.histogram("weights", w)
    tf.summary.histogram("biases", b)
    tf.summary.histogram("activations", act)
    return tf.nn.max_pool(act, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

我正在尝试找出 conv2d 对输入张量大小的影响。据我所知,前 3 个维度似乎没有变化,但输出的最后一个维度遵循 w.

最后一个维度的大小

例如,?x47x36x64 输入变为 ?x47x36x128,w shape=5x5x64x128

而且我还看到: ?x24x18x128 变成了 ?x24x18x256 w shape=5x5x128x256

那么,输入的结果大小是:[a,b,c,d] [a,b,c,w.shape[3]] 的输出大小吗?

第一个维度不变的想法对吗?

这适用于您的情况,因为使用了步幅和应用了填充。输出宽度和高度不会总是与输入相同。

查看this excellent discussion的话题。基本要点(几乎是从 link 中逐字记录的)是一个卷积层:

  • 接受大小为 W1 x H1 x D1
  • 的输入量
  • 需要四个超参数:
    • 过滤器数量K
    • 过滤器的空间范围F
    • 过滤器移动的步幅S
    • 零填充量P
  • 生成大小为 W2 x H2 x D2 的卷,其中:
    • W2 = (W1 - F + 2*P)/S + 1
    • H2 = (H1 - F + 2*P)/S + 1
    • D2 = K

当您在 Tensorflow 中处理数据批次时,它们通常具有 [batch_size, width, height, depth] 的形状,因此第一个维度,即批次中的样本数量不应改变。

请注意,上面的填充量 P 对于 TF 来说有点棘手。当您将 padding='same' 参数提供给 tf.nn.conv2d 时,tensorflow 会对图像的两侧应用零填充以确保您的过滤器不会忽略图像的任何像素,但它可能不会添加相同的数量两侧的填充(我认为只能相差一个)。 对该主题进行了一些很好的讨论。

一般来说,步长 S 为 1(您的网络有),P = (F - 1) / 2 的零填充将确保输出 width/height 等于输入,即 W2 = W1H2 = H1。在您的情况下,F 是 5,因此 tf.nn.conv2d 必须在图像的每一侧添加两个零,使 P 为 2,根据上述等式,您的输出宽度是 W2 = (W1 - 5 + 2*2)/1 + 1 = W1 - 1 + 1 = W1.