如何处理预测值的转换

Sre*_* TP 10 python machine-learning forecasting deep-learning keras

我在Keras使用LSTM实现了预测模型.数据集分离15分钟,我预测12个未来步骤.

该模型对该问题表现良好.但预测有一个小问题.它显示出一个小的移位效果.要获得更清晰的图片,请参见下图.

在此输入图像描述

如何处理这个问题.如何转换数据来处理这类问题.

我使用的模型如下

init_lstm = RandomUniform(minval=-.05, maxval=.05)
init_dense_1 = RandomUniform(minval=-.03, maxval=.06)

model = Sequential()

model.add(LSTM(15, input_shape=(X.shape[1], X.shape[2]), kernel_initializer=init_lstm, recurrent_dropout=0.33))

model.add(Dense(1, kernel_initializer=init_dense_1, activation='linear'))

model.compile(loss='mae', optimizer=Adam(lr=1e-4))

history = model.fit(X, y, epochs=1000, batch_size=16, validation_data=(X_valid, y_valid), verbose=1, shuffle=False)
Run Code Online (Sandbox Code Playgroud)

我做了这样的预测

my_forecasts = model.predict(X_valid, batch_size=16)
Run Code Online (Sandbox Code Playgroud)

时间序列数据被转换为监督以使用该函数来馈送LSTM

# convert time series into supervised learning problem
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    n_vars = 1 if type(data) is list else data.shape[1]
    df = DataFrame(data)
    cols, names = list(), list()
    # input sequence (t-n, ... t-1)
    for i in range(n_in, 0, -1):
        cols.append(df.shift(i))
        names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    # forecast sequence (t, t+1, ... t+n)
    for i in range(0, n_out):
        cols.append(df.shift(-i))
        if i == 0:
            names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
        else:
            names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
    # put it all together
    agg = concat(cols, axis=1)
    agg.columns = names
    # drop rows with NaN values
    if dropnan:
        agg.dropna(inplace=True)
    return agg

super_data = series_to_supervised(data, 12, 1)
Run Code Online (Sandbox Code Playgroud)

我的时间序列是多变量的.var2是我需要预测的那个.我放弃了未来var1

del super_data['var1(t)']
Run Code Online (Sandbox Code Playgroud)

分开的火车和这样的有效

features = super_data[feat_names]
values = super_data[val_name]

ntest = 3444

train_feats, test_feats = features[0:-n_test], features[-n_test:]
train_vals, test_vals = values [0:-n_test], values [-n_test:]

X, y = train_feats.values, train_vals.values
X = X.reshape(X.shape[0], 1, X.shape[1])

X_valid, y_valid = test_feats .values, test_vals .values
X_valid = X_valid.reshape(X_valid.shape[0], 1, X_valid.shape[1])
Run Code Online (Sandbox Code Playgroud)

我没有为此预测确定数据.我也尝试采取差异,尽可能使模型保持静止,但问题仍然存在.

我还尝试了最小 - 最大缩放器的不同缩放范围,希望它可以帮助模型.但预测正在恶化.

Other Things I have tried

=> Tried other optimizers
=> Tried mse loss and custom log-mae loss functions
=> Tried varying batch_size
=> Tried adding more past timesteps
=> Tried training with sliding window and TimeSeriesSplit
Run Code Online (Sandbox Code Playgroud)

我知道该模型正在复制最后一个已知值,从而尽可能地减少损失

在整个培训过程中,验证和培训损失仍然很低.这让我想到我是否需要为此目的提出一个新的损失函数.

这是必要的吗?如果是这样,我应该选择什么样的损失功能.

我已经尝试了我偶然发现的所有方法.我找不到任何指向这类问题的资源.这是数据的问题吗?这是因为LSTM很难学习这个问题.

小智 7

您在以下位置寻求我的帮助:

股票预测:GRU模型预测相同的给定值而不是未来的股票价格

希望不晚。您可以尝试的是,可以转移特征的数字明确性。让我解释:

与上一个主题中的答案相似;回归算法将使用您提供的时间窗口中的值作为样本,以最大程度地减少误差。假设您正在尝试预测时间t的BTC收盘价。您的功能之一包括先前的收盘价,您将给出一个从t-20到t-1的最后20个输入的时间序列窗口。回归者可能会学会在时间步t-1或t-2处选择关闭值,或者在这种情况下选择关闭值作弊。这样想:如果在t-1时收盘价为$ 6340,那么预测$ 6340或在t + 1时收盘价将最大程度地减小误差。但是实际上该算法没有学习任何模式。它只是复制,因此除了完成优化任务外,它基本上什么也不做。

从我的示例中类似地思考:通过改变明确性,我的意思是:不要直接给出收盘价,而是要缩放收盘价或根本不使用明确的收盘价。不要使用任何明确显示算法收盘价的功能,也不要在每个时间步使用开盘价,最高价,最低价等。您将需要在这里发挥创造力,设计功能以摆脱明显的功能;您可以给出平方的紧密差异(回归者仍然可以凭经验和线性差异从过去窃取),其比例与数量。或者,可以通过使用某种有意义的方式将其数字化来将其分类。重点是不能直接直观地预测其结果,而只是为算法提供模式。

根据您的任务,可能会建议一种更快的方法。如果要预测标签足以满足您的变化百分比,则可以进行多类别分类,只需注意类别不平衡的情况即可。如果仅上下波动就足够了,您可以直接进行二进制分类。如果您没有从训练中泄漏数据到测试集,则仅在回归任务中看到复制或转移问题。如果可能,请摆脱时间序列窗口化应用程序的回归。

如果有任何误解或丢失,我会在附近。希望我能帮上忙。祝好运。


Ale*_*lex 3

您的 LSTM 很可能正在学习粗略地猜测其先前的输入值(稍作调整)。这就是为什么你会看到“转变”。

假设您的数据如下所示:

x = [1, 1, 1, 4, 5, 4, 1, 1]
Run Code Online (Sandbox Code Playgroud)

并且您的 LSTM 学会了仅输出当前时间步的先前输入。那么你的输出将如下所示:

y = [?, 1, 1, 1, 4, 5, 4, 1]
Run Code Online (Sandbox Code Playgroud)

因为您的网络有一些复杂的机制,所以并不是那么简单,但原则上您看到的“转变”是由这种现象引起的。