2017-10-08 9 views
0

J'ai un ensemble de données de timeséries avec N observations et caractéristiques F. Chaque fonctionnalité peut soit manifester (1) soit ne pas se manifester (0). Ainsi, l'ensemble de données ressemblerait à ceci:Keras LSTM pour la prédiction de timesérie: prédire les vecteurs de caractéristiques

T F1 F2 F3 F4 F5 ... F 
0 1  0  0  1  0  0 
1 0  1  0  0  1  1 
2 0  0  0  1  1  0 
3 1  1  1  1  0  0 
... 
N 1  1  0  1  0  0 

Je suis en train d'utiliser une architecture basée LSTM pour prédire qui dispose manifeste à l'instant T + 1 sur la base des observations TW - T, où W est la largeur de certains fenêtre de temps. Si W = 4, le LSTM 'voit' 4 pas dans le passé pour faire la prédiction. Le LSTM attend une entrée 3D, qui sera de la forme (number_batches, W, F). Une naïve mise en œuvre Keras pourrait ressembler à:

model = Sequential() 
model.add(LSTM(128, stateful=True, batch_input_shape=(batch_size, W, F))) 
model.add(Dense(F, activation='sigmoid')) 

model.compile(loss='binary_crossentropy', 
       optimizer='rmsprop', 
       metrics=['accuracy']) 
model.fit(x_train, y_train, 
      batch_size=batch_size, epochs=250, shuffle=False, 
      validation_data=(x_val, y_val)) 

Le principal problème que j'ai est ceci: l'ensemble des données a un grand nombre de fonctionnalités (> 200) et il est relativement rare que les caractéristiques de manifester, à savoir 0 est beaucoup plus commun que 1. Le réseau neuronal apprend simplement à mettre toutes les valeurs à 0 et obtient ainsi un degré élevé de «précision».

Essentiellement, je veux pondérer tous les 1 dans la matrice d'entrée par une valeur pour lui donner plus d'importance, mais je suis confus comment implémenter cela dans Keras. Je sais qu'il y a une option sample_weight dans Keras, mais comment ça marche? Je ne saurais pas comment l'implémenter dans mon exemple, par exemple. Est-ce une solution raisonnable au problème que j'ai? Quelles fonctions d'optimisation et de perte sont couramment utilisées pour ce type de problème?

+0

avez-vous essayé au lieu d'utiliser 0 = -1, 1 = 1 à la place? – DJK

Répondre

1

Il s'agit d'une fonction de perte que j'utilise pour les données 2D très déséquilibrées, cela fonctionne très bien. Vous pouvez remplacer le binary_crossentropy pour un autre type de perte.

import keras.backend as K 

def weightedByBatch(yTrue,yPred): 

    nVec = K.ones_like(yTrue) #to sum the total number of elements in the tensor 
    percent = K.sum(yTrue)/K.sum(nVec) #percent of ones relative to total 
    percent2 = 1 - percent #percent of zeros relative to total 
    yTrue2 = 1 - yTrue #complement of yTrue (yTrue+ yTrue2 = full of ones) 

    weights = (yTrue2 * percent2) + (yTrue*percent) 
    return K.mean(K.binary_crossentropy(yTrue,yPred)/weights) 

Pour vos données 3D, cela peut fonctionner, mais vous pourriez peut-être travailler dans les colonnes, la création d'une paire de poids pour chaque fonction, au lieu de sommer toutes les fonctionnalités ensemble.

Cela pourrait se faire comme ceci:

def weightedByBatch2D(yTrue,yPred): 

    nVec = K.ones_like(yTrue) #to sum the total number of elements in the tensor 
    percent = K.sum(K.sum(yTrue,axis=0,keepdims=True),axis=1,keepdims=True)/K.sum(K.sum(nVec,axis=0,keepdims=True),axis=1,keepdims=True) #percent of ones relative to total 
    percent2 = 1 - percent #percent of zeros relative to total 
    yTrue2 = 1 - yTrue #complement of yTrue (yTrue+ yTrue2 = full of ones) 

    weights = (yTrue2 * percent2) + (yTrue*percent) 
    return K.mean(K.binary_crossentropy(yTrue,yPred)/weights) 
+0

Merci! Cela ressemble à ce dont j'avais besoin. –