2016-10-21 105 views
0

我使用Keras來構建LSTM recurrent neural network。我的代碼運行良好,但可以通過嚴重的重構來完成。我預測的是時間序列值,根據我想預測的窗口大小,我最終編寫的代碼似乎與窗口大小有很大的關係,即很難滿足大量不同的大小。由於動態變量在Python中有效創建列表

我拆我的數據集到火車&試臺

print "Dataset length: %d" % len(dataset) 
train_size = int(len(dataset) * 0.67) 
test_size = len(dataset) - train_size 
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:] 
print "Train length: %d, Test length: %d" % (len(train), len(test)) 

數據集長度:1826列車長度:1223,測試長度:603

則兩個traintest我需要創建一個X這是輸入,和一個Y這是輸出(我試圖預測)

def create_dataset(dataset, look_back=1, predict_steps=1): 

    dataX, dataY = [], [] 

    for i in range(dataset.shape[0] - look_back - predict_steps): 
     dataX.append(dataset[i:(i + look_back), 0]) 
     dataY.append(dataset[i + look_back:i + look_back + predict_steps, 0]) 

    return np.array(dataX), np.array(dataY) 

look_back = 10 
predict_steps = 5 
input_dim = look_back + 1 
trainX, trainY = create_dataset(train, look_back=look_back, predict_steps=predict_steps) 
testX, testY = create_dataset(test, look_back=look_back, predict_steps=predict_steps) 
print "trainX shape: %s, trainY shape: %s" % (trainX.shape, trainY.shape,) 

trainX形狀:(1208,10),trainY形狀:(1208,5)

如果我想預測未來5時步,然後我的預測,存儲在變量trainY,將採取形式[[t+6, t+7, t+8, t+9, t+10], [t+7, t+8, t+9, t+10, t+11]],即

prediction 1 [t+6, t+7, t+8, t+9, t+10] 
prediction 2 [t+7, t+8, t+9, t+10, t+11] 
prediction 3 [t+8, t+9, t+10, t+11, t+12] 
prediction 4 [t+9, t+10, t+11, t+12, t+13] 
prediction 5 [t+10, t+11, t+12, t+13, t+14] 

enter image description here

現在,如果我要得到這些值早在一個邏輯順序,即t+6, t+7, t+8,...,t+14 我使用此代碼

output = trainY 
output_plot = np.array([]) 
output_plot = np.append(output_plot, output[0][0]) 
output_plot = np.append(output_plot, np.mean([output[0][1], output[1][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][2], output[1][1], output[2][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][3], output[1][2], output[2][1], output[3][0]])) 

for i in range (len(output) - predict_steps + 1): 
    tmp = np.mean([output[i][4], output[i+1][3], output[i+2][2], output[i+3][1], output[i+4][0]]) 
    output_plot = np.append(output_plot, tmp) 

我的問題出現時,我想向外伸出預測窗口說10個時間步。然後,我手動擴展前面的代碼,如下所示

output = trainY 
output_plot = np.array([]) 
output_plot = np.append(output_plot, output[0][0]) 
output_plot = np.append(output_plot, np.mean([output[0][1], output[1][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][2], output[1][1], output[2][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][3], output[1][2], output[2][1], output[3][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][4], output[1][3], output[2][2], output[3][1], output[4][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][5], output[1][4], output[2][3], output[3][2], output[4][1], output[5][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][6], output[1][5], output[2][4], output[3][3], output[4][2], output[5][1], output[6][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][7], output[1][6], output[2][5], output[3][4], output[4][3], output[5][2], output[6][1], output[7][0]])) 
output_plot = np.append(output_plot, np.mean([output[0][8], output[1][7], output[2][6], output[3][5], output[4][4], output[5][3], output[6][2], output[7][1], output[8][0]])) 


for i in range (len(output) - predict_steps + 1): 
    tmp = np.mean([output[i][9], output[i+1][8], output[i+2][7], output[i+3][6], output[i+4][5], output[i+5][4], output[i+6][3], output[i+7][2], output[i+8][1], output[i+9][0]]) 
    output_plot = np.append(output_plot, tmp) 

