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

数据挖掘 Python 神经网络 深度学习 喀拉斯 超参数
2021-10-05 00:17:57

来自 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 基本相同。虽然结果意味着它没有学到任何东西。但是,当我使用 vanilla MLP-NN 时,我没有同样的问题,模型学习并且分数增加。我尝试增加 epoch 的数量并增加 - 减少 LTSM 单元的数量,但分数不会增加。

所以我想知道调整网络的标准方法,因为理论上该算法应该比专门针对这个时间序列数据的多层感知器网络执行得更好。

4个回答

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

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

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


顺便说一句,超参数通常使用随机搜索或贝叶斯优化进行调整。我会使用 RMSProp 并专注于调整批量大小(大小,如 32、64、128、256 和 512)、梯度裁剪(在 0.1-10 的区间内)和 dropout(在 0.1-0.6 的区间内)。具体细节当然取决于您的数据和模型架构。

我会推荐使用贝叶斯优化进行超参数搜索,并使用Spearmint取得了不错的效果。您可能必须将旧版本用于商业用途。

我建议使用hyperopt,它使用一种贝叶斯优化来搜索给定目标函数的超参数的最佳值。它比 Spearmint 使用起来更直观。

PS:有一个 hyperopt 的包装器,专门用于 keras,hyperas你也可以使用它。

Talos正是您正在寻找的;用于搜索 Keras 模型的超参数组合的自动化解决方案。作为作者,我可能并不客观,但其目的是提供一种学习曲线尽可能低的替代方案,同时完全公开 Keras 的功能。

或者,正如已经提到的,您可以查看Hyperas,或者SKlearnAutoKeras据我所知,在撰写本文时,这 4 个是专门针对 Keras 用户的选项。