Num*_*ind 1 python forecasting lstm keras recurrent-neural-network
我的数据框是每小时一次(我的 df 的索引),我想预测 y。
> df.head()
Date y
2019-10-03 00:00:00 343
2019-10-03 01:00:00 101
2019-10-03 02:00:00 70
2019-10-03 03:00:00 67
2019-10-03 04:00:00 122
Run Code Online (Sandbox Code Playgroud)
我现在将导入库并训练模型:
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
min_max_scaler = MinMaxScaler()
prediction_hours = 24
df_train= df[:len(df)-prediction_hours]
df_test= df[len(df)-prediction_hours:]
print(df_train.head())
print('/////////////////////////////////////////')
print (df_test.head())
training_set = df_train.values
training_set = min_max_scaler.fit_transform(training_set)
x_train = training_set[0:len(training_set)-1]
y_train = training_set[1:len(training_set)]
x_train = np.reshape(x_train, (len(x_train), 1, 1))
num_units = 2
activation_function = 'sigmoid'
optimizer = 'adam'
loss_function = 'mean_squared_error'
batch_size = 10
num_epochs = 100
regressor = Sequential()
regressor.add(LSTM(units = num_units, activation = activation_function, input_shape=(None, 1)))
regressor.add(Dense(units = 1))
regressor.compile(optimizer = optimizer, loss = loss_function)
regressor.fit(x_train, y_train, batch_size = batch_size, epochs = num_epochs)
Run Code Online (Sandbox Code Playgroud)
训练后,我实际上可以在我的测试数据上使用它:
test_set = df_test.values
inputs = np.reshape(test_set, (len(test_set), 1))
inputs = min_max_scaler.transform(inputs)
inputs = np.reshape(inputs, (len(inputs), 1, 1))
predicted_y = regressor.predict(inputs)
predicted_y = min_max_scaler.inverse_transform(predicted_y)
Run Code Online (Sandbox Code Playgroud)
这是我得到的预测:
预测实际上非常好:它好得令人难以置信吗?我做错了什么吗?我从一个 GitHub 实现一步一步地遵循了这个实现。
我想添加一些外生变量,即v1、v2、v3。如果我的数据集现在看起来像这样带有新变量,
df.head()
Date y v1 v2 v3
2019-10-03 00:00:00 343 4 6 10
2019-10-03 01:00:00 101 3 2 24
2019-10-03 02:00:00 70 0 0 50
2019-10-03 03:00:00 67 0 4 54
2019-10-03 04:00:00 122 3 3 23
Run Code Online (Sandbox Code Playgroud)
如何在我的 LSTM 模型中包含这些变量 v1、v2 和 v3?多元 LSTM 的实现让我很困惑。
编辑回答 Yoan 建议:
对于以日期为索引并包含 y、v1、v2 和 v3 列的数据框,我已按照建议执行以下操作:
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
min_max_scaler = MinMaxScaler()
prediction_hours = 24
df_train= df[:len(df)-prediction_hours]
df_test= df[len(df)-prediction_hours:]
print(df_train.head())
print('/////////////////////////////////////////')
print (df_test.head())
training_set = df_train.values
training_set = min_max_scaler.fit_transform(training_set)
x_train = np.reshape(x_train, (len(x_train), 1, 4))
y_train = training_set[0:len(training_set),1] #I've tried with 0:len.. and
#for 1:len..
num_units = 2
activation_function = 'sigmoid'
optimizer = 'adam'
loss_function = 'mean_squared_error'
batch_size = 10
num_epochs = 100
regressor = Sequential()
regressor.add(LSTM(units = num_units, activation = activation_function,
input_shape=(None, 1,4)))
regressor.add(Dense(units = 1))
regressor.compile(optimizer = optimizer, loss = loss_function)
regressor.fit(x_train, y_train, batch_size = batch_size, epochs =
num_epochs)
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
only integer scalar arrays can be converted to a scalar index
Run Code Online (Sandbox Code Playgroud)
有多种使用 LSTM 处理辅助特征的方法,所有这些都受到您的数据包含的内容以及您希望如何对这些特征进行建模的启发。我将讨论 4 种不同的场景和策略,供您在下面使用一些虚拟代码参考。
假设您有 4 个连续特征,并且所有这些特征都是连续的(不是以文本或分类方式编码的标签)。在这种情况下,LSTM 可以很好地直接处理这些特征。LSTM 层期望的形状为(batch, sequence, features)
,因此无需任何修改即可很好地适应这种场景。
Features --> LSTM --> Process --> Predict
Run Code Online (Sandbox Code Playgroud)
代码
from tensorflow.keras import layers, Model, utils
#Four continuous features
X = np.random.random((100,10,4))
Y = np.random.random((100,))
###Define model###
inp = layers.Input((10,4))
#LSTMs
x = layers.LSTM(8, return_sequences=True)(inp)
x = layers.LSTM(8)(x)
out = layers.Dense(1)(x)
model = Model(inp, out)
utils.plot_model(model, show_layer_names=False, show_shapes=True)
Run Code Online (Sandbox Code Playgroud)
接下来,让我们假设另一个简单的案例。您有 2 个标签编码序列(比如文本)。正如人们所想的那样,您想要做的就是通过为每个特征构建 LSTM 来分别创建序列特征,然后在下游预测任务之前将它们连接起来。
Sequence --> Embed --> LSTM -->|
* --> Append --> Process --> Predict
Sequence --> Embed --> LSTM -->|
Run Code Online (Sandbox Code Playgroud)
代码
from tensorflow.keras import layers, Model, utils
#Two sequential, label encoded features
X = np.random.random((100,10,2))
Y = np.random.random((100,))
###Define model###
inp = layers.Input((10,2))
feature1 = layers.Lambda(lambda x: x[...,0])(inp)
feature2 = layers.Lambda(lambda x: x[...,1])(inp)
#Append embeddings features
x1 = layers.Embedding(1000, 5)(feature1)
x2 = layers.Embedding(1200, 7)(feature2)
#LSTMs
x1 = layers.LSTM(8, return_sequences=True)(x1)
x1 = layers.LSTM(8)(x1)
x2 = layers.LSTM(8, return_sequences=True)(x2)
x2 = layers.LSTM(8)(x2)
#Combine LSTM final states
x = layers.concatenate([x1,x2])
out = layers.Dense(1)(x)
model = Model(inp, out)
utils.plot_model(model, show_layer_names=False, show_shapes=True)
Run Code Online (Sandbox Code Playgroud)
下一个场景,让我们假设您正在使用一个特征,即标签编码序列(比如文本)。在将此功能传递给 LSTM 之前,您必须n
使用embedding
层将其编码为维向量。这将导致(batch, sequence, embedding_dim)
LSTM的形状输入完全没有问题。但是,假设您还有 3 个连续的辅助特征(并正确归一化)。您可以做的一件简单的事情就是将append
这些添加到嵌入层的输出中,以获得(batch, sequence, embedding_dims+auxiliary)
LSTM 也可以处理的输入!
Sequence --> Embed ----->|
*--> Append --> LSTM -> Process --> Predict
Auxiliary --> Process -->|
Run Code Online (Sandbox Code Playgroud)
代码
from tensorflow.keras import layers, Model, utils
#One sequential, label encoded feature & 3 auxilary features for each timestep
X = np.random.random((100,10,4))
Y = np.random.random((100,))
###Define model###
inp = layers.Input((10,4))
feature1 = layers.Lambda(lambda x: x[...,0])(inp)
feature2 = layers.Lambda(lambda x: x[...,1:4])(inp)
#Append embeddings features
x = layers.Embedding(1000, 5)(feature1)
x = layers.concatenate([x, feature2])
#LSTMs
x = layers.LSTM(8, return_sequences=True)(x)
x = layers.LSTM(8)(x)
out = layers.Dense(1)(x)
model = Model(inp, out)
utils.plot_model(model, show_layer_names=False, show_shapes=True)
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,在将标签编码的输入嵌入到5-dimensional
向量中之后,附加了 3 个辅助输入,然后将(10,8)
维度序列传递给 LSTM 以发挥它们的作用。
假设您有与上述相同的场景,但在附加辅助输入之前,您希望序列特征具有更丰富的表示。在这里,您可以简单地将序列特征传递给 LSTM,并将辅助输入附加到 LSTM 的 OUTPUT,然后决定在需要时将其传递到另一个 LSTM。这将需要您return_sequences=True
这样做,以便您可以获得相同长度的序列,这些序列可以附加到该组时间步长的辅助特征中。
Sequence --> Embed --> LSTM(seq) -->|
*--> Append --> Process --> Predict
Auxiliary --> Process ------------->|
Run Code Online (Sandbox Code Playgroud)
代码
from tensorflow.keras import layers, Model, utils
#One sequential, label and 3 auxilary continous features
X = np.random.random((100,10,4))
Y = np.random.random((100,))
###Define model###
inp = layers.Input((10,4))
feature1 = layers.Lambda(lambda x: x[...,0])(inp)
feature2 = layers.Lambda(lambda x: x[...,1:4])(inp)
#feature2 = layers.Reshape((-1,1))(feature2)
#Append embeddings features
x = layers.Embedding(1000, 5)(feature1)
#LSTMs
x = layers.LSTM(8, return_sequences=True)(x)
x = layers.concatenate([x, feature2])
x = layers.LSTM(8)(x)
#Combine LSTM final states
out = layers.Dense(1)(x)
model = Model(inp, out)
utils.plot_model(model, show_layer_names=False, show_shapes=True)
Run Code Online (Sandbox Code Playgroud)
有些架构将单个特征添加到 LSTM 的输出中,然后在 LSTM 中再次对它们进行编码,然后添加下一个特征等等,而不是将它们全部加在一起。这是一种设计选择,必须针对您的特定数据进行测试。
希望这能澄清你的问题。
归档时间: |
|
查看次数: |
833 次 |
最近记录: |