2017-10-08 205 views
0

我有一個包含N個觀測值和F特徵的時間序列數據集。每個功能都可以顯示(1)或不顯示(0)。因此,該數據集是這樣的:用於時間序列預測的Keras LSTM:預測特徵向量

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 

我試圖使用基於LSTM架構,預測其在基於觀測TW時間T + 1功能清單 - T,其中,W是一些寬度時間窗口。如果W = 4,爲了進行預測,LSTM'看見'4個時間步進到過去。 LSTM預計3D輸入,其格式爲(number_batches,W,F)。一個天真Keras實現可能看起來像:

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)) 

我遇到的主要問題是:完整數據集有大量的功能(> 200),這是比較少見的功能來體現,即0比1更常見。神經網絡只是簡單地學習將所有值設置爲0,從而達到高度的「準確性」。

實質上,我想通過某個值來對輸入矩陣中的每個1進行加權以使其更加重要,但是我很困惑如何在Keras中實現這一點。我知道凱拉斯有一個選項sample_weight,但它是如何工作的?例如,我不知道如何在我的示例中實現它。這是對我有問題的合理解決方案嗎?這類問題通常使用哪些優化器和損失函數?

+0

你嘗試,而不是使用0 = -1,1 = 1呢? – DJK

回答

1

這是我用於2D高度不平衡數據的損失函數,它工作得很好。您可以將binary_crossentropy替換爲另一種損失。

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) 

爲了您的3D數據,這可能會工作,但也許你可以在列工作,建立各功能的對權重,而不是彙總所有特徵組合在一起。

這就像這樣:

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

謝謝!這看起來像我所需要的。 –