我在使用IMDB数据集训练Keras模型。对于包含LSTM层的这个模型,准确率大约为50%:
model = Sequential() model.add(Embedding(max_features, 32)) model.add(LSTM(32, return_sequences=True)) model.add(LSTM(32, return_sequences=True)) model.add(LSTM(32)) model.add(Dense(1, activation='sigmoid'))
准确率:
loss: 0.6933 - acc: 0.5007 - val_loss: 0.6932 - val_acc: 0.4947
我还尝试过使用单个LSTM层,但准确率也差不多。
然而,如果我不使用LSTM层,准确率可以达到约82%
model = models.Sequential()model.add(layers.Dense(16, kernel_regularizer=regularizers.l1(0.001), activation='relu', input_shape=(10000,)))model.add(layers.Dropout(0.5))model.add(layers.Dense(16, kernel_regularizer=regularizers.l1(0.001), activation='relu'))model.add(layers.Dropout(0.5))model.add(layers.Dense(1, activation='sigmoid'))
准确率:
loss: 0.6738 - acc: 0.8214 - val_loss: 0.6250 - val_acc: 0.8320
这是我编译和训练模型的方式:
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])model.fit(partial_x_train, partial_y_train, epochs=Numepochs, batch_size=Batchsize, validation_data=(x_val, y_val))
这如何解释?我以为LSTM在处理顺序文本数据时表现得很好?
回答:
不要忘记,LSTM用于处理序列数据,如时间序列或文本数据。在序列中,元素的顺序非常重要,如果你重新排列元素,那么整个序列的意义可能会完全改变。
现在,你的情况中的问题是,你使用的预处理步骤不适合LSTM模型。你将每个句子编码为一个向量,其中每个元素代表特定词语的存在或不存在。因此,你完全忽略了句子中词语出现的顺序,而这是LSTM层擅长建模的。基于你使用的预处理方案,你的LSTM模型还有另一个问题,即Embedding层接受的是词索引作为输入,而不是零和一的向量(即预处理阶段的输出)。
由于IMDB数据已经存储为词索引序列,要解决这个问题,你只需要通过只填充/截断序列来预处理IMDB数据,使其具有指定的长度,以便能够利用批处理。例如:
from keras.preprocessing.sequences import pad_sequencesvocab_size = 10000 # 只考虑最常见的10000个词(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size)x_train = pad_sequences(x_train, maxlen=500) # 截断或填充序列,使它们全部长度为500
现在,x_train
的形状将是(25000, 500)
,它由25000个长度为500的序列组成,编码为整数词索引。现在你可以通过将其传递给fit
方法来使用它进行训练。我猜你可以使用一个Embedding层和一个LSTM层达到至少80%的训练准确率。别忘了使用验证方案来监控过拟合(一个简单的选项是调用fit
方法时设置validation_split
参数)。