Recherche hyperparamétrique pour LSTM-RNN à l'aide de Keras (Python)

18

De Keras RNN Tutorial: "Les RNN sont difficiles. Le choix de la taille des lots est important, le choix de la perte et de l'optimiseur est critique, etc. Certaines configurations ne convergent pas."

Il s'agit donc plus d'une question générale sur le réglage des hyperparamètres d'un LSTM-RNN sur Keras. Je voudrais connaître une approche pour trouver les meilleurs paramètres pour votre RNN.

J'ai commencé avec l' exemple IMDB sur le Github de Keras .

le modèle principal ressemble à ceci:

(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 est un bon score et plus important encore, cela signifie que le modèle, même s'il n'est pas entièrement optimisé, fonctionne.

Mes données sont des séries temporelles et la tâche est une prédiction binaire, la même que l'exemple. Et maintenant mon problème ressemble à ceci:

#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

Le modèle est fondamentalement le même que celui de l'IMDB. Bien que le résultat signifie qu'il n'apprend rien. Cependant, lorsque j'utilise un MLP-NN vanille, je n'ai pas le même problème, le modèle apprend et le score augmente. J'ai essayé d'augmenter le nombre d'époques et d'augmenter-diminuer le nombre d'unités LTSM mais le score n'augmentera pas.

Je voudrais donc connaître une approche standard pour régler le réseau car, en théorie, l'algorithme devrait être plus performant qu'un réseau perceptron multicouche spécialement pour ces données de série chronologique.

wacax
la source
1
De combien de données disposez-vous? Quelle est la durée de vos séquences? Les LSTM ne sont vraiment utiles que pour les problèmes avec beaucoup de données et les dépendances à long terme.
pir
La recherche aléatoire ou l'optimisation bayésienne sont des moyens standard de trouver des hyperparamètres :)
pir
1
Êtes-vous sûr d'avoir besoin de la couche d'intégration? De nombreux jeux de données chronologiques n'en auraient pas besoin.
pir
J'ai près de 100 000 points de données et deux fois plus de fonctionnalités que l'exemple IMDB, donc je ne pense pas que ce soit le problème. En ce qui concerne la couche d'intégration, comment connecteriez-vous exactement la couche LSTM à l'entrée? Selon la documentation keras.io/layers/recurrent/#lstm , le LSTM de Keras ne prend que les initialisations, les activations et output_dim comme arguments. Si c'est la source de l'erreur, un code décrivant comment éliminer la couche d'intégration sera grandement apprécié.
wacax
Veuillez voir ma réponse. Il semble que vous n'ayez pas besoin de la couche d'intégration.
pir

Réponses:

5

Une couche d'intégration transforme les entiers positifs (index) en vecteurs denses de taille fixe. Par exemple, [[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]. Cette conversion de représentation est apprise automatiquement avec la couche d'intégration dans Keras (voir la documentation ).

Cependant, il semble que vos données n'aient pas besoin d'une telle couche d'intégration pour effectuer une conversion. Avoir une couche d'intégration inutile est probablement la raison pour laquelle vous ne pouvez pas faire fonctionner correctement votre LSTM. Si tel est le cas, vous devez simplement supprimer la couche d'intégration.

La première couche de votre réseau devrait alors avoir l' input_shapeargument ajouté avec des informations sur les dimensions de vos données (voir exemples ). Notez que vous pouvez ajouter cet argument à n'importe quelle couche - il ne sera présent dans la documentation d'aucune couche spécifique.


Soit dit en passant, les hyperparamètres sont souvent réglés à l'aide d'une recherche aléatoire ou d'une optimisation bayésienne. J'utiliserais RMSProp et me concentrerais sur le réglage de la taille des lots (tailles comme 32, 64, 128, 256 et 512), l'écrêtage du gradient (sur l'intervalle 0,1-10) et le décrochage (sur l'intervalle 0,1-0,6). Les spécificités dépendent bien sûr de vos données et de l'architecture du modèle.

pir
la source
Que proposez-vous pour remplacer la couche d'intégration? J'ai simplement essayé de supprimer la couche d'intégration, mais cela ne fonctionne pas.
wacax du
1
Regardez les autres exemples - commencez par exemple directement avec la couche Dense. N'oubliez pas de définir le paramètre input_shape.
pir
5

Je recommanderais l'optimisation bayésienne pour la recherche d'hyperparamètres et j'ai obtenu de bons résultats avec Spearmint. https://github.com/HIPS/Spearmint Vous devrez peut-être utiliser une ancienne version à des fins commerciales.

Mutian Zhai
la source
2

Je suggérerais d'utiliser hyperopt ( https://github.com/hyperopt/hyperopt ), qui utilise une sorte d'optimisation bayésienne pour rechercher des valeurs optimales d'hyperparamètres étant donné la fonction objectif. Il est plus intuitif à utiliser que Spearmint.

PS: Il existe un wrapper d'hyperopt spécifiquement pour les keras, les hyperas ( https://github.com/maxpumperla/hyperas ). Vous pouvez également l'utiliser.

SHASHANK GUPTA
la source
2

Talos est exactement ce que vous recherchez; une solution automatisée de recherche de combinaisons d'hyperparamètres pour les modèles Keras. Je ne suis peut-être pas objectif car je suis l'auteur, mais l'intention était de fournir une alternative avec la courbe d'apprentissage la plus basse possible tout en exposant entièrement la fonctionnalité Keras.

Alternativement, comme cela avait déjà été mentionné, vous pouvez regarder dans Hyperas , ou ensuite SKlearn ou AutoKeras . À ma connaissance, au moment de la rédaction de ce document, ces quatre options sont spécifiquement destinées aux utilisateurs de Keras.

mikkokotila
la source