keras lstm 不正确 input_shape
keras lstm incorrect input_shape
我正在尝试使用 lstm 模型来预测天气(主要是为了了解 lstm 并使用 python)。
我有一个包含 500,000 行的数据集,每行代表一个日期,并且有 8 列是我的特征。
下面是我的模型。
model = Sequential()
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.fit(
X,
y,
batch_size=512,
epochs=100,
validation_split=0.05)
据我所知,对于输入参数,第一个参数是时间步长,所以我在这里说的是,我认为应该使用最后 30 个观察值来预测下一个值。我理解的8就是这样的特征,气压,温度等
所以我的 X 矩阵用下面的线转换成 3D 矩阵所以 X 现在是 500000, 8, 1 矩阵。
X = np.reshape(X, (X.shape[0], X.shape[1], 1))
当我 运行 模型时,我得到以下错误。
ValueError: Error when checking input: expected lstm_3_input
to have shape (30, 8) but got array with shape (8, 1)
我做错了什么?
我认为您的输入形状不对。 NN 不理解您希望它采用 30 个点的切片来预测第 31 个点。您需要做的是将数据集切成长度为 30 的块(这意味着每个点将被复制 29 次)并对其进行训练,其形状为 (499969, 30, 8) ,假设最后点只进入 y
。也不要在末尾添加虚拟维度,在 RGB 通道的转换层中需要它。
您的问题与数据准备有关。
查找有关 LSTM here.
数据准备的详细信息
LSTM 将一系列过去的观察结果映射为输出观察结果的输入。因此,必须将观察序列转换为多个样本考虑给定的单变量序列:
[10, 20, 30, 40, 50, 60, 70, 80, 90]
我们可以将序列分成多个 input/output 称为样本的模式,其中三个 n_steps
时间步用作输入,一个时间步用作一步预测的标签,即学习中。
X, y
10, 20, 30 40
20, 30, 40 50
30, 40, 50 60
# ...
所以你想做的是在下面的split_sequence()
函数中实现的:
# split a univariate sequence into samples
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
# find the end of this pattern
end_ix = i + n_steps
# check if we are beyond the sequence
if end_ix > len(sequence)-1:
break
# gather input and output parts of the pattern
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
回到我们的初始示例,发生以下情况:
# define input sequence
raw_seq = [10, 20, 30, 40, 50, 60, 70, 80, 90]
# choose a number of time steps
n_steps = 3
# split into samples
X, y = split_sequence(raw_seq, n_steps)
# summarize the data
for i in range(len(X)):
print(X[i], y[i])
# [10 20 30] 40
# [20 30 40] 50
# [30 40 50] 60
# [40 50 60] 70
# [50 60 70] 80
# [60 70 80] 90
要点: 现在你的形状应该是你的 LSTM 模型所期望的,你应该能够根据你的需要调整你的数据形状。显然同样适用于多个输入特征行。
让我复制一个用于为 LSTM 准备数据的函数:
from itertools import islice
def slice_data_for_lstm(data, lookback):
return np.array(list(zip(*[islice(np.array(data), i, None, 1) for i in range(lookback)])))
X_sliced = slice_data_for_lstm(X, 30)
在您的案例中,lookback 应为 30,并将创建 30 个 (8, 1) 特征堆栈。结果数据的形状为 (N, 30, 8, 1)。
我认为您可能只需要简单解释一下图层的工作原理。特别要注意的是,所有 Keras 层的行为都是这样的:
NAME(output_dim, input_shape = (...,input_dim))
例如,假设我有 15000 个 3 个长向量,我想将它们更改为 5 个长向量。然后像这样的事情会做到这一点:
import numpy as np, tensorflow as tf
X = np.random.random((15000,3))
Y = np.random.random((15000,5))
M = tf.keras.models.Sequential()
M.add(tf.keras.layers.Dense(5,input_shape=(3,)))
M.compile('sgd','mse')
M.fit(X,Y) # Take note that I provided complete working code here. Good practice.
# I even include the imports and random data to check that it works.
同样,如果我的输入看起来像 (1000,10,5) 并且我 运行 通过 LSTM 之类的 LSTM(7);那么我应该(自动)知道我会得到类似 (...,7) 的输出。这 5 个长向量将变为 7 个长向量。规则来理解。最后一个维度始终是您要更改的向量,图层的第一个参数始终是要将其更改为的维度。
现在是学习 LSTM 的第二件事。他们使用时间轴(这不是最后一个轴,因为我们刚刚过去,它总是 "changing dimension axis")如果 return_sequences=False 则删除,如果 return_sequences= 则保留真的。一些示例:
LSTM(7) # (10000,100,5) -> (10000,7)
# Here the LSTM will loop through the 100, 5 long vectors (like a time series with memory),
# producing 7 long vectors. Only the last 7 long vector is kept.
LSTM(7,return_sequences=True) # (10000,100,5) -> (10000,100,7)
# Same thing as the layer above, except we keep all the intermediate steps.
您提供的图层如下所示:
LSTM(50,input_shape=(30,8),return_sequences=True) # (10000,30,8) -> (10000,30,50)
注意 30 是 LSTM 模型中使用的时间维度。 8和50是INPUT_DIM和OUTPUT_DIM,与时间轴无关。另一个常见的误解是,请注意 LSTM 希望您为每个样本提供它自己的完整过去和时间轴。也就是说,LSTM 不会将先前的样本点用于下一个样本点;每个样本都是独立的,并带有自己完整的过去数据。
让我们来看看您的模型。步骤1。你的模型在做什么,它期望什么样的数据?
from tensorflow.keras.layers import LSTM, Dropout, Activation
from tensorflow.keras.models import Sequential
model = Sequential()
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.compile('sgd','mse')
print(model.input_shape)
model.summary() # Lets see what your model is doing.
所以,现在我清楚地看到你的模型做了:
(10000,30,8) -> (10000,30,50) -> (10000,30,100) -> (10000,50) -> (10000,1)
你预料到了吗?您是否看到这些是中间步骤的尺寸?现在我知道您的模型期望的输入和输出是什么,我可以轻松地验证您的模型是否训练并处理此类数据。
from tensorflow.keras.layers import LSTM, Dropout, Activation
from tensorflow.keras.models import Sequential
import numpy as np
X = np.random.random((10000,30,8))
Y = np.random.random((10000,1))
model = Sequential()
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.compile('sgd','mse')
model.fit(X,Y)
您是否注意到您的模型需要像 (...,30,8) 这样的输入?您知道您的模型期望输出数据看起来像 (...,1) 吗?了解您的模型想要什么,也意味着您现在可以更改模型以适应您感兴趣的数据。如果您希望数据 运行 在 8 个参数(如时间轴)上,那么您的输入维度需要反映这一点.将 30 更改为 8,并将 8 更改为 1。如果您这样做,还要注意您的第一层正在将每个 1 长向量(单个数字)扩展为 50 长向量。这听起来像您希望模型执行的操作吗?也许您的 LSTM 应该是 LSTM(2) 或 LSTM(5) 而不是 50...等。您可能会花费接下来的 1000 小时来尝试找到适用于您正在使用的数据的正确参数。
也许您不想将 FEATURE space 作为 TIME SPACE,也许尝试将您的数据重复成大小为 10 的批次,其中每个样本都有自己的历史、维度说(10000,10,8)。然后 LSTM(50) 将使用您的 8 长特征 space 并将其更改为 50 长特征 space,同时超过 10 的时间轴。也许您只想保留最后一个 return_sequences=假。
我正在尝试使用 lstm 模型来预测天气(主要是为了了解 lstm 并使用 python)。
我有一个包含 500,000 行的数据集,每行代表一个日期,并且有 8 列是我的特征。
下面是我的模型。
model = Sequential()
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.fit(
X,
y,
batch_size=512,
epochs=100,
validation_split=0.05)
据我所知,对于输入参数,第一个参数是时间步长,所以我在这里说的是,我认为应该使用最后 30 个观察值来预测下一个值。我理解的8就是这样的特征,气压,温度等
所以我的 X 矩阵用下面的线转换成 3D 矩阵所以 X 现在是 500000, 8, 1 矩阵。
X = np.reshape(X, (X.shape[0], X.shape[1], 1))
当我 运行 模型时,我得到以下错误。
ValueError: Error when checking input: expected
lstm_3_input
to have shape (30, 8) but got array with shape (8, 1)
我做错了什么?
我认为您的输入形状不对。 NN 不理解您希望它采用 30 个点的切片来预测第 31 个点。您需要做的是将数据集切成长度为 30 的块(这意味着每个点将被复制 29 次)并对其进行训练,其形状为 (499969, 30, 8) ,假设最后点只进入 y
。也不要在末尾添加虚拟维度,在 RGB 通道的转换层中需要它。
您的问题与数据准备有关。 查找有关 LSTM here.
数据准备的详细信息LSTM 将一系列过去的观察结果映射为输出观察结果的输入。因此,必须将观察序列转换为多个样本考虑给定的单变量序列:
[10, 20, 30, 40, 50, 60, 70, 80, 90]
我们可以将序列分成多个 input/output 称为样本的模式,其中三个 n_steps
时间步用作输入,一个时间步用作一步预测的标签,即学习中。
X, y
10, 20, 30 40
20, 30, 40 50
30, 40, 50 60
# ...
所以你想做的是在下面的split_sequence()
函数中实现的:
# split a univariate sequence into samples
def split_sequence(sequence, n_steps):
X, y = list(), list()
for i in range(len(sequence)):
# find the end of this pattern
end_ix = i + n_steps
# check if we are beyond the sequence
if end_ix > len(sequence)-1:
break
# gather input and output parts of the pattern
seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
X.append(seq_x)
y.append(seq_y)
return array(X), array(y)
回到我们的初始示例,发生以下情况:
# define input sequence
raw_seq = [10, 20, 30, 40, 50, 60, 70, 80, 90]
# choose a number of time steps
n_steps = 3
# split into samples
X, y = split_sequence(raw_seq, n_steps)
# summarize the data
for i in range(len(X)):
print(X[i], y[i])
# [10 20 30] 40
# [20 30 40] 50
# [30 40 50] 60
# [40 50 60] 70
# [50 60 70] 80
# [60 70 80] 90
要点: 现在你的形状应该是你的 LSTM 模型所期望的,你应该能够根据你的需要调整你的数据形状。显然同样适用于多个输入特征行。
让我复制一个用于为 LSTM 准备数据的函数:
from itertools import islice
def slice_data_for_lstm(data, lookback):
return np.array(list(zip(*[islice(np.array(data), i, None, 1) for i in range(lookback)])))
X_sliced = slice_data_for_lstm(X, 30)
在您的案例中,lookback 应为 30,并将创建 30 个 (8, 1) 特征堆栈。结果数据的形状为 (N, 30, 8, 1)。
我认为您可能只需要简单解释一下图层的工作原理。特别要注意的是,所有 Keras 层的行为都是这样的:
NAME(output_dim, input_shape = (...,input_dim))
例如,假设我有 15000 个 3 个长向量,我想将它们更改为 5 个长向量。然后像这样的事情会做到这一点:
import numpy as np, tensorflow as tf
X = np.random.random((15000,3))
Y = np.random.random((15000,5))
M = tf.keras.models.Sequential()
M.add(tf.keras.layers.Dense(5,input_shape=(3,)))
M.compile('sgd','mse')
M.fit(X,Y) # Take note that I provided complete working code here. Good practice.
# I even include the imports and random data to check that it works.
同样,如果我的输入看起来像 (1000,10,5) 并且我 运行 通过 LSTM 之类的 LSTM(7);那么我应该(自动)知道我会得到类似 (...,7) 的输出。这 5 个长向量将变为 7 个长向量。规则来理解。最后一个维度始终是您要更改的向量,图层的第一个参数始终是要将其更改为的维度。
现在是学习 LSTM 的第二件事。他们使用时间轴(这不是最后一个轴,因为我们刚刚过去,它总是 "changing dimension axis")如果 return_sequences=False 则删除,如果 return_sequences= 则保留真的。一些示例:
LSTM(7) # (10000,100,5) -> (10000,7)
# Here the LSTM will loop through the 100, 5 long vectors (like a time series with memory),
# producing 7 long vectors. Only the last 7 long vector is kept.
LSTM(7,return_sequences=True) # (10000,100,5) -> (10000,100,7)
# Same thing as the layer above, except we keep all the intermediate steps.
您提供的图层如下所示:
LSTM(50,input_shape=(30,8),return_sequences=True) # (10000,30,8) -> (10000,30,50)
注意 30 是 LSTM 模型中使用的时间维度。 8和50是INPUT_DIM和OUTPUT_DIM,与时间轴无关。另一个常见的误解是,请注意 LSTM 希望您为每个样本提供它自己的完整过去和时间轴。也就是说,LSTM 不会将先前的样本点用于下一个样本点;每个样本都是独立的,并带有自己完整的过去数据。
让我们来看看您的模型。步骤1。你的模型在做什么,它期望什么样的数据?
from tensorflow.keras.layers import LSTM, Dropout, Activation
from tensorflow.keras.models import Sequential
model = Sequential()
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.compile('sgd','mse')
print(model.input_shape)
model.summary() # Lets see what your model is doing.
所以,现在我清楚地看到你的模型做了: (10000,30,8) -> (10000,30,50) -> (10000,30,100) -> (10000,50) -> (10000,1)
你预料到了吗?您是否看到这些是中间步骤的尺寸?现在我知道您的模型期望的输入和输出是什么,我可以轻松地验证您的模型是否训练并处理此类数据。
from tensorflow.keras.layers import LSTM, Dropout, Activation
from tensorflow.keras.models import Sequential
import numpy as np
X = np.random.random((10000,30,8))
Y = np.random.random((10000,1))
model = Sequential()
model.add(LSTM(50, input_shape=(30, 8), return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(100, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation('linear'))
model.compile('sgd','mse')
model.fit(X,Y)
您是否注意到您的模型需要像 (...,30,8) 这样的输入?您知道您的模型期望输出数据看起来像 (...,1) 吗?了解您的模型想要什么,也意味着您现在可以更改模型以适应您感兴趣的数据。如果您希望数据 运行 在 8 个参数(如时间轴)上,那么您的输入维度需要反映这一点.将 30 更改为 8,并将 8 更改为 1。如果您这样做,还要注意您的第一层正在将每个 1 长向量(单个数字)扩展为 50 长向量。这听起来像您希望模型执行的操作吗?也许您的 LSTM 应该是 LSTM(2) 或 LSTM(5) 而不是 50...等。您可能会花费接下来的 1000 小时来尝试找到适用于您正在使用的数据的正确参数。
也许您不想将 FEATURE space 作为 TIME SPACE,也许尝试将您的数据重复成大小为 10 的批次,其中每个样本都有自己的历史、维度说(10000,10,8)。然后 LSTM(50) 将使用您的 8 长特征 space 并将其更改为 50 长特征 space,同时超过 10 的时间轴。也许您只想保留最后一个 return_sequences=假。