python - 由于动态变量,在 Python 中高效地创建列表

标签 python algorithm design-patterns refactoring

我正在使用 Keras建立一个LSTM recurrent neural network .我的代码运行良好,但可以进行认真的重构。我正在预测时间序列值,并且根据我想要预测的窗口大小,我最终编写的代码似乎过于具体到该窗口大小,即很难满足许多不同的大小。

我将我的数据集分成训练集和测试集

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

Dataset length: 1826 Train length: 1223, Test length: 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 shape: (1208, 10), trainY shape: (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)

虽然这行得通,但效率极低。我怎样才能最好地重构这些步骤以使代码更适合更广泛的预测窗口?另外,我的问题标题可以做一些改进,所以请编辑掉!

最佳答案

(注意:我对你的神经网络问题一无所知,我只是在解决你的编码/数组遍历问题)

取矩阵的对角线可以用循环来完成——你只需要将循环的参数调整到合适的维度。以下代码是纯 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 数组进行操作并取每条对角线的平均值。然后您应该能够调整预测窗口而无需重复太多代码。

让我知道这是否符合您的要求。

关于python - 由于动态变量,在 Python 中高效地创建列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40185061/

相关文章:

java - 面向对象设计 : Scalable and maintainable car store system

python - Cython 优化 numpy 数组求和的关键部分

algorithm - 计数排序如何稳定?

algorithm - 找到点之间最小距离的最快方法

asp.net-mvc - 具有两个重载操作方法的 ASP.NET MVC : post-redirect-get pattern,

c++ - 当观察者希望观察不同的项目时实现观察者模式

python - BeautifulSoup 使用 select 多次

python - 仅将关键字参数传递给 __new__() 而永远不会将其进一步传递给 __init__()?

Python 幂律趋势线

java - 摇床排序或双向冒泡排序