Keras使用TensorFlow和Theano等快速的符号数学库作为后端。
使用这些库的一个缺点是,数据的大小和形状必须预先定义好,并且保持不变,无论您是在训练网络还是进行预测。
在序列预测问题上,在训练网络时使用大批次大小,在预测时使用批次大小为1,以便预测序列中的下一个步,这可能是可取的。
在本教程中,您将了解如何解决这个问题,甚至可以在训练和预测时使用不同的批次大小。
完成本教程后,您将了解:
- 如何设计一个简单的序列预测问题并开发一个LSTM来学习它。
- 如何为在线和基于批次的学习和预测调整LSTM配置。
- 如何调整用于训练的批次大小以区别于用于预测的批次大小。
用我的新书《Python LSTM长短期记忆网络》来启动你的项目,其中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。

如何在Keras中使用Python进行训练和预测的不同批次大小
照片由steveandtwyla拍摄,保留部分权利。
教程概述
本教程分为6个部分,如下所示
- 关于批次大小
- 序列预测问题描述
- LSTM模型和变化的批次大小
- 解决方案1:在线学习(批次大小=1)
- 解决方案2:批量预测(批次大小=N)
- 解决方案3:复制权重
教程环境
假定已安装并正常运行Python 2或3环境。
这包括带有NumPy和Pandas的SciPy。必须安装Keras 2.0或更高版本,并使用TensorFlow或Keras后端。
有关设置 Python 环境的帮助,请参阅以下帖子
需要 LSTM 帮助进行序列预测吗?
参加我的免费7天电子邮件课程,了解6种不同的LSTM架构(附代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
关于批次大小
使用Keras的一个好处是它构建在TensorFlow和Theano等符号数学库之上,用于快速高效的计算。这对于大型神经网络是必需的。
使用这些高效库的一个缺点是,您必须预先定义数据范围并始终保持不变。特别是,批次大小。
批次大小限制了在执行权重更新之前要展示给网络的样本数量。当使用拟合模型进行预测时,同样的限制也会被施加。
具体来说,拟合模型时使用的批次大小决定了您必须一次预测多少次。
当您希望一次预测的数量与训练期间使用的批次大小相同时,这通常不是问题。
当您希望进行的预测少于批次大小时,这会成为一个问题。例如,您可能会从大批次大小中获得最佳结果,但在处理时间序列或序列问题时,可能需要一次预测一个观测值。
这就是为什么在拟合模型到训练数据与预测测试数据或新输入数据时,使用不同的批次大小可能是可取的。
在本教程中,我们将探讨解决此问题的不同方法。
序列预测问题描述
我们将使用一个简单的序列预测问题作为背景,来演示调整训练和预测之间批次大小的解决方案。
序列预测问题非常适合使用变化的批次大小,因为您可能希望在训练期间使用等于训练数据集大小的批次大小(批次学习),而在进行单步预测时使用批次大小为1。
序列预测问题涉及学习预测以下10步序列中的下一步
1 |
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] |
我们可以使用Python创建此序列,如下所示
1 2 3 |
长度 = 10 sequence = [i/float(length) for i in range(length)] 打印(序列) |
运行示例将打印我们的序列
1 |
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] |
我们必须将序列转换为监督学习问题。这意味着当输入模式显示为0.0时,网络必须学会预测下一个步为0.1。
我们可以使用Pandas的shift()函数在Python中执行此操作,如下所示
1 2 3 4 5 6 7 8 9 10 |
从 pandas 导入 concat from pandas import DataFrame # 创建序列 长度 = 10 sequence = [i/float(length) for i in range(length)] # 创建 X/y 对 df = DataFrame(sequence) df = concat([df, df.shift(1)], axis=1) df.dropna(inplace=True) print(df) |
运行示例显示所有输入和输出对。
1 2 3 4 5 6 7 8 9 |
1 0.1 0.0 2 0.2 0.1 3 0.3 0.2 4 0.4 0.3 5 0.5 0.4 6 0.6 0.5 7 0.7 0.6 8 0.8 0.7 9 0.9 0.8 |
我们将使用一种称为长短期记忆网络的递归神经网络来学习序列。因此,我们必须将输入模式从2D数组(1列9行)转换为3D数组,该数组由[行数,时间步长,列数]组成,其中时间步长为1,因为我们每行每个观测值只有一个时间步长。
我们可以使用NumPy的reshape()函数来实现这一点,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
从 pandas 导入 concat from pandas import DataFrame # 创建序列 长度 = 10 sequence = [i/float(length) for i in range(length)] # 创建 X/y 对 df = DataFrame(sequence) df = concat([df, df.shift(1)], axis=1) df.dropna(inplace=True) # 转换为LSTM友好的格式 值 = df。值 X, y = values[:, 0], values[:, 1] X = X.reshape(len(X), 1, 1) print(X.shape, y.shape) |
运行示例将创建可用于LSTM的X和y数组,并打印它们的形状。
1 |
(9, 1, 1) (9,) |
LSTM模型和变化的批次大小
在本节中,我们将为该问题设计一个LSTM网络。
训练批次大小将覆盖整个训练数据集(批次学习),并且预测将一次一个地进行(单步预测)。我们将展示,尽管模型学习了该问题,但单步预测会导致错误。
我们将使用一个LSTM网络,训练1000个周期。
在每个训练周期结束时(批次学习),权重将更新,这意味着批次大小将等于训练观测值的数量(9)。
对于这些实验,我们将需要对LSTM内部状态何时更新进行细粒度控制。正常情况下,Keras会在每个批次结束后清除LSTM状态,但我们可以通过使LSTM状态化并调用model.reset_state()来手动管理此状态。这将在后续部分中使用。
网络有一个输入,一个包含10个单元的隐藏层,以及一个包含1个单元的输出层。LSTM单元使用默认的tanh激活函数,输出层使用线性激活函数。
对于这个回归问题,我们使用均方误差优化函数和高效的ADAM优化算法。
下面的示例配置并创建了网络。
1 2 3 4 5 6 7 8 9 |
# 配置网络 n_batch = len(X) n_epoch = 1000 n_neurons = 10 # 设计网络 model = Sequential() model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') |
我们将拟合网络到每个周期的所有示例,并手动重置网络的狀態。
1 2 3 4 |
# 拟合网络 for i in range(n_epoch): model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False) model.reset_states() |
最后,我们将逐个预测序列中的每个步。
这需要批次大小为1,这与拟合网络时使用的批次大小9不同,并且在运行示例时会导致错误。
1 2 3 4 5 6 |
# 在线预测 for i in range(len(X)): testX, testy = X[i], y[i] testX = testX.reshape(1, 1, 1) yhat = model.predict(testX, batch_size=1) print('>预期=%.1f, 预测=%.1f' % (testy, yhat)) |
下面是完整的代码示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
from pandas import DataFrame 从 pandas 导入 concat from keras.models import Sequential from keras.layers import Dense 来自 keras.层 导入 LSTM # 创建序列 长度 = 10 sequence = [i/float(length) for i in range(length)] # 创建 X/y 对 df = DataFrame(sequence) df = concat([df, df.shift(1)], axis=1) df.dropna(inplace=True) # 转换为LSTM友好的格式 值 = df。值 X, y = values[:, 0], values[:, 1] X = X.reshape(len(X), 1, 1) # 配置网络 n_batch = len(X) n_epoch = 1000 n_neurons = 10 # 设计网络 model = Sequential() model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') # 拟合网络 for i in range(n_epoch): model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False) model.reset_states() # 在线预测 for i in range(len(X)): testX, testy = X[i], y[i] testX = testX.reshape(1, 1, 1) yhat = model.predict(testX, batch_size=1) print('>预期=%.1f, 预测=%.1f' % (testy, yhat)) |
运行示例可以正常拟合模型,但在进行预测时会出错。
报告的错误如下:
1 |
ValueError: 无法为形状为'(9, 1, 1)'的Tensor 'lstm_1_input:0'提供形状为'(1, 1, 1)'的值 |
解决方案1:在线学习(批次大小=1)
解决此问题的一种方法是使用在线学习拟合模型。
这是将批次大小设置为1,并在每个训练示例后更新网络权重。
这可以加快学习速度,但也会增加学习过程的不稳定性,因为权重会随着每个批次而广泛变化。
尽管如此,这也能让我们对该问题进行单步预测。唯一需要的更改是将n_batch设置为1,如下所示:
1 |
n_batch = 1 |
完整的代码列表如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
from pandas import DataFrame 从 pandas 导入 concat from keras.models import Sequential from keras.layers import Dense 来自 keras.层 导入 LSTM # 创建序列 长度 = 10 sequence = [i/float(length) for i in range(length)] # 创建 X/y 对 df = DataFrame(sequence) df = concat([df, df.shift(1)], axis=1) df.dropna(inplace=True) # 转换为LSTM友好的格式 值 = df。值 X, y = values[:, 0], values[:, 1] X = X.reshape(len(X), 1, 1) # 配置网络 n_batch = 1 n_epoch = 1000 n_neurons = 10 # 设计网络 model = Sequential() model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') # 拟合网络 for i in range(n_epoch): model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False) model.reset_states() # 在线预测 for i in range(len(X)): testX, testy = X[i], y[i] testX = testX.reshape(1, 1, 1) yhat = model.predict(testX, batch_size=1) print('>预期=%.1f, 预测=%.1f' % (testy, yhat)) |
运行示例将打印9个预期结果和正确的预测。
1 2 3 4 5 6 7 8 9 |
>预期=0.0, 预测=0.0 >预期=0.1, 预测=0.1 >预期=0.2, 预测=0.2 >预期=0.3, 预测=0.3 >预期=0.4, 预测=0.4 >预期=0.5, 预测=0.5 >预期=0.6, 预测=0.6 >预期=0.7, 预测=0.7 >预期=0.8, 预测=0.8 |
解决方案2:批量预测(批次大小=N)
另一种解决方案是一次性批量处理所有预测。
这意味着模型的使用方式会受到很大限制。
我们必须一次性使用所有预测,或者只保留第一个预测并丢弃其余的。
我们可以通过使用等于训练批次大小的批次进行预测,然后枚举批量预测来调整示例,如下所示:
1 2 3 4 |
# 批量预测 yhat = model.predict(X, batch_size=n_batch) for i in range(len(y)): print('>预期=%.1f, 预测=%.1f' % (y[i], yhat[i])) |
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
from pandas import DataFrame 从 pandas 导入 concat from keras.models import Sequential from keras.layers import Dense 来自 keras.层 导入 LSTM # 创建序列 长度 = 10 sequence = [i/float(length) for i in range(length)] # 创建 X/y 对 df = DataFrame(sequence) df = concat([df, df.shift(1)], axis=1) df.dropna(inplace=True) # 转换为LSTM友好的格式 值 = df。值 X, y = values[:, 0], values[:, 1] X = X.reshape(len(X), 1, 1) # 配置网络 n_batch = len(X) n_epoch = 1000 n_neurons = 10 # 设计网络 model = Sequential() model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') # 拟合网络 for i in range(n_epoch): model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False) model.reset_states() # 批量预测 yhat = model.predict(X, batch_size=n_batch) for i in range(len(y)): print('>预期=%.1f, 预测=%.1f' % (y[i], yhat[i])) |
运行示例将打印预期的和正确预测的值。
1 2 3 4 5 6 7 8 9 |
>预期=0.0, 预测=0.0 >预期=0.1, 预测=0.1 >预期=0.2, 预测=0.2 >预期=0.3, 预测=0.3 >预期=0.4, 预测=0.4 >预期=0.5, 预测=0.5 >预期=0.6, 预测=0.6 >预期=0.7, 预测=0.7 >预期=0.8, 预测=0.8 |
解决方案3:复制权重
一个更好的解决方案是为训练和预测使用不同的批次大小。
做到这一点的方法是复制拟合网络的权重,并创建一个具有预训练权重的新网络。
我们可以使用Keras API中的get_weights()和set_weights()函数轻松地做到这一点,如下所示:
1 2 3 4 5 6 7 8 9 |
# 重新定义批次大小 n_batch = 1 # 重新定义模型 new_model = Sequential() new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) new_model.add(Dense(1)) # 复制权重 old_weights = model.get_weights() new_model.set_weights(old_weights) |
这创建了一个用批次大小为1编译的新模型。然后,我们可以使用这个新模型进行单步预测:
1 2 3 4 5 6 |
# 在线预测 for i in range(len(X)): testX, testy = X[i], y[i] testX = testX.reshape(1, 1, 1) yhat = new_model.predict(testX, batch_size=n_batch) print('>预期=%.1f, 预测=%.1f' % (testy, yhat)) |
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
from pandas import DataFrame 从 pandas 导入 concat from keras.models import Sequential from keras.layers import Dense 来自 keras.层 导入 LSTM # 创建序列 长度 = 10 sequence = [i/float(length) for i in range(length)] # 创建 X/y 对 df = DataFrame(sequence) df = concat([df, df.shift(1)], axis=1) df.dropna(inplace=True) # 转换为LSTM友好的格式 值 = df。值 X, y = values[:, 0], values[:, 1] X = X.reshape(len(X), 1, 1) # 配置网络 n_batch = 3 n_epoch = 1000 n_neurons = 10 # 设计网络 model = Sequential() model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') # 拟合网络 for i in range(n_epoch): model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False) model.reset_states() # 重新定义批次大小 n_batch = 1 # 重新定义模型 new_model = Sequential() new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) new_model.add(Dense(1)) # 复制权重 old_weights = model.get_weights() new_model.set_weights(old_weights) # 编译模型 new_model.compile(loss='mean_squared_error', optimizer='adam') # 在线预测 for i in range(len(X)): testX, testy = X[i], y[i] testX = testX.reshape(1, 1, 1) yhat = new_model.predict(testX, batch_size=n_batch) print('>预期=%.1f, 预测=%.1f' % (testy, yhat)) |
运行示例将打印预期值,并再次正确预测值。
1 2 3 4 5 6 7 8 9 |
>预期=0.0, 预测=0.0 >预期=0.1, 预测=0.1 >预期=0.2, 预测=0.2 >预期=0.3, 预测=0.3 >预期=0.4, 预测=0.4 >预期=0.5, 预测=0.5 >预期=0.6, 预测=0.6 >预期=0.7, 预测=0.7 >预期=0.8, 预测=0.8 |
总结
在本教程中,您了解了如何解决在同一网络中训练和预测时需要改变批次大小的问题。
具体来说,你学到了:
- 如何设计一个简单的序列预测问题并开发一个LSTM来学习它。
- 如何为在线和基于批次的学习和预测调整LSTM配置。
- 如何调整用于训练的批次大小以区别于用于预测的批次大小。
关于批次大小,您有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
一个很好的技巧。创建另一个仅用于评估测试数据集的模型以比较训练/测试的RMSE也很有用。
Sam,你到底是什么意思?
你好 Jason,
我有一些数据,每100行代表一个类别。我应该如何为LSTM处理数据?
,emg1,emg2,emg3,emg4,emg5,emg6,emg7,emg8,quat1,quat2,quat3,quat4,acc1,acc2,acc3,gyro1,gyro2,gyro3
0,81,342,283,146,39,71,36,31,1121,-2490,930,16128,-797,4,2274,49,2920,252
0,70,323,259,125,34,53,29,31,1055,-3112,1075,16015,-878,369,1830,516,3590,243
0,53,298,246,100,49,37,27,33,1019,-3792,1239,15858,-809,527,1511,632,3953,46
0,42,154,193,172,95,48,28,28,1018,-4433,1360,15681,-724,358,1235,486,3754,-183
0,41,150,179,242,225,76,51,43,1066,-4980,1464,15503,-827,176,1073,525,3209,-415
…
好问题,这会给你一些想法
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
您好,我想问您如何将当前网络的权重乘以一个参数并将其分配给另一个网络,这就是所谓的软更新。非常感谢!
您能解释一下这个模型的权重矩阵的维度吗?只是好奇想知道。我想了解Keras如何存储权重。
编译模型后,您可以按如下方式打印它:
您好,您能解释一下为什么在最后一个示例的第18行重新定义n_batch = 1吗?我认为它应该是一个不同的值,对吗?
在什么情况下Logan?
我认为他指的是最后一个完整示例的第18行和第31行。第18行应该是以下内容,或者? n_batch=len(X)
您好,Jason Brownlee博士。您能告诉我您在这个示例中使用的Keras版本吗?我尝试复制代码在我的Mac上运行,但它不起作用。
Keras 2.0或更高版本。
您好,Jason Brownlee。您能解释一下为什么在最后一个示例的第18行定义n_batch=1吗?我认为n_batch应该分配给其他值。
我尝试重新定义n_batch=len(X),训练模型,并将权重复制到新模型“new_model”中。但我没有得到正确的预测结果。您能帮忙找出原因吗?
>预期=0.0, 预测=0.0
>预期=0.1, 预测=0.1
>预期=0.2, 预测=0.3
>预期=0.3, 预测=0.5
>预期=0.4, 预测=0.8
>预期=0.5, 预测=1.1
>预期=0.6, 预测=1.4
>预期=0.7, 预测=1.7
>预期=0.8, 预测=2.1
以下是我使用的代码,除了第18行之外,它与最后一个示例相同
from pandas import DataFrame
from pandas import concat
来自 keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
# 创建序列
length = 10
sequence = [i/float(length) for i in range(length)]
# 创建 X/y 对
df = DataFrame(sequence)
df = concat([df, df.shift(1)], axis=1)
df.dropna(inplace=True)
# 转换为LSTM友好的格式
values = df.values
X, y = values[:, 0], values[:, 1]
X = X.reshape(len(X), 1, 1)
# 配置网络
n_batch = len(X)
n_epoch = 1000
n_neurons = 10
# 设计网络
model = Sequential()
model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
# 拟合网络
for i in range(n_epoch)
model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False)
model.reset_states()
# 重新定义批次大小
n_batch = 1
# 重新定义模型
new_model = Sequential()
new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
new_model.add(Dense(1))
# 复制权重
old_weights = model.get_weights()
new_model.set_weights(old_weights)
# 编译模型
new_model.compile(loss=’mean_squared_error’, optimizer=’adam’)
# 在线预测
for i in range(len(X))
testX, testy = X[i], y[i]
testX = testX.reshape(1, 1, 1)
yhat = new_model.predict(testX, batch_size=n_batch)
print(‘>预期=%.1f, 预测=%.1f’ % (testy, yhat))
在测试中,我发现虽然批次大小为1时模型似乎在学习一个模式:http://tinyurl.com/ycutvy7h,但较大的批次大小通常会收敛到静态预测,类似于线性回归(批次大小5):http://tinyurl.com/yblzfus4
尽管如此,后一个示例(批次大小5)的RMSE实际上更低。这让我不禁想,我是否真的有东西可以学习,或者平坦的线是否表明除了回归之外没有其他模式?
有意思。
有些问题可能无法从LSTM这样的复杂模型中受益。这就是为什么我们使用简单方法进行基线测试——以查看我们能否增加价值。
更复杂/更灵活的不总是更好。
严格来说,我的问题可能是一个分类问题,因为我真正想知道的是,“明天的走势是向上还是向下?”但并非如此,因为幅度很重要。例如,以下示例都具有相同的奖励:a)正确预测明天“向上”,实际结果为+6;b)预测三天“向上”,实际结果为+2;c)预测两天“向下”,实际结果为-3。
对于这种类型的问题,您认为哪种模型最好?考虑强化学习,例如https://github.com/matthiasplappert/keras-rl。
头脑风暴所有可能的框架,然后评估每个框架。
我很少看到从业者将DQN RL概念从Gym游戏示例中推广出来。您认为有没有理由不能将时间序列预测视为一个雅达利游戏,其中观察到的游戏状态被替换为我们的时间序列观测值,我们要求代理预测(玩两种球拍位置之一)明天的“向上”或“向下”,如上所述?这是否听起来比您在本帖中采取的更偏向回归的方法有渐进式进步?
你可以试试,我还没有深入考虑过DRL在时间序列上的适用性,抱歉。
非常好的帖子,Jason!我昨天遇到了这个问题,您的博客帮助我解决了它。
我认为您应该将n_batch重置为不同于1的值,正如@Zhiyu Wang在第三种解决方案中提到的,因为您在后面的代码(第31行)中将其重新定义为1,所以您最终没有在训练和预测之间实现不同的批次大小。
谢谢Saad,我明白了。我已经更新了示例,在最后一个示例中*实际*使用了不同的批次大小!
Brownlee医生您好,作为一名刚开始接触机器学习的人,我想感谢您提供的所有精彩内容。您的博客非常有帮助。
至于不同批次的数量,我们能否不提供“batch_input_shape”而是提供“input_shape”,然后使用“model.train_on_batch”并为每个训练步骤手动切片输入?我们还需要删除“stateful=True”,但由于状态在每个批次上都会重置,我相信它仍然可以正常工作。类似这样
…
model.add(LSTM(n_neurons, input_shape=(X.shape[1], X.shape[2]))
…
for i in range(n_epoch)
batch_start = 0
for j in range(1, len(X) + 1)
if j % n_batch == 0
model.train_on_batch(X[batch_start:j], y[batch_start:j])
batch_start = j
我猜我专注于展示如何做到这一点,当LSTM是stateful的时候。
风险在于您会缩短序列长度,并影响BPTT。
对于所有事情,请进行测试,看看它在您的项目上表现如何。
嗨,Jason,
我在stateful LSTM的model.predict()上遇到了麻烦,多亏了从这个页面学到的东西,我终于让它工作了,谢谢!
然而,我仍然对一件事感到困惑。
在页面顶部的介绍中,它说在使用Keras时,“你必须预先定义好数据的范围,并且永远如此。特别是,批次大小。”
这似乎对stateful LSTM是真的,对stateless LSTM不是,我对其他RNN或Keras的其他部分一无所知。也许你可以澄清一下。
我之所以对stateless LSTM有所怀疑,是因为这个例子
https://github.com/fchollet/keras/blob/master/examples/lstm_text_generation.py
工作正常。它的要点是
model = Sequential()
model.add(LSTM(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
model.fit(X, y, batch_size=128, epochs=1)
x = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence)
x[0, t, char_indices[char]] = 1.
preds = model.predict(x, verbose=0)[0]
所以它在构建模型时没有指定批次大小;它使用128的显式批次大小参数进行训练;并且在没有批次大小参数的情况下对批次大小为1的数据集调用predict()。看起来模型没有绑定批次大小,而是动态地适应你给它的任何数据。
但我花了很长时间试图修改那个例子以适用于stateful LSTM,但失败了。显然,你说的对,对于stateful LSTM,你不能这样做。你必须显式地指定批次大小来向模型添加一个stateful LSTM层,之后模型就严格地绑定到该大小,并且不能使用任何其他批次大小的数据进行训练或预测。
如果我错了,请纠正我,我刚开始接触这个。
谢谢!
是的,这只对stateful LSTM是正确的。
嗨,Jason,
感谢这篇很棒的教程。
批次大小限制了在执行权重更新之前可以看到网络的样本数量。
“””””””””这个限制同样适用于使用拟合模型进行预测。
具体来说,在拟合模型时使用的批次大小决定了您必须一次进行多少次预测。”””””””
你能否详细说明一下批次大小如何影响预测?
是的,具体问题是什么?
非常感谢您的教程。非常有帮助。
你能帮我解决我的问题吗?
我使用了您的解决方案3,即从训练模型复制权重到新模型。
但仍然在用单批次测试数据进行预测时出现相同的错误,即
“AttributeError: ‘list’ object has no attribute ‘shape'”
我的数据
训练输入数据的形状是(5,2,3)
测试输入数据的形状是(1,2,3)
训练输出数据的形状是(5,2,5)
预期输出数据的形状是(1,2,5)
代码
model = Sequential()
model.add(LSTM(5, batch_input_shape=(5, 2, 3), unroll=True, return_sequences=True))
model.add(Dense(5))
model.compile(loss=’mean_absolute_error’, optimizer=’adam’)
model.fit(x, o, nb_epoch=2000, batch_size=5, verbose=2)
new_model = Sequential()
new_model.add(LSTM(5, batch_input_shape=(1, 2, 3), unroll=True, return_sequences=True))
new_model.add(Dense(5))
old_weights = model.get_weights()
new_model.set_weights(old_weights)
new_model.compile(loss=’mean_absolute_error’, optimizer=’adam’)
提前感谢!
很高兴听到这个消息。
错误表明输入数据可能是列表而不是numpy数组。尝试将其转换为numpy数组。
我尝试使用第三种方法,保存模型的权重,然后定义一个新的批次大小为一的模型。然而,当我用新模型处理相同的数据集时,我发现除了第一次预测之外,很多结果都不同。如果我用批次大小=1训练模型,然后用旧模型的权重创建一个新模型,就会得到完全相同的预测。批次大小不同的模型在根本上处理数据的方式不同吗?例如,如果我的批次大小=32,预测1-32、33-64、65-96……是否使用每个组的一个状态进行预测,而批次大小为1的模型则为每个输入更新状态?
批次大小可能会影响训练,它决定了在更新之前使用多少样本来估计误差梯度。
这可能就是您的情况。尝试用不同的批次大小进行测试,看看您的模型对该值的敏感程度如何?
我看到了类似的结果。如果我用一个批次大小进行训练,并将权重复制到一个具有不同批次大小的模型中,那么新模型的预测误差总是更差。
我决定简化我的数据集。现在我正在处理50个余弦周期,每个周期有1000个点,并根据当前点预测下一个点。简化数据集并没有给我带来更好的结果。
我为我训练的模型和复制权重的模型尝试了各种批次大小。批次大小似乎没有太大区别。
好消息是,将权重复制到具有相同批次大小的模型中不会改变任何内容,所以我知道我复制得是正确的。
这可能是神经网络的随机性。
确保您对模型进行了稳健的评估。我推荐此过程
https://machinelearning.org.cn/evaluate-skill-deep-learning-models/
感谢您的建议。这给了我很大的帮助。
具有复制权重的模型仍然表现较差,并且我有更好的指标来证明这一点。
好消息是,我也改进了从训练中产生的模型,并且这种改进也体现在了复制权重的模型中。
由于我训练的是序列数据,我不允许对其进行混洗,并且在各个时期之间也没有对其进行混洗。每个时期都只是根据前一个时期相同的数据序列进行训练。
您关于k折交叉验证的部分促使我尝试类似的方法来保留数据序列。现在,我在各个时期之间移动序列的起始点,并获得了一组似乎转移得更好的权重。
做得好,谢谢Michael告知。
Jason您好,我复制并粘贴了您在本地运行的最后一个示例,但输出与您的不同。
keras版本:2.0.8
>预期=0.0, 预测=0.0
>预期=0.1, 预测=0.1
>预期=0.2, 预测=0.3
>预期=0.3, 预测=0.5
>预期=0.4,预测=0.6
>预期=0.5,预测=0.7
>预期=0.6,预测=0.8
>预期=0.7,预测=0.9
>预期=0.8,预测=0.9
也许可以尝试运行几次示例?
我遇到了类似的预测不准确的问题。当我使新模型非stateful时,一切都开始正常工作了。我接下来的功课是弄清楚原因。我目前的理论是,状态被定义为一次处理9个样本,而不是1个。
我将尝试使用不同的训练和预测批次大小,看看stateful模型的预测是否会收敛。
坚持住。
我也有同样的问题,与
new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
我得到
>预期=0.0, 预测=0.0
>预期=0.1, 预测=0.1
>预期=0.2, 预测=0.3
>预期=0.3, 预测=0.5
>预期=0.4,预测=0.7
>预期=0.5,预测=1.0
>预期=0.6,预测=1.3
>预期=0.7,预测=1.6
>预期=0.8,预测=1.8
用
new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=False))
我得到
>预期=0.0, 预测=0.0
>预期=0.1, 预测=0.1
>预期=0.2, 预测=0.2
>预期=0.3, 预测=0.3
>预期=0.4, 预测=0.4
>预期=0.5, 预测=0.5
>预期=0.6, 预测=0.6
>预期=0.7, 预测=0.7
>预期=0.8, 预测=0.8
由于原始模型是stateful的,新的模型不应该是stateful的吗?
嗨,Jason!
我认为这里应该将DataFrame的移位从
# 创建 X/y 对
df = DataFrame(sequence)
df = concat([df, df.shift(1)], axis=1)
推广到
# 创建 X/y 对
df = DataFrame(sequence)
df = concat([df, df.shift(-1)], axis=1)
改为以不同的顺序获取训练/测试集
1 0.0 0.1
2 0.1 0.2
3 0.2 0.3
4 0.3 0.4
5 0.4 0.5
6 0.6 0.7
7 0.7 0.8
8 0.8 0.9
9 0.9 NA ????
或者我错过了什么?
我同意——一开始就让我感到困惑!
嗨,Jason,
我有一个问题想请教您,希望能得到您的见解。
我正在构建一个模型,一个堆叠LSTM模型,return sequences = True,stateful = True,带有一个TimeDistributed dense层。
本质上,我感到困惑的是以下几点。
假设我的数据集是X = [0,1,2,3,4,5],Y = [7,8,9,10,11,12],并且我使用batch_size = 2进行训练
所以我将X转换为[[[0],[3]],[[1],[4]],[[2],[5]]],也就是说,3个批次输入2个时间步,每个时间步包含一个特征。
我还假设我需要将Y也转换为[[[7],[10]],[[8],[11]],[[9],[12]]]。
这是正确的吗?如果是,这是否意味着我需要在收到预测时重新排列我的输出?
以及当我们将预测批次大小更改为1时,这会如何变化?
哦,抱歉,我的意思是数据集 = [1,2,3,4,5,6,7,8,9,10]
我想让我的输入序列是[1,2],我的模型返回输出序列[3,4]
当batch size = 2时,我的输入/输出会是什么样的?
当batch size = 1时,这会有什么不同?
这篇文章将帮助您重塑数据集。
https://machinelearning.org.cn/reshape-input-data-long-short-term-memory-networks-keras/
你好,
非常感谢您的教程。作为初学者,我学到了很多,但我在理解stateful LSTM的批次大小和时间步长概念时遇到了麻烦。
根据Keras文档,“stateful: Boolean(默认False)。如果为True,则批次中索引i的样本的最后一个状态将被用作下一个批次中索引i的样本的初始状态。”这似乎与解决方案2和3不同。
例如,考虑4个序列作为x,
[1,2,3,4]
[a,b,c,d]
[5,6,7,8]
[e,f,g,h]
当batch size != 1时,如何构造x?
当timesteps = 1时,
根据文档,x似乎是[[1,a,5,e],[2,b,6,f],[3,c,7,g],[4,d,8,h]]
根据您的教程,x似乎是[[1,2,3,4],[a,b,c,d],[5,6,7,8],[e,f,g,h]]
哪个是正确的?
您的输入样本的构造不受您的批次大小的影响。
我不确定我目前的方法是否能达到同样的效果。
我有一个训练过程,在结束时,它将模型和权重保存到一个文件中。
model.save(model_file)
model.save_weights(weights_file)
然后预测程序使用以下方法加载它们
model = load_model(model_file)
model.load_weights(weights_file)
预测程序不会在代码中重建网络,而是从文件中重建。
然后我使用
raw_prediction = model.predict(x_scaled, batch_size=1)
有什么我应该做但没做的事情吗?您的代码有stateful LSTM,并且从头开始重建网络,我不知道这些步骤是否会导致任何不同的结果。
我也很不清楚在同一数据集上多次运行.fit()的理由。
# 拟合网络
for i in range(n_epoch)
model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False)
model.reset_states()
这有什么作用?
这展示了如何在整个训练数据集上手动运行训练周期,让您能够控制在各个周期之间重置状态。
感谢您的教程,我有一个关于stateful RNN/LSTM的问题。
Kerras文档在这里 https://keras.org.cn/getting-started/faq/ 声明
使RNN stateful意味着每个批次中样本的状态将被用作下一个批次中样本的初始状态。
因此,在使用stateful RNN时,假设
所有批次都具有相同数量的样本
如果x1和x2是连续的样本批次,那么对于每个i,x2[i]是x1[i]的后续序列。
如果这是正确的,那么它意味着如果我有m个独立测量的时序(比如同一现象的m个观察值来自不同来源),每个时序由n个点组成。为了简单起见,每个点都是一个标量。
1) 那么对于stateful RNN,总共需要n个批次。
2) 每个批次的大小为(m,1),并且包含每个时序的第i个样本,其中
i<=n。
3) 批次需要按1到n的顺序排列
通俗地说,每个批次都将包含每个时序的第i个样本。进行水平切片以获得批次。
我的理解正确吗?
PS. 将每个时序转换为监督时序的效果未在此考虑。
听起来没错。
在您的第一个示例中,当n_batch = len(X)时,如果您将Stateful设置为False,并且在每个时期之后不重置状态(reset_states),结果是否相同?
一个批次中的所有样本都会保留状态,并在最后进行一次权重更新。
您好,教程很棒。我学到了很多。我只有一个问题。通过这个,我能否在3年的数据集上训练我的LSTM,然后保存权重,并创建一个新的LSTM网络加载权重,并用每个新传入的观测值来训练它并预测1个观测值?
我想要的是在训练步骤之后避免保留3年的历史记录,并且只用新数据重新训练网络。
谢谢!
是的,这被称为模型更新。请参阅此帖子。
https://machinelearning.org.cn/update-lstm-networks-training-time-series-forecasting/
太好了!谢谢Jason,文章很棒!
谢谢。
你好,
我很难找到RNN的输入结构在字符和时间序列分析中不同的原因。例如,
对于字符分析,我们使用以下输入结构
input = tf.placeholder(tf.int32, [batch_size, num_steps], name = "input"]
但对于时间序列分析,它是这样的
input = tf.placeholder(tf.int32, [batch_size,time_steps, inputs], name = "input"]
假设
num_step
和time_steps
是相同的(RNN回溯的周期数),为什么在RNN的时间序列分析中会使用额外的inputs
?如果有人能帮助我回答这个问题,我将不胜感激!我很难理解这个问题。
谢谢!
抱歉,我没有Tensorflow的直接示例。
嗨,Jason博士,
我使用的是keras 2.1.2,我正在查看您的示例。
我想知道为什么我们需要构建一个全新的网络来使用不同的批次大小,因为我们已经可以选择将batch_size传递给model.predict方法。
如果我可以简单地使用
model.fit(….batch_size=n1)
然后
model.predict(….batch_size=n2)
我是否忽略了这篇文章的整个直觉?
如果那样的话,我先致歉。
此致,
Mohaimen
因为它会引发一个错误。
嗨,Jason博士,
非常感谢您的回复。
我查看了model.predict的文档。它说如果您不在这里传递批次大小,它将使用默认批次大小32。我测试过,它没有失败。
可能是我遗漏了什么。我会再看一遍,如果我发现它失败了,我会回来说明。
顺便问一下,除了使用elephas和dist-keras之外,还有什么方法可以在Keras中进行分布式模型训练吗?Elephas似乎坏了,而且作者没有修复它。您能推荐一种方法吗?
提前感谢。
什么是“elephas”?
嗨,Jason,
Elephas和Dist-Keras都是Keras的扩展,允许分布式深度学习(我尝试了Elephas但无法运行)与Spark集成。
顺便说一下:我使用了您许多示例来学习如何编写基于Keras的模型。非常感谢您的慷慨!
谢谢。
https://github.com/maxpumperla/elephas
感谢分享。
很棒的教程。我浪费了很多时间在Keras文档中寻找解决方案,但毫无用处……我想知道为什么他们不像这个精彩的教程那样清楚地说明。无论如何,再次感谢,继续保持出色的工作!
我很高兴它有帮助!
我的问题是,我的一个keras编码器-解码器在GPU上只能使用batch_size=1工作。对于CPU没有问题。您是否理解这与GPU/CPU的关系?
抱歉,我不知道,也许在CPU上运行?
Jason您好,教程很棒。但我想问一下LSTM的输入层是什么“LSTM友好格式”。
使用LSTM作为第一个隐藏层时,数据必须具有[样本,时间步长,特征]的3D形状。
您好,Bronwlee博士,我用batch_size=8训练了模型,并尝试用batch_size=1进行预测。我认为第三种方法,即复制权重,会是一个很好的选择,并且我会尝试复制您的代码。但是,有没有可能使用Keras函数“predict_on_batch”呢?实际上,我在我的代码中使用predict_on_batch没有出现ValueError,但是出现了不同的结果,我不确定这是否是“predict_on_batch”的后果。总而言之,您能否告诉我是否可以使用Keras函数“predict_on_batch”来代替?
也许它会起作用,我还没有尝试过。
感谢您提供的精彩教程。我正在尝试对体育数据集实现一个多变量时间序列预测模型。我有几个问题,如果您能帮助我,我将不胜感激。
每个样本(每个比赛有唯一的ID)的频率(30秒)是相同的,但数据框中的样本大小不同。也就是说,有时比赛需要更长的时间来完成。
每个样本或比赛(有20多个特征)都具有相同的起始时间格式00:00:00,但大多数样本的结束时间不同。可能是01:32:30, 01:33:30, 01:35:00, 01:36:30……
我能否使用唯一的ID来指定序列长度,也就是说,不同的batch_size?
时间格式是否必须始终为Y/M/D H/M/S,或者上面的格式是否被接受?
也许这会有帮助。
https://machinelearning.org.cn/data-preparation-variable-length-input-sequences-sequence-prediction/
这与使用batch_input_shape=(None, None, X.shape[2])有什么区别??
据我理解的API,这只在处理有状态的(当你控制状态重置)LSTM时使用。
谢谢 Jason。
如果您能澄清滞后(lags)、时间步(timesteps)、周期(epochs)、批次大小(batchsize)将是很好的。更多细节请参见
https://stats.stackexchange.com/questions/307744/lstm-for-time-series-lags-timesteps-epochs-batchsize
滞后是先前时间步的观测值。
滞后观测值可用作LSTM的时间步。
一个周期由一个或多个样本组成,其中一个样本由一个或多个时间步和特征组成。
一个批次是周期中样本的子集。一个周期包含一个或多个样本批次。
你好 Jason,
我有一个地方没弄懂,
当我使用LSTM时,预测步长(在训练中)不依赖于训练批次大小,即使根据您的帖子(https://machinelearning.org.cn/use-different-batch-sizes-training-predicting-python-keras/),您也只使用series_to_supervised函数向前一步,那么为什么在这篇博客中您说您预测的样本数由训练阶段的批次大小定义?
在使用Keras的有状态LSTM时,训练和预测时的批次大小必须匹配。
也许重新阅读一下帖子会更清楚?
你好,
如果我堆叠了LSTM层,我是否必须在每一层都设置‘stateful=True’,还是只需要在最后一层设置?
通常,所有的LSTM层要么都有状态,要么都没有状态。
您好,我有很多时间序列,我想用一个模型来拟合它们。将一个for循环用于n个时间序列,并将batch_size设置为我标准的TS大小,这样有意义吗?
抱歉,我不明白您的问题,您能否详细说明一下?
嗨,Jason,
感谢您的分享。我有一个问题,如果您能指导我一下,那就太好了。我有一个二元分类问题,用于预测性维护,即预测发动机的下一次故障时间或剩余寿命。我有很多数据集,即使我只选择5%的数据,大小也约为2GB。我们有近86个传感器的系列数据集。时间步长为1分钟。我们大约有1000个事件,我们可以将其标记为发动机即将发生故障。
我们选择了LSTM,但问题是用户的要求是提前1-2天或1440或2880个时间步(每分钟一个时间步)来了解情况,因此我们必须设置序列的时间窗口和输入长度=1440–2880,这在创建要训练到LSTM的序列时会导致失败。
建议是将数据集分为450个系列进行训练,每次20个系列,然后循环直到完全训练完450个系列或我们拥有的海量数据集。
我能否使用您的技术来进行这种实验?或者您是否有任何进一步的建议或更好的方法。请随时提供建议。
非常感谢。
此致,
Wirasak Chomphu
也许您可以以不同的规模/分辨率来模拟这个问题?
嗨,Jason,
感谢您的回复。我只是想知道,如果生产要求是知道分钟级的故障时间,这在实际情况中是否有效?
您必须通过开发和评估在您的特定数据集上的模型来找到答案。
你好,
感谢您提供很棒的网站和这篇文章。我有2个问题
1. 当我复制粘贴完整的示例时,我得到的结果与您给出的结果不同(似乎您获得了100%的准确率)。
2. 为什么您使用stateful=True?如果不使用它会发生什么?
是的,这是可以预期的,参见
https://machinelearning.org.cn/faq/single-faq/why-do-i-get-different-results-each-time-i-run-the-code
有状态意味着LSTM的内部状态只有在我们手动重置它时才会重置。否则,状态会在每个批次结束时重置。
我还有另一个问题
为什么您使用“compile”来处理新模型,而不是使用“fit”函数?“compile”对“old_weights”有什么影响?
我知道Keras模型在使用前必须编译。
也许在最终示例中不需要编译——我以为需要。您在没有它的情况下测试过吗?
没有,我没试过。但我尝试修改您的示例,并用大于1的时间步长进行测试,但我遇到了这样的错误
ValueError: Error when checking input: expected lstm_114_input to have shape (1, 1) but got array with shape (60, 1)
我的代码看起来像这样,但在这一行代码上我得到了上述错误:“new_model.set_weights(old_weights)”
model = Sequential()
model.add(LSTM(units = 60, return_sequences = True, batch_input_shape = (60, 60, 1) , stateful=True))
model.add(Dropout(0.2))
model.add(LSTM(units = 60, return_sequences = True))
model.add(Dropout(0.2))
model.add(LSTM(units = 60, return_sequences = True))
model.add(Dropout(0.2))
model.add(LSTM(units = 60))
model.add(Dropout(0.2))
model.add(Dense(units = 1))
model.compile(optimizer = ‘adam’, loss = ‘mean_squared_error’)
for i in range(100)
model.fit(X_train, y_train, epochs=1, batch_size = 60 , verbose=1, shuffle=False)
model.reset_states()
new_model = Sequential()
new_model.add(LSTM(units = 60 , batch_input_shape=(1, 60 , 1) , stateful = True))
new_model.add(Dense(units = 1))
old_weights = model.get_weights()
new_model.set_weights(old_weights)
new_model.compile(optimizer = ‘adam’, loss = ‘mean_squared_error’)
new_model.reset_states()
也许您数据的形状不正确?
您必须更改数据集和模型。
我的数据是训练用的形状为“1140*60*1”的矩阵,标签是“1140*1”的矩阵。但是当我使用形状为“1*60*1”的矩阵来预测下一天时,我得到了这样的错误
ValueError: Error when checking input: expected lstm_114_input to have shape (1, 1) but got array with shape (60, 1)
也许您将模型的形状改为了(1,1),请将其改为(60,1)。
请记住,您试图改变的是批次大小,而不是输入形状。
嗨,您的解决方案似乎不适用于“timesteps > 1”。如果您可以改进,请改进。
为什么不呢?您具体遇到了什么问题?
陈述:“有状态意味着LSTM的内部状态只有在我们手动重置它时才会重置。”
所以
model.fit(X, y, epochs=10, verbose=2, batch_size=5, shuffle=False ) 难道不会在每个epoch后自动reset_states(),对吗?
这就是为什么我们在每次迭代中重置它的原因吗?
for i in range(n_epoch)
model.fit(X, y, epochs=1, batch_size=n_batch, verbose=1, shuffle=False)
model.reset_states()
如果模型是“无状态”的(默认),它会在每个epoch内的每个批次之后重置,
使用有状态模型,我们可以手动迭代epoch并在每个epoch结束时重置。
如果数据集大小是100K,批次大小应该是什么?我的数据集中有120个不同的数字。
我希望模型能给我提供数据集中的一个底层序列。
例如:假设数据集样本为 1,2,3……8,10,14…..1,2,3…. 8,10,14,……。是否有模型可以给我提供隐藏的模式?
我建议测试多种不同的批次大小,以查看哪种最适合您的模型/数据/学习率。
你好,
我使用批次大小32训练了我的模型以获得最优权重,并将其保存在文件中。现在,我使用了您的步骤3,创建了一个加载了文件中权重的模型。然后我使用model.predict(),批次大小为1。我有一个包含305个数据点的测试文件。当我打开文件并逐个数据点进行预测时,就像您在步骤3中所做的那样,我得到了与批预测几乎相同的结果。所以这是好的。但是,假设我想从用户那里获取一些输入,并想对该特定数据点(基本上是从只有一个数据点的文件中)进行预测,我会得到一个准确率低得多的结果。您能解释一下为什么会发生这种情况,以及有什么特定的解决方案吗?
提前感谢
也许您的模型过度拟合了训练数据?
我在这里有一些建议
https://machinelearning.org.cn/start-here/#better
嗨 Jason
您能否解释一下您这里的X和Y变量——我感觉它们应该正好相反?
我们试图预测比小值更大的值?正确吗?
目前这个问题表述为
X Y
1 0.1 0.0
2 0.2 0.1
3 0.3 0.2
4 0.4 0.3
5 0.5 0.4
6 0.6 0.5
7 0.7 0.6
8 0.8 0.7
9 0.9 0.8
以下情况不应该更正确吗?
Y X
1 0.1 0.0
2 0.2 0.1
3 0.3 0.2
4 0.4 0.3
5 0.5 0.4
6 0.6 0.5
7 0.7 0.6
8 0.8 0.7
9 0.9 0.8
然后情况看起来就不太好了……
>预期=0.1, 预测=0.1
>预期=0.2, 预测=0.3
>预期=0.3, 预测=0.5
>预期=0.4,预测=0.7
>预期=0.5, 预测=0.8
>预期=0.6, 预测=1.0
>预期=0.7, 预测=1.1
>预期=0.8, 预测=1.1
>预期=0.9, 预测=1.2
这可能是更好的起点
https://machinelearning.org.cn/how-to-develop-lstm-models-for-time-series-forecasting/
嗨,Jason!
感谢您的帖子!
我对Keras模型中的输入形状和批次大小感到有些困惑。
如果我有一个输入(150,10,1),然后是批次大小为5,当我拟合模型时,如:model.fit(x_train,y_train, batch_size=5, epoch = 200),我输入张量中定义的10个样本是什么?它们也被称为批次大小吗?为什么它们不需要与fit中的大小相同?
提前感谢!
当我们使用有状态LSTM时,我们必须在输入形状中指定批次大小。
嗨,Jason,
我最初是手动推进epoch来在每个epoch结束时重置LSTM状态,正如您建议的那样。当我尝试实现早期停止和模型检查点等功能以仅保存最佳权重时,我意识到我无法使用内置的Keras回调,因为当我们退出fit方法以重置LSTM状态时,它们会在每个epoch结束时重置。
我查看了Keras代码中这些回调的实现方式,并发现我可以编写自己的自定义回调,并指定它们在训练的各个阶段运行。所以我写了以下代码
from keras.callbacks import Callback
class ResetStatesAfterEachEpoch(Callback)
def on_epoch_end(self, epoch, logs=None)
self.model.reset_states()
将这个自定义的ResetStatesAfterEachEpoch()回调包含在回调列表中,可以实现我们在不手动推进每个epoch的情况下手动重置有状态LSTM状态的目标。这也意味着我们可以正常使用Keras的fit函数和其他回调。以防万一有用,只是想分享一下。
非常棒,谢谢分享!
嘿 Leland。这正是我想要的,谢谢分享!
“复制权重”的方法在我目前的环境中看起来非常有用的。不幸的是,我没有使用Keras,因为我使用C++/CUDA完全定制了整个NN堆栈。我想知道,get_weights()/set_weights()究竟做了什么来修剪未使用的权重?它是用某个向量乘以原始权重矩阵吗?还是别的什么?谢谢
在这个示例中,权重的数量没有改变,只改变了批次大小。
嗨 Jason,谢谢你的回答;它让我(几乎)明白了。
为了澄清一下,假设我进行了一次批次大小为20的训练,现在我想推断单个样本,即批次大小为1。
如果权重数量没有改变,那么我想输入神经元数量也没有改变,而那19个“孤儿”只是没有加载值。是这样吗?
我想你可能混淆了“批次”和“特征”的数量
批次大小是模型权重更新之前馈送到模型的样本数量(行)。您可以在此处了解更多信息
https://machinelearning.org.cn/difference-between-a-batch-and-an-epoch/
还有这里
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
您能向我解释一下Batch_size和timestep的区别吗?我在这两者之间感到困惑,我还有另一个问题。我的数据集很大,多达数百万条记录,而且我没有选择最佳batch_size和epochs的标准。
谢谢你,
是的,请看这个
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
还有这个。
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-a-batch-and-an-epoch
感谢您的这篇帖子,它真的阐明了在每种情况下使用不同的批次大小。我刚遇到这个问题,很高兴找到了您的帖子。
谢谢,我很高兴它有帮助!
嗨 Jason,谢谢您的帖子,您帮了我很多!
我有两个问题,也许您可以为我的应用程序提供一些提示。在我的案例中,我需要将训练序列分成不同随机大小的小序列,即
[ 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 …] -> [ [0.1 0.2 0.3] [0.3 0.4] [0.4 0.5 0.6 0.7][0.7 0.8 0.9] … ]
使用在线学习很容易,因为我一次只输入一个序列,问题是我的数据集是图像,这使得训练非常慢。
我的第一个问题是:有没有办法在序列大小可变的情况下实现类似批量预测的方法?
我的第二个问题是:如果我只有一个epoch的在线训练,我该如何实现一个早期停止回调?我猜我需要自己检查损失?
谢谢帮助。
您说的在线学习是什么意思?每次更新一个样本?
您可以使用零填充来使所有序列具有相同的长度,然后使用掩码来忽略模型中的填充值。
这是一个早期停止的例子
https://machinelearning.org.cn/how-to-stop-training-deep-neural-networks-at-the-right-time-using-early-stopping/
是的,这就是我的意思,每次序列更新一个,批次大小=1。谢谢,我将尝试对我的图像序列使用零填充!
我有点困惑,这会有什么区别?
假设我用批次大小为50来编译我的时间序列预测模型。
现在,如果我基于X_test预测y值,为每个时间步生成一个预测y,
在此过程中,权重不会更新,所以无论我将model.predict的批次大小设为50还是1,应该都会产生相同的预测结果?
批次大小会改变误差梯度的估计,进而影响学习的速度。
我明白了,但是当在持有的测试集上进行预测时,模型并没有学习?所以无论我以50个批次还是1个批次进行预测,结果都应该相同?
批次大小仅在训练模型时产生影响。
在进行预测时,模型不会改变,批次大小也不会有影响——这只是在那种情况下块内存的计算效率。
那么,在进行预测时,为什么会想要与训练网络时不同的批次大小呢?
“在序列预测问题中,当训练网络时使用大批次大小,而在进行预测时使用批次大小为1来预测序列的下一步,可能会更理想。”
我们可能想用大批次大小来训练,这样效率更高,但在推理时进行单步预测。
嗨 Jason,又一篇好文章!
有些事情我不清楚:我明白为什么使用更小的批次大小进行预测在计算上可能更有效。
然而,这也限制了数据集的大小:不断增长的数据集,获得越来越多的数据,会不会产生更好的结果?(尤其因为我们不会在每个批次之前重新拟合模型,因为这会太慢。)
我相信您在这篇文章中正是这样做的:https://machinelearning.org.cn/how-to-develop-lstm-models-for-multi-step-time-series-forecasting-of-household-power-consumption/
如果我没理解错的话,每次预测后,您会将实际值添加到历史记录中用于所有未来的预测,并且您只保留最后一个预测。
所以我不太明白其中的意义,这仅仅是为了节省内存资源,还是有其他好处?
再次感谢您提供如此出色的网站!
这篇博文是关于在训练完最终模型后,如何对新数据进行预测。而不是关于滚动预测验证。
Jason,我有一个关于Keras的fit方法中的batch的问题。
假设我有一个非常大的数据集,如果我将batch size设置为数据集的长度(进行全批量梯度下降),像这样:
model.fit(X_train, y_train, batch_size=)
将会导致“内存错误”。
我找到的一个解决方案是使用小批量,例如每批512个样本来更新权重。
然而,我的数据集高度不平衡,因此我需要更加关注AUC-PR。
我的理解是:
1. Keras将根据batch size更新权重。例如,对于batch_size=512,Keras将在计算了512个样本的损失后更新我的权重。
2. 我们只能在一个epoch后计算P-R(精确率-召回率)和AUC-PR,因为对每个小批量计算P-R或AUC-PR会产生误导(我的模型可能处理了500个类别0和12个类别1的批次,而下一个批次全部是类别0)。
如何将数据集作为批次传递给我的模型以进行全批量梯度下降(仅将它们作为批次传递,但不是为每个批次更新权重)?
谢谢你
两种情况都正确。
或许可以使用一台内存更大的机器,例如一个大型EC2实例?
您收到错误的原因
ValueError: Cannot feed value of shape (1, 1, 1) for Tensor ‘lstm_1_input:0’, which has shape ‘(9, 1, 1)’
似乎是您正在使用有状态LSTM。我不清楚您为什么在这里需要stateful=True。
如果stateful不是True,那么您就不需要在LSTM()中指定batch size。您可以在训练过程中使用不同的batch size,也可以在训练和预测之间使用不同的batch size,对吗?谢谢。
这个问题只在使用有状态LSTM时出现(据我回忆),这正是教程的重点。
您好,Jason。
如何在3D坐标预测中应用LSTM?
或许可以修改您的LSTM以预测3个数字——在输出层有3个节点。
谢谢
你好,Jason
我想用LSTM预测项目的最终成本和持续时间(项目管理)(例如,在常见领域训练10个项目,测试2个项目),但有一件事在我提出论文提案时没有想到,那就是每个项目在时间序列背景下都是独特的模式,我该如何处理这个问题?
我的论文提案是,每个项目在时间序列背景下都是独特的模式,我该如何处理这个问题?
或许可以从这个框架开始
https://machinelearning.org.cn/start-here/#process
还有这个。
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
谢谢回复
每10个项目从时间(月或...)的第1天开始,我如何将它们结合起来并在新项目中进行预测??
或许是按相对时间步归一化的并行时间序列?
发挥创意,进行实验。
你好,先生,
我有一个分类问题,目标变量从0到4(5个类别)。
例如,我有三个用户。
用户A:样本被归类为0和1
用户B:样本被归类为2和3
用户C:样本被归类为0和4
我不能合并数据,因为样本可能对应于同一时期。也就是说,如果我将用户A与用户B合并并对数据进行排序,那么在尝试构建滑动窗口时,数据集将变得不一致,因为我会拥有属于不同用户的数据。
是否有可能用相同的LSTM训练用户A,然后是用户B,依此类推?在这种情况下,每次使用不同的用户拟合模型时,是否应该调用reset_state?
如果这不是最佳方法,您是否有任何关于如何实现的见解?
提前感谢!
我不确定我是否理解。
或许可以原型化几个解决方案,并利用它们来更多地了解如何构建和建模您的问题。
谢谢回复!
最后一个问题:如果我们使用无状态LSTM,在for循环中使用Epoch(fit中的epoch参数为1)与在fit函数本身中使用Epoch数有什么区别吗?
粗略地说,我认为没有区别。
感谢您关于此主题的所有教程!
我对参数[samples, timesteps, features]感到有些困惑,
例如,为什么在您关于两个序列的示例中,您决定将任何序列作为一个特征,而不是任何序列作为一个样本?(只有一个特征)
还有一些关于维度的问题,如果我的数据由9列组成
列(它们是特征),每一列都包含一个给定商店3天的信息
(所以例如我有rev_day1, customers_day1, new_customers_day1, rev_day2...
new_customers_day3。现在我想将其转换为时间序列,使每一行都是一个样本(目标是一个列向量,代表一家商店一周的总收入,这是一个多对一的问题)。
3天的信息,我考虑将其重塑为3个特征,3个时间步,所以新的结构将是
(对于商店A)
第1行:rev_day1, customers_day1, new_customers_day1
第2行:rev_day2, customers_day2, new_customers_day2
第3行:rev_day3, customers_day3, new_customers_day3
(对于商店B)
第1行:rev_day1, customers_day1, new_customers_day1
第2行:rev_day2, customers_day2, new_customers_day2
第3行:rev_day3, customers_day3, new_customers_day3
其他所有商店亦然。
这样,每个商店就是一个不同的样本。
这有意义吗,还是我又在混淆参数了?
谢谢!!
好问题,我相信这会有帮助。
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
您好,Jason。感谢分享这篇博文。
我有一个困惑:在解决方案2中,您将batch size设置为N(Batch Size = N)。您说“我们必须一次性使用所有预测,或者只保留第一个预测并丢弃其余的。”
我的问题是:解决方案2中的batch size必须是数据的长度(n_batch = len(X))吗?或者,如果1<bath size < N,并且我必须保留第一个预测并丢弃其余的,那么它是否也适用?
先谢谢您了。
或许可以根据您的用例尝试一下,看看效果如何?
嗨,Jason,
我正在尝试在多变量时间序列数据上使用LSTM,其中包含多个时间步。但是,在我一次只预测一个值时,我收到了以下错误:ValueError: Input 0 of layer sequential_13 is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: [1, 8] .. 我该如何解决这个问题?请帮助我。
谢谢
您可以选择更改数据以匹配您模型的期望,或者更改模型以匹配您的数据。
或许可以从此处的一个工作示例开始,并根据您的数据集进行调整。
https://machinelearning.org.cn/how-to-develop-lstm-models-for-time-series-forecasting/
非常感谢,我以前从未自己想过解决方案3。
不客气。
你好,Jason。
感谢分享这篇博文。
请问,当我们想要用同一个模型训练10个Excel文件,并将这10个文件视为序列时,是否应用的是同样的原理?
谢谢
抱歉,我不明白您的问题。您能重新表述一下吗?
在某些情况下,您可以将一个维度的长度设置为None以接受可变大小的输入。例如,LSTM层设置为input_size=(None, n_features)。为什么不能设置n_batches = None?
Batch size是在权重更新之前馈送给模型的样本数量。它不能是None或零。
很棒的平台!
问题
Timesteps用于使滞后信息能够用于创建更好的输出。
既然LSTM有记忆,我们不能用batchsize来实现吗?
例如
以30天的每日温度记录为例。
使用Timestep
我可以设置timestep=2和samples=28,batchsize=1。因此形状为(28,2,1)。
那么,我能否通过设置batchsize=2和timestep=1来实现同样的效果?
在这种情况下,隐藏状态不会在输入最后2天数据之前重置,因此它期望单元在最后通过考虑最后2天的温度来调整权重,然后输出新的隐藏状态。
本质上,因为LSTM有记忆,所以它应该利用它来从过去的记录中学习。那么在这种情况下,我们还需要timesteps吗?
也许可以。只要您能控制何时重置状态(例如,有状态LSTM)。
嗨,Jason,
不幸的是,将权重转移到另一个模型以解决batch size问题的巧妙技巧在使用最近的Keras版本(v2.4.3)时似乎不起作用。每当我执行脚本时,我都会得到错误的结果,例如:
>预期=0.0, 预测=0.0
>预期=0.1, 预测=0.1
>预期=0.2, 预测=0.3
>Expected=0.3, Predicted=0.4
>Expected=0.4, Predicted=0.5
>Expected=0.5, Predicted=0.6
>预期=0.6,预测=0.8
>预期=0.7,预测=0.9
>Expected=0.8, Predicted=1.0
然而,如果我使用批处理版本进行推理,预测是正确的,例如使用以下代码:
model.reset_states()
yhat = model.predict(X, batch_size=3)
for _yhat, _y in zip(yhat, y):
print(‘>Expected=%.1f, Predicted=%.1f’ % (_y, _yhat[0]))
您能重现这个bug吗?您知道这是在最近的Keras版本中引入的吗?您能想到一个变通方法吗?
感谢您的持续工作。
你好 Jason,
不确定您是否还在关注这些,但感谢您的教程,它帮助我解决了困扰我太久的问题。
在这种情况下,将batch size更改为1是否会从根本上消除拥有LSTM模型的优势,因为它不会预测下一个序列,而是基本上对新输入进行分类?
你好Lahan……你的理解是正确的!感谢您的反馈!