在keras中Flatten()和GlobalAveragePooling2D()之间有什么区别?

时间:2018-03-15 09:11:30

标签: keras keras-layer

我想将ConvLSTM和Conv2D的输出传递给Keras中的Dense Layer,使用全局平均池和flatten之间的区别是什么 两者都在我的情况下工作。

model.add(ConvLSTM2D(filters=256,kernel_size=(3,3)))
model.add(Flatten())
# or model.add(GlobalAveragePooling2D())
model.add(Dense(256,activation='relu'))

4 个答案:

答案 0 :(得分:12)

这两者似乎都起作用并不代表他们也这样做。

展平将采用任何形状的张量并将其转换为一维张量(加上样本维度),但将所有值保持在张量中。例如,张量(样本,10,20,1)将被展平为(样本,10 * 20 * 1)。

GlobalAveragePooling2D做了不同的事情。它在空间维度上应用平均池,直到每个空间维度为1,并保持其他维度不变。在这种情况下,值不会保持平均值。例如,张量(样本,10,20,1)将输出为(样本1,1,1),假设第二维和第三维是空间的(通道最后)。

答案 1 :(得分:6)

Flatten 层的作用

经过卷积运算后,tf.keras.layers.Flatten 会将张量重塑为 (n_samples, height*width*channels),例如将 (16, 28, 28, 3) 变成 (16, 2352)。我们来试试:

import tensorflow as tf

x = tf.random.uniform(shape=(100, 28, 28, 3), minval=0, maxval=256, dtype=tf.int32)

flat = tf.keras.layers.Flatten()

flat(x).shape
TensorShape([100, 2352])

GlobalAveragePooling 层的作用

经过卷积运算后,tf.keras.layers.GlobalAveragePooling 层会根据最后一个轴对所有值进行平均。这意味着生成的形状将为 (n_samples, last_axis)。例如,如果您的最后一个卷积层有 64 个过滤器,它会将 (16, 7, 7, 64) 变成 (16, 64)。经过一些卷积运算后,让我们进行测试:

import tensorflow as tf

x = tf.cast(
    tf.random.uniform(shape=(16, 28, 28, 3), minval=0, maxval=256, dtype=tf.int32),
    tf.float32)


gap = tf.keras.layers.GlobalAveragePooling2D()

for i in range(5):
    conv = tf.keras.layers.Conv2D(64, 3)
    x = conv(x)
    print(x.shape)

print(gap(x).shape)
(16, 24, 24, 64)
(16, 22, 22, 64)
(16, 20, 20, 64)
(16, 18, 18, 64)
(16, 16, 16, 64)

(16, 64)

你应该使用哪个?

Flatten 层将始终具有至少与 GlobalAveragePooling2D 层一样多的参数。如果展平前的最终张量形状仍然很大,例如 (16, 240, 240, 128),使用 Flatten 会产生大量参数:240*240*128 = 7,372,800。这个巨大的数字将乘以下一个密集层中的单元数!此时,在大多数情况下可能首选 GlobalAveragePooling2D。如果您使用 MaxPooling2DConv2D 以至于展平前的张量形状类似于 (16, 1, 1, 128),则不会有什么不同。如果您过度拟合,您可能想尝试 GlobalAveragePooling2D

答案 2 :(得分:3)

如果您更有信心,可以自己与numpy进行比较,测试 Flatten和GlobalPooling之间的差异

我们使用一批(batch_dim, height, width, n_channel)形状的图像作为输入进行演示。

import numpy as np
from tensorflow.keras.layers import *

batch_dim, H, W, n_channels = 32, 5, 5, 3
X = np.random.uniform(0,1, (batch_dim,H,W,n_channels)).astype('float32')
  • Flatten接受至少3D的输入张量。它使用(batch_dim, all the rest)格式以2D形式对输入进行整形。在我们的4D情况下,它以(batch_dim, H*W*n_channels)格式进行重塑。

    np_flatten = X.reshape(batch_dim, -1) # (batch_dim, H*W*n_channels)
    tf_flatten = Flatten()(X).numpy() # (batch_dim, H*W*n_channels)
    
    (tf_flatten == np_flatten).all() # True
    
  • GlobalAveragePooling2D接受4D张量作为输入。它对所有通道的高度和宽度尺寸进行均值运算。产生的尺寸为2D (batch_dim, n_channels)GlobalMaxPooling2D相同,但具有最大操作。

    np_GlobalAvgPool2D = X.mean(axis=(1,2)) # (batch_dim, n_channels)
    tf_GlobalAvgPool2D = GlobalAveragePooling2D()(X).numpy() # (batch_dim, n_channels)
    
    (tf_GlobalAvgPool2D == np_GlobalAvgPool2D).all() # True
    

答案 3 :(得分:0)

平移不再费心,它只是通过重新排列元素将多维对象转换为一维。

GlobalAveragePooling是一种用于更好地表示向量的方法。可以是1D / 2D / 3D。它使用一个解析器窗口,该窗口在对象上移动并通过对数据求平均值(GlobalAveragePooling)或选择最大值(GlobalMaxPooling)来合并数据。基本上需要填充,以考虑到极端情况。

这两种方法都是为了以更简单的方式考虑测序的效果。