这个展平层在我的 LSTM 中做什么?

What is this flatten layer doing in my LSTM?

我正在使用 Keras 创建一个 LSTM,用于使用 IMDB 数据库(的一个子集)进行情感分析。如果我在最后的密集层之前添加一个展平层,我的训练、验证和测试准确性会显着提高:

def lstm_model_flatten():
    embedding_dim = 128
    model = Sequential()
    model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
    model.add(layers.LSTM(128, return_sequences = True,  dropout=0.2)) 
    # Flatten layer
    model.add(layers.Flatten())
    model.add(layers.Dense(1,activation='sigmoid'))
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    model.summary()
    return model

过拟合很快,但验证准确率高达 76% 左右:

Model: "sequential_43"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_42 (Embedding)     (None, 500, 128)          4768256   
_________________________________________________________________
lstm_63 (LSTM)               (None, 500, 128)          131584    
_________________________________________________________________
flatten_10 (Flatten)         (None, 64000)             0         
_________________________________________________________________
dense_40 (Dense)             (None, 1)                 64001     
=================================================================
Total params: 4,963,841
Trainable params: 4,963,841
Non-trainable params: 0
_________________________________________________________________
Epoch 1/7
14/14 [==============================] - 26s 2s/step - loss: 0.6911 - accuracy: 0.5290 - val_loss: 0.6802 - val_accuracy: 0.5650
Epoch 2/7
14/14 [==============================] - 23s 2s/step - loss: 0.6451 - accuracy: 0.6783 - val_loss: 0.6074 - val_accuracy: 0.6950
Epoch 3/7
14/14 [==============================] - 23s 2s/step - loss: 0.4594 - accuracy: 0.7910 - val_loss: 0.5237 - val_accuracy: 0.7300
Epoch 4/7
14/14 [==============================] - 23s 2s/step - loss: 0.2566 - accuracy: 0.9149 - val_loss: 0.4753 - val_accuracy: 0.7650
Epoch 5/7
14/14 [==============================] - 23s 2s/step - loss: 0.1397 - accuracy: 0.9566 - val_loss: 0.6011 - val_accuracy: 0.8050
Epoch 6/7
14/14 [==============================] - 23s 2s/step - loss: 0.0348 - accuracy: 0.9898 - val_loss: 0.7648 - val_accuracy: 0.8100
Epoch 7/7
14/14 [==============================] - 23s 2s/step - loss: 0.0136 - accuracy: 0.9955 - val_loss: 0.8829 - val_accuracy: 0.8150

使用没有展平层的相同架构(并在 LSTM 层上使用 return_sequences = False)仅产生大约 50% 的验证准确率。

的评论建议在dense layer之前使用return_sequences = False,而不是flatten layer

但为什么会这样呢?如果可以改进我的模型,可以使用展平层吗? flatten layer 到底在做什么,为什么会提高精度?

LSTM 层由按顺序处理的不同 LSTM 单元组成。如下图所示,第一个单元格采用 input/embedding 计算隐藏状态,下一个单元格使用其输入和前一时间步的隐藏状态来计算自己的隐藏状态。基本上,单元格之间的箭头也传递隐藏状态。 如果return_sequences=False,lstm层只输出最后一个隐藏状态!(图中h_4)。 因此,来自所有输入和单元格的所有这些信息都嵌入在一个固定大小的信息中,它不能包含很多信息。这就是为什么,当你只使用最后一个隐藏状态。

当您执行 return_sequences=True 时,lstm 层输出每个隐藏状态,因此下一层可以访问所有隐藏状态,它们自然包含更多信息。然而,LSTM 层 returns 一个矩阵。您还可以在模型摘要中看到这一点。它 returns 大小为 (None, 500, 128) 的矩阵。 None 基本上是你批次中的样本数,你可以忽略它。 500 是您的输入大小,128 是您的隐藏状态大小。密集层不能处理矩阵,它必须是向量。这就是为什么您需要应用 flatten 的原因,它所做的基本上只是打开 2D 矩阵并将其表示为 1D 向量。因此,Flatten 层的大小为 64000,因为 500*128 = 64000。当然,隐藏状态越多,准确度就越高,因为它们包含的信息越多。