web-dev-qa-db-fra.com

Masquage Keras pour RNN avec des pas de temps variables

J'essaie d'adapter un RNN dans Keras en utilisant des séquences qui ont des durées variables. Mes données sont dans un tableau Numpy au format (sample, time, feature) = (20631, max_time, 24)max_time est déterminé au moment de l'exécution comme le nombre de pas de temps disponibles pour l'échantillon avec le plus d'horodatages. J'ai complété le début de chaque série chronologique avec 0, sauf le plus long, évidemment.

J'ai d'abord défini mon modèle comme ça ...

model = Sequential()
model.add(Masking(mask_value=0., input_shape=(max_time, 24)))
model.add(LSTM(100, input_dim=24))
model.add(Dense(2))
model.add(Activation(activate))
model.compile(loss=weibull_loglik_discrete, optimizer=RMSprop(lr=.01))
model.fit(train_x, train_y, nb_Epoch=100, batch_size=1000, verbose=2, validation_data=(test_x, test_y))

Pour être complet, voici le code de la fonction de perte:

def weibull_loglik_discrete(y_true, ab_pred, name=None):
    y_ = y_true[:, 0]
    u_ = y_true[:, 1]
    a_ = ab_pred[:, 0]
    b_ = ab_pred[:, 1]

    hazard0 = k.pow((y_ + 1e-35) / a_, b_)
    hazard1 = k.pow((y_ + 1) / a_, b_)

    return -1 * k.mean(u_ * k.log(k.exp(hazard1 - hazard0) - 1.0) - hazard1)

Et voici le code de la fonction d'activation personnalisée:

def activate(ab):
    a = k.exp(ab[:, 0])
    b = k.softplus(ab[:, 1])

    a = k.reshape(a, (k.shape(a)[0], 1))
    b = k.reshape(b, (k.shape(b)[0], 1))

    return k.concatenate((a, b), axis=1)

Lorsque j'adapte le modèle et fais des prédictions de test, chaque échantillon de l'ensemble de test obtient exactement la même prédiction, ce qui semble louche.

Les choses s'améliorent si je supprime la couche de masquage, ce qui me fait penser qu'il y a un problème avec la couche de masquage, mais pour autant que je sache, j'ai suivi la documentation exactement.

Y a-t-il quelque chose de mal spécifié avec la couche de masquage? Suis-je en train de manquer autre chose?

21
John Chrysostom

Je ne pouvais pas valider sans données réelles, mais j'ai eu une expérience similaire avec un RNN. Dans mon cas, la normalisation a résolu le problème. Ajoutez une couche de normalisation à votre modèle.

4
vagoston

La façon dont vous avez implémenté le masquage doit être correcte. Si vous avez des données avec la forme (échantillons, pas de temps, caractéristiques) , et que vous souhaitez masquer les pas de temps manquant de données avec un masque zéro de la même taille que l'argument features, puis vous ajoutez Masking(mask_value=0., input_shape=(timesteps, features)). Voir ici: keras.io/layers/core/#masking

Votre modèle pourrait être trop simple et/ou votre nombre d'époques pourrait être insuffisant pour que le modèle fasse la différence entre toutes vos classes. Essayez ce modèle:

model = Sequential()
model.add(Masking(mask_value=0., input_shape=(max_time, 24)))
model.add(LSTM(256, input_dim=24))
model.add(Dense(1024))
model.add(Dense(2))
model.add(Activation(activate))
model.compile(loss=weibull_loglik_discrete, optimizer=RMSprop(lr=.01))
model.fit(train_x, train_y, nb_Epoch=100, batch_size=1000, verbose=2, validation_data=(test_x, test_y)) 

Si cela ne fonctionne pas, essayez de doubler les époques plusieurs fois (par exemple 200, 400) et voyez si cela améliore les résultats.

5
Robert Valencia