Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 经过卷积步骤后,全连通层中张量的形状应该是什么?_Python_Tensorflow_Neural Network_Conv Neural Network - Fatal编程技术网

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

Python 经过卷积步骤后,全连通层中张量的形状应该是什么?,python,tensorflow,neural-network,conv-neural-network,Python,Tensorflow,Neural Network,Conv Neural Network,因此,让我们假设我有形状为[128128,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)

因此,让我们假设我有形状为
[128128,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特征映射转换为一个向量,该向量可以馈送到完全连接的层中。或者精确地说,包括批次尺寸,从形状
[批次、宽度、高度、特征映射]
[批次,N]

上面已经暗示了
N=batch*width*height
,因为重塑使元素总数保持不变<代码>宽度和高度取决于输入的大小和网络层的跨步(卷积和/或池)。
x
的跨步只是将大小除以
x
。在每个维度中都有大小为128的输入,以及两个跨步为2的池层。因此,在第一个池层之后,图像是64x64,在第二个池层之后是32x32,因此
width=height=32
。通常情况下,我们也必须考虑填充,但
相同的
填充的要点正是我们不必担心这一点。
最后,
feature\u maps
是50,因为这是您的上一个卷积层拥有的过滤器数量(池不会修改这一点)。所以
N=32*32*50=51200

因此,您应该能够执行
tf.reforme(max_pool2,[-151200])
(或者
tf.reforme(max_pool2,[-1,32*32*50])
,以使其更易于解释)并通过完全连接的层(即
tf.matmul
)提供生成的二维张量

最简单的方法就是使用
tf.layers.flatten(max\u pool2)
。此函数为您完成上述所有操作,并仅为您提供
[批处理,N]
结果。

展平层:

var_name = tf.layers.flatten(max_pool2)

这应该行得通,而且几乎每个Tensorflow CNN的例子都是这样使用的。

首先,既然你刚开始工作,我推荐Keras而不是纯Tensorflow。要回答您关于形状的问题,请参阅Andrej karpathy的文章

引自博客: 我们可以计算输出体积的空间大小,作为输入体积大小(W)、Conv层神经元的感受野大小(F)、应用它们的步幅(S)以及边界上使用的零填充量(p)的函数。你可以说服自己,计算多少神经元“适合”的正确公式是(W−F+2P)/S+1。例如,对于7x7输入和3x3滤波器,步幅为1,键盘为0,我们将得到5x5输出。使用stride 2,我们将获得3x3输出。

现在来看tensorflow的实现: 对于conv1阶段,您提供了深度为25的4*4过滤器。由于您对conv1和maxpoolg1使用了padding=“SAME”,因此在这两种情况下,您的输出二维空间尺寸将与输入相同。也就是说,在conv1之后,您的输出大小是:128*128*25。出于同样的原因,maxpool1层的输出也是相同的。由于第二次conv2的填充是“相同”的,所以输出形状也是128*128*50(您更改了输出通道)。因此,在maxpool2之后,您的维度是:批次大小,128*128*50。因此,在添加致密层之前,您有3个主要选项:

1) 将张量展平,得到一个形状:批量大小,128*128*50

2) 全局平均池结果的形状为:批量大小,50

3) 全局最大池也会产生一个形状:批量大小,50

注: 全局平均池层类似于平均池,但我们平均整个特征映射,而不是窗口。因此被称为全球。例如:在您的情况下,批量大小为128128,50。这意味着您有50个空间尺寸为128*128的要素地图。全球平均池的作用是 对128*128要素图求平均值以给出单个数字。因此,总共有50个值。这在设计完全卷积的体系结构(如inception、resnet等)时非常有用。因为这使网络的输入变得通用,这意味着您可以将任意大小的图像作为输入发送到网络。全局最大池与上面的非常相似,但稍有不同的是它找到的是特征映射的最大值,而不是平均值

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

这是值得一提的。谢谢然而,我对池的部分感到困惑。如果我选择保持填充
不变
,它不是通过添加零来保持输出的形状吗?或者您的回答是假设我们不使用相同的
选项?在计算
N
时,使用和不使用
相同的
填充有什么区别?填充在跨步之前适用。如果没有填充(也称为“有效”填充),大小为n(一维)的图像和大小为k的过滤器将生成大小为n-k+1的输出。“相同”填充将k-1零添加到图像中,以便结果的大小为n(n-k+1+k-1)。如果您使用的是跨步(如在最大池层中),这仍然会将输出大小减少一倍(在您的情况下为2)。步幅+“相同”填充只是意味着输出大小是n/2而不是(n-k+1)/2。我也很好奇,