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

use*_*457 10 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'))
Run Code Online (Sandbox Code Playgroud)

Mat*_*gro 17

两者似乎都有效并不意味着他们也这样做.

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

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

  • GAP2D 的输出形状来自 `(n, h, w, c)` --> `(n, c)` (3认同)
  • @NicolasGervais 实际上不,它更复杂,我的答案是基于 2018 年的 Keras,你的答案是基于 tf.keras(我猜是从 2020 年开始),它们的行为不同。这并不意味着我的回答是错误的。 (2认同)

Nic*_*ais 11

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
Run Code Online (Sandbox Code Playgroud)
TensorShape([100, 2352])
Run Code Online (Sandbox Code Playgroud)

GlobalAveragePooling 层的作用

卷积运算后,tf.keras.layers.GlobalAveragePoolinglayer 会根据最后一个轴对所有值进行平均。这意味着生成的形状将为(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)
Run Code Online (Sandbox Code Playgroud)
(16, 24, 24, 64)
(16, 22, 22, 64)
(16, 20, 20, 64)
(16, 18, 18, 64)
(16, 16, 16, 64)

(16, 64)
Run Code Online (Sandbox Code Playgroud)

你应该使用哪个?

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


小智 9

扁平化是毫无意义的,它只是通过重新排列元素将多维对象转换为一维对象。

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

两者都是为了更简单的考虑排序的影响。


Mar*_*ani 7

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

我们使用一批具有这种形状的图像作为输入进行演示 (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')
Run Code Online (Sandbox Code Playgroud)
  • Flatten接受作为至少 3D 的输入张量。它使用这种格式在 2D 中对输入进行重塑(batch_dim, all the rest)。在我们的 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
    
    Run Code Online (Sandbox Code Playgroud)
  • 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
    
    Run Code Online (Sandbox Code Playgroud)