雖然這種方法有效,但效率非常低。我怎樣才能最好地重構這些步驟,使代碼更適合更廣泛的預測窗口?此外,我的問題標題可以做一些改進,所以請編輯!

+1

在你的代碼示例的第一部分中,看起來你只是在平方2D列表的主對角線上方取對角線的平均值。但我不明白你的循環試圖做什麼。不是'len(輸出)'總是等於'predict_steps'?如果'i'不是'0'以外的任何東西,你的循環中的第一行是不是會引發'IndexError'? –

+0

根據數據集的不同,任何輸出都不是真的。它可能會從't + 6,...,t + 500'出現,但輸出的是在窗口中預測的,其長度等於'predict_steps'。那有意義嗎?或者我會用一個我的意思是什麼來更新這個問題? –

+0

但是'output'仍然是一個二維列表形式的正方形對稱矩陣,對嗎?你能舉一個例子,比如說'predict_steps'是'3','len(output)'是'5'嗎? 「輸出」是什麼樣的,你的循環是什麼樣的呢? –

回答

1

(注:我什麼都不知道你的神經網絡的問題,我只是在解決您的編碼/陣列穿越問題)

以矩陣可以用循環來完成的對角線 - 你只需要將環路的參數調整到適當的尺寸。下面的代碼是純Python中的一個簡化的模型,用於瞭解您對數據形狀所瞭解的內容。

from pprint import pprint 

def create_mock_data(n): 
    return [[100 + i] for i in range(n)] 

def create_dataset(dataset, look_back = 1, predict_steps = 1): 
    X, Y = [], [] 

    for i in range(len(dataset) - look_back - predict_steps): 
     X.append([row[0] for row in dataset[i : i+look_back]]) 
     Y.append([row[0] for row in dataset[i+look_back : i+look_back+predict_steps]]) 

    return X, Y 

def antidiagonals(a): 
    m, n = len(a), len(a[0]) 

    for k in range(0, n): 
     yield [a[k-i][i] for i in range(k + 1)] 

    for k in range(n, m): 
     yield [a[k-i][i] for i in range(n)] 

def pp(label, x): 
    print('---', label, '---') 
    pprint(x, width = 108) 
    print() 

def test(n, look_back, predict_steps): 
    print('=' * 72) 
    print('n =', n) 
    print('look_back =', look_back) 
    print('predict_steps =', predict_steps) 
    print() 

    dataset = create_mock_data(n) 
    pp('dataset', dataset) 

    X, Y = create_dataset(dataset, look_back, predict_steps) 
    pp('X', X) 
    pp('Y', Y) 

    diagonals = list(antidiagonals(Y)) 
    pp('diagonals of Y', diagonals) 

    print() 

test(50, look_back = 10, predict_steps = 5) 
test(50, look_back = 10, predict_steps = 10) 
# test(50, look_back = 15, predict_steps = 10) 

需要注意的是:

  • 我用Python列表,而不是numpy的陣列,所以請糾正我,如果我誤解你的數組索引,尤其是在create_dataset功能。
  • 爲了簡單起見,我跳過了將原始數據集分成訓練和測試數據集的部分。

主要代碼在antidiagonals函數中。對於MxN矩陣的每一行,它將從該行的第一個元素開始產生上升的對角線。第一個循環產生第一個N對角線,它們都有不同的長度。第二個循環產生下一個M-N對角線,所有對角線都有N元素。當你運行上面的代碼時,你可以檢查模擬Y數組及其對角線的輸出。

假設這些數據是您想要添加到output_plot的正確系列數據,您只需修改該函數即可在numpy陣列上進行操作並獲取每個對角線的平均值。那麼你應該能夠調整預測窗口而不用重複太多的代碼。

讓我知道這是否符合您的目標。

+0

這很好用,謝謝。由於某種原因,當我這樣實現時,我在返回的數字中失去了一小部分的精度,我在'antidiagonal'循環中糾正了'yield np.mean([a [ki] [i] k + 1)],dtype = np.float64)'。 –