2016-10-21 104 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)'。 –