繁体   English   中英

经过卷积步骤后,完全连接层中的张量的形状应该是什么?

[英]After going through convolution steps, what should be the shape of the tensor in fully connected layer?

因此,假设我有形状为[128,128,3] RGB图像,我想创建一个具有两个Conv-ReLu-MaxPool层的CNN,如下所示。

def cnn(input_data):

    #conv1
    conv1_weight = tf.Variable(tf.truncated_normal([4,4,3,25], stddev=0.1,),tf.float32)
    conv1_bias = tf.Variable(tf.zeros([25]), tf.float32)

    conv1 = tf.nn.conv2d(input_data, conv1_weight, [1,1,1,1], 'SAME')
    relu1 = tf.nn.relu(tf.nn.add(conv1, conv1_bias))
    max_pool1 = tf.nn.max_pool(relu1, [1,2,2,1], [1,1,1,1], 'SAME')

    #conv2
    conv2_weight = tf.Variable(tf.truncated_normal([4,4,25,50]),0.1,tf.float32)
    conv2_bias = tf.Variable(tf.zeros([50]), tf.float32)

    conv2 = tf.nn.conv2d(max_pool1, conv2_weight, [1,1,1,1], 'SAME')
    relu2 = tf.nn.relu(tf.nn.add(conv2, conv2_bias))
    max_pool2 = tf.nn.max_pool(relu2, [1,2,2,1], [1,1,1,1], 'SAME')

完成此步骤后,我需要将输出转换为下一个完全连接的层的1xN层。 但是,我不确定如何确定1xN中的N。 是否有特定的公式,包括图层大小,步幅,最大池大小,图像大小等? 尽管我认为我对CNN有了直觉,但我在问题的这一阶段非常失落。

我知道您想将来自最后一个卷积/合并层的多个2D特征图转换为可以馈入全连接层的向量。 为了精确起见并包括批处理尺寸,请从形状[batch, width, height, feature_maps]更改为[batch, N]

上面已经暗示N = batch * width * height因为重塑使元素的总数保持不变。 widthheight取决于输入的大小和网络层的步幅(卷积和/或池化)。
x的步幅只是将大小除以x 您在每个维度上都有大小为128的输入,并且具有两个跨步为2的合并层。因此,在第一个合并层之后,图像为64x64,第二个之后为32x32,因此width = height = 32 通常,我们也必须考虑填充,但SAME填充的要点恰恰是我们不必为此担心。
最后, feature_maps是50,因为这是最后一个卷积层具有的过滤器数量(池化不会对此进行修改)。 所以N = 32*32*50 = 51200

因此,您应该能够执行tf.reshape(max_pool2, [-1, 51200]) (或tf.reshape(max_pool2, [-1, 32*32*50])以使其更易于解释)并将结果馈入通过一个全连接层(即tf.matmul )的2D张量。

最简单的方法是只使用tf.layers.flatten(max_pool2) 此函数可以为您完成以上所有操作,并且只为您提供[batch, N]结果。

首先,因为您刚开始,所以我建议使用Keras而不是纯张量流。 并回答有关形状的问题,请参阅Andrej karpathy的此博客

引用博客:

我们可以根据输入体积大小(W),Conv层神经元的感受野大小(F),应用步幅(S)以及输出量的函数来计算输出体积的空间大小在边框上使用零填充(P)。 您可以说服自己,用于计算“适合”多少个神经元的正确公式由(WF + 2P)/ S + 1给出。 例如,对于一个7x7输入和一个3x3滤波器(步幅为1,填充为0),我们将获得5x5的输出。 跨度为2时,我们将获得3x3的输出。

现在进入您的tensorflow的实现:

对于conv1阶段,您提供了一个深度为25的4 * 4过滤器。由于对conv1和maxpooling1使用padding =“ SAME”,因此两种情况下的输出2D空间尺寸将与输入相同。 也就是说,在conv1之后,您的输出大小为:128 * 128 * 25。 出于同样的原因,maxpool1层的输出也相同。 由于第二个conv2的填充设置为“ SAME”,因此您的输出形状为128 * 128 * 50(您更改了输出通道)。 因此,在maxpool2之后,您的尺寸为:batch_size,128 * 128 * 50。 因此,在添加密集层之前,您有3个主要选择:

1)将张量展平为以下形状:batch_size,128 * 128 * 50

2)全局平均池结果为以下形状:batch_size,50

3)全局最大池也产生一个形状:batch_size,50。

注意:

全局平均池化层与平均池化相似,但是我们对整个要素图而不是窗口进行平均。 因此,名称为global。 例如:在您的情况下,您有batch_size,128,128,50作为尺寸。 这意味着您有50个具有128 * 128空间尺寸的要素图。 全局平均池的作用是将128 * 128特征图取平均值以给出一个数字。 因此,您总共将有50个值。 这对于设计完全卷积的体系结构(如初始,resnet等)非常有用。因为,这使网络的输入具有通用的含义,您可以将任何图像大小作为输入发送到网络。 全局最大池与上面非常相似,但略有不同是它找到了特征图的最大值而不是平均值。

该体系结构的问题:

通常,不建议在maxpooling层中使用padding =“ SAME”。 如果您看到vgg16的源代码,则将看到在每个块(conv relu和maxpooling)之后,输入大小减半。 因此,总体结构是在增加深度/通道的同时减小空间尺寸。

展平层:

var_name = tf.layers.flatten(max_pool2)

应该可行,几乎所有Tensorflow CNN示例都使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM