我试图了解Keras中Flatten
函数的作用。下面是我的代码,这是一个简单的双层网络。它接收形状(3,2)的二维数据,并输出形状(1,4)的1维数据:
model = Sequential()
model.add(Dense(16, input_shape=(3, 2)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(4))
model.compile(loss='mean_squared_error', optimizer='SGD')
x = np.array([[[1, 2], [3, 4], [5, 6]]])
y = model.predict(x)
print y.shape
这打印出y
具有形状(1,4)。但是,如果我删除Flatten
行,则打印出y
具有形状(1,3,4)。
我不明白这一点。根据我对神经网络的理解,model.add(Dense(16, input_shape=(3, 2)))
函数创建了一个隐藏的完全连接层,有16个节点。这些节点中的每一个都连接到3x2输入元件中的每一个。因此,该第一层输出处的16个节点已经“平坦”。因此,第一层的输出形状应为(1,16)。然后,第二层将其作为输入,并输出形状(1,4)的数据。
因此,如果第一层的输出已经“平坦”并且形状(1,16),为什么我需要进一步展平它呢?
谢谢!
答案 0 :(得分:77)
如果您在此处阅读Dense
的文档,您会看到:
Dense(16, input_shape=(5,3))
将导致Dense
网络具有3个输入和16个输出,这些输入将分别针对5个步骤中的每个步骤应用。因此,如果D(x)
将3维向量转换为16维向量,那么从图层输出的结果将是一系列向量:[D(x[0,:], D(x[1,:],..., D(x[4,:]]
,其形状为(5, 16)
。为了获得您指定的行为,您可以先Flatten
输入15-d向量,然后应用Dense
:
model = Sequential()
model.add(Flatten(input_shape=(3, 2)))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(4))
model.compile(loss='mean_squared_error', optimizer='SGD')
修改强> 有些人很难理解 - 在这里你有一个解释图像:
答案 1 :(得分:9)
简短阅读:
使张量平整是指除去一个尺寸之外的所有尺寸。这正是Flatten层所做的。
长读:
如果我们考虑考虑创建的原始模型(具有Flatten层),则可以得到以下模型摘要:
Layer (type) Output Shape Param #
=================================================================
D16 (Dense) (None, 3, 16) 48
_________________________________________________________________
A (Activation) (None, 3, 16) 0
_________________________________________________________________
F (Flatten) (None, 48) 0
_________________________________________________________________
D4 (Dense) (None, 4) 196
=================================================================
Total params: 244
Trainable params: 244
Non-trainable params: 0
对于此摘要,下一张图像有望对每一层的输入和输出大小提供更多的了解。
您可以读取的Flatten层的输出形状为(None,48)。这里是提示。实际上,您应该阅读它(1,48)。它是1级数组。
当Tensorflow在图形构建期间无法推断形状时,会将尺寸值设置为“无”,但我们知道它是1。
在Keras中 Flatten层strong>的作用非常简单:
对张量进行展平操作会将张量整形为具有等于张量中包含的元素数量的形状。这与一维元素数组相同。
根据您的情况,它会将尺寸缩小为一个原始尺寸:(1,48)
现在让我们检查一下删除Flatten层的第二种情况:
Layer (type) Output Shape Param #
=================================================================
D16 (Dense) (None, 3, 16) 48
_________________________________________________________________
A (Activation) (None, 3, 16) 0
_________________________________________________________________
D4 (Dense) (None, 3, 4) 68
=================================================================
Total params: 116
Trainable params: 116
Non-trainable params: 0
没有Flatten层,将不会减少尺寸,并且不会输入数组:
x = np.array([[[1, 2], [3, 4], [5, 6]]])
形状为(1,3,2)的将输出形状为(1、3、4)的y
。
注意:我使用了model.summary()
方法来提供输出形状和参数的详细信息。
答案 2 :(得分:2)
根据经验,您网络中的第一层应该与您的数据具有相同的形状。例如,我们的数据是 28x28 的图像,28 个神经元的 28 层是不可行的,因此将 28,28 '展平'为 784x1 更有意义。我们不是自己编写所有代码来处理它,而是在开始时添加 Flatten() 层,当数组稍后加载到模型中时,它们会自动为我们展平。
答案 3 :(得分:1)
答案 4 :(得分:1)
我最近遇到了这个问题,它无疑帮助我理解了:https://www.cs.ryerson.ca/~aharley/vis/conv/
因此,有一个输入,Conv2D,MaxPooling2D等,Flatten层位于最后,并准确显示它们的形成方式以及如何定义最终分类(0-9)。
答案 5 :(得分:0)
Flatten明确说明如何序列化多维张量(通常是输入张量)。这允许在(拉平的)输入张量和第一隐藏层之间进行映射。如果第一个隐藏层是“致密的”,则(序列化)输入张量的每个元素都将与隐藏数组的每个元素连接。 如果不使用Flatten,则输入张量映射到第一个隐藏层的方式将是模棱两可的。
答案 6 :(得分:0)
在这里,我想提出Flatten函数的另一种选择。这可能有助于了解内部情况。替代方法增加了三行代码。 代替使用
#==========================================Build a Model
model = tf.keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=(28, 28, 3)))#reshapes to (2352)=28x28x3
model.add(layers.experimental.preprocessing.Rescaling(1./255))#normalize
model.add(keras.layers.Dense(128,activation=tf.nn.relu))
model.add(keras.layers.Dense(2,activation=tf.nn.softmax))
model.build()
model.summary()# summary of the model
我们可以使用
#==========================================Build a Model
tensor = tf.keras.backend.placeholder(dtype=tf.float32, shape=(None, 28, 28, 3))
model = tf.keras.models.Sequential()
model.add(keras.layers.InputLayer(input_tensor=tensor))
model.add(keras.layers.Reshape([2352]))
model.add(layers.experimental.preprocessing.Rescaling(1./255))#normalize
model.add(keras.layers.Dense(128,activation=tf.nn.relu))
model.add(keras.layers.Dense(2,activation=tf.nn.softmax))
model.build()
model.summary()# summary of the model
在第二种情况下,我们首先创建一个张量(使用占位符) 然后创建一个输入层。之后,我们将张量整形为平坦形式。所以基本上,
Create tensor->Create InputLayer->Reshape == Flatten
Flatten是一项便捷功能,可以自动执行所有操作。当然,这两种方式都有其特定的用例。 Keras提供了足够的灵活性来操纵您想要创建模型的方式。