使用Keras(Python)进行LSTM-RNN的超参数搜索


18

来自Keras RNN教程的文章: RNN 很棘手。批大小的选择很重要,损耗和优化器的选择很重要,等等。某些配置无法融合。”

因此,这是关于在Keras上调整LSTM-RNN的超参数的一个普遍问题。我想知道一种为您的RNN查找最佳参数的方法。

我从Keras'Github上的IMDB示例开始。

主要模型如下:

(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features,
                                                      test_split=0.2)

max_features = 20000
maxlen = 100  # cut texts after this number of words (among top max_features most common words)
batch_size = 32

model = Sequential()
model.add(Embedding(max_features, 128, input_length=maxlen))
model.add(LSTM(128))  
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

# try using different optimizers and different optimizer configs
model.compile(loss='binary_crossentropy',
          optimizer='adam',
          class_mode="binary")

print("Train...")
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=3,
      validation_data=(X_test, y_test), show_accuracy=True)
score, acc = model.evaluate(X_test, y_test,
                        batch_size=batch_size,
                        show_accuracy=True)

print('Test accuracy:', acc)
Test accuracy:81.54321846

81.5是一个不错的成绩,更重要的是,它表明该模型即使没有完全优化也可以运行。

我的数据是时间序列,任务是二进制预测,与示例相同。现在我的问题看起来像这样:

#Training Data
train = genfromtxt(os.getcwd() + "/Data/trainMatrix.csv", delimiter=',', skip_header=1)
validation = genfromtxt(os.getcwd() + "/Data/validationMatrix.csv", delimiter=',', skip_header=1)

#Targets
miniTrainTargets = [int(x) for x in genfromtxt(os.getcwd() + "/Data/trainTarget.csv", delimiter=',', skip_header=1)]
validationTargets = [int(x) for x in genfromtxt(os.getcwd() + "/Data/validationTarget.csv", delimiter=',', skip_header=1)]

#LSTM
model = Sequential()
model.add(Embedding(train.shape[0], 64, input_length=train.shape[1]))
model.add(LSTM(64)) 
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

# try using different optimizers and different optimizer configs
model.compile(loss='binary_crossentropy',
          optimizer='adam',
          class_mode="binary")

model.fit(train, miniTrainTargets, batch_size=batch_size, nb_epoch=5,
      validation_data=(validation, validationTargets), show_accuracy=True)
valid_preds = model.predict_proba(validation, verbose=0)
roc = metrics.roc_auc_score(validationTargets, valid_preds)
print("ROC:", roc)
ROC:0.5006526

该模型与IMDB基本相同。尽管结果表明它没有学到任何东西。但是,当我使用普通的MLP-NN时,我不会遇到相同的问题,该模型会学习并且分数会增加。我尝试增加时期数并增加或减少LTSM单位的数量,但分数不会增加。

因此,我想知道一种用于调整网络的标准方法,因为从理论上讲,该算法应比专门针对此时间序列数据的多层感知器网络性能更好。


1
您有多少数据?您的序列长度是多少?LSTM仅对于具有大量数据和长期依赖性的问题非常有用。
pir

随机搜索或贝叶斯优化是查找超参数的标准方法:)
pir

1
您确定需要嵌入层吗?许多时间序列数据集将不需要它。
pir

我有近10万个数据点,功能是IMDB示例的两倍,所以我认为这不是问题。至于嵌入层,您如何将LSTM层准确地连接到输入?根据文档keras.io/layers/recurrent/#lstm,Keras的LSTM仅将初始化,激活和output_dim作为参数。如果这是错误的根源,将非常感谢您描述如何消除嵌入层的代码。
wacax

请看我的回答。看来您不需要嵌入层。
pir

Answers:


5

嵌入层将正整数(索引)转换为固定大小的密集向量。例如,[[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]。表示转换是通过Keras中的嵌入层自动学习的(请参阅文档)。

但是,您的数据似乎不需要任何此类嵌入层即可执行转换。拥有不必要的嵌入层可能是为什么您无法使LSTM正常工作的原因。如果是这种情况,那么您应该简单地删除嵌入层。

然后,网络中的第一层应在input_shape参数上添加有关数据维度的信息(请参阅示例)。请注意,您可以将此参数添加到任何层-它不会出现在文档中任何特定层。


顺便说一下,通常使用随机搜索或贝叶斯优化来调整超参数。我将使用RMSProp并专注于调整批处理大小(大小分别为32、64、128、256和512),渐变剪切(间隔为0.1-10)和辍学(间隔为0.1-0.6)。当然,具体细节取决于您的数据和模型架构。


您打算用什么来替换嵌入层?我试着简单地删除嵌入层,但这不起作用。
wacax

1
查看其他示例-例如直接从Dense层开始。记住要设置input_shape参数。
pir



2

塔罗斯正是您要找的东西;用于搜索Keras模型的超参数组合的自动化解决方案。我可能不是客观的,因为我是作者,但其目的是在完全暴露Keras功能的同时,提供尽可能低的学习曲线的替代方案。

另外,如前所述,您可以研究Hyperas,或者SKlearnAutoKeras。据我所知,在撰写本文时,这4个是Keras用户的专用选项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.