长短期记忆(LSTM)循环神经网络有望学习长序列的观测值。
它似乎是时间序列预测的完美匹配,事实上,它确实可能如此。
在本教程中,您将学习如何为单步单变量时间序列预测问题开发LSTM预测模型。
完成本教程后,您将了解:
- 如何为预测问题开发性能基线。
- 如何为单步时间序列预测设计鲁棒的测试框架。
- 如何准备数据、开发和评估用于时间序列预测的LSTM循环神经网络。
通过我新书《时间序列预测深度学习》来启动您的项目,其中包括分步教程以及所有示例的Python源代码文件。
让我们开始吧。
- 更新2017年5月:修正了invert_scale()函数中的错误,感谢Max。
- 2019 年 4 月更新:更新了数据集链接。

Python 中使用长短期记忆网络进行时间序列预测
照片由Matt MacGillivray拍摄,保留部分权利。
教程概述
这是一个很大的主题,我们将涵盖很多内容。准备好了。
本教程分为9个部分;它们是
- 洗发水销售数据集
- 测试设置
- 持久性模型预测
- LSTM数据准备
- LSTM模型开发
- LSTM预测
- 完整的LSTM示例
- 开发可靠的结果
- 教程扩展
Python 环境
本教程假设您已安装Python SciPy环境。您可以使用Python 2或3进行本教程的学习。
您必须安装 Keras(2.0 或更高版本),并使用 TensorFlow 或 Theano 后端。
本教程还假定您已安装 scikit-learn、Pandas、NumPy 和 Matplotlib。
如果您在环境方面需要帮助,请参阅此帖子
时间序列深度学习需要帮助吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
洗发水销售数据集
此数据集描述了 3 年期间洗发水月销量。
单位是销售计数,共有 36 个观测值。原始数据集归功于 Makridakis、Wheelwright 和 Hyndman (1998)。
将数据集下载到您当前的目录中,并命名为“shampoo-sales.csv”。
以下示例加载并创建加载数据集的图表。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 加载并绘制数据集 from pandas import read_csv from pandas import datetime from matplotlib import pyplot # 加载数据集 def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) # 总结前几行 print(series.head()) # 线图 series.plot() pyplot.show() |
运行该示例将数据集作为 Pandas Series 加载并打印前 5 行。
1 2 3 4 5 6 7 |
月份 1901-01-01 266.0 1901-02-01 145.9 1901-03-01 183.1 1901-04-01 119.3 1901-05-01 180.3 名称:销售额,数据类型:float64 |
然后创建该系列的线图,显示出明显的上升趋势。

月度洗发水销量数据集的折线图
实验测试设置
我们将把洗发水销售数据集分为两部分:训练集和测试集。
前两年的数据将用于训练数据集,剩下的一年数据将用于测试集。
例如
1 2 3 |
# 分割数据为训练集和测试集 X = series.values train, test = X[0:-12], X[-12:] |
模型将使用训练数据集进行开发,并对测试数据集进行预测。
将使用滚动预测场景,也称为前向模型验证。
测试数据集的每个时间步将逐一进行。模型将用于对该时间步进行预测,然后将从测试集中获取实际期望值,并将其提供给模型用于下一个时间步的预测。
例如
1 2 3 4 5 |
# 步进验证 history = [x for x in train] predictions = list() for i in range(len(test)): # 进行预测... |
这模拟了现实世界场景,其中每个月都会有新的洗发水销售观察值,并用于预测下个月。
最后,将收集测试数据集上的所有预测,并计算一个误差分数来总结模型的技能。根均方误差(RMSE)将被使用,因为它会惩罚较大的误差,并产生一个与预测数据单位相同的分数,即月度洗发水销量。
例如
1 2 3 |
from sklearn.metrics import mean_squared_error rmse = sqrt(mean_squared_error(test, predictions)) print('RMSE: %.3f' % rmse) |
持久性模型预测
具有线性增长趋势的时间序列的一个良好基线预测是持久性预测。
持久性预测是指使用前一个时间步(t-1)的观测值来预测当前时间步(t)的观测值。
我们可以通过采用训练数据中的最后一个观测值和通过前向验证累积的历史来实施这一点,并使用它来预测当前时间步。
例如
1 2 |
# 进行预测 yhat = history[-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 |
from pandas import read_csv from pandas import datetime from sklearn.metrics import mean_squared_error from math import sqrt from matplotlib import pyplot # 加载数据集 def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) # 分割数据为训练集和测试集 X = series.values train, test = X[0:-12], X[-12:] # 步进验证 history = [x for x in train] predictions = list() for i in range(len(test)): # 进行预测 predictions.append(history[-1]) # 观测 history.append(test[i]) # 报告表现 rmse = sqrt(mean_squared_error(test, predictions)) print('RMSE: %.3f' % rmse) # 观测值与预测值的线图 pyplot.plot(test) pyplot.plot(predictions) pyplot.show() |
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
运行该示例将打印出测试数据集上的预测的RMSE,大约为136个(月度洗发水销量)。
1 |
RMSE: 136.761 |
还将创建一个测试数据集(蓝色)与预测值(橙色)进行比较的折线图,在上下文中显示持久性模型的预测。

洗发水销量数据集的观测值与预测值对比的持久性预测
有关时间序列预测的持久性模型的更多信息,请参阅此帖
现在我们有了数据集的性能基线,我们可以开始为数据开发LSTM模型。
需要 LSTM 帮助进行序列预测吗?
参加我的免费7天电子邮件课程,了解6种不同的LSTM架构(附代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
LSTM数据准备
在我们使用 LSTM 模型拟合数据集之前,我们必须转换数据。
本节分为三个步骤
- 将时间序列转换为监督学习问题
- 转换时间序列数据使其平稳。
- 将观测值转换为特定的比例。
将时间序列转换为监督学习
Keras中的LSTM模型假设您的数据已划分为输入(X)和输出(y)部分。
对于时间序列问题,我们可以通过使用最后一个时间步(t-1)的观测值作为输入,当前时间步(t)的观测值作为输出来实现这一点。
我们可以使用Pandas中的shift()函数来实现这一点,该函数将使序列中的所有值向下移动指定的位数。我们需要移动1位,这将成为输入变量。时间序列按原样将成为输出变量。
然后,我们可以将这两个序列连接起来,创建一个准备好进行监督学习的DataFrame。向下移动的序列将在顶部有一个新的位置,没有值。我们将用0值替换这些NaN值,LSTM模型必须学习这些值作为“序列的开始”或“这里没有数据”,因为在此数据集中未观察到销量为零的月份。
下面的代码定义了一个名为timeseries_to_supervised()的辅助函数。它接受原始时间序列数据的NumPy数组和一个滞后值或要创建和用作输入的移位序列的数量。
1 2 3 4 5 6 7 8 |
# 将序列构造成监督学习问题 def timeseries_to_supervised(data, lag=1): df = DataFrame(data) columns = [df.shift(i) for i in range(1, lag+1)] columns.append(df) df = concat(columns, axis=1) df.fillna(0, inplace=True) return df |
我们可以用加载的洗发水销量数据集来测试这个函数,并将其转换为一个监督学习问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from pandas import read_csv from pandas import datetime from pandas import DataFrame from pandas import concat # 将序列构造成监督学习问题 def timeseries_to_supervised(data, lag=1): df = DataFrame(data) columns = [df.shift(i) for i in range(1, lag+1)] columns.append(df) df = concat(columns, axis=1) df.fillna(0, inplace=True) return df # 加载数据集 def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) # 转换为监督学习 X = series.values supervised = timeseries_to_supervised(X, 1) print(supervised.head()) |
运行该示例将打印出新的监督学习问题的前5行。
1 2 3 4 5 6 |
0 0 0 0.000000 266.000000 1 266.000000 145.899994 2 145.899994 183.100006 3 183.100006 119.300003 4 119.300003 180.300003 |
有关将时间序列问题转换为监督学习问题的更多信息,请参阅帖子
将时间序列转换为平稳
洗发水销量数据集不是平稳的。
这意味着数据中存在依赖于时间的结构。特别是,数据存在增长趋势。
平稳数据更容易建模,并且很可能产生更具技能的预测。
趋势可以从观测值中移除,然后添加到预测值中,以便将预测值恢复到原始尺度并计算可比较的误差分数。
移除趋势的标准方法是对数据进行差分。也就是说,将当前观测值(t)减去前一个时间步(t-1)的观测值。这消除了趋势,我们得到的是差分序列,或者说观测值随时间步长的变化。
我们可以使用Pandas中的diff()函数自动实现这一点。或者,我们可以获得更精细地控制并编写自己的函数来实现这一点,在这种情况下,后者因其灵活性而更受青睐。
下面的函数称为difference(),它计算差分序列。请注意,序列中的第一个观测值被跳过了,因为没有之前的观测值可以用来计算差分值。
1 2 3 4 5 6 7 |
# 创建差分序列 def difference(dataset, interval=1): diff = list() for i in range(interval, len(dataset)): value = dataset[i] - dataset[i - interval] diff.append(value) return Series(diff) |
我们还需要反转这个过程,以便将对差分序列进行的预测值恢复到原始尺度。
下面的函数称为inverse_difference(),它反转了这个操作。
1 2 3 |
# 反转差分值 def inverse_difference(history, yhat, interval=1): return yhat + history[-interval] |
我们可以像下面这样,通过对整个序列进行差分,然后将其恢复到原始尺度来测试这些函数
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 |
from pandas import read_csv from pandas import datetime from pandas import Series # 创建差分序列 def difference(dataset, interval=1): diff = list() for i in range(interval, len(dataset)): value = dataset[i] - dataset[i - interval] diff.append(value) return Series(diff) # 反转差分值 def inverse_difference(history, yhat, interval=1): return yhat + history[-interval] # 加载数据集 def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) print(series.head()) # 转换为平稳 differenced = difference(series, 1) print(differenced.head()) # 反向转换 inverted = list() for i in range(len(differenced)): value = inverse_difference(series, differenced[i], len(series)-i) inverted.append(value) inverted = Series(inverted) print(inverted.head()) |
运行该示例,首先打印加载数据的前5行,然后是差分序列的前5行,最后是反转差分操作后的前5行。
请注意,原始数据集的第一个观测值已从反转差分数据中移除。除此之外,最后一组数据与预期的第一组数据匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
月份 1901-01-01 266.0 1901-02-01 145.9 1901-03-01 183.1 1901-04-01 119.3 1901-05-01 180.3 名称:销售额,数据类型:float64 0 -120.1 1 37.2 2 -63.8 3 61.0 4 -11.8 dtype: float64 0 145.9 1 183.1 2 119.3 3 180.3 4 168.5 dtype: float64 |
有关使时间序列平稳和差分的更多信息,请参阅帖子
将时间序列转换为比例
与其他神经网络一样,LSTM期望数据在网络使用的激活函数的范围内。
LSTM的默认激活函数是双曲正切(tanh),它输出介于-1和1之间的值。这是时间序列数据的首选范围。
为了使实验公平,必须在训练数据集上计算缩放系数(最小值和最大值),并将它们应用于测试数据集和任何预测。这是为了避免用测试数据集的知识污染实验,这可能会给模型带来微小的优势。
我们可以使用MinMaxScaler类将数据集转换为[-1, 1]范围。与其他scikit-learn的转换类一样,它要求数据以矩阵格式提供,包含行和列。因此,我们必须在转换之前重塑我们的NumPy数组。
例如
1 2 3 4 5 6 |
# 缩放转换 X = series.values X = X.reshape(len(X), 1, X.shape[1]) scaler = MinMaxScaler(feature_range=(-1, 1)) scaler = scaler.fit(X) scaled_X = scaler.transform(X) |
同样,我们必须对预测值进行反向缩放,将它们恢复到原始尺度,以便可以解释结果并计算可比较的误差分数。
1 2 |
# 反向转换 inverted_X = scaler.inverse_transform(scaled_X) |
将所有这些内容放在一起,下面的示例转换了洗发水销量数据的比例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from pandas import read_csv from pandas import datetime from pandas import Series from sklearn.preprocessing import MinMaxScaler # 加载数据集 def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) print(series.head()) # 缩放转换 X = series.values X = X.reshape(len(X), 1, X.shape[1]) scaler = MinMaxScaler(feature_range=(-1, 1)) scaler = scaler.fit(X) scaled_X = scaler.transform(X) scaled_series = Series(scaled_X[:, 0]) print(scaled_series.head()) # 反向转换 inverted_X = scaler.inverse_transform(scaled_X) inverted_series = Series(inverted_X[:, 0]) print(inverted_series.head()) |
运行该示例,首先打印加载数据的前5行,然后是缩放数据的前5行,最后是反转缩放转换后的前5行,这与原始数据匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
月份 1901-01-01 266.0 1901-02-01 145.9 1901-03-01 183.1 1901-04-01 119.3 1901-05-01 180.3 名称:销售额,数据类型:float64 0 -0.478585 1 -0.905456 2 -0.773236 3 -1.000000 4 -0.783188 dtype: float64 0 266.0 1 145.9 2 183.1 3 119.3 4 180.3 dtype: float64 |
现在我们知道如何为LSTM网络准备数据,我们可以开始开发我们的模型。
LSTM模型开发
长短期记忆网络(LSTM)是一种循环神经网络(RNN)的类型。
这种类型网络的优点在于它可以学习和记忆长序列,并且不依赖于预先指定的窗口滞后观测值作为输入。
在Keras中,这被称为有状态,并且涉及在定义LSTM层时将“stateful”参数设置为“True”。
默认情况下,Keras中的LSTM层在批次数据之间保持状态。数据批次是训练数据集中固定数量的行,它定义了在更新网络权重之前要处理多少模式。LSTM层在批次之间的状态默认被清除,因此我们必须使LSTM有状态。这使我们能够精细地控制LSTM层何时被清除状态,通过调用reset_states()函数。
LSTM层期望输入是一个矩阵,其维度为:[样本数, 时间步数, 特征数]。
- 样本数:这些是领域中的独立观测值,通常是数据行。
- 时间步数:这些是给定观测值的给定变量的独立时间步。
- 特征数:这些是在观测时观测到的独立度量。
我们在如何为网络构建洗发水销量数据集方面有一些灵活性。我们将保持简单,并将问题构建为原始序列中的每个时间步都是一个单独的样本,具有一个时间步和一个特征。
鉴于训练数据集定义为X输入和y输出,它必须被重塑为样本/时间步/特征格式,例如
1 2 |
X, y = train[:, 0:-1], train[:, -1] X = X.reshape(X.shape[0], 1, X.shape[1]) |
输入数据的形状必须在LSTM层中使用“batch_input_shape”参数指定,该参数是一个元组,指定了每批读取的预期观测数、时间步数和特征数。
批次大小通常远小于总样本数。它与训练轮数一起定义了网络学习数据的速度(权重更新的频率)。
定义LSTM层的最后一个导入参数是神经元数量,也称为内存单元或块的数量。这是一个相对简单的问题,1到5之间的数字应该足够了。
下面的行创建了一个单一的LSTM隐藏层,该层还通过“batch_input_shape”参数指定了对输入层的期望。
1 |
layer = LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True) |
网络需要在输出层有一个神经元,并使用线性激活来预测下一个时间步的洗发水销量。
一旦网络被指定,它必须使用后端数学库(如TensorFlow或Theano)编译成一个有效的符号表示。
在编译网络时,我们必须指定一个损失函数和一个优化算法。我们将使用“mean_squared_error”作为损失函数,因为它与我们感兴趣的RMSE非常接近,并且使用高效的ADAM优化算法。
使用Sequential Keras API来定义网络,下面的代码片段创建并编译了网络。
1 2 3 4 |
model = Sequential() model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') |
编译后,可以将其拟合到训练数据。由于网络是状态保持的,我们必须控制何时重置内部状态。因此,我们必须手动管理训练过程,一次一个 epoch,跨越所需的 epoch 数量。
默认情况下,epoch 中的样本在暴露给网络之前会被打乱。同样,这对于 LSTM 是不理想的,因为我们希望网络在学习跨观测序列时能够建立状态。我们可以通过将“shuffle”设置为“False“来禁用样本的打乱。
默认情况下,网络会在每个 epoch 结束时报告有关模型学习进度和技能的大量调试信息。我们可以通过将“verbose”参数设置为“0“级别来禁用此功能。
然后,我们可以在训练 epoch 结束时重置内部状态,为下一次训练迭代做好准备。
下面是一个手动将网络拟合到训练数据的循环。
1 2 3 |
for i in range(nb_epoch): model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False) model.reset_states() |
将所有这些结合起来,我们可以定义一个名为 fit_lstm() 的函数来训练并返回一个 LSTM 模型。作为参数,它接受监督学习格式的训练数据集、批量大小、 epoch 数量和神经元数量。
1 2 3 4 5 6 7 8 9 10 11 |
def fit_lstm(train, batch_size, nb_epoch, neurons): X, y = train[:, 0:-1], train[:, -1] X = X.reshape(X.shape[0], 1, X.shape[1]) model = Sequential() model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') for i in range(nb_epoch): model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False) model.reset_states() return model |
批量大小必须设置为 1。这是因为它必须是训练集和测试集大小的因子。
模型上的 predict() 函数也受到批量大小的限制;在那里,它必须设置为 1,因为我们有兴趣对测试数据进行一步预测。
在本教程中,我们不会调整网络参数;相反,我们将使用以下配置,通过一些试错法找到的配置:
- 批量大小:1
- Epoch:3000
- 神经元:4
作为本教程的扩展,您可能想探索不同的模型参数,看看是否可以提高性能。
- 更新:尝试 1500 个 epoch 和 1 个神经元,性能可能会更好!
接下来,我们将看看如何使用已拟合的 LSTM 模型来进行一步预测。
LSTM预测
一旦 LSTM 模型拟合到训练数据,就可以用于进行预测。
同样,我们也有一些灵活性。我们可以选择在所有训练数据上拟合模型一次,然后从测试数据中一次一个时间步长进行预测(我们称之为固定方法),或者我们可以每次在测试数据的时间步长上重新拟合模型或更新模型,因为测试数据中的新观测值可用(我们称之为动态方法)。
在本教程中,我们将采用固定方法,因为它更简单,尽管我们预计动态方法将带来更好的模型技能。
要进行预测,我们可以调用模型上的 predict() 函数。这需要一个 3D NumPy 数组作为输入参数。在这种情况下,它将是一个包含一个值的数组,即前一个时间步长的观测值。
predict() 函数返回一个预测数组,每个输入行一个。由于我们提供单个输入,输出将是一个包含一个值的 2D NumPy 数组。
我们可以将此行为捕获在名为 forecast() 的函数中,如下所示。给定一个已拟合的模型、拟合模型时使用的批量大小(例如 1)以及来自测试数据的一行,该函数将从测试行中分离出输入数据,对其进行重塑,并将预测作为一个浮点值返回。
1 2 3 4 5 |
def forecast(model, batch_size, row): X = row[0:-1] X = X.reshape(1, 1, len(X)) yhat = model.predict(X, batch_size=batch_size) return yhat[0,0] |
在训练期间,内部状态会在每个 epoch 后重置。在预测期间,我们不希望在预测之间重置内部状态。实际上,我们希望模型在预测测试数据集中的每个时间步长时都能建立状态。
这引出了一个问题:在预测测试数据集之前,网络的初始状态应该是什么?
在本教程中,我们将通过对训练数据集中的所有样本进行预测来播种状态。理论上,内部状态应该设置好,以便预测下一个时间步长。
现在我们拥有了拟合洗发水销量数据集的 LSTM 网络模型并评估其性能的所有要素。
在下一节中,我们将把所有这些要素结合起来。
完整的LSTM示例
本节将拟合一个 LSTM 到洗发水销量数据集并评估模型。
这将涉及整合前面各节的所有元素。它们很多,所以让我们回顾一下:
- 从 CSV 文件加载数据集。
- 转换数据集,使其适合 LSTM 模型,包括:
- 将数据转换为监督学习问题。
- 将数据转换为平稳。
- 将数据转换为尺度为 -1 到 1。
- 将状态保持的 LSTM 网络模型拟合到训练数据。
- 在测试数据上评估静态 LSTM 模型。
- 报告预测的性能。
关于示例的一些注意事项:
- 缩放和反向缩放行为已移至 scale() 和 invert_scale() 函数中,以保持简洁。
- 测试数据使用从训练数据拟合的缩放器进行缩放,这是必需的,以确保测试数据的 min/max 值不会影响模型。
- 为了方便起见,调整了数据转换的顺序,首先使数据平稳,然后转换为监督学习问题,最后进行缩放。
- 为了方便起见,在将数据拆分为训练集和测试集之前,对整个数据集进行了差分。我们也可以在步进验证期间收集观测值并逐个进行差分。我为了可读性而放弃了这一点。
完整的示例如下所示。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
from pandas import DataFrame from pandas import Series 从 pandas 导入 concat from pandas import read_csv from pandas import datetime from sklearn.metrics import mean_squared_error 从 sklearn.预处理 导入 MinMaxScaler from keras.models import Sequential from keras.layers import Dense 从 keras.layers 导入 LSTM from math import sqrt from matplotlib import pyplot import numpy # 用于加载数据集的日期时间解析函数 def parser(x): return datetime.strptime('190'+x, '%Y-%m') # 将序列构造成监督学习问题 def timeseries_to_supervised(data, lag=1): df = DataFrame(data) columns = [df.shift(i) for i in range(1, lag+1)] columns.append(df) df = concat(columns, axis=1) df.fillna(0, inplace=True) return df # 创建差分序列 def difference(dataset, interval=1): diff = list() for i in range(interval, len(dataset)): value = dataset[i] - dataset[i - interval] diff.append(value) return Series(diff) # 反转差分值 def inverse_difference(history, yhat, interval=1): return yhat + history[-interval] # 将训练和测试数据缩放到 [-1, 1] def scale(train, test): # 拟合缩放器 scaler = MinMaxScaler(feature_range=(-1, 1)) scaler = scaler.fit(train) # 转换训练集 train = train.reshape(train.shape[0], train.shape[1]) train_scaled = scaler.transform(train) # 转换测试集 test = test.reshape(test.shape[0], test.shape[1]) test_scaled = scaler.transform(test) return scaler, train_scaled, test_scaled # 预测值的逆缩放 def invert_scale(scaler, X, value): new_row = [x for x in X] + [value] array = numpy.array(new_row) array = array.reshape(1, len(array)) inverted = scaler.inverse_transform(array) return inverted[0, -1] # 训练一个 LSTM 网络 def fit_lstm(train, batch_size, nb_epoch, neurons): X, y = train[:, 0:-1], train[:, -1] X = X.reshape(X.shape[0], 1, X.shape[1]) model = Sequential() model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') for i in range(nb_epoch): model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False) model.reset_states() return model # 进行一步预测 def forecast_lstm(model, batch_size, X): X = X.reshape(1, 1, len(X)) yhat = model.predict(X, batch_size=batch_size) return yhat[0,0] # 加载数据集 series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) # 将数据转换为平稳 raw_values = series.values diff_values = difference(raw_values, 1) # 将数据转换为监督学习 supervised = timeseries_to_supervised(diff_values, 1) supervised_values = supervised.values # 将数据分为训练集和测试集 train, test = supervised_values[0:-12], supervised_values[-12:] # 转换数据尺度 scaler, train_scaled, test_scaled = scale(train, test) # 拟合模型 lstm_model = fit_lstm(train_scaled, 1, 3000, 4) # 预测整个训练数据集以建立预测状态 train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1) lstm_model.predict(train_reshaped, batch_size=1) # 对测试数据进行步进验证 predictions = list() for i in range(len(test_scaled)): # 进行一步预测 X, y = test_scaled[i, 0:-1], test_scaled[i, -1] yhat = forecast_lstm(lstm_model, 1, X) # 反转缩放 yhat = invert_scale(scaler, X, yhat) # 反转差分 yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i) # 存储预测 predictions.append(yhat) expected = raw_values[len(train) + i + 1] print('Month=%d, Predicted=%f, Expected=%f' % (i+1, yhat, expected)) # 报告表现 rmse = sqrt(mean_squared_error(raw_values[-12:], predictions)) print('Test RMSE: %.3f' % rmse) # 观测值与预测值的线图 pyplot.plot(raw_values[-12:]) pyplot.plot(predictions) pyplot.show() |
运行示例会打印测试数据集中 12 个月的预期值和预测值。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
示例还会打印所有预测的 RMSE。该模型显示月度洗发水销量 RMSE 为 71.721,这比达到 136.761 销量 RMSE 的持久性模型要好。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Month=1, Predicted=351.582196, Expected=339.700000 Month=2, Predicted=432.169667, Expected=440.400000 Month=3, Predicted=378.064505, Expected=315.900000 Month=4, Predicted=441.370077, Expected=439.300000 Month=5, Predicted=446.872627, Expected=401.300000 Month=6, Predicted=514.021244, Expected=437.400000 Month=7, Predicted=525.608903, Expected=575.500000 Month=8, Predicted=473.072365, Expected=407.600000 Month=9, Predicted=523.126979, Expected=682.000000 Month=10, Predicted=592.274106, Expected=475.300000 Month=11, Predicted=589.299863, Expected=581.300000 Month=12, Predicted=584.149152, Expected=646.900000 Test RMSE: 71.721 |
还会创建一个测试数据(蓝色)与预测值(橙色)的折线图,为模型技能提供背景。

LSTM 预测与预期值折线图
作为附注,您可以进行一个快速实验,以建立对测试框架以及所有转换和反向转换的信任。
注释掉在步进验证中拟合 LSTM 模型的行。
1 |
yhat = forecast_lstm(lstm_model, 1, X) |
并替换为以下内容:
1 |
yhat = y |
这应该会产生一个具有完美技能的模型(例如,一个将预期结果作为模型输出的模型)。
结果应如下所示,表明如果 LSTM 模型可以完美地预测序列,则反向转换和误差计算将正确显示它。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Month=1, Predicted=339.700000, Expected=339.700000 Month=2, Predicted=440.400000, Expected=440.400000 Month=3, Predicted=315.900000, Expected=315.900000 Month=4, Predicted=439.300000, Expected=439.300000 Month=5, Predicted=401.300000, Expected=401.300000 Month=6, Predicted=437.400000, Expected=437.400000 Month=7, Predicted=575.500000, Expected=575.500000 Month=8, Predicted=407.600000, Expected=407.600000 Month=9, Predicted=682.000000, Expected=682.000000 Month=10, Predicted=475.300000, Expected=475.300000 Month=11, Predicted=581.300000, Expected=581.300000 Month=12, Predicted=646.900000, Expected=646.900000 Test RMSE: 0.000 |
开发可靠的结果
神经网络的一个难题是它们在不同的初始条件下会产生不同的结果。
一种方法可能是固定 Keras 使用的随机数种子以确保结果可复现。另一种方法是通过不同的实验设置来控制随机初始条件。
我们可以重复上一节的实验多次,然后取平均 RMSE 作为配置在平均情况下对未见数据的预期性能的指示。
这通常称为多次重复或多次重启。
我们可以将模型拟合和步进验证包装在一个固定次数的重复循环中。每次迭代都会记录该次运行的 RMSE。然后我们可以总结 RMSE 分数的分布。
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 |
# 重复实验 repeats = 30 error_scores = list() for r in range(repeats): # 拟合模型 lstm_model = fit_lstm(train_scaled, 1, 3000, 4) # 预测整个训练数据集以建立预测状态 train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1) lstm_model.predict(train_reshaped, batch_size=1) # walk-forward validation on the test data predictions = list() for i in range(len(test_scaled)): # 进行一步预测 X, y = test_scaled[i, 0:-1], test_scaled[i, -1] yhat = forecast_lstm(lstm_model, 1, X) # 反转缩放 yhat = invert_scale(scaler, X, yhat) # 反转差分 yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i) # 存储预测 predictions.append(yhat) # 报告性能 rmse = sqrt(mean_squared_error(raw_values[-12:], predictions)) print('%d) Test RMSE: %.3f' % (r+1, rmse)) error_scores.append(rmse) |
数据准备与之前相同。
我们将使用 30 次重复,因为这足以提供良好的 RMSE 分数分布。
完整的示例如下所示。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
from pandas import DataFrame from pandas import Series 从 pandas 导入 concat from pandas import read_csv from pandas import datetime from sklearn.metrics import mean_squared_error 从 sklearn.预处理 导入 MinMaxScaler from keras.models import Sequential from keras.layers import Dense 从 keras.layers 导入 LSTM from math import sqrt from matplotlib import pyplot import numpy # 用于加载数据集的日期时间解析函数 def parser(x): return datetime.strptime('190'+x, '%Y-%m') # 将序列构造成监督学习问题 def timeseries_to_supervised(data, lag=1): df = DataFrame(data) columns = [df.shift(i) for i in range(1, lag+1)] columns.append(df) df = concat(columns, axis=1) df.fillna(0, inplace=True) return df # 创建差分序列 def difference(dataset, interval=1): diff = list() for i in range(interval, len(dataset)): value = dataset[i] - dataset[i - interval] diff.append(value) return Series(diff) # 反转差分值 def inverse_difference(history, yhat, interval=1): return yhat + history[-interval] # 将训练和测试数据缩放到 [-1, 1] def scale(train, test): # 拟合缩放器 scaler = MinMaxScaler(feature_range=(-1, 1)) scaler = scaler.fit(train) # 转换训练集 train = train.reshape(train.shape[0], train.shape[1]) train_scaled = scaler.transform(train) # 转换测试集 test = test.reshape(test.shape[0], test.shape[1]) test_scaled = scaler.transform(test) return scaler, train_scaled, test_scaled # 预测值的逆缩放 def invert_scale(scaler, X, value): new_row = [x for x in X] + [value] array = numpy.array(new_row) array = array.reshape(1, len(array)) inverted = scaler.inverse_transform(array) return inverted[0, -1] # 训练一个 LSTM 网络 def fit_lstm(train, batch_size, nb_epoch, neurons): X, y = train[:, 0:-1], train[:, -1] X = X.reshape(X.shape[0], 1, X.shape[1]) model = Sequential() model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') for i in range(nb_epoch): model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False) model.reset_states() return model # 进行一步预测 def forecast_lstm(model, batch_size, X): X = X.reshape(1, 1, len(X)) yhat = model.predict(X, batch_size=batch_size) return yhat[0,0] # 加载数据集 series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) # 将数据转换为平稳 raw_values = series.values diff_values = difference(raw_values, 1) # 将数据转换为监督学习 supervised = timeseries_to_supervised(diff_values, 1) supervised_values = supervised.values # 将数据分为训练集和测试集 train, test = supervised_values[0:-12], supervised_values[-12:] # 转换数据尺度 scaler, train_scaled, test_scaled = scale(train, test) # 重复实验 repeats = 30 error_scores = list() for r in range(repeats): # 拟合模型 lstm_model = fit_lstm(train_scaled, 1, 3000, 4) # 预测整个训练数据集以建立预测状态 train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1) lstm_model.predict(train_reshaped, batch_size=1) # walk-forward validation on the test data predictions = list() for i in range(len(test_scaled)): # 进行一步预测 X, y = test_scaled[i, 0:-1], test_scaled[i, -1] yhat = forecast_lstm(lstm_model, 1, X) # 反转缩放 yhat = invert_scale(scaler, X, yhat) # 反转差分 yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i) # 存储预测 predictions.append(yhat) # 报告性能 rmse = sqrt(mean_squared_error(raw_values[-12:], predictions)) print('%d) Test RMSE: %.3f' % (r+1, rmse)) error_scores.append(rmse) # 总结结果 results = DataFrame() results['rmse'] = error_scores print(results.describe()) results.boxplot() pyplot.show() |
运行示例会为每次重复打印 RMSE 分数。运行结束时提供收集的 RMSE 分数的摘要统计信息。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。请考虑运行示例几次并比较平均结果。
我们可以看到平均和标准差 RMSE 分数分别为 138.491905 和 46.313783 个月洗发水销量。
这是一个非常有用的结果,因为它表明上面报告的结果可能是一个统计上的巧合。实验表明,该模型平均而言(136.761)与持久性模型差不多,甚至可能稍差。
这表明,至少,还需要进一步的模型调优。
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 |
1) Test RMSE: 136.191 2) Test RMSE: 169.693 3) Test RMSE: 176.553 4) Test RMSE: 198.954 5) Test RMSE: 148.960 6) Test RMSE: 103.744 7) Test RMSE: 164.344 8) Test RMSE: 108.829 9) Test RMSE: 232.282 10) Test RMSE: 110.824 11) Test RMSE: 163.741 12) Test RMSE: 111.535 13) 测试 RMSE:118.324 14) 测试 RMSE:107.486 15) 测试 RMSE:97.719 16) 测试 RMSE:87.817 17) 测试 RMSE:92.920 18) 测试 RMSE:112.528 19) 测试 RMSE:131.687 20) 测试 RMSE:92.343 21) 测试 RMSE:173.249 22) 测试 RMSE:182.336 23) 测试 RMSE:101.477 24) 测试 RMSE:108.171 25) 测试 RMSE:135.880 26) 测试 RMSE:254.507 27) 测试 RMSE:87.198 28) 测试 RMSE:122.588 29) 测试 RMSE:228.449 30) 测试 RMSE:94.427 RMSE count 30.000000 均值 138.491905 标准差 46.313783 最小值 87.198493 25% 104.679391 50% 120.456233 75% 168.356040 最大值 254.507272 |
基于下面显示的分布创建了一个箱线图。它捕获了数据的中间值以及范围和异常值的结果。

LSTM 重复实验箱线图
这是一种可以将一种 LSTM 模型配置与另一种进行比较的实验设置。
教程扩展
本教程还有许多可供考虑的扩展。
也许您可以自己探索其中一些,并在下面的评论中分享您的发现。
- 多步预测。实验设置可以更改为预测未来 n 个时间步,而不是下一个单一时间步。这还将允许更大的批量大小和更快的训练。请注意,在本教程中,鉴于模型没有更新,尽管有新的观测值可用并用作输入变量,我们基本上执行了 12 次单步预测。
- 调整 LSTM 模型。模型没有进行调整;相反,配置是通过一些快速的试错找到的。我相信通过至少调整神经元数量和训练轮数可以获得更好的结果。我还认为使用回调进行早期停止在训练期间可能有用。
- 种子状态实验。通过预测所有训练数据来播种系统在预测之前是否有益尚不清楚。理论上这似乎是个好主意,但这需要得到证明。此外,也许有其他方法可以在预测前播种模型可能是有益的。
- 更新模型。可以在前向验证的每个时间步更新模型。需要进行实验来确定是从头开始重新拟合模型还是通过包括新样本的几轮额外训练来更新权重更好。
- 输入时间步。LSTM 输入支持样本的多个时间步。需要进行实验以查看包含滞后观测值作为时间步是否提供任何好处。
- 输入滞后特征。滞后观测值可以包含在输入特征中。需要进行实验以查看包含滞后特征是否提供任何好处,这与 AR(k) 线性模型无异。
- 输入误差序列。可以构建一个误差序列(来自持久性模型的预测误差),并将其用作附加输入特征,这与 MA(k) 线性模型无异。需要进行实验以查看这是否提供任何好处。
- 学习非平稳性。LSTM 网络可能能够学习数据中的趋势并进行合理的预测。需要进行实验以查看是否存在于数据中的时间依赖结构(如趋势和季节性)是否可以被 LSTM 学习并有效地预测。
- 对比无状态。本教程使用了有状态 LSTM。结果应与无状态 LSTM 配置进行比较。
- 统计显著性。多重复实验协议可以进一步扩展,以包括统计显著性检验,以证明具有不同配置的 RMSE 结果总体之间的差异是否具有统计学意义。
总结
在本教程中,您了解了如何开发用于时间序列预测的 LSTM 模型。
具体来说,你学到了:
- 如何准备时间序列数据以开发 LSTM 模型。
- 如何开发用于时间序列预测的 LSTM 模型。
- 如何使用强大的测试平台评估 LSTM 模型。
你能获得更好的结果吗?
在下面的评论中分享您的发现。
在阅读了您的电子书并遵循了“一步一步”的教程后,我一直在进行多步预测。但仍然没有进展。似乎使用了 seq2seq 模型,但我想配置一个简单的 LSTM 进行多步预测。你能给我一个基本思路吗?
是的,我有一些 seq2seq 示例计划很快在博客上发布。
这一切都很好,但如何进行数据集之外的真正提前预测?我看到的每个博客都只显示实际值和预测值的比较图。如何使用此模型来简单地查看数据之后的 x 个时间段,而无需图形?谢谢!
嗨 Shawn,
也许以下内容可以帮助您通过一种略有不同的方法来消除一些困惑。
https://www.youtube.com/watch?v=tepxdcepTbY&t=24s
嗨,Jason,
感谢这篇博客。我正在使用递归预测技术进行多步预测,遇到了一些困难。关于这个特定主题的博客会很有帮助。
另外,是否有可能以某种方式在 ARIMA 中实现递归技术?
当然,您可以将预测作为历史记录,然后重新拟合 ARIMA。
谢谢您的建议,这可以成为一篇不错的博客文章。
我想知道,如果我得到预测(不是好的预测)并且在没有用测试集验证的情况下重新拟合,会不会再次产生错误的预测?
可能会,设计一个实验来测试该方法。
嗨,Jason,
感谢这篇博客。您能否分享一个使用 LSTM 进行递归预测的多步预测示例。
谢谢,
Shifu
感谢您的建议。
我在那里有一个直接用于多步预测的模型的示例
https://machinelearning.org.cn/multi-step-time-series-forecasting-long-short-term-memory-networks-python/
嗨,Jason,
LSTM 能够记住序列,但有没有办法将日历效应编码到网络中,以便它能够记住或学习在序列内的不同间隔和每个周期发生的事件?一个具体的例子是具有特定事件的时间序列,这些事件会随着一年中的特定时间重复发生,例如每个月的第一个星期一和/或每个月的最后一天。我想知道我们是否可以提前标记这些数据以帮助 LSTM 更好地预测这些事件?
你好 Peter,
您可能想查看 X-11 方法来分离序列中的趋势、季节性和随机变化。然后对每个部分应用算法。
您可以查看以下文章
使用航天器遥测数据进行长期性能预测方法研究
作者:Hongzeng Fang
(抱歉,我找不到免费下载页面了……)。
谢谢提示。
嗨 Jason,在从数据集中获取最后一次观测值以预测下一个未来时间步(我们当前没有值)的情况下,模型仅使用该 1 个观测值来预测下一个?还是因为它是 LSTM,它同时使用了训练期间所有先前观测值的记忆+最后一个观测值来预测下一个时间步?
如果是后者——对我来说会更有意义。否则,我看不到只使用 1 个观测值来预测下一个并保证任何准确性的意义。
根据模型的定义,提供一个输入序列是为了预测一个时间步。
不过,您可以根据自己的问题定义映射方式。
嗨,Jason,
很好的帖子。是否有关于多元时间序列预测问题的教程?
我有两组数据:交通流量数据和天气数据。我打算使用这两组数据来预测交通流量。
我想了解如果我将天气状况纳入其中,我的模型会发生什么。
您能否给我一些建议?
谢谢你。
我没有多元回归的例子,但我希望很快能发布一个。
太好了。提前谢谢您。
那真是太棒了。
嗨 Jason。这是一个很好的 LSTM 使用示例。我正在努力学习。
我也问同样的问题,您是否会提供多元时间序列预测的示例?我在这方面遇到了困难。
我这里有一个例子
https://machinelearning.org.cn/multivariate-time-series-forecasting-lstms-keras/
你做得很好。这非常详细!干得好😉
很高兴您觉得它有用,Gabriel。
很棒的教程,
如何对当前不存在的点进行预测?
yhat = model.predict(X)
我的意思是,没有 y。
误差度量很棒,但我也想进行下一步预测。
这也是我阅读本教程的主要目的。
由于还有其他教程也存在同样的问题,因此最好有一个完整的示例,并带有实际的输出/结果/值。
我意识到每个问题都应该有自己的解决方案/模型,但有了实际结果(或清晰的实现方式),代码就会更实用/可重用——尤其是对于试图预测某些值的 python-ml 初学者。
在整个训练数据集上拟合您的模型,然后预测下一个时间步,方法如下:
嗨 Jason,感谢您的教程。但您能否具体说明如何将模型拟合到整个训练集并对未来点进行预测?谢谢。
这有点过于事无巨细了,Donna。您究竟遇到了什么问题?
嗨,Jason
yhat = model.predict(X): X 是当前值吗?yhat 是预测值吗?
是的,X 是进行一个或多个预测所需的输入,yhat 是预测值。
嗨,Jason,我有一个关于预测的问题。在您的示例中,您只进行了对测试数据的预测(已知),其中您有原始数据来反转差值。那么对于未来未知数据,如何进行差值反转呢?
是的,反转预测的差值只需要最后一个已知观测值。
谢谢你,Jason。
我是 Python 的新手(主要编码其他语言),才开始理解代码——这要归功于您出色的详细描述。
在过去的几周里,我尝试了另外两个教程,但都失败了(未能进行第一次自己的测试应用并得到结果)。
A) 您能否建议一个用于该行的代码示例中的位置/行号?
B) 是否有魔法技巧可以避免日期转换,而是使用自己数据集中的实际日期?
目前我将不得不将我的数据转换为使用数据的日期格式。
我担心会破坏代码逻辑。
但我也在尝试单独研究代码的每个关键部分,例如在此
https://docs.scipy.org.cn/doc/numpy/reference/arrays.indexing.html
我目前的 Python 技能水平与本教程相当
https://www.youtube.com/watch?v=N4mEzFDjqtA .
嗨 Hans,
您说的“第一次自己的测试应用并得到结果”是什么意思?我不明白。
您的意思是进行预测吗?如果是,您可以通过在所有数据上拟合模型并调用 model.predict(X) 来进行预测。
Pandas 在加载日期数据方面非常灵活。对您来说一个好的方法可能是指定您自己的日期解析函数来加载数据。此帖子提供了示例
https://machinelearning.org.cn/stateful-stateless-lstm-time-series-forecasting-python/
值得一提的是(最新 Windows 信息 4.2017)
Windows 上的 Keras/Anaconda 存在一个问题。
要在 Win 上运行最后一个示例,我们必须手动重新安装 Keras。
更多信息可以在这里找到
https://github.com/llSourcell/How-to-Predict-Stock-Prices-Easily-Demo/issues/3#issuecomment-288981625
…否则它会抛出编译错误。
这个教程对您有效吗?
https://machinelearning.org.cn/setup-python-environment-machine-learning-deep-learning-anaconda/
我之前已经看过您写的这个教程。
在 Windows (而非 Mac) 上,构建这样的环境会有些不同,即使使用 Anaconda。
它始于 Windows 上没有版本号小于等于 3 的 TensorFlow,并以 Keras 提示结束。
我们花了好几天时间在 Github 上讨论它,并在另一个 RNN 脚本(参见链接)的背景下找到正确的设置。
我使用虚拟 conda 环境,并且您的脚本在 Windows 上运行,前提是实现了 keras 提示。
在此之前,我曾遇到过与您的一些脚本以及 Github 上讨论的脚本相同的问题(编译错误)。
更新,我的意思
我想可以从最后两个示例脚本的末尾调用“forecast_lstm(model, batch_size, X)”或“yhat = model.predict(X)”。
但是如何结合训练好的模型来做到这一点?
“月份=13,预测=???”
我是否必须定义一个新的“虚构”X?如果是,如何定义?
您必须加载需要进行预测的新输入数据作为 X,并使用您已拟合的模型通过调用 predict() 函数进行预测。
我乐于提供帮助,但也许我没有完全理解困难所在?
再次嗨 Jason!又一个精彩的教程,
我相信很多人都在问 model.predict(),因为它的工作方式并不完全符合预期。
第一个问题是,执行
yhat = model.predict(X)
使用之前的代码示例,返回
NameError: 名称“model”未定义
如我所理解的,这是因为模型在“lstm_model”而不是“model”的名称下创建的,所以使用
yhat = lstm_model.predict(X)
可以工作,但返回
ValueError: Error when checking : expected lstm_1_input to have 3 dimensions, but got array with shape (1, 1)
所以,我个人所做的,是使用“forecast_lstm”函数,如下所示
yhat = forecast_lstm(lstm_model, 1, X)
print(yhat)
0.28453988
这实际上返回了一个值。
现在下一个问题是 X 只是示例中的最后一个 X,因为我从未重新定义它。
我发现应用于训练数据的函数和过滤器的数量相当大,因此我需要复制它们以使形状匹配。
这是我的原始训练数据。
series = read_sql_query(seleccion, conn, parse_dates=[‘creacion’], index_col=[‘creacion’])
print(series)
sys.exit()
menores
creacion
2018-06-17 03:56:11 0.0
2018-06-17 03:54:03 2.0
2018-06-17 03:52:11 4.0
2018-06-17 03:50:05 6.0
2018-06-17 03:48:17 4.0
2018-06-17 03:46:04 4.0
2018-06-17 03:44:01 4.0
2018-06-17 03:43:05 1.0
2018-06-17 03:40:12 2.0
2018-06-17 03:38:12 0.0
2018-06-17 03:36:21 4.0
2018-06-17 03:34:32 4.0
2018-06-17 03:32:05 3.0
2018-06-17 03:30:01 2.0
2018-06-17 03:28:23 1.0
2018-06-17 03:26:17 3.0
2018-06-17 03:24:04 0.0
2018-06-17 03:22:34 4.0
2018-06-17 03:20:04 2.0
2018-06-17 03:18:18 2.0
2018-06-17 03:16:00 3.0
2018-06-17 03:14:06 6.0
2018-06-17 03:12:06 4.0
2018-06-17 03:10:04 2.0
2018-06-17 03:08:02 0.0
2018-06-17 03:06:02 4.0
2018-06-17 03:04:02 4.0
2018-06-17 03:02:10 3.0
2018-06-17 03:00:22 4.0
2018-06-17 02:59:13 3.0
…… ……
[7161 rows x 1 columns]
然后,这个过程应用于“series”
# 将数据转换为平稳
raw_values = series.values
diff_values = difference(raw_values, 1)
# 将数据转换为监督学习
supervised = timeseries_to_supervised(diff_values, 1)
supervised_values = supervised.values
如果您此时打印“supervised_values”,原始数据已被转换为
[[0 array([4.])]
[array([4.]) array([-3.])]
[array([-3.]) array([1.])]
…
[array([2.]) array([4.])]
[array([4.]) array([-3.])]
[array([-3.]) array([-1.])]
这显然是更少、更集中的信息……
因此,如果我尝试应用
yhat = forecast_lstm(lstm_model, 1, X)
在加载新数据之后
predecir = read_sql_query(seleccion, conn, parse_dates=[‘creacion’], index_col=[‘creacion’])
#limpiamos la cache
conn.commit()
print(predecir)
print(X)
yhat = forecast_lstm(lstm_model, 1, X)
#ynew = ynew[0]
print(yhat)
我收到以下错误:
AttributeError: ‘DataFrame’ object has no attribute ‘reshape’
————
所以我有点迷失,不知道如何实际将相同的结构应用于新数据,然后才能进行新的预测!
我将粘贴我的源代码,以防有人需要
https://codepen.io/anon/pen/xzPVxE
您会看到我直接从 MySQL 加载数据,并且还使用不同于博客之前示例的方法来分割训练和测试数据!
我也不确定如何进行下一步预测!
再次感谢您的这篇博客……如果没有您的帮助和解释,我甚至不会尝试这个!!!
我最好的祝愿,
克里斯
感谢分享。
我通过以下 Stack Overflow 帖子中的建议解决了这个问题:https://stackoverflow.com/questions/42240376/dataframe-object-has-no-attribute-reshape
我不再直接调用 pandas 训练和测试 DataFrame 的 reshape 方法,而是通过它们的 values 间接调用
train = train.values.reshape(train.shape[0], train.shape[1])
test = test.values.reshape(test.shape[0], test.shape[1])
很高兴听到这个消息。
你好 Jason,
我就知道不该提日期转换的事 :-)。现在我通过“return datetime.strptime(x, ‘%Y-%m-%d’)”解决了。
我将您所有脚本示例的部分都保存在单独的 Python 文件版本中。这样我就可以测试特定要求的修改。
python basic_data_loading.py
python persistence_forecast_model.py
python transform_time_series_to_supervised.py
python transform_time_series_to_statonary_remove_trends.py
python transform_scales.py
python complete_example.py
我自己的数据加载问题已解决。那是一项相对容易的任务。
鉴于转换和性能测量部分正在运行(我猜即使是整数数据它们也会运行)
我现在需要构建一个部分,我们称之为
“python predict_one_value.py”
当然,我需要加载我自己的数据,这是显而易见的。
问题是,在哪个示例脚本的上下文中触发该函数
yhat = model.predict(X)
并且最终说
print(yhat)。就是这样。
我想一个简短的代码示例片段可以解决问题。
您能提供一个示例吗?这将大有帮助?
目前我也不完全理解 X 的作用。
在“datetime.strptime”的上下文中,它似乎只是一个日期,如果我打印出来的话。
所以,如果我的训练数据是
– 01.12.1977
– 02.12.1977
– 03.12.1977
我想我可以这样说:“yhat = model.predict(“1977-12-04″)”。
问题是,在哪个代码上下文中的何时何地。
谢谢你。
更新
我现在使用的是“complete example”中的代码(“没有稳健的结果”)。
如果我注释掉第 106 行到第 127 行,然后在脚本末尾说
# 报告未来的一个值
test = datetime.strptime('2017-04-15', '%Y-%m-%d')
yhat = model.predict(test)
print(yhat)
我会收到错误消息“model is not defined”。所以,我尝试一下…
# 报告未来的一个值
test = datetime.strptime('2017-04-15', '%Y-%m-%d')
yhat = lstm_model.predict(test)
print(yhat)
……会抛出错误“Data should be a Numby array”。
我想也许我可以向原始数据添加一个新日期(没有 y),
但我不知道这是否正确。
要让这个运行起来的最佳方式是提供一个相关的代码片段示例。
本帖将为您更清晰地了解如何在 Keras 中使用神经网络,包括进行预测
https://machinelearning.org.cn/5-step-life-cycle-neural-network-models-keras/
是的,用于进行预测的输入数据必须是二维 numpy 数组。它不是日期数据,而是时间序列预测中的过去观测值。
谢谢你,
我会去读的 ;-)。
我读了教程并尝试了 pima indians diabetes 示例。
我想我明白了,也理解了这5个步骤(大部分)。
不幸的是,这并没有回答我的问题。或者是我遗漏了什么?
在我的问题中,我只有一个输入,就像本网站上的教程一样。
当你说
“yhat = model.predict(X)”
这将为下一步提供一个预测。
那一个既不在训练数据也不在测试数据中的步骤呢?
我有一个SVM模型,它基于我的原始数据进行证明和预测(在另一个环境中实现)。
假设我有100个训练数据项,10个测试数据项。
它将输出10个预测以及相应的性能数据。
最后打印的预测是关于一个未来的步骤。
在你的例子中,这会如何实现?
我需要移位什么吗?
要进行超出您数据集的预测,您必须将数据集的最后几个观测值作为输入(X)馈送,以预测下一步(y)会发生什么。
这篇帖子可能会澄清您对X和y的看法。
https://machinelearning.org.cn/time-series-forecasting-supervised-learning/
>要进行超出您数据集的预测,您必须将数据集的最后几个观测值作为输入(X)馈送,以预测下一步(y)会发生什么。
是否有可用的示例?
是的,就是这篇帖子的“LSTM预测”部分。
假设“X = row[0:-1]”是一个观测值,
我们如何采样/收集最后几个观测值来做出预测?
这取决于您的模型。如果您的模型期望将最后一个观测值作为输入,那么将该值重塑为一个二维数组,并将其作为X提供给model.predict(X)。
如果您的模型需要最后两个滞后观测值作为输入,则检索它们,将它们定义为一个行、两列的矩阵,并将它们提供给model.predict()。
依此类推。希望这有帮助。
嗨 Jason,
我也刚开始学习机器学习,也有类似的疑问,所以在一个步骤的预测中,我们只能得到一个时间步的未来观测值,对吗?为了得到预测,我提供了最后一个输入观测值,然后从model.predict(X)中获得的值需要再次进行缩放和反转,对吗?
见下文代码
X = test_scaled[3,-1:] (我的最后一个观测值)
yhat = forecast_lstm(lstm_model, 1, X)
yhat = invert_scale(scaler, X, yhat)
yhat = inverse_difference(raw_values, yhat, 1)
print(yhat)
你能指导我一下我是否走在正确的方向吗?
是的,一步预测涉及预测下一个时间步。
您可以进行多步预测,了解更多信息,请参阅这篇帖子。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
是的,要使用预测,您将需要反转执行的任何数据转换,例如缩放和差分。
谢谢 Jason ..
嗨,Jason,
说了这些,我还有另一个澄清,所以当我使用这个模型预测下一个时间步时,使用下面的代码
X = test_scaled[3,-1:] (我的最后一个观测值)
yhat = forecast_lstm(lstm_model, 1, X)
yhat = invert_scale(scaler, X, yhat)
yhat = inverse_difference(raw_values, yhat, 1)
print(yhat)
在上面的代码中,让yhat成为未来时间步的预测,我是否可以使用yhat的结果并使用相同的模型来预测未来一个时间步?这就是所谓的递归多步预测吗?
是的。这是递归的。
嗨,Jason,
我可以使用下面的代码来进行递归多步预测吗?
例如
yhat 值是否可以再次用作同一模型的输入以获得下一个未来步骤,依此类推?
X = test_scaled[3,-1:] (我的最后一个观测值)
yhat = forecast_lstm(lstm_model, 1, X)
yhat = invert_scale(scaler, X, yhat)
yhat = inverse_difference(raw_values, yhat, 1)
print(yhat)
嗨,Jason,
在预测分析中,使用这种机器学习技术,我们应该能够预测多少未来步骤?是否有理想的未来预测范围?例如,如果我有过去10天的可用数据,并且我想预测未来,那么预测的未来时间步越少,结果就越好,因为误差越小,对吗?我是否可以使用相同的代码来预测生产中的网络流量时间序列数据,以预测未来3天?我的要求是预测过去一年的网络带宽,预测下一周的网络带宽。
您的评论和建议始终受到欢迎:)
此致,
Arun
这取决于问题和模型。
通常,您想预测的未来越远,模型的性能就越差。
你好,
我们可以对RMSE值进行归一化吗?
如果可以,怎么做?
归一化技能分数?
是的,但您需要知道最大的可能误差。
我正在用范围从1到70的值来输入你的例子。
我的原始数据没有上升趋势。
对于预测,脚本会预测大于70的值。
关于另一个教程(5步生命周期),我认为这与编译部分(model.compile)有关。
但我不太确定。你能就本网站上的示例脚本提供一个清晰的提示吗?
嗨,Jason,
假设您有多个特征(您可以向洗发水数据集添加一个特征)并想使用多个时间步,那么我将数据集放入模型中会是什么样子?它是一个三维数组吗,其中特征是值的列表,每个观测值是这些特征的列表以及标签(也可能是值的列表)?
好问题,它将是一个三维数组,维度为 [样本数, 时间步数, 特征数]。
目前模型只提供一步预测。如果我想创建一个提供未来60个月预测的模型,该怎么办?
我将有一篇关于这个的帖子,在此之前,请看这篇帖子。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
Jason你好,我有一个问题。
raw_values = series.values
diff_values = difference(raw_values, 1)
print(len(raw_values)) 36
print(len(diff_values)) 35
所以,在差分后我们丢失了第一个值?
正确。
亲爱的 Jason,
非常感谢您这篇非常有用的有趣帖子。
我可能遗漏了什么,但我认为有一个遗漏:通过差分,您会丢失趋势,包括其起始和结束水平。之后您试图恢复趋势,但在您的代码中,您似乎未能恢复结束水平。我认为当前观测值的结束水平应该添加到所有预测中。
再次感谢!
您说的结束水平是什么意思?抱歉,我不明白,也许您可以重述一下您的评论?
很棒的教程!
快速提问:在教程的缩放部分,您说
“为了使实验公平,必须在训练数据集上计算缩放系数(最小和最大)值,并将它们应用于缩放测试数据集和任何预测。这是为了避免用来自测试数据集的知识污染实验,这可能会给模型带来微小的优势。”
然而,如果您的样本最大值在测试数据集中,那么使用来自训练集的参数进行缩放将产生一个超出[-1,1]范围的数字。如何处理这种情况?
谢谢!
正确。
一个好的方法是估计该域可能预期的最小和最大值,并使用这些值进行缩放。
如果即使那样您也看到超出范围的值,您可以将它们限制在0/1的边界。
亲爱的 Jason,
更确切地说:您应该加上训练集的起始水平与结束水平之间的差值。这是因为当前代码有效地复制了训练集。通过这一点,我的意思是它从与训练集相同的水平开始。但是,它应该从训练集的结束水平开始。
诚挚的问候,
吉多
我将尝试重述我的评论。
目前,预测(您的测试集)的开始水平与观测值(您的训练集)的开始水平相同。因此,最后一个观测值(在您的训练集中)和第一个预测值(您的测试集)之间存在一个偏移。此偏移的大小等于:观测值的起始水平减去观测值的结束水平(在您的训练集中)。您应该通过将其添加到预测值来纠正此偏移。
使数据平稳化难道不就解决了这个问题吗?
你好,
1. 你能详细解释一下下面的两行代码吗?
model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1))
2.我想了解层架构。隐藏层中有多少个神经元?
3.如果我想再添加一个隐藏层,语法是怎样的?
4.测试RMSE小于训练RMSE的原因可能是什么?
该行定义了输入层和第一个LSTM隐藏层,具有“neurons”数量的内存单元。
您可以堆叠LSTM,第一个隐藏层必须返回序列(return_sequence=True),您可以添加第二个LSTM层。我有一个例子在这里。
https://machinelearning.org.cn/time-series-prediction-lstm-recurrent-neural-networks-python-keras/
测试数据比训练数据表现更好可能是模型不稳定/欠拟合的迹象。
你好Jason,谢谢你的帖子!我买了你书的第一版,我看到你在这方面进行了更深入的分析。非常好!🙂 我还有些东西不清楚。
“样本:这些是来自领域的独立观测值,通常是数据行。
时间步:这些是给定观测值的给定变量的独立时间步。”
我能理解时间步参数为1的情况,就像在你的书和本例中一样,但我无法弄清楚为什么以及如何使它大于1…
我的假设,当然是错误的🙂
也许当一个时间步由n个观测值组成时,你可以给它赋值n……但那样的话,我期望当有人在模型中写(第192页)
“model.add(LSTM(4, input_shape=(1, look_back)))”
LSTM会为每个时间步使用(look_back * timesteps)行来预测下一行……
我也无法理解为什么你说“给定变量的”……一行通常由许多变量的值组成,不是吗?
你能给我一个时间步大于1的例子吗?谢谢!
你好 Fabio,
LSTM输入的结构是 [样本数, 时间步数, 特征数]。
如果您在一个时间步有多个观测值,那么这些将作为特征表示。
这有帮助吗?
你好 Jason,
不幸的是,如果没有具体的例子,我无法完全理解……您帖子和您书中的例子对我来说都很清楚,但它们总是关于时间步=1……如果我没记错的话。例如,如何调整本帖中描述的场景以处理时间步>1?
非常感谢!
PS. 同时我也购买了您关于时间序列的书。
请参阅这篇关于多步预测的帖子。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
感谢 Jason 提供精彩的教程!
我正在使用您的教程将 LSTM 网络应用于一些系统日志/网络日志数据。
我过去一年的每天都有系统日志数据(一个特定事件),所以我正在使用 LSTM 网络进行时间序列分析。
根据我从您的教程中的理解。
1.数据批次是训练数据集中固定大小的行数,它定义了在更新网络权重之前要处理的模式数量。根据batch_size,模型会从数据中随机抽取样本进行分析。对于时间序列来说,这是不理想的,因此batch_size应始终为1。
2.默认情况下,在将样本暴露给网络之前,样本会在一个 epoch 中被打乱。这对 LSTM 是不理想的,因为我们希望网络在学习序列观测值时建立状态。我们可以通过将“shuffle”设置为“False”来禁用样本的随机播放。
场景1 -
使用上述两条规则/指南 - 我进行了多次试验,使用了不同数量的神经元、epoch大小和不同的层,并获得了比基线模型(持久化模型)更好的结果。
场景2-
未使用上述指南/规则 - 我进行了多次试验,使用了不同数量的神经元、epoch大小和不同的层,并获得了比场景1更好的结果。
查询 - 为时间序列设置shuffle为True和Batch_size为1。这是一个规则还是一个指南?
逻辑上阅读您的教程,我理解时间序列的数据不应该被打乱,因为我们不希望改变数据序列,但对于我的数据,如果允许数据被打乱,结果会更好。
最终我认为,重要的是我如何通过我的运行获得更好的预测。
我认为我应该尝试将“理论”抛开,重视具体证据,例如指标、肘部、RMSEs 等。
请阐明。
不取随机样本,LSTM需要序列数据是有序的——它们学习顺序依赖性。
如果序列数据分布在各个样本中,“shuffle”参数必须设置为“False”。
亲爱的 Jason,
我有两个小时的时间序列数据,包含120个观测值,使用LSTM RNN,如何在我将所有数据放入训练部分的情况下预测接下来的30个观测值?
我们通常将原始数据集分成两个数据集(测试数据集和验证数据集)来检查我们的模型性能。我想看到我的模型只从训练数据集中获取帮助来产生一个与验证数据集匹配的输出。我从您几篇博客中的理解是,我们正在预测单个值,并使用这个单个预测值,以及从验证数据集中获得的帮助,来预测其余值。我认为我在这里迷失了?当只有过去和当前数据(假设没有验证数据)而我们想预测下一个半小时时,这会如何工作?
例如,假设我有从下午12点到下午1:30的产品价格数据,其中包含90个观测值,使用这过去的90个观测值,我们能否预测该产品在下午1:31到下午2:00(即接下来的30个观测值)的价格?
你能帮我解决我的困惑吗?顺便说一句,我正在阅读您的《Python时间序列预测》和《Python深度学习》等书籍。
您可以通过直接使用 LSTM(一次性预测 n 个时间步)或递归使用(一遍又一遍地使用相同的模型,并将预测用作后续预测的输入)来创建多步模型。
关于多步预测的更多内容请看这里。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
这有帮助吗?
感谢您的快速回复。
看起来您睡得很少,因为您在清晨从您的网站上提供了反馈。
感谢您对学生如此友善。愿上帝保佑你。
顺便说一句,您是否有关于我提供的第二个选项(一遍又一遍地使用相同的模型,并将预测用作后续预测的输入)的博客或示例?显然,我想确保我没有使用验证数据集中的任何数据,也没有获得任何来自验证数据的信息。模型应该只使用过去和当前数据以及当前的预测。我希望您能理解这个困惑的学生。
谢谢你
抱歉,我没有使用模型进行递归预测的例子。我相信您可以修改上面的示例。
您能否给我一些关于在哪里修改代码以使模型递归的提示,因为我的编码能力不太好。
预测将被用作历史(输入)以对后续时间步进行预测。
感谢 Jason 提供精彩的教程!
这里有一个小问题。
def invert_scale(scaler, X, value):
new_row = [x for x in X] + [yhat]
...
这应该是
def invert_scale(scaler, X, value):
new_row = [x for x in X] + [value]
...
谢谢 Max。
运行您提供的第一个代码块时,我遇到了以下错误。
TypeError: strptime() 参数 1 必须是 str,而不是 numpy.ndarray
这似乎是Python 3.6如何处理字节字符串的问题。
我只在Python 2.7和Python 3.5上测试过代码,也许可以尝试其中一个?
否则,您可能需要为您的特定平台改编示例,如果API更改确实是您问题的原因。
问题出在页脚的文字“过去三年洗发水销量”。
要么删除页脚,要么
更改这一行
series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)
推广到
series = read_csv(‘shampoo-sales.csv’, header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser, skipfooter=2)
我认为这个错误是由洗发水销售数据文件底部的一行描述性文字引起的。如果您看到此评论在数据文件的底部,请将其删除。
过去三年洗发水销量
数据文件还用双引号括起了日期。这几次也卡了我。date_parser回调有点不稳定。
你好,你的例子很棒,谢谢。
我有一个问题。
1- 在示例中使用lstm_model.predict() 和 train 数据时,我们如何处理预测值数组?它们似乎没有被使用。这对网络重要吗?
谢谢 Logan。
您具体是指什么?您指的是教程中的哪个特定部分和哪一行代码?
是的,第101行 lstm_model.predict(train_reshaped, batch_size=1) 在“Complete LSTM Example”部分。
另外,我还有一个问题:当差分应用于整个数据集时,它是否为模型提供了有关测试数据集的信息?
谢谢。您给了我很多帮助。
在这种情况下是的,但在实践中,我们可以逐步地将相同的方法应用于测试数据,并使用训练数据,而不会作弊。
Jason你好,我也有和Logan一样的疑问。第101行
lstm_model.predict(train_reshaped, batch_size=1)
我们需要这一行吗。
我注释掉了这一行,并没有看到任何区别。您能多解释一下为什么需要这一行吗?
感谢您提供的精彩教程。
此致,Long
它应该用于在训练数据上初始化状态。
如果它没有增加价值,就移除它。
嗨,Jason,
非常感谢您提供这个有用的教程。您能否澄清一下,在所有参数中,哪些需要更新才能改变滞后值?我一直无法使其工作。
谢谢!
很好的问题。
更改 timeseries_to_supervised() 函数的参数。
我不得不更改 range() 函数的限制,才能使循环对滞后值>1工作。
def timeseries_to_supervised(data, lag=1)
df = DataFrame(data)
columns = [df.shift(i) for i in range(lag, 0, -1)]
columns.append(df)
df = concat(columns, axis=1)
df.fillna(0, inplace=True)
return df
太棒了!
嗨,Jason,
我关注你已经有一段时间了。又一个关于时间序列的精彩例子。我记得在早期的博客中尝试过滑动窗口方法。我仍然在等待你写一篇关于包含外部特征的博客(它可以很简单,比如(is_weekday =0/1 is_weekend=0/1)),看看它是如何实现的。
你能指出在上面的例子中,我们可以在哪里添加上述外部变量,以及这些变量的格式吗?我会尝试一下。由于我刚开始接触Python,对于LSTM所需的重塑和预格式化感到非常困惑。
#aspring data scientist, student
你可以将它们添加为单独的特征。
我目前正在处理一个例子。我希望在它给出好的结果时发布它。
嗨 Jason,好例子!我有一个类似的问题,但我不知道如何解决。我有两个不同的类别需要预测,在不同的文件中。我必须用这些不同的文件训练我的神经网络。问题是每个文件有不同数量的样本,而且我必须为每个文件使用相同的LSTM。我如何泛化每个LSTM的输入数量??
这是我的问题
https://drive.google.com/file/d/0B5hOtU0Xa45RUDJJWHVyeHVNQWM/view?usp=sharing
也许这篇帖子能帮助你更好地理解你的预测问题,并将其构建为监督学习。
https://machinelearning.org.cn/how-to-define-your-machine-learning-problem/
感谢你的回答,我明白了我的问题。这取决于训练,因为我有大量的文件用于训练,当我插入一个新文件并重新进行拟合时,之前的信息就会被遗忘。你有没有一些关于用更多文件训练LSTM的例子?并且每个文件都有监督学习,应用于时间序列和预测信息?谢谢!
是的,这个例子展示了如何用更多数据更新现有模型。
https://machinelearning.org.cn/update-lstm-networks-training-time-series-forecasting/
亲爱的Jason
你做得很好!!
感谢您与我们分享这篇很棒的帖子。
我是机器学习的初学者,这些天我一直在做一个预测海上船舶运动的项目。
我发现这篇帖子非常有用且易于理解。
我有一个问题:
如果神经元的数量是用来预测下一步的过去步数吗?
提前感谢您的回答。
祝好
我不确定你的意思。
神经元的数量定义了模型的大小/复杂性。模型用于进行预测。
也许你可以重新表述你的问题?
你好,
恭喜这篇博客,谢谢!它对我有很大帮助。
我有一个关于数据转换的问题。我理解将一个输入设为最后一个输出来让LSTM学习和保存信息这一步。但我有一个不同的案例(分类),我不知道如何应用它。
在我的案例中,我的输入是图像(视频帧),它们具有时间依赖性,而我的输出是数字(0,1或2)。首先我想将图像通过CNN网络,然后获取特征,这些特征将是我的LSTM输入。在这种情况下,有必要像这里一样处理数据吗?我以为LSTM会自己保存这些信息,但现在我不确定了。
先谢谢您了。
我没有处理视频数据的例子。
总的来说,原理是相同的。作为一个分类问题,你需要将输出层更改为使用一个对数损失激活函数。输入将来自CNN或类似网络,例如 [cnn]->[lstm]->[dense]。
告诉我进展如何。
嘿,你最终有没有解决这个问题?我有一个类似的问题想解决,希望得到你的建议!!
在你的ARIMA教程中,你也使用了洗发水数据集,但通过MSE衡量准确性。将它改为RMSE
rmse = sqrt(mean_squared_error(test, predictions))
print('Test RMSE: %.3f' % rmse)
我得到
> Test RMSE: 83.417
根据我们目前的研究,我们能得出ARIMA比LSTM更适合这个问题吗?
不,这些只是演示。两种算法都需要进行调整,以展示它们最好的一面(“钢人”对“稻草人”)以供模型选择。
我们正在编写timeseries_to_supervised函数来接受滞后值
def timeseries_to_supervised(data, lag=1):
这个功能本质上是你在2016年7月21日教程中描述的窗口方法+重塑吗?
但我们似乎没有使用那个参数,总是“timeseries_to_supervised(diff_values, 1)”
使用滞后值高达50(在航空公司数据上),并像这样更改predict()
# 预测整个训练数据集以建立预测状态
train_reshaped = train_scaled[:, 0:look_back].reshape(len(train_scaled), 1, look_back)
# train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
lstm_model.predict(train_reshaped, batch_size=1)
似乎能做出很好的预测,在测试集上具有非常低的RMSE。
我是否可能破坏了模型,使其作弊了?
look_back = 60
epochs = 15
Month=1, Predicted=321.813110, Expected=315.000000
Month=2, Predicted=310.719757, Expected=301.000000
Month=3, Predicted=363.746643, Expected=356.000000
...
Month=46, Predicted=458.424683, Expected=461.000000
Month=47, Predicted=418.427124, Expected=390.000000
Month=48, Predicted=412.831085, Expected=432.000000
Test RMSE: 18.078
用于测试环境
yhat = y
Test RMSE: 0.000
似乎在测试预测中存在训练数据的污染,因为forecast_lstm(model, batch_size, X)被给予X个观测值,每个观测值都有60个历史过去观测值,这些观测值与训练数据重叠。但那又怎样呢?那是训练看到过的历史,当它进入测试数据时,它只增加了测试集中看到的历史。但这似乎就是真实世界的情况:你总是有过去可以参考。
最后,你说,“在本教程中,我们将采用固定方法,因为它比较简单,尽管我们预计动态方法会带来更好的模型技能。”对于我们这样的小数据集,一个大的滞后值在某些方面就给了我们一种半动态的方法,不是吗?
这是一个稳健的模型,具有一个看似不错的RMSE?
完整代码: http://tinyurl.com/y74ypvde
预测与实际图: http://tinyurl.com/y9ouajdm
在洗发水数据集上
look_back = 18 (滞后)
epochs = 30
Test RMSE: 110.594
预测与实际图: http://tinyurl.com/ycoy6aes
非常敏锐!
不错。
嗯,我认为动态是指用新数据更新模型。
如果你有资源,我建议探索一下用新观测值更新模型是否会影响模型技能。我预计会。我这里有一个例子
https://machinelearning.org.cn/update-lstm-networks-training-time-series-forecasting/
嗨,Jason,
你做得很好,帮助人们学习如何应用机器学习。一周前,我还不了解时间序列,但现在我已经能够稍微玩转它了。谢谢你!
关于这篇帖子,我有一个疑问。当我们说
“为了使实验公平,必须在训练数据集上计算缩放系数(最小值和最大值),并将它们应用于缩放测试数据集和任何预测。这是为了避免用测试数据集的知识污染实验,这可能会给模型带来微小的优势。”
我们不应该这样做吗?
scaler = scaler.fit(X[:-12])
而不是
scaler = scaler.fit(X) ?
如果我们使用X,我们是否使用了测试集的数据?
感谢您的关注,并继续保持出色的工作!
是的。理想情况下,我们应该利用领域知识来估计可能观察到的值的预期最小值/最大值。
你好 Jason,
在使用健壮的代码(最后一个)后,我得到了这些结果
1) Test RMSE: 180.438
2) Test RMSE: 110.352
3) Test RMSE: 119.655
4) Test RMSE: 170.720
5) Test RMSE: 211.877
6) Test RMSE: 101.453
7) Test RMSE: 105.532
8) Test RMSE: 149.351
9) Test RMSE: 88.118
10) Test RMSE: 138.013
11) Test RMSE: 265.045
12) Test RMSE: 135.861
13) Test RMSE: 167.766 …(其余省略,花费时间太长)。
作为机器学习的初学者,并使用你的教程来学习它,你能告诉我这些结果是否正常(与你的结果差异很大),而之前的一切都还好吗?如果这些结果不正常,你能告诉我造成这种差异的原因吗?
感谢您的关注,请继续制作这样的教程,它真的很有帮助!
嗨 Eric,请看这篇帖子,以便更好地理解神经网络算法的随机性。
https://machinelearning.org.cn/randomness-in-machine-learning/
请看这篇帖子了解更多关于如何开发模型技能的稳健估计。
https://machinelearning.org.cn/evaluate-skill-deep-learning-models/
请看这篇帖子关于如何固定随机数种子。
https://machinelearning.org.cn/reproducible-results-neural-networks-keras/
我明白了,非常感谢您提供的链接和解决方案!
不客气。
阅读了这些链接后,我理解的是
– 由于可能来自许多因素的随机性,总是得到相同的结果非常困难(几乎不可能)。
– 只有通过大量重复操作(就像你在上一个例子中那样,有30个例子(但如果做100个例子会给出更好的想法?)),才能帮助你确定结果的差异程度,并找到一个“可接受的范围”?
– 设定随机数生成器的种子可以有所帮助。
所以,为了继续我的项目,我想象你解释的那样设定随机数生成器的种子。比如在这里,重复过程30次(因为我有一台服务器,我可以让它过夜,然后进行100次),然后确定平均值并确定一个范围。
一开始这样似乎可以吗?
我是否遗漏了什么?
感谢您的关注以及您为大家提供的帮助。
请看这篇关于如何估计重复次数的帖子。
https://machinelearning.org.cn/estimate-number-experiment-repeats-stochastic-machine-learning-algorithms/
我不建议为实验工作固定随机数种子。你的结果会产生误导。
嗨,Jason,
非常感谢您的教程。
不过我还有几个疑问。
1. 我正在处理一个问题,其中去趋势数据的自相关图显示,时间t的值与系列中大约过去100个值显著相关。是否适合将批量大小设置为100来建模该序列?
2. 您提到对于这个例子来说,少于5个记忆单元就足够了。您能否给我一些关于如何为上述特定问题选择记忆单元数量的思路?这个数量还取决于其他哪些因素?
请澄清。
谢谢
尝试输入100-200个时间步长,看看效果。
系统地测试一系列不同的记忆单元,看看哪种效果最好。
谢谢你,Jason。
不客气。
嗨 Jason!非常感谢您的教程,它真的很有帮助。
我使用了这个教程,直接用于预测一个物品的成本,该物品的成本在几美元和几美分之间。
我的数据集有262行,即0到261。
当我运行模型时,图表完美地捕捉了最细微的趋势,但预测数据似乎有1个时间步的滞后。
这个月的预测值几乎与上个月的预期值完全匹配。并且一直都是这样。
我唯一更改的代码是索引:
推广到
train, test = supervised_values[0:200], supervised_values[200:]
rmse = sqrt(mean_squared_error(raw_values[200:], predictions))
pyplot.plot(raw_values[200:])
是我真正更改的唯一代码行。
考虑从一个更简单的线性模型开始。
https://machinelearning.org.cn/start-here/#timeseries
我不认为LSTM是自回归模型的第一选择或最佳选择。
https://machinelearning.org.cn/suitability-long-short-term-memory-networks-time-series-forecasting/
我认为我遇到了同样的问题。你解决这个问题了吗?
嗨,Jason
LSTM在输入端不是有一个挤压门吗?输出在(-1, 1)之间?那么,如果第一个输入门会为我们做这件事,为什么我们还需要准备输入数据使其在(-1, 1)之间呢?
我是否错过了什么?
是的,你可以将输入重新缩放到[0,1]。
考虑到
unseenPredict = lstm_model.predict(X)
……我们如何构建X来获得单步向前预测的不可见数据?
或者我们可以修改脚本“Complete LSTM Example”中的一些偏移量来达到相同的效果,如果可以的话,如何修改?
嗨,Jason,
感谢您出色的教程。我尝试修改上述代码以包含模型中的多个时间步长和多个滞后值。我运行这些参数作为输入,并并行运行脚本以配置不同的模型来选择最准确的模型。你认为我所做的修改对以下函数有何看法?我特别担心模型中包含的时间步长,这是正确的吗?
def timeseries_to_supervised(data, lag=1, time_steps=0)
df = DataFrame(data)
columns = [df.shift(i) for i in range(1, lag+1)]
#考虑涉及的时间步长t,并且
#在每个x列旁边添加下一个t x列
#问题??如果time_steps = 3,是否意味着y应该从y_4开始
#我们将最后3个值从数据集中修剪掉?
if time_steps > 0
columns_df = concat(columns,axis=1)
#请注意,我已经将i乘以-1来执行左移而不是右移
timestep_columns = [columns_df.shift(i*-1) for i in range(1, time_steps+1)]
timestep_columns_df =concat(timestep_columns, axis=1)
columns.append(timestep_columns_df)
columns.append(df)
df = concat(columns, axis=1)
df.fillna(0, inplace=True)
return df
def fit_lstm(train, batch_size, nb_epoch, neurons, lag, time_steps)
X, y = train[:, 0:-1], train[:, -1]
X = X.reshape(X.shape[0], time_steps+1, lag)
model = Sequential()
model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1] , X.shape[2]), stateful=True, return_sequences=True))
model.add(LSTM(neurons, stateful=True))
model.add(Dense(1))
model.compile(loss=’mean_squared_error’ optimizer=’adam’)
model.summary()
for i in range(nb_epoch)
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=1, shuffle=False)
model.reset_states()
return model
def forecast_lstm(model, batch_size, X, lag,time_steps)
X = X.reshape(1,time_steps+1,lag)
pad = np.zeros(shape=(batch_size-1, time_steps+1, lag))
padded = np.vstack((X, pad))
yhat = model.predict(padded, batch_size=batch_size)
return yhat[0,0]
干得漂亮!
我想将这个想法扩展到多个特征x的每个x时间观测值的滞后值。将MinMaxScaler应用于这个3D对象是否合理?y的真实值如何适应我提供给MinMaxScaler的内容,因为它只有2D?
不,我建议单独缩放每个序列。
上面你似乎将y和X一起缩放了。但是对于多个特征,其中其余的不仅仅是y的时间移位副本,我认为我们可以先对y_train进行拟合,然后再转换y_train和y_val?那么这实际上是我们为以后反转需要保存的唯一缩放器对象了吗?
我建议在任何移位操作之前单独缩放每个序列,以将其变成监督学习问题。
希望这能回答你的问题,如果我误解了,请随时提出。
我认为“分别缩放每个序列”这句话让我感到困惑。我认为我们仍然可以使用单个缩放器对象来缩放所有传入值(所有X以及将成为y并被移位的时序数据,其中一个X)。然后我们从缩放后的值创建滞后值。最后,使用这个单个缩放器对象来反转y的预测。我理解得对吗?
每个序列是不同的“特征”或“列”或“时序”或我们称之为任何东西。
用于每个序列缩放的系数(最小值/最大值或平均值/标准差)需要被保留,以便以后对预测进行反向操作和将操作应用于输入数据。你可以保存系数或包装它们的那些对象。
Jason,很棒的教程,谢谢!
一个问题:你为什么要在fit()函数中设置一个适当的epoch数量,而是循环遍历epochs?这不会得到相同的结果并且更整洁吗?
这样我就可以手动管理网络内部状态的重置。
啊,我明白了,这与keras中“stateful”的定义不同,这里解释得很清楚:http://philipperemy.github.io/keras-stateful-lstm/
你好,Jason博士
非常感谢您的教程。
我想有多重时间步长,但我不知道如何修改函数“timeseries_to_supervised()”。
我找到了你的另一篇关于这个的帖子,但你使用了函数“create_dataset()”。
我修改了函数如下:
def create_dataset(dataset, look_back=1)
dataset = np.insert(dataset,[0]*look_back,0)
dataX, dataY = [], []
for i in range(len(dataset)-look_back)
a = dataset[i:(i+look_back)]
dataX.append(a)
dataY.append(dataset[i + look_back])
dataY=numpy.array(dataY)
dataY = np.reshape(dataY,(dataY.shape[0],1))
dataset = np.concatenate((dataX,dataY),axis=1)
return dataset
请检查我的修改,是对的还是什么?
请看这篇文章
https://machinelearning.org.cn/convert-time-series-supervised-learning-problem-python/
嗨,Jason,
抱歉,如果这看起来很愚蠢,但有一部分我没弄明白。
为了预测,你使用:“yhat = model.predict(X, batch_size=batch_size)”
但正如我们所见,X是
train, test = supervised_values[0:-12], supervised_values[-12:]
scaler, train_scaled, test_scaled = scale(train, test)
yhat = forecast_lstm(lstm_model, 1, X)
所以X是我们要预测的12个值(在经过scale函数处理后)。为什么我们要使用它们,因为在正常情况下我们不会知道它们的值?
再次感谢您的教程,它真的帮助了我进行机器学习训练。
在一般情况下,你可以输入任何你想要的东西来做出预测。
例如,如果你的模型是根据过去6天的值来预测下一天,并且你想预测明天,那么就输入今天和前5天的值。
这有帮助吗?
我认为这对我有帮助。在我的例子中,我每分钟都有一个值,我必须预测下一周(大约10K的预测)。
我有一年前的数据,所以我的训练没有问题,只是想知道在预测部分应该怎么做(所以我可以直接用我的训练集再次输入,而不是用test_scaled?)
感谢您的帮助和快速回复!
是的,如果你的模型设置是根据固定的滞后值进行预测,那么你必须在数据集结束之后提供这些滞后值。这些可能属于你的训练数据集。
我不认为它在我的训练数据集中,在这部分我几乎是按照你的方法做的(将序列转化为监督学习问题时出现的滞后)。我几乎和你一样给模型喂数据。对我来说的问题在于调用 predict 命令时不知道该喂什么。发送 "train_scaled" 是个坏主意(结果很差,预测值很大,而它应该预测较低的值,预测值较低,而它应该预测较高的值)。我正在努力解决这个问题,但任何建议都受欢迎。再次感谢,并且抱歉我学习/理解得有点慢。
predict() 函数的参数与 fit() 函数的参数相同。
数据必须以相同的方式缩放并具有相同的形状,尽管样本数量可能不同,例如,你可能只有一个样本。
很明显,你不需要为训练数据做预测,所以传递给 predict 的数据将是进行所需预测所需的输入。这 realmente 取决于你的问题/模型的构建方式。
这有帮助吗?
感谢您的快速回复!我认为我理解得更好了,但有些地方我仍然难以理解。
输入是 X,对吗?
如果我遵循你关于输入/输出的教程(https://machinelearning.org.cn/time-series-forecasting-supervised-learning/),并以我的案例为例(数据库每3分钟记录一次值,我们想预测下一个值(所以例如一开始是12:24:00))
日期,拥堵
2016-07-08 12:12:00,92
2016-07-08 12:15:00,80
2016-07-08 12:18:00,92
2016-07-08 12:21:00,86
这是(部分)我的训练数据,当将其转化为监督训练数据(并移位)时,我得到
X, y
?, 92
92, 80
80, 92
92, 86
86, ?
问题是我不知道预测用的 X,我只知道用于训练的 X(train_scaled)和用于比较结果的 X(test_scaled)。
我应该喂给它什么输入?我不能喂给它 test_scaled,因为在实际情况中我不知道它会是什么。
如果我的问题看起来很愚蠢,请原谅,并感谢您花时间解释。
这取决于你如何构建你的模型。
如果输入(X)是 t-1 时刻的观测值,用于预测 t 时刻的值,那么你输入最后一个观测值来预测下一个时间步。
是的,我的每个输入 X 都是 t-1 时刻的观测值(很像教程中使用的洗发水案例)。
感谢您的回答,您回答了我的问题,我现在应该没有问题了!
也感谢您的教程,它们真的帮了我很多!
很高兴听到。
为了确保我的推理没有错误,如果我从之前的例子中提取
X, y
?, 92 / T-3
92, 80 / T-2
80, 92 / T-1
92, 86 / T
86, ? / T+1
来预测下一步(T+1),我必须使用“yhat = model.predict(X, , batch_size=batch_size)”,其中 X 是 86(经过缩放/重塑后)。对吗?
然后我将得到 T+1 的预测值(需要对其进行逆缩放和差分才能得到可读的值)。
如果我想预测得更远,我将继续(将 T+1 预测的缩放/重塑值输入以获得 T+2,然后直到我预测到想要的程度)。
感谢您的时间和答案!
正确。
感谢 Jason,在您的帮助下,我成功地预测了下周的每分钟值。不过我有两个问题:
首先:我删除了测试集的代码(因为在现实中我不会有它),我拥有的唯一东西是 Excel 文件中的测试集(最后10000行)。
当使用这段代码(用于训练)时
# 将数据转换为平稳
raw_values = data.values
diff_values = difference(raw_values, 1)
# 将数据转换为监督学习
supervised = timeseries_to_supervised(diff_values, 1)
supervised_values = supervised.values
# 将数据分为训练集和测试集
train = supervised_values[:-10000]
# 转换数据尺度
scaler, train_scaled = scale(train)
和这段代码(用于预测)
# 预测整个训练数据集以建立预测状态
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
lstm_model.predict(train_reshaped)
# 对测试数据进行步进验证
predictions = list()
predictionFeeder = list() # 用于用 T-1 的值喂模型
X, y = train_scaled[0, 0:-1], train_scaled[0, -1]
predictionFeeder.append(X) # 提供训练的最后一个值
for i in range(0, 10000)
# 进行单步预测
yhat = forecast_lstm2(lstm_model, predictionFeeder[i])
predictionFeeder.append(yhat)
# 逆缩放
yhat2 = invert_scale(scaler, testa[i + 1], yhat)
yhat3 = inverse_difference(raw_values, yhat2, 10000 + 1 – i)
predictions.append(yhat3)
并训练一个模型(25 个 epoch),然后预测结果,我得到的结果太好了(RMSE 为 2 或更低,预测误差小于 5%)。
由于习惯了事情毫无原因地出错,我决定从 Excel 中删除测试数据(即使不应该有任何影响,因为我没有使用它们(我甚至一开始将变量设置为 None))。然后当我这样做时,预测结果变差了很多,并且出现了一些滞后(尽管,如果你消除了滞后,仍然有好的结果,只是不如之前好)。
为什么会这样?
我的第二个问题是关于滞后,从预测中可以看出,虽然图表的形状(预测和实际)看起来相似,但预测的上升/下降趋势比实际情况早,您有什么办法可以解决吗?您认为改变滞后或时间步长会有帮助吗?
再次感谢您的帮助,我认为没有您的教程我达不到现在的成就。
抱歉,我无法为您调试代码。
也许你无意中在训练和测试数据上拟合了模型,然后在测试集上进行评估(例如,在它已经见过的数据上)。
我鼓励你尝试不同的滞后值,看看哪种最适合你的问题。
不用担心,我不会让你调试的。
也许吧,我不知道,我确实移除了变量以确保从未影响过测试集并使用它,但由于我是人,我可能犯了错误。
那么改变滞后会帮助我解决现实与预测之间的这些差距吗?谢谢,我会这样做的。
感谢您的回复!
我能购买您书籍的实体版(非电子书)吗?谢谢。
抱歉,我现在看到了,这是不可能的。但还是谢谢您。您的解释和教程非常精彩。恭喜!
谢谢 Josep。
你好,
感谢非常好的教程。我有一个问题/疑虑。
在以下代码部分
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
不应该依赖预测值而不是已经已知的原始值吗?在您的验证示例中,调用 inverse_difference 时总是引用测试值(已知)。但在现实中,我们只有预测值(用作 X),当然也有已知的起始点(t=0)。或者我错过了什么?
我的建议
# 逆差分 – (从第二个循环周期开始(第一个将是起点(raw_values[-1])))
yhat = inverse_difference(predictions, yhat, 1)
提前感谢
Pawel
我们可以这样做,但在这种情况下,已知观测值是可用的,并且不在未来,使用它们进行重缩放(逆转换)是合理的。
您好,感谢您的解释,我现在明白了。因为我训练的模型使用了例如 5 月份的数据(15 秒采样),然后用该模型预测整个 6 月份的数据。之后,我将预测数据与 6 月份的数据进行了比较,我不得不说模型不起作用,几次预测后就出现了巨大的“不同步”。
在验证阶段,如您案例所述,我得到的 RMSE 是 0.11,不算差,但在现实中,当你使用预测值(t-1)来预测下一个(t)值时,就会出现问题。
您知道如何改进模型吗?我应该使用多步预测,还是滞后特征,输入时间步长?
非常感谢。
Pawel
我建议进行头脑风暴,然后尝试你能想到的所有方法。
这里有一个很好的列表
https://machinelearning.org.cn/improve-deep-learning-performance/
此外,与经过良好调整的带窗口的 MLPs 进行比较。
嗨 Jason,我有一点不明白您的帖子。您想训练一个 state-full LSTM,但 reset_states() 在每个 epoch 之后都会执行。这意味着,前一个批次的 states 不会在当前批次中使用。这如何使网络 state-full?
谢谢
状态在每个 epoch 内的样本之间保持。
嗨,Jason,
感谢精彩的教程。我有一个问题。使用回调函数来重置状态会不会更好?这可以让你也使用例如 EarlyStopping Monitor 进行训练,这是我更改的内容
class resetStates(Callback)
def on_epoch_end(self, epoch, logs=None)
self.model.reset_states()
model.fit(X, y, epochs=nb_epoch, batch_size=batch_size, verbose=1, shuffle=False, callbacks=[resetStates(),EarlyStopping(monitor=’loss’, patience=5, verbose=1, mode=’min’)])
是的,对于需要重置每个 epoch 结束时状态的问题,这是一个更干净的实现。
您好,这是否可以扩展到异常检测技术?
也许吧,我没有将 LSTM 用于异常检测,我无法给出好的建议。
也许你可以将其构建为序列分类?
嗨,Jason,
在持续性模型图中,有一个时间间隔的滞后。在进行单步预测时,是否可以克服这个问题?这到底是怎么发生的?似乎模型对时间间隔 x[t-1] 给予了极大的权重。
这是我正在分析的数据集的一个例子
迭代:969
月份=970,预测=-7.344685,预期=280.000000
迭代:970
月份=971,预测=73.259611,预期=212.000000
迭代:971
月份=972,预测=137.053028,预期=0.000000
预期值应为 280 和 212(幅度很大),模型捕获了 73 和 137,但滞后了一个时间间隔。
谢谢!
LSTM 在自回归问题上并不擅长,并且经常收敛到持续性模型。
好的,谢谢。什么模型是捕捉这个问题的良好替代方案?我用 ARIMA 也遇到了同样的问题。这可能只是一个难以预测的数据集。
我建议从一个经过良好调整的 MLP + Window 开始,看看是否有其他模型能做得更好。
嗨,Jason,
多亏了您,我成功地得到了一个有效的 LSTM 网络,它似乎具有良好的准确性(因此 RMSE 较低)。
但是我遇到了一个问题,您知道可能是什么原因导致了现实值和预测值之间的巨大延迟(我的预测值与现实值形状相同,但上涨/下跌趋势比现实值早)?
此致敬礼,请继续您的工作,它真的很有用。
你好 Eric,这可能是你在评估模型方式上的一个错误。
这可能是原因,我不得不对预测系统做一些更改,以使用最后一个预测值,我可能在那里遗漏了什么。(另外,我必须使用 Tflearn 而不是 Tensorflow,但这应该不是问题,因为 Tflearn 是使用 tensorflow 的更透明的方式)。
谢谢你的回答!
加油 Eric!
谢谢!
好吧……我有一个 151(指的是宝可梦?)的间隔。
为了尝试一下,我从我的训练集中删除了这 151 个值,现在我没有值间隔了(坦白说,对于 15 个 epoch 的训练,准确性似乎不错)。我知道这远非一个修复方法,但它让我思考我在哪里出了问题。
会不会是我的训练集有 400K 个值,而我的预测从训练集的末尾提前 151 个值开始(所以预测 399849 的值),(这很奇怪,因为训练中的信息告诉我我正在训练 400K 的数据)。
这意味着我的机器试图预测用于训练的某个时间点。
或者这意味着最后的 151 个数据根本没有用于训练(我尝试减少数据量,但问题还是一样)。
算法是逐样本、逐批次、逐 epoch 进行训练的。最后一个样本是关键。
谢谢您的回复。
仔细想想,我的预测比实际情况要提前。
所以我的模型开始预测不是在我完成训练的地方,而是在之后(这很奇怪,因为我的训练结束的地方就是我的测试开始的地方,并且每个输入都是一个值(每一行都对应一分钟,就像洗发水数据集的行对应一个月一样)。
我一定在哪里犯了错误。
感谢您的回答,我认为我正在朝着正确的方向前进!
坚持住!
我仍然不理解这些模型的一点是,我如何预测未来。
比如说,我训练了我的模型,我们现在生活在 2017 年 8 月 8 日。现在 model.predict() 似乎需要一些测试样本才能预测任何内容,在这种情况下是 test_scaled 中的值。那么,当我想要预测 2017 年 8 月 9 日的值时,我该输入什么,我们还不知道?所以我想知道 yhat(t+1)。我能让模型为我预测未来 5 天吗?
我可能是错的,但在我的情况中,我用我拥有的数据(假设是一年,直到 2017 年 8 月 8 日)训练了我的模型,要预测 T 时刻的值,你输入 T-1 时刻的值(所以在这种情况下是 2017 年 8 月 8 日的值),你就会得到 8 月 9 日的值。
然后如果你想要 8 月 10 日(T+1)的值,你输入 8 月 9 日(T)的值。但是这段代码展示的是单步预测实现。也许如果你想预测更多,你应该看看多步预测?我想这个网站上有一些例子。
我想 Jason 会给你一个更好的答案。
说得好 Eric!
是的,我还要补充一点,如果模型被训练成以昨天的数据作为输入来预测今天,那么在最终使用时,模型需要昨天的数据才能预测明天。
这一切都取决于你如何构建预测问题,来决定你需要什么样的输入。
如果你想预测一天,模型就需要被训练成预测一天。
你必须决定模型将输入什么来做出该预测,例如,过去一个月或一年的数据。这就是模型的训练方式。
然后,在训练完成后,你可以使用它来预测未来值,也许使用训练数据的最后几个值。你可以使用一个被训练成预测一天的模型,通过递归的方式预测多天,其中预测值成为后续预测的输入。更多关于这方面的信息在这里
https://machinelearning.org.cn/multi-step-time-series-forecasting/
你也可以直接进行多步预测,这里有一个例子
https://machinelearning.org.cn/multi-step-time-series-forecasting-long-short-term-memory-networks-python/
这是否让你更清楚了?
谢谢 Eric 和 Jason。这正是我所做的,但对我来说,我得到的预测似乎不是提前一个时间步(T+1),而是 T 的预测,这没有意义。我使用的是股票收盘价作为数据。我得再检查一下,它是否真的在预测未来,正如你所坚持的那样。我将查看 Jason 的链接。
总之,感谢 Jason 的精彩教程!🙂
这里是收盘价的一个样本
2017-05-30 5.660
2017-05-31 5.645
2017-06-01 5.795
2017-06-02 5.830
事实上,在我看来,预测值比预期的值滞后一个时间步。
日期=1,预测=5.705567,预期=5.660000
日期=1,预测=5.671651,预期=5.645000
日期=1,预测=5.657278,预期=5.795000
日期=1,预测=5.805318,预期=5.830000
在这里,我是一天一天地前进,正如你所见,预测值比前一天实际值更接近。而且,无论如何,
让我们看看第二行
日期=1,预测=5.671651,预期=5.645000
预期的价格(即 2017-05-31 的实际价格)是我在 2017-05-31 交易日结束后输入模型的值。我期望模型预测的值更接近 5.79 而不是 5.67(后者更接近前一天的实际价格!)。看到了问题吗?我是否错过了什么?我没有更改框架中的任何内容,除了数据。
这是一个持续性模型,算法将收敛到它(例如,预测输入作为输出),如果它不能做得更好。
也许可以探索调整算法。
另外,我相信证券价格是随机游走的,而且持续性是我们所能做的最好的。
https://machinelearning.org.cn/gentle-introduction-random-walk-times-series-forecasting-python/
请做一些 RNN、NN 的教程,数据集中包含更多分类值?拜托,我找不到太多使用分类值资源的。
谢谢
我在博客上有一些教程 – 例如,文本数据输入或输出是分类变量。
你到底在找什么?
RNN 回归代码可以写出来吗?我需要为回归 RNN 提供什么激活函数?它与分类有何不同?
是的。回归的输出应该是“线性”的。
布朗利博士,您好,
我正在尝试理解这段代码。我是一名初学者,正在处理时间序列和 LSTM。
我关于您的代码的问题
1. “转换数据以使其平稳”是什么意思?
2. 为什么您创建 diff?它意味着什么?
3. 如果 raw_values 是 36 个数据,为什么 diff 只有 35 个?
我提前感谢您的回复,
Maria
没关系,我已经明白了。🙂
很高兴听到这个消息。
考虑使用博客搜索。
关于平稳数据请看这里
https://machinelearning.org.cn/time-series-data-stationary-python/
关于差分请看这里
https://machinelearning.org.cn/remove-trends-seasonality-difference-transform-python/
希望这能有所帮助。
谢谢,您写得很棒!
但是,我有一个疑问,对于时间序列预测,像自回归和ARIMA这样的经典方法,还是使用LSTM RNN模型的机器学习方法,哪种方法更好?两者各有所长,那么,在预测任何数据集时,我们的首选应该是哪种?我们应该如何在这两者之间进行选择?
这取决于你的问题。可以尝试几种方法,看看哪种效果最好。
我建议从ARIMA等线性方法开始,然后尝试一些机器学习方法,如树模型等,然后是多层感知机,最后可能是RNN。
当我将LSTM代码中的训练/测试比例改为0.8/0.2时,预测花了半个小时,而对于包含约4000条记录的另一组数据,它需要几个小时(我仍然无法得到结果,我不知道还需要多久)。您能给我一些关于如何为非常长的序列更改设置的建议吗?谢谢。
我这里有一些想法
https://machinelearning.org.cn/handle-long-sequences-long-short-term-memory-recurrent-neural-networks/
嗨Jason,对于像4000条记录这样长的序列,你能否根据你现在的例子,从代码的角度帮我理解一下变化?上面的链接是关于分类的,我正在寻找序列预测问题。
你必须将你的序列分割成子序列,例如,看看这篇文章以获取想法。
https://machinelearning.org.cn/truncated-backpropagation-through-time-in-keras/
谢谢Jason,你能否提供一个完整的代码示例来帮助我们理解?上面的链接只有一个想法,但没有代码实现,我想从代码的角度来理解。
此致,
Arun
这篇文章中的评估方法真的是“前向预测”吗?我读过你关于时间序列回测的文章。前向预测相当于对非时间序列数据的交叉验证。在这两种方法中,我们都会建立很多模型来学习,所以这些方法不适合深度学习,包括本文的主题LSTM。
是的,我们在这里使用的是前向预测验证。
前向预测验证是序列预测(如时间序列预测)所必需的。
有关该方法以及何时使用的更多信息,请参阅这篇文章。
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
感谢您的回复。抱歉,我不是这个意思。我读了您上面粘贴的文章,其中您将数据分割了2820次用于训练/测试,并构建了2820个模型。但是,在这篇LSTM文章中,您只分割了一次数据并构建了一个LSTM网络,所以我建议本文中的测试不是前向预测。是排序的(不打乱)保持测试吗?
抱歉,请删除此评论。
上面,该模型被评估了30次。
在对一个模型进行评估时,我们使用前向预测验证,并且样本不被打乱。
我建议重新阅读上面的教程和代码。
谢谢你的回复!哦,重复了30次!抱歉,我误会了。但是我认为在回测文章中,训练数据的大小是变化的,而在LSTM文章中,训练数据的大小是固定的,对吗?抱歉问了这么多问题。
感谢您的工作,非常棒。
我想看看每轮的训练损失与验证损失的对比图,见图:https://ibb.co/kqcnBk。正如你在另一篇文章中所提到的
“从损失图来看,模型在训练集和验证集(标记为测试集)上的表现相当。如果这些平行的图开始持续偏离,可能就需要提前停止训练。”
然而,在这种情况下,测试损失从未真正降低,而且两条线根本不平行。对于这个问题,以及总的来说,这是否意味着从训练中没有学到有意义的测试集模式,正如RMSE平均值接近于持续/哑变量方法所证实的那样?
这是终点吗?神经网络失败了吗?如果不是,接下来该怎么办?
我修改代码的主要地方是fit_lstm函数末尾
for i in range(nb_epoch)
e=model.fit(X, y, epochs=10, batch_size=batch_size, verbose=0,validation_split=0.33, shuffle=False)
model.reset_states()
return model, e
谢谢Gauthier。
这可能意味着模型对问题的配置不足。
好的……那么在这种情况下,您建议增加神经元数量,或者尝试另一种机器学习算法吗?
两者都是安全的选择。
嗨,@Gauthier,请问您是如何编辑代码以获得损失函数的?
Json,
感谢您的博客和教程。作为一名研究学者,当我不知道如何学习机器学习时,您的教程为我提供了一个很好的起点,使我能够开展我的机器学习和深度学习工作。
我尝试使用此页面的示例,但是,我无法从datamarket.com下载洗发水销售数据集。您能否在博客中提供数据集的链接?如果需要下载的步骤,请告知。
谢谢,听到这个我很高兴。
这是完整的数据集。
嗨,Jason,
我在第12个月收到NAN:
月=1, 预测=440.400000, 实际=440.400000
月=2, 预测=315.900000, 实际=315.900000
月=3, 预测=439.300000, 实际=439.300000
月=4, 预测=401.300000, 实际=401.300000
月=5, 预测=437.400000, 实际=437.400000
月=6, 预测=575.500000, 实际=575.500000
月=7, 预测=407.600000, 实际=407.600000
月=8, 预测=682.000000, 实际=682.000000
月=9, 预测=475.300000, 实际=475.300000
月=10, 预测=581.300000, 实际=581.300000
月=11, 预测=646.900000, 实际=646.900000
月=12, 预测=646.900000, 实际=nan
从下面的代码
predictions = list()
for i in range(len(test_scaled))
# 进行单步预测
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
#yhat = forecast_lstm(lstm_model, 1, X)
yhat=y
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
# store forecast
predictions.append(yhat)
expected = raw_values[len(train) + i + 1]
print(‘Month=%d, Predicted=%f, Expected=%f’ % (i+1, yhat, expected))
我不明白为什么会发生这种情况。
感谢您的反馈。
有意思。
每次都这样吗?
我想知道这是否是平台特定的。您使用的是32位机器吗?Python版本是多少?
我也有同样的问题,因为从https://datamarket.com/data/set/22r0/sales-of-shampoo-over-a-three-year-period#!ds=22r0&display=line下载后,CSV文件的末尾——
“3-10”,475.3
“3-11”,581.3
“3-12″,646.9
包含
”
过去三年洗发水销量
”
移除后即可正常工作
太棒了!
亲爱的 Jason,
我有一个问题,如果我们按照“我们不知道未来”的思路,应该将什么作为inverse_difference的第一个参数?
无论我做什么,如果我传入测试集,它就会有完美的准确性和值。如果我传入训练集,它会看起来像最后的len(test_scaled)个训练值。
此致
您需要传递一个过去观测值的列表,以便您可以反转差分操作。
尊敬的Jason先生,
抱歉,我不太明白,您说的“过去观测值的列表”是什么意思?会是我们预测的值(预测列表)吗?
那么这将遵循“Pawel”之前提出的问题和说法吗?
“我的建议
# 反转差分 – (从第二轮循环开始(第一轮将是起始点(raw_values[-1]))
yhat = inverse_difference(predictions, yhat, 1)”
此致,
埃里克
抱歉,我的意思是它是先前时间步的真实或实际观测值。例如,不是预测值。
尊敬的Jason先生,
谢谢,那么,假设有一个500,000条记录的文件。
我的训练集是前490,000行。我想预测最后10,000行。
在预测时,我传入训练集的最后一行(然后对于下一次预测,我传入我的第一次预测,而没有进行反归一化或反差分)。
为了得到真实值,我将“Invert_difference”的参数设置为我的训练集,或者更具体地说,我的最后10,000行?
此致,
Eric Godard。
我不建议预测10K个时间步。我预计其准确性会非常差。
尽管如此,观测值490000将用于反转观测值490001,然后将490001的转换预测值用于解码490002,依此类推。
这有帮助吗?
抱歉,我可能在这里措辞不当。
我的数据集每分钟有一个条目,一天是1440个条目,我的数据集中有几年的数据。我想预测接下来的一天,我应该将训练集的最后一天(trained_scaled[-1440:])作为inverse_difference的参数传递吗?
此致,
也许这篇文章能帮助您更好地理解不同的转换。
https://machinelearning.org.cn/remove-trends-seasonality-difference-transform-python/
我每次重新运行代码时都会得到不一致的RMSE结果,所以我添加了
np.random.seed(1) # 为了结果的一致性
到我的代码的最顶部,这样每次运行都会产生一致的RMSE。
要获得可重现的结果非常困难,请参阅这篇文章了解更多信息,Brian。
https://machinelearning.org.cn/reproducible-results-neural-networks-keras/
当我尝试加载数据并执行以下代码行(使用Python 3.6)时,我收到以下错误:
series = read_csv(‘shampoo-sales.csv’, header=0, parse_dates=[0], index_col=0,
squeeze=True, date_parser=parser)
TypeError: ufunc ‘add’ did not contain a loop with signature matching types dtype(‘<U32') dtype('<U32') dtype('<U32').
你能帮我一下吗?
哎呀,我之前没见过这个错误。
也许确认数据是CSV并且您已经删除了页脚。
也许确保您的环境已正确安装。
https://machinelearning.org.cn/setup-python-environment-machine-learning-deep-learning-anaconda/
如果这没有帮助,也许可以尝试发布到stack overflow?
你好 Jason,
感谢分享这篇帖子,非常有帮助,因为我目前正在进行一个时间序列项目。我有一个问题……我们如何保存具有最佳RMSE的模型并使用它进行进一步预测?
谢谢
这篇文章向您展示了如何保存模型并使用它进行预测。
https://machinelearning.org.cn/save-load-keras-deep-learning-models/
谢谢Jason提供了很棒的教程!
您能否为我澄清一下这个声明:“batch_size必须设置为1。因为它是训练和测试数据集大小的因子。”
我不明白为什么在这种情况下1是训练和测试数据集的因子?
此外,对于时间序列数据,我们是否可以将batch_size设置为大于1?如果不行,上述陈述的意义何在?
谢谢你
是的,这是问题所选框架的一个约束,以便我们可以使用有状态LSTM进行单步预测。
它通常不是一个约束。
很棒的帖子Jason,解释了LSTM的例子,非常详细。非常感谢。我正在尝试训练一个模型来预测科学计数法数据,如“9.543301358961403E-9”,您能否建议一种适合LSTM的数据重缩放方法?
对于输入数据,将值重缩放到0-1范围。
嗨,我看了您很多帖子,仍然不清楚BPTT什么时候应用?这个例子中是否应用了BPTT?或者只有在我们取多个先前输入来预测当前输出时才应用?
在这个例子中,参数在每个 epoch(批量梯度下降)更新,这与随机梯度下降(在线学习)完全相反,对吗?
这篇文章提供了BPTT的介绍。
https://machinelearning.org.cn/gentle-introduction-backpropagation-time/
当您的输入序列数据中包含多个时间步时,BPTT就会被应用。
嗨,Jason,
感谢您的精彩教程。请告诉我以下两者的区别——
1)model.fit(trainX, trainY, epochs=3000, batch_size=1, verbose=0)
2)for i in range(3000)
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
model.reset_states()
差别不大。
嗨,Jason,
您已重塑X的值,然后预测了yhat的值,之后对yhat进行了反归一化,然后将此值添加到前一个月原始值中。我的问题是,如果我将yhat的重塑值和前一个月的重塑值相加,然后调用invert_scale_function而不调用inverse_difference函数,会怎么样?两者会得到相同的结果吗?
此致
我相信是这样,我们需要将yhat与任何值(即使是0值)进行分组,以确保我们在反转转换时满足形状要求。
我多次运行了您的代码,使用了不同的参数。还有一个问题,当我们同时绘制“pyplot.plot(raw_values[-12:])和pyplot.plot(predictions)”时,我期望两条线在某些点重合(就像您示例图中的第1个月和第3个月的值几乎接近)或者至少显示相似的趋势,但为什么在大多数结果中,时间(t)的橙色线总是似乎与时间(t-1)的蓝色线更相关?起初,我以为是因为我们应该绘制第24-36个月的原始值和第25-37个月的预测值,但情况并非如此,我们同时绘制预测值(从第23-35个月预测)和原始值(从第24-36个月)。您能解释一下为什么会这样吗?我肯定遗漏了什么,但找不到!再次感谢。
这表明存在一个持续模型(例如,无技能)。
我正在使用lag>1
“timeseries_to_supervised”函数是否应该反转range(1, lag+1)?
columns = [df.shift(i) for i in reversed(range(1, lag+1))]
嗨,Jason,
非常感谢您提供的深入教程。我有一个关于fit_lstm()中这段代码的问题
for i in range(nb_epoch)
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
model.reset_states()
是否可以直接通过这一行完成?
model.fit(X, y, epochs=nb_epoch, batch_size=batch_size, verbose=0, shuffle=False)
感谢您的澄清。
是的,但我想在每个 epoch 结束时显式地重置状态,而不是在每个 batch 结束时。
这两种方法有什么区别?
您可以在此处了解更多关于LSTM内部状态的信息。
https://machinelearning.org.cn/understanding-stateful-lstm-recurrent-neural-networks-python-keras/
嗨,Jason,
我是一名大学生。我对机器学习特别感兴趣,并且正在努力学习。但我的英语不好,所以我的问题可能有点粗糙。
1.本文的rmse有点大,您是否还有其他文章描述如何调整参数以减小rmse?正规化的原因是?
2.您是否有更好的关于使用LSTM预测时间序列问题的文章?Ps:在单变量时间序列中。因为我自己做过实验,如果我使用本文的模型,我的实验准确率是85%到90%。我想提高它。
3.是否有解决多变量时间序列预测问题的文章?如果有,最新的是在哪里?
4.我已经在我的Macbookpro上运行了模型几次,速度太慢了。如果我想提高效率,我是否可以购买一些GPU云服务?比如亚马逊?但这似乎特别昂贵。您有什么好的解决方案吗?
非常感谢!我想说您是我的机器学习入门老师。
这篇文章列出了可以尝试以提高模型技能的项目。
https://machinelearning.org.cn/improve-deep-learning-performance/
总的来说,我不建议将LSTM用于自回归问题,请参阅这篇文章。
https://machinelearning.org.cn/suitability-long-short-term-memory-networks-time-series-forecasting/
这是一个多变量时间序列示例。
https://machinelearning.org.cn/multivariate-time-series-forecasting-lstms-keras/
实际上,AWS非常便宜。
https://machinelearning.org.cn/develop-evaluate-large-deep-learning-models-keras-amazon-web-services/
你好,Jason
感谢您上次的回复。我通过各种方法将准确率提高了4%。我使用了bias_regularizer =L1L2 (0.01, 0.01)来减小rmse的值。(基于我自己的数据集)。但是我想问一下关于教程的扩展。
我想知道如何完成多步预测。例如,我的训练集是2016年1月至2017年12月,共24个数据集,我想预测2017年1月至2017年6月这六个月的数据。这六个月的数据没有期望值,是空的。我尝试了10多种方法但都失败了,也许是我的Python太差了?或者是我对LSTM的理解不够?我实在弄不明白解决方案,非常沮丧……
我希望您能给我一些建议。谢谢。或者您知道有什么文章可以作为我的参考吗?
这里有一个例子
https://machinelearning.org.cn/multi-step-time-series-forecasting-long-short-term-memory-networks-python/
你好
您在动态预测方面的术语有些问题,您定义如下:
“每次时间步测试数据时,重新拟合模型或更新模型,因为新的观测值可用(我们称之为动态方法)。”
这在时间序列和计量经济学分析中并不是动态预测的叫法。动态预测涉及使用前一个预测值作为下一个预测的输入。在您的情况下,您正在使用因变量的滞后值作为模型估计中的回归量:X(t) = Y(t-1)。例如,请参阅这篇论文https://files.stlouisfed.org/files/htdocs/publications/review/80/06/Forecasting_Jun_Jul1980.pdf
因此,动态多步预测将涉及类似以下的内容:Yhat(t) = function(Yhat(t-1))。它不需要在每个步骤重新估计模型来做到动态。它只需要使用前一个预测值来得出下一个。
特别是这一步将改为使用yhat作为X
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
感谢您的澄清。
我想将时间步之间的差值输入LSTM来模拟衰减。我看到有人手动将这个项放入权重中,所以权重现在是W(t)的形式。我想知道我们是否可以将时间差包含在输入X中。您对此有什么建议吗?
抱歉,我没有这样做过,也许可以问问向您提出这个想法的人?
我的观察是,模型试图预测前一个值,这样它就能获得适度的精度。(我使用了另一个数据集)。
嗨,Jason
使用洗发水销售数据和我自己的测试数据,结果很好。但是当时间序列具有季节性趋势时,LSTM的结果非常糟糕。所以我想问有没有什么方法可以解决包含季节性时间序列预测的问题?
谢谢您。
您可以对数据进行季节性调整。
https://machinelearning.org.cn/time-series-seasonality-with-python/
虽然本教程中的图表和数字很有说服力,但有几件事是严重错误的,直到你仔细检查才会显现出来。在所有飞来飞去的数组、列表和索引中,存在使结果无法复现的错误。
在细节层面,您有这个预测输出
Month=1, Predicted=339.700000, Expected=339.700000
Month=2, Predicted=440.400000, Expected=440.400000
Month=3, Predicted=315.900000, Expected=315.900000
....
但是运行应该产生该结果的代码块会导致 IndexError,因为“Expected”应该来自
expected = raw_values[len(train) + i + 1]
索引 i 最初为 0,因为您正在遍历 len(train),所以 raw_values[len(train) + i + 1] 将首先是 raw_values[len(train) + 0 + 1],即 raw_values[25],即 440.40(2 月),而不是 339.7(1 月)。
这类事情看起来很小,但对于试图获得可复现输出的读者来说,这实际上是非常令人沮丧的,因为他们反而必须从一开始就跟踪代码中的一个 bug。
在更普遍的层面上,构建机器学习模型的目的不是仅仅生成一些测试数据的指标。相反,它是要构建一个在您尚未遇到的样本外数据上表现良好的模型。从一开始,您就应用差分函数来消除趋势,然后预测残差,然后用逆差分函数将趋势加回去。这本身就是一种主要违规,因为您正在将已知信息植入本应是预测的内容中。逆差分函数以 raw_values 作为参数,但在实际的样本外场景中,您将无法访问这些 raw_values,因此无法以这种方式简单地调整预测的残差以反映趋势。这怎么没人发现?
我正在进行一项关于 LSTM 用于时间序列数据的研究项目,并试图从本教程中提取一些有用的东西来应用于这个问题,但我发现其中隐藏着太多的雷区。
嗨,Jason!
我有一个包含 20 万个时间序列的数据集。每个数据集有 150 个时间戳。
假设它们是同一产品的销售数据,但针对不同的商店。
如何最好地设计问题?
我无法弄清楚理想的结构是什么。是只输入 149 个值的序列来预测第 150 个值;还是应该采用滚动窗口?如果我给出整个序列,我就给了它很多上下文来工作,但我担心序列太长,训练会很困难。
有什么想法?
关于如何使用 LSTM 设计时间序列问题,这方面的文献很少。你是唯一一个谈论这个问题的人。谢谢!
我建议探索许多不同的问题建模方法,看看哪种效果最好。
200K 个序列是一个很大的数量。也许您可以将序列分组并使用子模型,然后以某种集成的方式组合结果。
嗨,Jason,
我想请求您帮助将上述代码更新为动态模型,该模型在每次观测后都会自行更新并相应地预测未来点。您能建议如何修改此代码以满足此目的吗?
请看这篇文章
https://machinelearning.org.cn/update-lstm-networks-training-time-series-forecasting/
另外,如果我需要创建除 1 以外的数字的回溯,例如 7,我需要在此代码中更新哪些内容才能使其为回溯 7 运行?
嗨,Jason,
感谢您提供有用的教程。
我有一个关于 X, y = test_scaled[i, 0:-1], test_scaled[i, -1] 的问题
yhat = forecast_lstm(lstm_model, 1, X)
(第 110 行)
我没有理解预测将如何使用时间戳来预测测试数据集。
据我所知,最终我们希望根据未来时间进行预测。因此,我们应该基于时间戳(而不是值)进行测试,并将预测结果与实际测试值进行比较,以了解预测的准确性。
但在代码中,您似乎是基于值进行预测,并再次与这些值进行比较!
您能向我解释一下吗?也许我误解了某些部分。
此致,
Bahar
我们正在预测 t+1。
也许这篇文章有助于更好地理解 Python 数组切片和范围。
https://machinelearning.org.cn/index-slice-reshape-numpy-arrays-machine-learning-python/
Jason,很棒的教程,有助于人们入门。
我有两个快速问题。
1.除了时间滞后,是否有添加其他“特征”的良好示例?例如,某个小时是否是高峰时段,某天是否是工作日。
2.我有三年的每小时数据,并希望预测未来三个月的小时数据。因此,我大约有 14600 个训练行,需要预测大约 2600 个测试行。多步预测似乎是正确的方法。但是,能否训练一个模型来提前预测这么多步?
这篇文章展示了如何使用多个输入变量。
https://machinelearning.org.cn/multivariate-time-series-forecasting-lstms-keras/
对于如此多的观测值进行多步预测可能会导致效果不佳。我建议测试一系列方法,看看哪种最适合您的数据。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
太棒了,谢谢 Jason。我会查看建议的链接。
您能否推荐任何其他多步预测的参考资料?
请看这篇文章
https://machinelearning.org.cn/multi-step-time-series-forecasting-long-short-term-memory-networks-python/
你好 Jason,我有一个季度销售数据集(如下),并尝试在本帖中使用相同的代码。
月份,销售额
5-09,11
5-12,20
6-03,66
6-06,50
6-09,65
6-12,63
7-06,25
7-12,34
我使用之前所有季度的销售数据来训练模型,以预测最后一个季度。
最后一个季度:预测值=-1.329951,实际值=34.000000
销售额不能为负数,但模型预测了一个负值。
有没有办法阻止模型预测负值?
我建议从一些简单的线性模型开始,以便更好地理解您的数据和时间序列的工作原理。
https://machinelearning.org.cn/start-here/#timeseries
谢谢 Jason,我尝试了线性回归,但它似乎没有给我预期的结果。
然后我调整了您代码中的 LSTM 以预测正值,方法是:
* 将缩放器范围从 (-1,1) 改为 (0,1)
* 在模型中添加激活函数 'relu'。
嗨,Jason,
需要一个小澄清。
第 100 行开始的 for 循环是否在第 102 行结束?
for r in range(repeats)
# 拟合模型
lstm_model = fit_lstm(train_scaled, 1, 3000, 4)
# 预测整个训练数据集以建立预测状态
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
lstm_model.predict(train_reshaped, batch_size=1)
在这里,上面的行
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
lstm_model.predict(train_reshaped, batch_size=1)
是否也属于 for 循环?
嘿 Jason,
如何预测上述示例的下个月?
也许这篇文章可以帮助您进行预测。
https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
嗨,Jason,
感谢您提供的所有精彩文章。我一直在尝试这个模型来预测客户的支出模式。我有客户每周支出的平均值。训练完成后,我看到一个模式,即当前预测输出与上周的预期输出相匹配。我改变了 yhat = y 来查看所有转换是否正确进行。但即使是 yhat = y 也显示了相同的行为。
周=1,预测=975.556027,预期=989.100588
周=2,预测=989.100588,预期=928.604400
周=3,预测=928.604400,预期=921.209794
周=4,预测=921.209794,预期=919.813532
周=5,预测=919.813532,预期=904.214533
周=6,预测=904.214533,预期=913.695025
周=7,预测=913.695025,预期=971.727005
周=8,预测=971.727005,预期=1095.774093
周=9,预测=1095.774093,预期=1159.611429
周=10,预测=1159.611429,预期=732.743950
周=11,预测=732.743950,预期=963.615794
周=12,预测=963.615794,预期=896.842055
周=13,预测=896.842055,预期=960.630000
周=14,预测=960.630000,预期=905.481048
周=15,预测=905.481048,预期=994.167244
周=16,预测=994.167244,预期=975.601111
周=17,预测=975.601111,预期=1210.307037
周=18,预测=1210.307037,预期=9293.130000
周=19,预测=9293.130000,预期=367.780000
我没有对数据进行差分,因为我的数据是平稳的,我没有看到支出模式的增加/减少。您能帮帮我吗?
这可能表明模型只学习了持久性模型(例如,输出输入)。
我建议从简单的 MLP 开始,看看 LSTM 是否能做得更好。
首先,感谢您的出色工作和所有帖子,它们非常棒且有帮助!
让我们看看我更改后的 CSV 数据。
“1-01”,0.1
“1-02”,-0.2
“1-03”,0.3
“1-04”,-0.4
“1-05”,0.5
“1-06”,-0.6
“1-07”,0.7
“1-08”,-0.8
“1-09”,0.9
“1-10”,-1.0
“1-11”,1.1
“1-12”,-1.2
“2-01”,1.3
“2-02”,-1.4
“2-03”,1.5
“2-04”,-1.6
“2-05”,1.7
“2-06”,-1.8
“2-07”,1.9
“2-08”,-2.0
“2-09”,2.1
“2-10”,-2.2
“2-11”,2.3
“2-12”,-2.4
“3-01”,2.5
“3-02”,-2.6
“3-03”,2.7
“3-04”,-2.8
“3-05”,2.9
“3-06”,-3.0
“3-07”,3.1
“3-08”,-3.2
“3-09”,3.3
“3-10”,-3.4
“3-11”,3.5
“3-12”,-3.6
这是一个非常简单的“共振”点序列,在 Y 轴上每一步都在增加。我没有对程序代码进行任何更改,结果如下:http://prntscr.com/hob1hf
为什么 LSTM 无法预测如此简单和合乎逻辑的数据序列?我们在这里错过了什么?
等待您的回复,再次非常感谢!
没有,LSTM 在自回归方面表现不佳,原因如下:
https://machinelearning.org.cn/suitability-long-short-term-memory-networks-time-series-forecasting/
请改用 MLP。
一个有趣的现象:我将时间序列延长了两年,但共振系数(0.1)相同。
“1-01”,0.1
“1-02”,-0.2
“1-03”,0.3
“1-04”,-0.4
“1-05”,0.5
“1-06”,-0.6
“1-07”,0.7
“1-08”,-0.8
“1-09”,0.9
“1-10”,-1.0
“1-11”,1.1
“1-12”,-1.2
“2-01”,1.3
“2-02”,-1.4
“2-03”,1.5
“2-04”,-1.6
“2-05”,1.7
“2-06”,-1.8
“2-07”,1.9
“2-08”,-2.0
“2-09”,2.1
“2-10”,-2.2
“2-11”,2.3
“2-12”,-2.4
“3-01”,2.5
“3-02”,-2.6
“3-03”,2.7
“3-04”,-2.8
“3-05”,2.9
“3-06”,-3.0
“3-07”,3.1
“3-08”,-3.2
“3-09”,3.3
“3-10”,-3.4
“3-11”,3.5
“3-12”,-3.6
“4-01”,3.7
“4-02”,-3.8
“4-03”,3.9
“4-04”,-4.0
“4-05”,4.1
“4-06”,-4.2
“4-07”,4.3
“4-08”,-4.4
“4-09”,4.5
“4-10”,-4.6
“4-11”,4.7
“4-12”,-4.8
“5-01”,4.9
“5-02”,-5.0
“5-03”,5.1
“5-04”,-5.2
“5-05”,5.3
“5-06”,-5.4
“5-07”,5.5
“5-08”,-5.6
“5-09”,5.7
“5-10”,-5.8
“5-11”,5.9
“5-12”,-6.0
现在,我们看到 LSTM 进行了更接近的预测,但仍然没有看到 Y 轴上的增量(红色线条和箭头是我自己绘制的)http://prntscr.com/hob7eo
有什么想法吗?
数据不足,模型需要调整,LSTM 在自回归方面表现不佳。
关于代码还有一件事。
为什么您在预测循环之前执行 1 次预测?
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
lstm_model.predict(train_reshaped, batch_size=1)
这是做什么用的?
并且在这一行
# 进行单步预测
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
“y” 是什么意思?
它未被使用。
嗨,Jason,
感谢您提供出色的帖子,非常有帮助且内容丰富。
我正在使用您的一些示例来预测股市。模型效果很好。您能否提供更多关于为什么模型响应有单样本延迟(滞后)的细节?在您所有的图表和我的图表中都可以看到。
因为模型不是很好,这表明它正在将输入作为输出,称为持久性。
https://machinelearning.org.cn/persistence-time-series-forecasting-with-python/
模型状态是否在每次
lstm_model.predict(train_reshaped, batch_size=1)
?
那么,我们能否确定在 100 次预测后模型将具有第 101 次预测的实际状态?或者我们是否应该在每次预测步骤后使用一些额外的模型更新技术?我不太清楚……
在这个例子中,状态似乎没有那么重要。
同意,但一般来说?`lstm_model.predict` 是否会更新模型?
它将更新内部状态变量,但不会更新权重。
这有帮助吗?
是的,非常感谢。
不客气。
感谢 Jason 提供本教程。
您对如何调整此网络以适应不同商店的洗发水销售有什么建议?我想到的事情是:
1- 分别为不同商店运行此模型(也许我们可以从所有商店的销售数据中学习,但通过这种方法,我们就无法受益于此)。
2- 将每个商店的销售数量作为特征输入。
一些想法
– 分别对每个商店建模
– 分别对每个商店建模,并添加所有商店的数据
– 分别对每个商店建模,并添加相关商店的数据(区域?剖面?等等)
– 创建区域商店模型,并与单独的商店模型集成。
– 创建所有商店模型,并与单独的商店模型集成。
– 以此类推……
想出 100 个想法并全部尝试,看看哪种最适合您特定的数据。
谢谢 Dr. Jason 的本教程。
如果我想对训练数据进行向前验证,那将是
for i in range(len(train_scaled))
# 进行单步预测
X, y = train_scaled[i, 0:-1], train_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(raw_values)-i)
# store forecast
predictions_train.append(yhat)
expected = raw_values[ i+1 ]
print(‘Month=%d, Predicted=%f, Expected=%f’ % (i+1, yhat, expected))
# 报告表现
rmse_train = sqrt(mean_squared_error(raw_values[1:len(train_scaled)+1], predictions_train))
请验证是否正确。
抱歉,我无法调试您的代码。您可以在此处了解更多关于向前验证的信息。
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
谢谢您的回复……
让我重新表述我的问题……我想知道在计算训练数据的 RMSE 时,是否跳过原始值的第一个点?
rmse_train = sqrt(mean_squared_error(raw_values[1:len(train_scaled)+1], predictions_train))
如果您注意到最后一个公式,我从第二个点 raw_values[1:len(train_scaled)+1] 开始计算。
因为我们不预测第一个点,实际上我们以第一个点作为 x,预测第二个点作为 y。
您好,感谢您的精彩文章。
我有一些来自我的蜜罐的日志数据。我已经使用标签编码器对发生的动作进行了编码。这些数据足以训练 LSTM 吗?我最终想要恢复下一个动作。我应该使用词向量吗?
也许可以尝试几种表示方法,看看哪种最适合您的数据?
嘿,我正在尝试理解为什么您实现持久性算法的方式与您在另一篇帖子中不同(https://machinelearning.org.cn/persistence-time-series-forecasting-with-python/)。在您的另一篇帖子中,您将问题建模为监督学习问题,但在这里没有这样做?您还在该帖子中谈论 t-1 和 t+1,而不是 t-1 和 t。您能否澄清为什么您在本帖子中没有将问题转换为监督学习直到 LSTM 模型?
我试图让示例更简单。
你好,如何用 RMSE 评估有效性?值越小越好还是越大越好?
RMSE 越小越好。
你好 Jason,本教程很棒。我正在使用 2017 年的 XBT 数据,但只是尝试每日数据。当我遵循这个建议“更新:考虑尝试 1500 个 epoch 和 1 个神经元,性能可能会更好!”时,RMSE 和图表看起来与持久性模型非常相似。这是您的发现吗?
抱歉,我不记得了。
你好,
是否可以将一些数据附加到训练集中并递归更新模型?使用 `fit` 函数和更新的训练集作为参数来做到这一点是否正确?
您可以这样做。试试看。
我尝试了两个实验:
1) 按照 https://machinelearning.org.cn/update-lstm-networks-training-time-series-forecasting/ 中的说明用新数据更新训练集,并用 1 个 epoch 更新模型。
2) 同第 1 点,但当我将新数据附加到训练集末尾时,我删除了其中的第一个元素(一种滑动窗口。这有意义吗?)。
两个实验中的 RMSE 都比没有更新训练集的版本差。有什么建议吗?
有趣,做得好。
如果您正在寻求进一步的改进,我建议头脑风暴 10 种不同的方法并进行比较。
之后,您可以考虑更一般的事情。
https://machinelearning.org.cn/improve-deep-learning-performance/
您好,感谢本教程,它很棒,给了我很多见解。我只有一个问题。
训练完网络后,历史数据是否仍然需要?或者只需要最后的观测值?
谢谢!
您的模型需要输入才能进行预测。具体需要保留什么取决于您如何定义您的模型。
通常,训练数据仅用于拟合模型,然后模型用于根据新观测值进行预测。
嗨,Jason
在此示例代码中,您使用了哪种 LSTM 方法?
1:[Hochreiter & Schmidhuber, 95;97] 简单 LSTM
2:[Gers & Schmidhuber, 99] 带遗忘门的 LSTM
3:[Gers & Schmidhuber, 00] 带窥视连接的 LSTM
4:[Graves & Schmidhuber, 05] LSTM 完全梯度
5:其他
我认为是简单 LSTM。您将来会展示其他模型吗?
Jason,
再次感谢您的这篇帖子。我也按照您的说明完成了测试。
但我有一个问题
与其他模型相比,训练这个 RNN 模型非常慢。我检查了代码,发现您将 batch_size 设置为 1。我相信加速训练的一个方法是将 batch_size 增加到一个更大的数字,但我担心这会引起其他错误,正如您在下面解释的那样
“batch_size 必须设置为 1。这是因为它必须是训练和测试数据集大小的因子。”
我的意思是,如果我们设置 batch_size 为训练集和测试集大小的公因子,那就可以了?例如,如果我的测试集大小是 1000,我的训练集大小是 100000,那么我可以设置 batch_size 为 1000,我的理解正确吗?
如果我的理解是错误的,我还需要注意哪些其他限制?
提前感谢。
Clock ZHONG
Jason,
我阅读了 Keras 网站上的解释
https://keras.org.cn/getting-started/faq/#how-can-i-use-stateful-rnns
看起来,如果我们能够确保训练批次中的样本序列,那么批次大小可以设置为任何数字。
而且,如果测试数据集遵循训练数据集,那么我们可以直接使用它们进行预测,而无需重置状态,我想是的。
谢谢!
Clock ZHONG
好的,试试看吧。
嗨,Jason,
感谢您关于 LSTM 的精彩解释。
我尝试运行了代码。但是,我在对序列进行差分时遇到了一个错误——关键字错误 1。
错误发生在运行以下代码之后:
# 转换为平稳
differenced = difference(series, 1)
如果您能帮助我解决这个问题,那就太好了。
谢谢!
Ridhima Kumar
也许您应该仔细检查是否已复制所有代码?
嗨,Jason,
感谢这篇很棒的教程。抱歉在这里问了愚蠢的问题,我是应用层面 ML 的新手。在这个领域只有业余知识,正试图通过构建一个 Web 应用程序来学习。
我使用三年的样本数据来预测未来三年的价格——我的数据集制作得和这里使用的样本完全一样。我遵循了您的教程,直到最后几步一切都正常(笑,我知道如何复制粘贴)。
但我现在卡在了编写预测未来三年价格的代码上。
最后一步的错误是什么?
我没有收到任何错误,但我不知道如何编写代码来预测例如 2030 年的值。
简单来说:我想用这个模型预测第四、第五和第六年的价格,那么我该如何修改我的代码?
你好 Peter,这篇帖子将向您展示如何进行多步预测。
https://machinelearning.org.cn/multi-step-time-series-forecasting-long-short-term-memory-networks-python/
嗨,Jason,
感谢您的教程。我有一个问题。我复制了您的源代码,并将 epoch 数和单元数(LSTM)参数更改为 10 和 1。使用此配置,我获得了非常好的结果。如果我现在注释掉负责训练神经网络的行,我会得到相同的结果。这是怎么回事?
是您的程序有错误,还是我自己的理解有问题?
也许您没有注释掉足够多的代码?
我注释掉了以下行:
# for i in range(nb_epoch)
# model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
# model.reset_states()
和
# train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
# lstm_model.predict(train_reshaped, batch_size=1)
我的意思是,这应该足够了。或者我有什么遗漏需要注释掉的?
看起来是合理的。
嗨,Jason,
我是 LSTM nn 的新手。我复制了您的示例,运行它并且它奏效了,但我仍然不明白为什么我每次运行代码时都会得到不同的结果。我没有找到任何随机数可能导致每次结果都不同。
此外,我想知道您为什么创建和拟合模型 30 次而不是一次?我可以取这 30 次中的最佳结果吗?
谢谢!
好问题,请看这篇帖子
https://machinelearning.org.cn/randomness-in-machine-learning/
嗨,Jason,
我正在尝试使用基于 LSTM 的架构来处理我的时间预测问题。我的数据集中有
大约 30 个 ID。每个 ID 的数据都与您的示例类似(时间相关
数据)。这是我的问题:
1.此模型能否同时训练多个数据集?(例如,您想处理
不同洗发水品牌的销量。您想同时预测每种销量。
也许每个数据集都是相关的,但您不在乎。)如果可以,如何确定输入
形状和输出形状?每个数据集是否会对网络产生任何影响?
2.如果我的数据是平稳的,我还需要对我的数据进行差分处理吗?我已经尝试
在不差分的情况下使用此架构训练我的数据。但测试数据的预测是线性的
(看起来像一条水平线)。我不知道为什么会这样。是我的错还是这种架构
是为此方法(差分)设计的?
谢谢!
当然,试试看。也许可以先从 MLP 开始。
如果数据是平稳的,则无需使用差分变换。
嗨 Jason!我在实习项目中使用您的博客作为参考,您的内容太棒了!!
在我的项目中,我需要同时进行序列预测和序列分类。所以我正在考虑两种模型作为我解决问题的第一个方法:一个用于预测的 LSTM 网络,以及一个我正在考虑使用滑动窗口 MLP 的模型,以获取时间序列的小片段并进行序列分类(我为所有时间步都有标签)。
因此,总体的想法是对预测序列进行分类(在我的预测结果上进行分类)。希望这有道理。
如果可行,我想就滑动窗口 MLP 征求建议,因为我在网上真的找不到好的参考资料。我应该怎么做?我会将来自前一个时间步的输入堆叠起来并将其作为输入提供给我的网络吗?所以举个简单的例子:如果我有 5 个变量,并且我想要一个 5 步滑动窗口,那么时间 t 的输入将是 [[t-4],[t-3],[t-2],[t-1], [t]] -> y[t],让我的网络自行学习如何从中学习?还是我必须采取 5 个向量并以某种方式聚合它们(例如平均值),然后只给我的网络一个结果向量和它的标签?我很抱歉,如果我的问题看起来很傻,但我真的没有找到关于这个主题的有用信息,如果您有任何关于这方面的内容或资源,请告诉我。
谢谢!
是的,通常滞后观测值会成为 MLP 输入的特征窗口。
另外,请考虑使用 LSTM 进行序列分类。
另外,请探索一个多输出模型,一次完成两个预测,看看它是否能提高技能(如果我正确理解了您的数据)。
告诉我进展如何。
谢谢 Jason,我一定会探索您的建议,让我再次尝试并将其简化,看看第三个选项是否可行,我也很好奇尝试一下。我将提供一个插图,它不是我的真实问题,但我发现它更容易解释,而且我认为这是一个很好的插图。
想象一下您有天气数据,您需要推荐今天是否是出门的好日子,您所关心的只是简单地说 0 表示不是好主意,1 表示是好主意。您有历史数据和多个输入(湿度、气压、气温等),并且您想在多个时间范围内(1 小时、2 小时等)进行预测。在每个时间步,您还有每个条目的真实标签。
所以所有的问题都会是推荐多个时间范围内的好/坏日子,但我曾想过,如果不是通过 2 个独立的模型,一个模型首先预测温度、湿度等的值,第二个模型进行序列分类并分类我第一个模型预测的序列,我该如何做到这一点?
有没有办法只用 1 个模型来完成我的推荐预测?它会是什么类型的模型(如果有的话)?谢谢 Jason!
是的,您可以进行多步预测。以下是您如何构建此模型的一些示例。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
嗨,Jason,
谢谢您的教程。
我使用了您的代码并做了一些修改,例如我将层数增加到 4 层,并在每层分别添加了神经元(6、12、18 和 1)。我还添加了“relu”和“tanh”激活函数以及正则化,但当我绘制图表时,输出滞后输入 1 个时间步,就像持久模型一样。
当我向下移动输出值并再次绘制它时,有时几乎与输入匹配。
例如,如果输入有 10 个值,输出也有 10 个值。当我绘制从 2 到 10 的输入值和从 1 到 9 的输出值时,我得到了更好的图表。所以我忽略了输入的第一个值和输出的最后一个值。
我试图匹配图表,但我认为我在这里是错的,因为我找不到任何原因。
您能帮我解释一下为什么我会得到这个结果吗?我的意思是,即使使用了复杂的模型,我的模型也表现得像一个持久模型。
请帮助!!!
我将热切等待您的回复。
谢谢
也许这个模型与问题不匹配?
“模型上的 predict() 函数也受批次大小的限制”。这是什么意思?如果我设置批次大小为 4,那么我是否需要提供 4 个时间步作为输入?
正确。
嗨 Jason。我收到了这个错误,但我无法发现哪里出了问题。
ValueError: time data '1901-Jan' does not match format '%Y-%m'
看起来您的数据有问题。
请从这里下载:
https://raw.githubusercontent.com/jbrownlee/Datasets/master/shampoo.csv
我也查看了数据集,第一个索引的值是 2018 年 1 月 1 日。
谢谢,
Hervaldo
我认为我遗漏了一些基本的东西,我是这个领域的新手。如何使用该模型预测测试数据之后发生的情况,例如第 13 个月?
问得好,是的,您缺少了一个部分。上面的帖子只是评估 LSTM 的一个例子。请看这篇帖子。
https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
嗨,Jason,
感谢所有精彩的文章。我有一个情况,有 18 个输入变量和 1 个输出变量(可以是 -1、0 或 1),我使用 numpy 的 to_categorical 函数将其转换为 3 个输出(1, 0, 0)、(0, 1, 0)和(0, 0, 1)。我训练了模型,它报告了高准确率(它开始时低,随着 epoch 的进行而越来越高)。到目前为止还不错。
所有 18 个输入变量都是浮点数,并缩放到 -1 和 1 之间。
问题出现在我使用 predict 函数来处理我的测试数据时——我的答案都是大约 0 的值(浮点数,如 (0.0001, 0.002, 0.00123)。根据 model.summary(),训练和测试数据的形状相同。这就像模型什么都没学会一样。
predict 函数的输出是否经过缩放或转换?我不需要它们那样,但这可能是我误解了什么(这是轻描淡写!)。
供参考,我的代码大致是这样的(有 5766 行数据):
model = Sequential()
model.add(LSTM(18, batch_input_shape=(1, 5766, 18), stateful=True, return_sequences=True))
model.add(Dense(10, input_shape=(18,), kernel_initializer=initializers.random_normal(seed=51)))
model.add(Dense(3, kernel_initializer=’uniform’))
model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])
X_train = np.reshape(X, (1, X.shape[0], X.shape[1]))
Y_train = np.reshape(Y_train, (1, Y_train.shape[0], Y_train.shape[1]))
for i in range(25)
model.fit(X_train, Y_train, epochs=1, batch_size=1, shuffle=False, verbose=2)
model.reset_states()
……然后以类似的方式重塑 x 测试数组并调用。
y_pred = model.predict(X_test)
谢谢,
Don
也许是出了 bug?也许您需要对模型进行更多调整?
我在这里提供了一些想法。
https://machinelearning.org.cn/improve-deep-learning-performance/
感谢您的回复。我会继续研究它。
Don
嗨
写得很好,Jason!
我有一个关于预测的问题,这有点不清楚。
我尝试了您使用 yhat = lstm_model.predict(X) 的示例,但它只给出了错误
ValueError: Error when checking : expected lstm_2_input to have 3 dimensions, but got array with shape (1, 1)
例如,我们如何对不存在于训练数据中的“4-01”甚至“4-02”这样的时期进行预测?
鉴于有很多人询问此事,也许是时候将其放入主文本中了?
感谢您的出色工作!
//Fredrik Nilsson
很遗憾听到这个,您是否复制了示例中的所有代码?
您使用的是相同的数据集吗?
您的环境(Python/Keras)是最新的吗?
这些例子很棒。我想知道神经网络是否太简单了,只有一个 LSTM 层和一个 Dense 层。通过添加更多层来更改模型是否会更好?
试试看吧。
先生,我在代码中遇到了一个问题。
# 进行单步预测
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
这意味着
yhat = yhat + raw_values [ -(len+1-i) ]
我们每次都使用观测值来添加 yhat 吗?这怎么会是预测?“y”成员是用来做什么的?
这称为前向验证,您可以在此处了解更多信息。
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
你好,Jason
这之间有什么区别吗?
for i in range(nb_epoch)
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
model.reset_states()
和
model.fit(X, y, epochs=nb_epoch, batch_size=batch_size, verbose=0, shuffle=False) ?
是的,我们可以控制状态何时被重置。
在第一种情况中,它在每个 epoch 结束时重置。在第二种情况中,它在每个批次结束时重置。
这个例子如何处理股票价格数据集?
我有一个 CSV 文件,基本上是
“DateTime”,”Price [USD]”
“2015-08-07 00:00:00”,2.77
“2015-08-08 00:00:00”,0.8077
.
.
.
我可以使用您上面代码的基础来试验和学习我自己的数据文件吗?
我在这里提供了一些关于为 LSTM 准备数据的建议。
https://machinelearning.org.cn/faq/single-faq/how-do-i-prepare-my-data-for-an-lstm
我在这里提供了一些关于预测股票市场的建议。
https://machinelearning.org.cn/faq/single-faq/can-you-help-me-with-machine-learning-for-finance-or-the-stock-market
我有一个关于 predict 函数的普遍问题。
假设我训练了一个 LSTM 模型(单步预测,例如 X 是 1D,Y 是 1D),我想为给定的未来 X 预测一些 Y( X=(X1, X2, X3, X4, X5, X6, X7) = (0.1, 0.2, 0.1, 0.5, 0.5, 0.9. 0.3) )
我知道我会得到一组 Y( Y = (Y1, Y2, Y3, Y4, Y5, Y6, Y7) )
因为 X1=X3=0.1,X4=X5=0.5,这是否意味着 Y1=Y3 且 Y4=Y5?
我的想法是,对于给定的模型,系数在训练后是固定的,当输入一个相同的值(例如,值=0.1)时,它将输出(预测)一个固定值。
如果不是这种情况,您能否简要说明一下上面示例中的 predict 函数是如何工作的?谢谢!
LSTM 权重在训练后是固定的,但 LSTM 还有一个内部状态,就像一个局部变量,它会随着输入序列累积。
您可以在此处详细了解 LSTM 的工作原理。
https://machinelearning.org.cn/start-here/#lstm
感谢您的分享。
对于一个处理时间序列数据的新手来说,这非常有帮助。
以下是我在重现代码时遇到的问题:
ValueError: Error when checking : expected lstm_2_input to have shape (1, 1) but got array with shape (1, 0)
(URL 上有更多信息)
我的环境是:
Windows 10
Python 3
很抱歉听到这个,这里有一些建议。
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,Jason,
在处理洗发水数据时遇到困难。出现以下错误:
TypeError: strptime() 参数 1 必须是 str,而不是 numpy.ndarray
ValueError: time data ‘190″1-01″,266.0’ does not match format ‘%Y-%m’
输入数据是逗号分隔的 CSV 文件,没有页脚。
“Month”,”Sales”
“1-01”,266.0
“1-02”,145.9
“1-03”,183.1
“1-04”,119.3
“1-05”,180.3
“1-06”,168.5
“1-07”,231.8
“1-08”,224.5
“1-09”,192.8
“1-10”,122.9
“1-11”,336.5
“1-12”,185.9
“2-01”,194.3
“2-02”,149.5
“2-03”,210.1
“2-04”,273.3
“2-05”,191.4
“2-06”,287.0
“2-07”,226.0
“2-08”,303.6
“2-09”,289.9
“2-10”,421.6
“2-11”,264.5
“2-12”,342.3
“3-01”,339.7
“3-02”,440.4
“3-03”,315.9
“3-04”,439.3
“3-05”,401.3
“3-06”,437.4
“3-07”,575.5
“3-08”,407.6
“3-09”,682.0
“3-10”,475.3
“3-11”,581.3
“3-12”,646.9
非常感谢您的帮助。
这是数据文件。
https://raw.githubusercontent.com/jbrownlee/Datasets/master/shampoo.csv
如果您仍然遇到问题,也许可以仔细检查您是否精确地复制了代码,包括空格。
这里有一些更多的建议。
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
您可以检查您的 x.csv 文件,最好更改月份列的格式为短日期,就像这样:
Month Sales
2018/1/1 266
2018/1/2 145.9
2018/1/3 183.1
2018/1/4 119.3
2018/1/5 180.3
看起来我的结果向前偏移了 1 个时间步,但我不确定原因。
这很常见,请看我这里的解释
https://machinelearning.org.cn/faq/single-faq/why-is-my-forecasted-time-series-right-behind-the-actual-time-series
您有关于进一步调整的链接吗?或者如果无法预测,为什么它看起来像一个很好的“移位”预测?有什么数学原因吗?
是的,请看这里
https://machinelearning.org.cn/faq/single-faq/why-is-my-forecasted-time-series-right-behind-the-actual-time-series
Jason,您好,感谢您的精彩文章,我能问几个问题吗?
如果我想预测不同产品的销量呢?
例如,洗发水、手机、T恤等。
我应该独立预测还是一起预测?
很好的问题。
这取决于数据。单独建模、分组建模或一起建模可能更好。需要进行一些实验。
为所有产品构建 10,000 个不同的模型是否是个好主意?有没有更好的方法,您之前在类似场景中使用过?
谢谢你
Jason,精彩的文章
是的,针对产品类别、相似产品和所有产品的模型。
如果我需要进行二次差分,我应该这样做吗?
first_diff = difference(raw_values, 1)
second_diff = difference(first_diff, 1)
first_diff.index = raw_values.index[1:]
.
.
.
predictions = []
temp = []
for i in range(len(test_scaled))
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
yhat = invert_scale(scaler, X, yhat)
temp.append(yhat)
yhat = inverse_difference(first_diff, yhat, len(test_scaled)+1-i)
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+12-i)
predictions.append(yhat)
您可以对差分序列进行差分,或者使用 ARIMA 模型,该模型可以为您进行不同阶数的差分。
亲爱的Jason
我对 `yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)` 感到有些困惑
而不是 `yhat = inverse_difference(raw_values, yhat, len(test_scaled)-i)`。我不确定为什么需要那个 1。
我是 LSTM 的新手。
嗨,Jason,
在您展示如何对时间序列进行差分和逆差分的章节中,您使用了这条代码行
inverse_difference(series, differenced[i], len(series)-i)
而在示例中,您使用了这条代码行
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
为什么要在代码中添加“1”呢?非常感谢。
我相信这是为了正确对齐操作。请尝试对 [1,2,3,4,5,6,7,8,9,10] 进行变换并检查结果。
嘿,杰森!
我正在使用您的 LSTM 示例。
由于数据被转换为监督学习问题 (t-1),我们不也应该将预测值向前移动 -1 吗?现在我的图表与真实数据几乎完全对齐,但提前了一天。
谢谢!
也许这篇文章可以更好地解释如何为监督学习准备时间序列数据。
https://machinelearning.org.cn/convert-time-series-supervised-learning-problem-python/
你好,
我收到关于期望 2D 但得到 1D 的错误,所以我更改了 scaler 为
scaler = scaler.fit([train]) # <—与教程不同
即添加方括号
这解决了问题,但现在我收到“IndexError: tuple index out of range”引用了这一行
train = train.reshape(train.shape[0], train.shape[1])
除了这个更改之外,代码都是相同的。您知道这是为什么吗?我正在使用 python 3.5.5
感谢您的任何帮助!
## 洗发水销量数据集
# LSTM
# 1. 将时间序列转换为监督学习问题
# 2. 转换时间序列数据使其平稳
# 3. 转换观测值以具有特定的销售量
# 导入包
from pandas import DataFrame
from pandas import Series
from pandas import concat
from pandas import read_csv
from pandas import datetime
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import MinMaxScaler
来自 keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from math import sqrt
from matplotlib import pyplot
import numpy
# 用于加载数据集的日期时间解析函数
def parser(x)
return datetime.strptime('190'+x, '%Y-%m')
# 将时间序列转换为监督学习
# 将所有值向下移动以创建 t-1 输入和 t 输出
# 辅助函数 time_series_to_supervised()
# 使用加载的销售数据测试函数 & 转换为监督学习问题
# 将序列构建为监督学习问题
def timeseries_to_supervised(data, lag=1)
df = DataFrame(data)
columns = [df.shift(i) for i in range(1, lag+1)]
columns.append(df)
df = concat(columns, axis=1)
df.fillna(0, inplace=True)
return df
# 转换时间序列以使其平稳 (去除趋势)
# 平稳 = 不依赖于时间
# 方法 = 对数据进行差分;从 t-1 的观测值减去 t 的值,只留下
# 创建一个差分序列
def difference(dataset, interval=1)
diff = list()
for i in range(interval, len(dataset))
value = dataset[i] – dataset[i – interval]
diff.append(value)
return Series(diff)
# 逆差分值
# 必须将对差分序列进行的预测值还原回其原始尺度
def inverse_difference(history, yhat, interval=1)
return yhat + history[-interval]
# 将训练和测试数据缩放到 [-1, 1]
def scaler(train, test)
# 拟合 scaler
scaler = MinMaxScaler(feature_range=(-1, 1))
scaler = scaler.fit([train]) # 监督学习格式,批量大小,周期,神经元
def fit_lstm(train, batch_size, nb_epoch, neurons)
# 将数据从 X, y 重塑为 Samples/TimeSteps/Features
X, y = train[:, 0:-1], train[:, -1]
X = X.reshape(X.shape[0], 1, X.shape[1])
# 指定网络 -> 使用后端库以高效的符号表示进行编译
# 指定损失函数和优化算法 (此处为均方误差)
model = Sequential()
model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
# 编译后,拟合训练数据
# 周期中的默认值 = shuffled = 不适合 LSTM - 设置为 FALSE!
# Verbose = 调试信息报告
# 手动循环将网络拟合到训练数据
for i in range(nb_epoch)
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
model.reset_states()
return model
# 固定方法 = 在所有训练数据上拟合模型一次
# 然后从测试数据一次一个时间步进行预测 (此处使用)。
# 动态方法 = 每次都重新拟合或更新模型
# 在测试数据的新观测值可用时,进行剩余数据的一个时间步预测。
# 给定一个已拟合的模型,拟合模型时使用的批量大小 (1),以及来自
# 测试数据的一行,该函数将把输入数据从
# 测试行中分离出来,重塑它,并将预测值返回为单个浮点值。
# 进行单步预测
def forecast(model, batch_size, row)
X = row[0: -1]
X = X.reshape(1, 1, len(X))
yhat = model.predict(X, batch_size=batch_size)
return yhat[0,0]
#使用较早的解析器函数加载数据集
series = read_csv(‘/Users/arianalemadriscoll/Documents/SeasonalityData/shampoo-sales.csv’,
header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser, engine=’python’,
skipfooter=3)
# 转换为平稳
raw_values = series.values
diff_values = difference(raw_values, 1)
# 转换为监督学习
supervised = timeseries_to_supervised(diff_values, 1)
supervised_values = series.values
# 将数据分为训练集和测试集
train, test = supervised_values[0:-12], supervised_values[-12:]
# 转换数据尺度
scaler, train_scaled, test_scaled = scaler(train, test)
# 拟合模型
lstm_model = fit_lstm(train_scaled, 1, 3000, 4)
# 也尝试 1, 1500, 2?
# 预测整个训练数据集以建立预测状态
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
lstm_model.predict(train_reshaped, batch_size=1)
# 在测试数据上进行前向验证 (滚动预测场景)
predictions = list()
for i in range(len(test_scaled))
# 进行单步预测
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
# 存储预测
predictions.append(yhat)
expected = raw_values[len(train) + i + 1]
print(‘Month=%d, Predicted=%f, Expected=%f’ % (i+1, yhat, expected))
# 报告性能
# RMSE 惩罚大误差,得分以预测数据相同的单位报告 (月洗发水销量)
rmse = sqrt(mean_squared_error(raw_values[-12:], predictions))
print('Test RMSE: %.3f' % rmse)
# 观察值与预测值的线图
pyplot.plot(raw_values[-12:])
pyplot.plot(predictions)
pyplot.show()
# batch_input_shape = 指定每批读取的预期观测值的元组
# + # 时间步,# 特征
# 批量大小和周期定义了网络学习数据的速度
# 即权重更新的频率
# 神经元/内存单元/块的数量 (对于简单问题,1-5 个足够)
#layer = LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True)
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
我认为您的提议存在错误。只需任意更改测试集中的点,您会发现您的模型仍然可以预测正确的值!如您所知,这是不可能的。
我认为错误在于 `inverse_difference` 函数。在此函数中,您将预测的增量添加到前一个原始值。但您不应该访问此值。
也就是说,您可以“看到”的最后一个点是训练集的最后一个值 v=raw_values[train_size]。当您预测增量 yhat0 时,预测值应为 v+yhat0。然后,在下一个迭代中,您从 yhat0 获得一个新值 yhat1。然后预测值是 v+ yhat0 + yhat1,但您使用的是 raw_values[train_size+1]+yhay1,这是错误的。
我认为您在其他关于 LSTM 的帖子中也发生了同样的情况。
模型不熟练。不要将 LSTM 用于时间序列预测。
https://machinelearning.org.cn/suitability-long-short-term-memory-networks-time-series-forecasting/
我明白了,谢谢您的参考。但是,我发现 LSTM 在非常短的时间预测中可以击败 ARIMA,仅在时间的前几个单位。
真的吗!?
我没有亲自见过。
我发现,在每次尝试处理的单变量时间序列数据集上,经过网格搜索的 SARIMA 或 Holt-Winters 模型都优于神经网络。
while_loop() 收到一个意外的关键字参数 ‘maximum_iterations’。有人遇到过这个错误吗?我认为这是 Keras/Tensorflow 版本引起的问题?
抱歉,我没见过这个错误。也许试试在 Stack Overflow 上发帖?
我遇到了同样的错误,我以为问题在于 Keras 版本,我更改了它,但问题仍然存在。
TypeError Traceback (most recent call last)
in ()
1 # 拟合模型
—-> 2 lstm_model = fit_lstm(train_scaled, 1, 3000, 4)
3 # 预测整个训练数据集以建立预测状态
4 train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
5 lstm_model.predict(train_reshaped, batch_size=1)
在 fit_lstm(train, batch_size, nb_epoch, neurons) 中
50 X = X.reshape(X.shape[0], 1, X.shape[1])
51 model = Sequential()
—> 52 model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
53 model.add(Dense(1))
54 model.compile(loss=’mean_squared_error’, optimizer=’adam’)
C:\Users\mmariscal\Anaconda3\lib\site-packages\keras\engine\sequential.py in add(self, layer)
C:\Users\mmariscal\Anaconda3\lib\site-packages\keras\layers\recurrent.py in __call__(self, inputs, initial_state, constants, **kwargs)
498
499 if initial_state is None and constants is None
–> 500 return super(RNN, self).__call__(inputs, **kwargs)
501
502 # If any of
initial_state
orconstants
are specified and are KerasC:\Users\mmariscal\Anaconda3\lib\site-packages\keras\engine\base_layer.py in __call__(self, inputs, **kwargs)
C:\Users\mmariscal\Anaconda3\lib\site-packages\keras\layers\recurrent.py in call(self, inputs, mask, training, initial_state)
2110 mask=mask,
2111 training=training,
-> 2112 initial_state=initial_state)
2113
2114 @property
C:\Users\mmariscal\Anaconda3\lib\site-packages\keras\layers\recurrent.py in call(self, inputs, mask, training, initial_state, constants)
607 mask=mask,
608 unroll=self.unroll,
–> 609 input_length=timesteps)
610 if self.stateful
611 updates = []
C:\Users\mmariscal\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py in rnn(step_function, inputs, initial_states, go_backwards, mask, constants, unroll, input_length)
2955 # Arguments
2956 x: A tensor or variable.
-> 2957 axis: The dimension softmax would be performed on.
2958 The default is -1 which indicates the last dimension.
2959
TypeError: while_loop() 收到意外的关键字参数 ‘maximum_iterations’
您能否确认您使用的是最新版本的 Keras 和 TensorFlow?
例如
tensorflow: 1.8.0
keras: 2.1.6
我在 tensorflow=1.3.1, keras=2.2.0 时遇到了同样的错误。
在我升级到 tensorflow=1.8.0, (keras=2.2.0) 后,错误就消失了!
所以这个错误是由较低版本的 tensorflow 引起的。
很高兴听到这个消息!
亲爱的 Jason,
我有多维数据,有 24 个特征。
我想将我的数据转换为批量,例如大小为 100,即 100 行 24 列:(100,24)。然后我想基于前 20 个批量预测下一个批量。这可能吗?我该如何实现?
谢谢你的帮助。
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/how-do-i-prepare-my-data-for-an-lstm
嗨,Jason,
您能否指导我是否可以在 R 中执行此过程?
抱歉,我没有关于 R 中的深度学习的资料。
嗨,Jason,
感谢您发布如此有用的帖子。我想问一下,神经元是什么意思?当它是 4 和 1 时是什么意思?
它是层内的节点数。
也许这会有帮助
https://machinelearning.org.cn/faq/single-faq/how-many-layers-and-nodes-do-i-need-in-my-neural-network
再次感谢 Jason。我花了很长时间在寻找一个问题。这个网站上有一些关于我的问题的启示,但没有确切的。我有一个电力时间序列消耗,包含每小时负载和温度。我实现了 NARXnet 来处理时间序列(3 年每小时负载),并预测了未来 24 小时。每周都有一个重复的周期,因此我为 NARXnet 选择 168 个时间延迟。预测是令人满意的。现在,我想实现 LSTM 来处理时间序列,但是,我无法概念化一些 LSTM 输入来建模。例如,LSTM 层中的输入必须是 3D 格式 [样本,时间步,特征]。我的 26304 个观测值、2-11 个预测属性(一些虚拟变量用于天)和 168 个周期,它们的样本、时间步和特征是什么?第二个问题是我能否将自回归性应用于 LSTM?第三个问题是,将 stateful 设置为 True 是否能实现 LSTM 的自回归适应,以及它是否与实现例如 168 个时间序列的 batch_size 相关?第四个问题是,如何表示 LSTM 中的 168 步周期,因为这个周期在数据中占主导地位?最后一个问题是我能否使用 CNN 来处理具有 24x7 维度的每对时间序列以捕捉一天中的相关性?
提前感谢您的回复。
样本是子序列,时间步是按时间变量排序的观测值,特征是每个时间步记录或观测到的内容。
您可以使用 LSTM 进行自回归类型的模型。
Stateful 可能不是必需的,我发现它通常不是必需的。
这可以帮助您准备数据。
https://machinelearning.org.cn/faq/single-faq/how-do-i-prepare-my-data-for-an-lstm
亲爱的 Jason,又见面了。
我尝试按照您指示的方法来准备数据。如前所述,我的数据有 26304 行(包含每小时观测值)和 1 个(特征)+ 9 个(天和节假日的虚拟变量)列。我想为问题增加自回归性,因此我准备的数据形状是(这部分包含验证集和训练集)25969x168x10。这里 25969 指的是观测次数,168 指的是对要预测的值的 168 个先前回溯(即,预测第 169 个值所需的 168 个回溯 AR 值),10 指的是数据维度。在实现过程中,我遇到了一些挑战。训练集和验证集分别有 24000 和 1969 个值,带有 168x10 的矩阵。当我将时间步设置为与 168 不同时,使用 input_shape=(time_steps,data_dim) 会导致错误,例如,期望 lstm_1_input 的形状为 (None,24,10),但得到了形状为 (24000,168,10) 的数组。这是否意味着我的序列将被链接为 168 或 24 的长度,这取决于时间步的设置,就像 168 或 24 一样?也就是说,168 个时间步是否指 168 个 LSTM 单元将水平连接在一起?
当我将时间步设置为 168 时,是可以的。
另一个问题是,当我使用 return sequences 时,它是否会在数据集中引起问题?问题实际上在于数据维度不匹配。
我的目标是,当我准备好 3D 矩阵数据时,通过将时间步设置为 24,我的每个 168x10 值将被馈送到一个长度为 24 的链中。当我设置批次大小例如 48 时,我的权重将在 48x168x10 的回合结束时更新,在 24 个水平 LSTM 单元的链中。我尝试使用第一个张量作为天的序列,正如您所期望的那样。然而,我在这些实现中失败了。我很难找到我哪里出错了。如果您也能帮助我,我将非常高兴。
提前感谢。
我有一些关于如何为 LSTM 准备时间序列数据的帖子,您可以从这里开始
https://machinelearning.org.cn/faq/single-faq/how-do-i-prepare-my-data-for-an-lstm
您可以将序列输出为向量或使用编码器-解码器架构。
Jason,您好
我正在进行单变量 LSTM,但结果非常糟糕,MSE 超过 300,我看到了您的教程:
注释掉在步进验证中拟合 LSTM 模型的行。
yhat = forecast_lstm(lstm_model, 1, X)
并替换为以下内容:
yhat = y
这应该会产生一个具有完美技能的模型(例如,一个将预期结果作为模型输出的模型)。
结果应如下所示,表明如果 LSTM 模型可以完美地预测序列,则反向转换和误差计算将正确显示它。
这部分是什么意思?为什么使用 yhat=y?如果使用它,预测结果就是测试集,对吗?那不是 LSTM 预测的结果。
LSTM 在时间序列预测方面表现不佳,我建议先尝试经典方法。
https://machinelearning.org.cn/start-here/#timeseries
Jason,您好。
你好,
所以我遵循了您的几个教程,我正在尝试构建一个 LSTM,它需要最后一个 3 个输入。
假设我的数据是 (1,2,3,4,5,6,7,8),那么我希望在预测中输入 (1,2,3) 并且预测应该是 4(在最好的情况下)。
所以这是我所做的
对于训练,我假设是好的
train_reshaped = train_scaled[:, 0:3 ].reshape(len(train_scaled), 1, 3)
lstm_model.predict(train_reshaped, batch_size=2)
以及测试
X,y= test_scaled[i, 0:3].reshape(1, 1, 3), test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
这是我的测试输入 [[[-0.94936709 -0.97468354 -0.8630137 ]]] # 形状
def forecast_lstm(model, batch_size, X)
yhat = model.predict(X, batch_size=batch_size)
return yhat[0,0]
我收到这个 ValueError: could not broadcast input array from shape (2,1) into shape (1,1)
我无法弄清楚它为什么会出现。
我认为输入形状应该是 (1,3,1),而不是 (1,1,3)。
除此之外,我不确定我是否理解您的问题,抱歉。您能否用另一种方式解释问题或提供更多背景信息?
所以,我正在尝试做以下事情。
我有一个时间戳序列,例如 [1,2,3,4,5,6,7,8,9,10,11]
我想输入网络 [[1],[2],[3]] 然后预测 [4],然后我将窗口滑动一个位置,[[2],[3],[4]] 然后预测 [5] 等等。
这是修改后的代码
repeats = 30
error_scores = list()
for r in range(repeats)
# 拟合模型
lstm_model = fit_lstm(train_scaled,1, 500, 3)
print(‘trained’,r,’/30\n’)
train_reshaped = train_scaled[:, 0:3 ].reshape(len(train_scaled), 1, 3)
#print(train_reshaped[0].shape)
lstm_model.predict(train_reshaped, batch_size=1)
# 对测试数据进行步进验证
predictions = list()
for i in range(len(test_scaled))
# 进行单步预测
# X, y = test_scaled[i, 0:3].reshape(1, 1, 3), test_scaled[i, -1]
X, y = test_scaled[i, 0:3], test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
#yhat = inverse_difference(raw_values[-10:], yhat, len(test_scaled)+1-i)
yhat = inverse_difference(raw_values, yhat, len(test_scaled)-i)
#print(convertToDate(yhat),convertToDate(raw_values[-(len(test_scaled)-i+1)]))
print(day_diff(yhat,raw_values[-(len(test_scaled)-i+1)]))
#yhat = inverse_difference(raw_values[-10:], yhat, len(test_scaled)+1-i)
# store forecast
predictions.append(yhat/86400)
# 报告表现
ytrue=raw_values[-(len(test_scaled)+1):-1]/86400
rmse = sqrt(mean_squared_error(ytrue, predictions))
mae = numpy.sum(numpy.absolute((ytrue/86400, predictions)))
print(‘%d) Test RMSE: %.3f’ % (r+1, rmse))
print(‘%d) Test MAE: %.3f’ % (r+1, mae))
error_scores.append(rmse)
# 总结结果
results = DataFrame()
results[‘rmse’] = error_scoresl
print(results.describe())
听起来不错,这个函数将有助于准备数据。
https://machinelearning.org.cn/convert-time-series-supervised-learning-problem-python/
你好,
我已经这样做了。所以我在这里所做的是获取时间序列,对它们进行差分(以天为单位),缩放这些差分并将它们输入网络。我只是想确保我输入一个包含 3 个数据点的序列,并且网络应该预测第 4 个数据点。
另一个问题是:在训练期间重置状态是否真的很重要?
这取决于问题,总的来说,我发现状态并没有增加太多。
您好 Jason,您能否解释一下为什么 LSTM 似乎有滞后(基于蓝色和橙色线)?
性能不佳。例如,它学会了一个持续模型。
您好 Jason,在我检查您的多步预测时,我想知道如果您将预测值反馈给下一步预测,是否会导致将不准确的数据传递到下一步并导致整个结果不准确。有什么技术可以最小化这种副作用吗?
是的,这被称为迭代或递归模型。
神经网络的一种替代方法是直接将多步预测为向量。
也许这篇文章可以帮助理解递归和直接多步预测的区别。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
非常感谢您的提示。非常有帮助。您是否有更多关于建模策略的教程,例如使用多个数据集构建模型,并利用不同的激活和正则化来找到改进模型行为的最佳方法?或者您是否有关于此主题的书?
这个通用流程可能会有帮助。
https://machinelearning.org.cn/start-here/#process
你好,
这句话似乎是错误的:“默认情况下,Keras 中的 LSTM 层在批次内维护状态”。根据 Keras 文档,批次内的样本是独立处理的。
您为什么这么说?您能提供参考吗?
当然,这里是 https://keras.org.cn/getting-started/faq/#what-does-sample-batch-epoch-mean
“Batch:一组 N 个样本。批次中的样本独立处理,并行处理。”
我是神经网络新手,我想了解 RNN 如何帮助检测时间序列中的异常。根据我目前的理解,唯一能让 LSTM 学习任意长依赖关系的 Keras 设置是:输入层只有一个神经元,batch_size=1 并且 stateful=True。
很好的发现。你可能是对的,但我并不确定这是否适用于 RNN。
Jason 你好,我想问一下,如果时间序列本身是稳定的,我需要建立一个持久性模型。建立之后,我发现它的性能比 LSTM 更好。
是的,这通常是这种情况。尝试一套其他方法,如 MLP、CNN 和混合模型。也尝试经典方法,如 SARIMA 和 ETS。
你好,
如果我们要将此应用于日志分析,如何转换数据并将其应用于时间序列和神经网络?
谢谢,
Geeta
这取决于日志。
你可能需要编写代码来使你的数据干净并准备好建模。
你好,
我不确定这个问题本身是否会过拟合?我们是否应该首先考虑用 LSTM 来解决这类问题?
谢谢,
Suker
不,LSTM 在单变量时间序列预测方面非常糟糕,而且很容易被 SARIMA 和 ETS 淘汰。
你好!
你为什么在这行反转了顺序?
X, y = train[:, 0:-1], train[:, -1]
谢谢!
我不明白,具体在哪儿?
感谢你的解释,
我的问题是,在当前这个阶段,在评估了模型之后,如何预测和可视化未来的一些值。
或者,如何可视化最后一个值之后跟随的 t+1 值?
谢谢
教程展示了如何绘制 y 与 yhat。
你到底遇到了什么问题?
嗨,Jason,
感谢你的教程,我非常喜欢!
我有一些问题
1.我想知道 LSTM 是否可以预测加密货币未来的价格。
2.我可以使用历史数据进行预测吗?我打算这样做,但仍然不确定结果。
3.我看到很多人用 ARIMA 来做这个,你能给我一些 LSTM 比 ARIMA 更好的理由吗?
抱歉我的知识不足。我希望收到您的回复。
你可以开发一个模型来预测任何你想要的东西。我不知道加密货币价格是否可预测,我怀疑它们是随机游走的。
根据定义,一个有技能的预测模型将利用历史数据来预测未来。
也许这会有帮助。
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
Jenson 你好,
这些 LSTM 神经网络能否保持多个时间序列的变化模式?在我的项目中,我有一组不同的时间序列变化模式。所以,我想知道的是:
1. LSTM 网络能否识别出正确的模式(从所有模式中),然后据此预测下一个值(给定前几个变化 x(i-1), x(i-2) 作为监督学习问题)?
2. 如果不能,这种情况(时间序列模式识别和预测)的解决方案是什么?
你能给我一些指导吗?
感谢您的教程。它们非常有帮助!!🙂
是的,但是 LSTM 在时间序列预测方面非常糟糕。也尝试 MLP、CNN 和混合模型。
查看此教程
https://machinelearning.org.cn/how-to-develop-lstm-models-for-multi-step-time-series-forecasting-of-household-power-consumption/
嗨,Jason,
是否有关于单(分类)变量、LSTM 时间序列预测的教程?
谢谢
我认为你指的是时间序列分类。
我在这里有一个使用 LSTM 进行时间序列分类的示例
https://machinelearning.org.cn/how-to-develop-rnn-models-for-human-activity-recognition-time-series-classification/
嗨,Jason,
对于分类变量 LSTM 预测,要求如下:
我想预测一个人在某个工作日的上午 10 点在做什么,所以我收集了他从第 1 天到第 n 天的所有活动。所有活动都在工作日。然后,如果我想预测他在第 (n+1) 天上午 10 点的活动。如何做到?您的帖子中有任何相关教程吗?
是的,我认为时间序列活动识别与你的需求非常接近。
https://machinelearning.org.cn/how-to-develop-rnn-models-for-human-activity-recognition-time-series-classification/
嗨,Jason,
在训练模型时,我们会在每个 epoch 后重置状态
for i in range(nb_epoch):
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
model.reset_states()
但是,如果我们想在训练期间使用 Keras 中定义的“ReduceLROnPlateau”回调来降低学习率,由于 Keras 提供的所有参数都被重置,学习率总是保持在初始值不变。因此,获得次优最小值的概率很高。
你对此有什么看法?
你可以手动计算每个 epoch 的新学习率。
或者,你可以通过回调重置网络状态,并使用内置的学习率调度器。
嗨,Jason,
根据您的实现,由于 Keras 中 Adam 优化器的初始化,每个 epoch 后的学习率都为 0.001。
keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
从你的第二点来看,你的意思是有一个在 epoch 开始时运行的学习率调度器。
我不确定我是否理解,你能详细说明吗?
嗨,Jason,
我运行了你的程序,但是在训练期间 epoch 是 23。我设置了 epoch 100,但在训练期间 epoch 仍然是 23。我有点困惑。
我有一些建议可能会有所帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
这里也有一些关于调试的建议。
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
你好,
我目前正在做一个涉及时间序列数据的项目,并考虑使用 LSTM 方法。我想到了,如果 LSTM 只考虑历史数据而忽略任何其他属性,它怎么能比其他模型表现更好呢?
例如,在这个案例中,我们处理的是产品价格。LSTM 唯一考虑的变量是历史牛奶价格。它怎么能超越考虑了许多其他因素的多元线性回归等模型呢?
通常 LSTM 在时间序列预测问题上表现不佳。
Jason 你好,我可以编辑函数 ‘def forecast_lstm(model, batch_size, X)’,
在“Complete lstm Example”的第 75 行,
在 ‘yhat = model.predict(X, batch_size=batch_size)’ 之前
使用 model.save(‘Lstm_model.h5 ‘) 保存的先前模型,
或者可以在其他地方进行编辑吗?非常感谢。
当然可以。
打扰一下,然后我在“Complete lstm Example”的哪个步骤需要编辑才能使用 model.save(‘Lstm_model.h5 ‘) 保存的先前模型?有示例吗?谢谢。
抱歉,我没有能力为您定制示例。
也许先熟悉一下 API 会有帮助。
https://machinelearning.org.cn/save-load-keras-deep-learning-models/
是的,当然,你是对的,但我只是想在“Complete LSTM Example”中,将第 98 行的 lstm_model = fit_lstm(train_scaled, 1, 3000, 4) 替换为 lstm_model = load_model(‘lstm_model.h5’),就像你在 ARIMA 的例子中那样,这里 https://machinelearning.org.cn/time-series-forecast-study-python-annual-water-usage-baltimore/ 的第 15 行,在第 7.3 节,你觉得怎么样?非常感谢。
你可以加载模型而不是重新拟合它。
我没有能力就如何最好地修改代码示例来满足您的需求提供建议——很可能一行代码的修改是不够的。
你好 Jeson,在“Complete LSTM Example”部分,我应该编辑代码中的什么内容来更改 batch_size?可以给我一个例子吗?
将 batch_size 参数指定给 fit() 函数。
Jeson,抱歉打扰。
在“Complete LSTM Example”代码中,我使用了另一个数据集,训练集和测试集的大小都是 5。这是一个因素。
所以,我更改了
第 98 行:lstm_model = fit_lstm(train_scaled, 1, 3000, 4)
为:lstm_model = fit_lstm(train_scaled, 5, 3000, 4)
第 101 行:lstm_model.predict(train_reshaped, batch_size=1)
为:lstm_model.predict(train_reshaped, batch_size=5)
第 108 行:yhat = forecast_lstm(lstm_model, 1, X)
为:yhat = forecast_lstm(lstm_model, 5, X)
但我得到了这个错误:
ValueError: could not broadcast input array from shape (5,1) into shape (1,1)
在第 77 行 yhat = model.predict(X, batch_size=batch_size)
你能帮我修复这个 bug 吗?谢谢。
我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
是的,当然,你不必为我编写代码或修复我的 bug,我只是想改变 batch_size 从 1 到另一个数字,我只是想澄清我没有通过阅读你的代码而很好地理解它。谢谢🙂
嗨,Jason,
我对输入形状有点困惑。
假设我有 2500 个 A 类时间序列,和 2500 个 B 类时间序列,每个长度为 1000 个时间步。每个时间序列只有一个数值特征。我想使用 Keras 训练一个 LSTM 来将时间序列分类到两个类别之一。它们可以通过需要 LSTM 理解数据之间时间相关性的特征轻松区分,例如一个类有季节性模式,而另一个类没有。因此,我认为我需要使用状态 LSTM,因此需要手动调用 model.reset_states(),对吧?
但我完全不清楚如何构建 Keras 的 input_dimensions。
据我所知,LSTM 的输入定义为(样本数,时间步数,特征数)。
我的 X 现在是(5000,1000,1),我只调用 model.fit() 一次吗?我什么时候调用 model.reset_states()?
或者我是一次展示一个时间步长的时间序列,所以我的输入是(1,1,1),我然后为每个时间序列显示 5000 次,每个时间步显示 1000 次,然后调用 model.fit() 5,000,000 次?!然后在我完成一个时间序列后,我会调用 model.reset_states() 方法来忘记新的时间序列的所有内容吗?这是你在本教程中使用的版本吗?
还是说是(1,1000,1),在调用 fit() 5000 次(每个时间序列)后,我调用 model.reset_states() 方法?
也许这会有帮助。
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
谢谢,这真的很有帮助!
好的,我又糊涂了。假设我有一个 LSTM 输入(25, 1000,2),那么批次大小为 25,时间步为 1000,特征为 2。为了构建训练 X,我取 25 个不同标签的时间序列并将它们放在一个批次中。训练后,我想让 LSTM 对一个时间序列进行分类。但是因为我指定了 25 的批次大小,我现在总是需要向它提供 25 个时间序列?!
不,你可以为一个样本 [1,1000,2] 进行预测。
Jason 你好,感谢你精彩的教程!
我现在对 Keras 中的 LSTM 的一些地方感到困惑。
希望你有时间回答这些问题!提前感谢!
假设有一个时间序列数据集,包含两个变量和一个输出。数据集不连续,所以实际上可以看作是两个独立序列的组合。每个序列的长度都不相同。一个有 100 个数据点,另一个只有 50 个数据点。我想使用长度为 100 的序列作为训练数据集,其余序列作为测试数据集。
第一个问题:我应该使用状态 LSTM 还是无状态 LSTM?顺便说一下,如果只有一个连续序列,我们应该选择状态 LSTM,对吧?
第二个问题:如何处理长度不同的输入?
再次感谢您!
从无状态开始,然后尝试状态,看看是否有区别。
使用填充使所有输入长度相同。
https://machinelearning.org.cn/data-preparation-variable-length-input-sequences-sequence-prediction/
感谢您的及时回复!您太好了!我会做一些实验。
Jason 你好。我现在正在进行一些实验,现在有另一个问题。
假设我想使用“多对多”架构来预测每个相同时间步的输入 x(t) 的输出 y(t)。因此,输入和输出数据都将是数据序列。假设我有 50 个输入和输出数据序列。输入数据或输出数据的最大长度固定为 100,并使用填充使所有序列长度相同(100)。
问题是:Keras 所需的输入形状(样本数,时间步数)应该是(50, 100),对吧?
提前感谢您的回复!
如果你想预测一个输入的一个输出,那么这将是“一对一”。
我有很多关于如何塑造数据的帮助,从这里开始。
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
谢谢你的回复。
实际上我读过这个网站。它非常有帮助。但是,我仍然对下面这段话感到困惑。
“作为另一个例子,如果你有 20 个时间步的数据,包含 2 个特征,你可能将其表示为 20 个样本,每个样本有 1 个时间步 [20, 1, 2],或者表示为 1 个样本,包含 20 个时间步 [1, 20, 2]。在第一种情况下,你有 20 个样本,意味着 20 个输入和输出示例,你的模型将做出 20 个预测。在后一种情况下,你只有 1 个样本,具有 1 个输入和 1 个输出,模型将做出 1 个预测,该预测会在 20 个时间步上累积。”
我理解第一种情况。但是,在第二种情况下,你说我们只有一个输出要预测。输出将在哪个时间步进行计算和输出?是在最后一个时间步(第 20 个时间步)吗?
至于 LSTM 的架构,下面的网站展示了它。X 有两个特征,Y 是一个标量。我想在每个相同的时间步预测一个 y 的一个 x。我认为这是多对多,对吧?
https://www.dropbox.com/s/e8zp520iz6lpk89/RNN.png?dl=0
感谢您的帮助!我真的很感激!再次感谢!
正确,输出是在最后一个时间步之后为输入样本计算的。
如果你想为每个时间步做出预测,这将是“一对一”(一个滞后观察到一个预测)或“多对一”(例如,多个滞后观察到一个预测)。ob 是 observation 的缩写,以防我造成混淆。
嗨,Jason!
如果数据包含季节性,而季节性也是携带了重要领域信息的异常,我还需要进行差分吗?
如果序列包含季节性结构,请将其从序列中移除,然后对残差进行建模。
这称为季节性调整。
https://machinelearning.org.cn/remove-trends-seasonality-difference-transform-python/
嗨,Jason,
我遵循了你的步骤,并测试了一些具有简单模式的合成数据,例如重复 n 次的(0,0,0,…,0,1)。我试图看看 LSTM 网络是否能够学习这种具有长程依赖的模式并进行正确的向前预测。结果发现,尽管我尝试了不同的学习率,但优化器经常陷入较差的局部最小值。相反,如果我将训练数据视为一个多步时间序列,并将 batch_input_shape 设置为 (1, seq_length, n_lags),训练就会容易得多,并且收敛得更快。你是否期望将训练数据视为一个样本的多个时间步比作为多个样本的一个时间步在一般情况下更好?谢谢。
这真的取决于问题。
例如,我展示了如何使用1个时间步的样本,LSTM可以在样本之间进行记忆
https://machinelearning.org.cn/memory-in-a-long-short-term-memory-network/
X, y = train[:,0:-1], train[:,-1]
X = X.reshape(X.shape[0], 1, X.shape[1])
IError
—————————————————————————
IndexError Traceback (最近一次调用)
in
—-> 1 X, y = train[:,0:-1], train[:,-1]
2 X = X.reshape(X.shape[0], 1, X.shape[1])
IndexError: 数组索引过多
我遇到了上面的错误。你能帮我吗,Jason??
很抱歉听到这个消息,我在这里有一些建议。
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,Jason!
我必须说,这篇博文非常有趣。我最近开始了一个新项目,对LSTM(实际上对NN还很新)还不熟悉。因此,我想请你给我一些建议:我的问题与这篇博文中的问题类似,但不是拥有一个长度为36的向量数据集,而是拥有大约500个长度为8的向量,因此,我不想只用一个向量进行训练,而是想用很多向量进行训练,然后用很多向量进行测试。
特别是,我想训练一个模型来预测每个向量的最后3-4个条目。为此,我计划使用大约300个向量进行训练,然后使用另外200个向量来测试每个向量最后3-4个条目的预测。
你能给我一些关于如何进行的建议/链接吗?
谢谢!
听起来合理。
是的,我有几十篇教程可以帮助你,从这里开始
https://machinelearning.org.cn/start-here/#deep_learning_time_series
Jason,做得很好——
一个问题,你有没有类似的教程来使用LSTM,其中时间步是在可变时间采取的,因此它们不是均匀分布的?
最棒的!
没有。但也许模型并不在意。你可以尝试用可变输入时间步建模,或者尝试用零填充,或者尝试重采样使其一致——然后比较每种方法的结果?
你说的“可变输入时间步”是什么意思?
据我所知,时间步在构建网络时需要固定,因为这是LSTM层的batch_input_shape参数所需要的。或者我错了?
谢谢!
它们可以变化,但是你可以用零填充差距,你可以假装时间步是均匀分布的,即使它们不是,你也可以截断或重采样时间序列,你有许多选择。
嗨,Jason,
感谢非常实用的实现。我有一个后续问题。
我用batch_size = 32在训练数据上训练了LSTM模型。然后我尝试使用训练好的模型和batch_size = 1的测试数据进行预测,但它不起作用。
是否需要将batch_size设置为= 1(在训练和预测中)才能进行单步预测?
谢谢。
这是使用状态LSTM时一个常见的问题,我在这里有一个解决方法
https://machinelearning.org.cn/use-different-batch-sizes-training-predicting-python-keras/
如何预测未来的值..假设我的数据直到12月,那么如何预测1月?
这篇文章会有帮助:
https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
保存模型后使用load_model,但是
X的输入值是什么?
例如。假设我有一个数据集(data.csv),我该如何将其输入?
代码
# sni...
# 稍后,可能从另一个脚本运行
# 从单个文件加载模型
model = load_model(‘lstm_model.h5’)
# 进行预测
yhat = model.predict(X, verbose=0)
print(yhat)
它给出多少时间步的结果。
X是你模型期望的任何输入,以便做出预测。例如,给定样本的输入分量,以获得样本的输出分量。
我输入了包含86个值的数据集,保存的模型给出了86个值,这些值被认为是预测值吗?
它不像ARIMA那样工作吗?我们输入历史数据,然后它预测未来值?
你将其建模为任何有监督学习问题,包含输入和输出,只是在这里,输入样本由时间步组成。
感谢这篇精彩的教程。
我一步一步地看了,但它在“魔法发生”之前就结束了(不幸的是)
X, y = train[:, 0:-1], train[:, -1]
X = X.reshape(X.shape[0], 1, X.shape[1])
到目前为止,你给我的建议非常完美,我也可以自己检查所有行。
现在,当使用完整的例子时,这并不那么容易;/
您可以在此处了解更多关于重塑数组的信息
https://machinelearning.org.cn/index-slice-reshape-numpy-arrays-machine-learning-python/
先生,
如何使用LSTM网络预测大规模数据处理中的发动机状况
我最好的建议是先从这里开始,然后遵循概述的流程
https://machinelearning.org.cn/start-here/#deep_learning_time_series
为什么是rmse?为什么不是其他类型的误差?误差的类型是否也与数据集的类型有关,还是其他原因?
RMSE被广泛使用且深入理解。
MAE也很受欢迎。
嗨,Jason,
我不确定这是否是发布此问题的最佳教程,但我要开始了!
我浏览了你关于RNN用于预测和分类的多个教程,并且我将它们应用到我的数据上,但成功有限。所以我想更进一步。这是我的问题
我有2个特征,我想预测它们。但是,一个是连续变量,另一个是类别。到目前为止,我分别预测它们,但现在我想合并预测,因为这两个特征是相互关联的。这就是为什么我想用基于LSTM单元的keras构建一个网络,该网络接收两个特征的输入,能够提供两个不同的输出,一个应该经过二元交叉熵激活函数来获得类别,另一个应该经过无激活函数(f(x)= x)。
我看到一个教程,你在一个编码器-解码器网络中包含了注意力机制,你展示了如何合并网络的上层。但是,你知道我们如何分割网络以获得两个不同的结果吗?
谢谢
Brain
也许你可以尝试一个具有两个输出的模型,每个输出都有自己的损失函数?
谢谢!你有什么例子这样做吗?
是的,本教程将有所帮助
https://machinelearning.org.cn/keras-functional-api-deep-learning/
嗨
第25-30行
我遇到了KeyError,因为history[-interval]的索引是负的,而这里是series[-interval]。
我应该使用history = series.values而不是series(第28行)吗?
value = inverse_difference(series.values, differenced[i], len(series)-i)?
也许试试看效果如何。
你好,
你有很多关于LSTM用于时间序列的帖子,有些似乎已经过时了。这是最新的一个吗?对于过时的,你能否在标题中清楚地说明?
谢谢!
你可以在这里看到我最新/最好的关于LSTM用于时间序列的帖子
https://machinelearning.org.cn/start-here/#deep_learning_time_series
你好 Jason,
因此,我正在尝试使用LSTM来预测时间序列,但我有一个重要特征的问题。假设X是我正在预测的。
假设X= a+b+c。a,b,c的值不仅取决于时间,还取决于代表颜色的另一个列。最佳的进行方式是什么?
1-使用LSTM仅根据时间预测a,b,c,然后求和得到X
2-将a,b,c相加然后应用LSTM
为了让这一点更有意义,假设a,b,c是3个不同业务单元的利润,X是总利润。
我还想了解为什么你的数据分割中没有验证集。
谢谢
一个接一个地使用两个模型是一个好的开始。
尝试预测所有元素,看看模型能否保持值的一致性?
发挥创意,也许可以构思问题的替代框架并进行测试?
嗨,Jason,
非常感谢你的详细教程!在训练数据并用测试数据集验证之后,我想在新的数据上生成预测,例如未来的时间步,而没有实际值y(即,训练数据为10年,预测未来几年)。你能告诉我如何制作一个合适的X来使用训练好的模型进行预测吗?
是的,你可以调用model.predict()。
也许这篇文章会有所帮助
https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
你好 Jason!谢谢你的教程。
我通过epochs、神经元数量和batch size调整了我的模型,并且进行了重复实验。在很多情况下,我的问题的rmse令人满意。但是,在某些情况下,误差不令人满意。这是正常的吗?如果大多数实验令人满意,我是否应该认为我的模型已准备就绪,或者只有当rmse几乎稳定时,模型才算准备就绪?
另外,在for循环之前和之内进行预测有什么区别?(见下文)
情况1:for循环之前的lstm_model.predict()
output = lstm_model.predict(test_reshaped, batch_size=batch_size)
predictions = list()
for i in range(len(output))
yhat = output[i,0]
X = test_scaled[i, 0:-1]
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
# store forecast
predictions.append(yhat)
情况2:for循环之内的lstm_model.predict()
for i in range(len(test_scaled))
# 进行单步预测
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
# store forecast
predictions.append(yhat)
通过集成预测来对抗最终模型的方差可能是一个好主意
https://machinelearning.org.cn/ensemble-methods-for-deep-learning-neural-networks/
很棒的博客!
谢谢!
你好,请问你是否可以为我们写一个用于未来预测(我们不知道的值)的函数,以及我们应该在代码的哪个位置放置它?我遇到了处理它的问题,非常感谢!
是的,我在这里解释了如何做
https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
你好,
我在前进式验证时遇到问题
运行
predictions = list()
for i in range(len(test_scaled))
# 进行单步预测
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
yhat = forecast_lstm(lstm_model, 1, X)
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
# store forecast
predictions.append(yhat)
expected = raw_values[len(train) + i + 1]
print(‘Month=%d, Predicted=%f, Expected=%f’ % (i+1, yhat, expected))
返回“KeyError: -76”
我的测试数据长度为75天,所以它似乎与此有关。上面这部分没有需要为我的特定数据指定的任何东西,对吗?
有趣的是,将inverse_difference函数编辑为返回“yhat + history[interval]”而不是“history[-interval]”似乎可以纠正这个问题,但我不知道为什么……
也许这篇文章会有所帮助
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
也尝试删除或数据缩放,直到模型/测试框架按您想要的方式工作,然后再添加回来。
嗨!
很棒的博客!
我正在阅读这一部分,我不太理解这个例子和这里展示的例子之间的区别(https://machinelearning.org.cn/time-series-prediction-lstm-recurrent-neural-networks-python-keras/)。两种情况都是预测一个时间步的值,对吗?
我正在做一个项目,数据集是车辆在一段时间内的速度,我正在尝试预测未来的速度。目前,我在这两个例子中都得到了准确的结果(0.51 RMSE),但我想知道它们之间的主要区别。
链接的示例较旧,而此版本较新,使用了更好的实践。
我这里有更好的例子,也许能帮到你
https://machinelearning.org.cn/start-here/#deep_learning_time_series
嗨,Jason,
在行
# 预测整个训练数据集以建立预测状态
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
你将重新整形train_scaled的第一列。如果使用lag=1,那么它会重塑特征列(1列)。但如果你使用例如3个前时间步(timeseries_to_supervised(data, lag=3)),它会生成3列的特征。那么,在这种情况下,“train_scaled[:, 0]”是什么意思?它应该是train_scaled[0:-1, 0]吗?
谢谢
嗨,Jason,
你有没有时间看这个?谢谢
理想情况下,数据应该在转换为监督学习问题之前进行缩放。
你好 Jason,
假设我在差分后有长度为100的history_data。现在我加载并使用我的模型:model.predict(history, batch_size=1)。然后我得到一个长度为100的预测数组,与历史数据相同。我对应该用什么来反差分感到困惑?我应该将预测的2019年6月与前一个月或与前一年的同月进行差分吗?
在预测之前的最后一个已知观测值用于反差分。
我在这里举了一个例子,可能有所帮助
https://machinelearning.org.cn/machine-learning-data-transforms-for-time-series-forecasting/
感谢这篇伟大的文章。我有一个问题:在使用神经网络(深度学习)时,使数据
平稳是必要的(重要的)吗?
我搜索了一些文章。大多数人都说答案应该是“否”
这里是
https://www.oreilly.com/ideas/3-reasons-to-add-deep-learning-to-your-time-series-toolkit
https://www.researchgate.net/post/In_financial_time_series_we_have_non-stationary_time_series_Is_it_needed_to_transfer_the_data_to_stationary_time_series_for_forecasting_or_not
你能给我你的意见吗?谢谢!
它可以提供帮助,但不是必需的。
谢谢!
嗨 Jason,你能否检查一下下面的问题。
我为测试集使用了r2_Score
from sklearn.metrics import r2_score,
results[‘r2train’] = r2_score(train_scaled[:, -1], lstm_model.predict(train_reshaped, batch_size=1))
results[‘r2test’] = r2_score(raw_values[-12:], predictions)
结果
1) Test RMSE: 113.155
rmse r2test r2train
count 1.000000 1.000000 1.000000
mean 113.155189 -0.016695 -0.389893
min 113.155189 -0.016695 -0.389893
25% 113.155189 -0.016695 -0.389893
50% 113.155189 -0.016695 -0.389893
75% 113.155189 -0.016695 -0.389893
max 113.155189 -0.016695 -0.389893
R2值是负的,而RMSE是113。
是的。
我使用了你的原始代码和数据(第:开发一个稳健的结果),只是在RMSE之外添加了R2 SCORE:r2=r2_score(raw_values[-12:], predictions),其输入与原始代码中的mean_squared_error相同。
结果
1) Test RMSE: 94.286 R2: 0.294
2) Test RMSE: 86.854 R2: 0.401
3) Test RMSE: 189.482 R2: -1.851
4) Test RMSE: 147.910 R2: -0.737
5) Test RMSE: 204.352 R2: -2.316
6) Test RMSE: 219.807 R2: -2.836
7) Test RMSE: 106.188 R2: 0.105
8) Test RMSE: 108.560 R2: 0.064
9) Test RMSE: 199.271 R2: -2.153
10) Test RMSE: 129.355 R2: -0.329
…
正如你所看到的,R2值很低甚至为负。
如果我的代码没有错误,我的问题是,我们是否应该同时检查多重标准,如RMSE、R2等?或者是否有根据数据选择R2或RMSE的规则?
另一个例子是,我使用网格搜索来查找具有最佳AIC的SARIMA模型(最佳AIC:4779),以生成SARIMA模型,测试R2为70%。当我检查训练R2时,大约是45%。模型可以接受吗?还是我应该使用训练R2而不是AIC?非常感谢!
我建议选择一个最符合项目利益相关者或领域专家对你的特定数据集的需求的指标。
如果你不确定,RMSE是一个很好的起点。
模型选择是具有挑战性的。选择一个指标以及选择一个能够反映你打算在实践中如何使用模型的模型评估策略是很重要的。
这是我能说的最好的,而不深入研究你的数据集的细节,我没有能力这样做。
如果数据量有数千行,在我这里是40K多行,算法需要花费很长时间来训练和评估或调整。一种方法是减少数据,但那样评估和训练结果就不是针对全部数据的。在这种情况下,我如何评估我的算法?
我正在使用ARIMA和LSTM,两者都花费很长时间,例如有时需要一整天。我切换到google colab GPU,但仍然是同样的问题。我想为上述问题找到一个解决方案,以便我能够更快地调整和评估这两种算法。
使用一个小样本来估计技能并选择模型,然后使用所有数据和一台大计算机一整夜来计算最终的技能估计。
嗨,Jason,
我看了你所有关于LSTM预测的教程。我训练了模型,使用了549个数据点,并为了进行预测,我使用了90个数据点。
X2 = scaler.fit_transform(X2)
X3 = X2[0:-1]
X3=np.reshape(X3, (X3.shape[0], 1, X3.shape[1]))
yhat = model.predict(X3, 1)
这生成了89个预测。但是,如果我想用89个数据点来预测31个数据点,该如何修改我的代码?如果能得到一些帮助,那就太好了。
你可以提供31个输入样本来生成31个输出预测。
也许我不理解你的问题?
嗨,Jason,
感谢您的及时回复。这是因为我拥有2017年7月至2018年12月的每日数据,共549个数据点。我曾尝试预测2019年1月,使用的是2018年10月至2018年12月的数据。在这个例子中,我能理解它会生成与输入数据相同数量的输出数据。
我的问题是
1.使用2018年10月至2018年12月数据生成的这些预测可以被认为是2019年1月至2019年3月的预测吗?我的理解是否正确?
2.有没有办法输入90个数据点来预测31个未来数据点?
在标准的LSTM中,我看到我们可以输入一个包含3个元素的数组[70,80,90]来预测[100],正如你的一篇教程所示
https://machinelearning.org.cn/how-to-develop-lstm-models-for-time-series-forecasting/
感谢您设计这些有用的教程并提供帮助。
你可以按照你想要的方式构建预测问题。这取决于你。
也许我没理解问题所在?
另外,我是否必须将新序列转换为监督格式才能获得预测?
通常是的。
你好。我正在尝试理解代码实现。我发现其中一些定义的函数很难理解,但也许我需要花更多时间去理解。然而,我想知道你在scale-function中用于变量‘train’和‘test’的这些reshape行的目的是什么?
train = train.reshape(train.shape[0], train.shape[1])
test = test.reshape(test.shape[0], test.shape[1])
变量不会改变它们的形状,对吗?因为它们已经是二维数组了?
或许可以从一个更简单的实现开始
https://machinelearning.org.cn/how-to-develop-lstm-models-for-time-series-forecasting/
我们使用上个月的洗发水销量来预测下个月的销量。
1. 为什么我们需要 LSTM 来做这个?我不明白 LSTM 的时间分量是如何起作用的。
2. 当我们将 statefulness 设置为 True 时,我认为网络在读取新月份的销量时会考虑到之前的内容。但当只有一个数据点(而不是一系列预测变量)时,这个信息是如何在预测中使用的?
不需要 LSTM,事实上它比线性方法效果更差。这是一个你可能想用作起点作为例子。
Statefulness 意味着我们控制何时重置内部状态,而不是在每个批次/权重更新结束时重置。
你好,读完这篇很棒的文章后,我也
很高兴能在这里和朋友们分享我的知识。
谢谢。
当我们需要预测大约 300 种产品,以日为单位时,如何应用相同的方法?我正在尝试解决我实习中的一个预测问题。即使我的问题看起来很愚蠢,我也会非常非常感谢您的指导。
好问题,你可以根据这里的建议进行调整
https://machinelearning.org.cn/faq/single-faq/how-to-develop-forecast-models-for-multiple-sites
先生,您好,
你的博客很有信息量。
我的问题是如何找到这个模型的准确性?
你无法为回归计算准确性,你必须计算误差,更多细节请看这里
https://machinelearning.org.cn/faq/single-faq/how-do-i-calculate-accuracy-for-regression
Jason,感谢您的帖子,我非常喜欢,清晰明了。我有一个关于 GPU 与 CPU 性能的问题。我最初在 CPU 上运行了示例,当我注意到它花费的时间太长时,我安装了 tensorflow-gpu 并改用 Nvidia RTX2070 卡,但仍然没有看到太多改进。据我所知,我正在使用 GPU,但遍历每个 epoch 仍然需要很长时间。是什么原因或者我如何提高性能?我以前用 CNN 和 Pytorch 工作过,注意到 CPU 和 GPU 性能之间有很大差异,因此,我不认为这是显卡的问题。
再次感谢,
是的。LSTM 的性能通常不会通过 GPU 得到改善。
你可以尝试探索一些展开参数,这些参数会占用更多内存但会提高执行速度。
你好 Jason,
我有一个问题,如何预测三年后的未来 12 个月?我应该使用什么样的代码和输入?
希望你能帮我!
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/how-do-you-use-lstms-for-multi-step-time-series-forecasting
你好,我一直在尝试绘制损失函数;我在第 126 行添加了这些代码行。代码如下:
training_loss = lstm_model.history.history[‘loss’]
epoch_count = range(1, len(training_loss) + 1)
pyplot.plot(epoch_count, training_loss, ‘r–‘)
pyplot.legend([‘Training Loss’, ‘Test Loss’])
pyplot.xlabel(‘Epoch’)
pyplot.ylabel(‘Loss’)
pyplot.show()
但是,我一直得到一个空白的损失函数;我该如何编辑之前的/这些代码行来绘制损失函数?
也许可以确认 history 对象是否包含你期望的数据?
嗨,Jason,
我尝试修改 lag size(例如,窗口大小为 3)在上面的代码中,但我遇到了 ValueError:cannot reshape array of size of…
代码似乎相当适应。你知道为什么会这样吗?
Vusal
目前还不确定,你可能需要调试一下。
你好,我可以在我的研究工作中应用这种 LSTM 模型吗?该研究是:
训练阶段:我将提供输入和输出信号,都是一维时间序列。
测试用例:我将提供输入信号,并希望模型根据它在训练阶段学到的知识来预测输出信号。
这听起来是一个很棒的项目。
也许可以尝试 LSTM 并比较结果?
嗨 Jason
我看了你很多文章,尤其是 LSTM。有基于测试集的预测,我们有直到 t-1 的值,然后我们预测 ‘t’ 值。但我想了解如何预测未来 1 个月或 10 天?
我尝试将预测值作为输入馈送给模型,但这导致输出平坦,方差丢失。
请看这些例子
https://machinelearning.org.cn/faq/single-faq/how-do-you-use-lstms-for-multi-step-time-series-forecasting
非常感谢这篇文章。如果我想根据此模型预测我没有数据的事例,该怎么办?
我的意思是,预测当前数据集中不存在的未来日期。
使用 predict() 函数,输入是你想要预测的那个时期之前的。
没有输入(因为它是单变量的)。我只有日期索引,在我的目标值位置是“nan”值,因为事件还没有发生。通过将数据分成训练集和测试集来进行预测很容易,因为这些数据在该时期是可用的。
不太对。
时间序列被框架为监督学习问题,有输入和输出,例如,模型接收一些先前的观测值并用它来预测未来的观测值。
这适用于所有预测模型。
更多信息请看这里:
https://machinelearning.org.cn/time-series-forecasting-supervised-learning/
我想要实现的是投影到我的训练集和测试集之外。
是的,我理解了并已相应回答。
也许从这个开始以了解基础知识
https://machinelearning.org.cn/start-here/#timeseries
我理解这个过程。使用监督方法意味着我需要有 X 来预测我想要在... 中预测的内容,而这个 X 实际上仍然是从值中获得的。您关于监督时间序列的文章解释了这一点。这意味着如果我要预测非样本数据集,我仍然需要我正在尝试预测的结果。
不。结果仅用于训练模型——例如历史数据。
要进行预测,即使是多步预测,您只需要模型的输入。
您可以选择如何构建问题。将其构建为仅使用您在预测时可用的数据。
我忘记提了,我处理的是单变量数据集。所以我拥有的唯一输入是日期,它将是我的索引。这就是我问的原因,因为对于单变量,我似乎无法绕过我的输入 (X) 将是什么用于非样本数据集。
索引/日期/时间被删除,您只处理观测序列。
你好,我只是按照你在 https://machinelearning.org.cn/how-to-develop-lstm-models-for-time-series-forecasting/ (多变量 LSTM 模型 - 多输入)中的说明和代码操作。并且我设置了步长 = 3,特征 = 3,向前预测 3 天的 1 个输出。从结果来看,预测的输出看起来(略有不同)与实际输出相似,但它被向前(延迟)移动了大约 1-3 天。有什么问题吗?或者我需要像这篇帖子一样添加 reset_state?这两个代码(多变量多输入 vs. 这篇帖子)之间有什么区别?(在 LSTM 部分)。谢谢
我相信模型学会了一个持续预测
https://machinelearning.org.cn/faq/single-faq/why-is-my-forecasted-time-series-right-behind-the-actual-time-series
第一个例子,我该如何输入,我应该把什么放在 x 的位置
parser(x)
尽管我将数据保存在了 Excel 中,但我还是没能找到。
如果您的日期时间格式正确,您可能不需要它。例如,read_csv 函数可以为您解析日期。
谢谢你的回答,现在我遇到了另一个问题,那就是如果我把执行文件放到那里,它会告诉我“Data_Digital_Currencies .csv”不存在:b’Data_Digital_Currencies .csv’
我把所有数据都保存在同一个文件夹里
from pandas import read_csv
from pandas import datetime
from matplotlib import pyplot
# 加载数据集
def parser(x)
return datetime.strptime( ‘%Y-%m’)
series = read_csv(‘Data_Digital_Currencies .csv’, header=0, parse_dates=[0], index_col=0, squeeze=True)
# 总结前几行
print(series.head())
# 线图
series.plot()
pyplot.show()
确保数据文件与您的代码文件位于同一目录中,或者指定文件的完整路径。
你好 Jason,
我想知道是否可以使用 LSTM 预测多输出时间序列,从多输入时间序列数据(例如,如果我有 10 个输入属性和 4 个输出属性在时间序列中)?您是否有关于此类建模的博客?
是的,您可以在这里开始学习简单示例。
https://machinelearning.org.cn/how-to-develop-lstm-models-for-time-series-forecasting/
这里有更高级的示例。
https://machinelearning.org.cn/start-here/#deep_learning_time_series
你好 Jason。祝贺您的伟大网站。我有一个问题想问您,我也在 Stack Overflow 上提问了(https://stackoverflow.com/questions/60669182/forecasting-with-multilayer-perceptron)。为什么我在测试集上进行预测时,预测效果很好,但当我进行预测时,预测值要么收敛到一个唯一值,要么发散?我尝试了许多模型(MLP、LSTM、GRU 等)。它们都会导致相同的问题。我认为是因为模型无法预测很多步。你怎么看?谢谢。
Luca。
是的,也许您的模型过度拟合了训练数据,或者没有能力。
可以尝试其他模型配置、其他模型类型等,并找出最适合您数据集的模型。请看这个。
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
嘿 Jason,这篇文章很棒。
我有一个疑问,是否可以在执行 shift() 函数之前对数据进行缩放?
因为在移位之后,数据被转换为 (len(data),2) 的形状。
然后在预测时,数据是 (len(data),1) 的形状。
所以我们必须编写一个复杂的 invert_scale 函数。
所以我们是否可以在移位之前进行缩放,这样可以省去编写复杂代码的麻烦,只需执行简单的 scaler.inverse_transform(prediction)?
是的,事情会变得非常棘手!
感谢您的精彩网站,
我可以使用这个模型(具有相同的编码结构)在我的数据集和我的超参数上吗?
您能否帮助我考虑一下如何使用不同于 1 的批次大小?
另一个问题是,您是否有关于自动超参数调整?和集成学习方法的课程?
也许可以。
我推荐这个过程
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
这里的教程将帮助您入门
https://machinelearning.org.cn/start-here/#deep_learning_time_series
嘿,感谢您的巨大帮助!
我想知道如何绘制此特定示例的训练损失与测试损失。我看了您通常在其他示例中是如何做的,但我无法使其正常工作。
我对 LSTM 还是有点陌生,所以如果您能帮助我,那将非常有帮助。
谢谢
Erik
这对于 LSTM 来说可能很困难,我预计您需要自己收集历史记录,或者更改模型拟合的方式。
非常感谢您的快速回复!
是的,你说对了,我改变了模型拟合的方式,它起作用了。
很棒的工作,感谢您提供这些指南!
祝好
Erik
干得好!
你好,
感谢这篇精彩的文章……我是一名时间序列预测新手,有一个重要的问题要问。
当我拟合模型并测试它时,它不会预测价格何时会上涨或下跌。当价格发生变化时,它会适应变化而不是预测它。例如,如果第 1 天的预期价格是 201,第 2 天的价格是 220,第 3 天是 200,它不会预测第 3 天的价格波动,而会在第 4 天显示出来……这就像模型复制了移动或者别的什么……请帮助我……我卡在这里,不知道问题出在哪里。谢谢。
我相信您的模型已学会持续预测模型。
https://machinelearning.org.cn/faq/single-faq/why-is-my-forecasted-time-series-right-behind-the-actual-time-series
非常感谢……你让我今天很开心🙂
不客气。
嗨
抱歉再次打扰……但我仍然在这件事上卡着……我无法摆脱持续预测,即使是改变数据或超参数……我不知道该怎么办……请帮帮我……
(还有另一个问题……我们是否可以使用 GRU 来预测股市,因为我没有遇到任何包含 GRU 用于股票预测的文章)
也许可以探索使用替代模型?
你好,
您能否提供一个如何增加窗口大小的例子,以预测下一个时间步。例如,与其只使用前一个值,我希望模型使用前 10 个值。
这需要对模型进行更改,称为多步预测。
https://machinelearning.org.cn/faq/single-faq/how-do-you-use-lstms-for-multi-step-time-series-forecasting
很棒的教程 Jason。
我计划预测测试数据之外的值,但陷入了困惑。如果您能提供一些关于预测未来未知值的代码片段,将非常有帮助,谢谢。
是的,请看这个
https://machinelearning.org.cn/make-sample-forecasts-arima-python/
这很棒 Jason。谢谢您的链接。
您能否提供一些与 LSTM 未知数据预测相关的链接?谢谢。
是的,在这里
https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
很棒的教程 Jason。
我有一个问题。
我们是对所有数据应用 difference() 然后将其拆分为训练集和测试集
还是先将数据拆分为训练集和测试集,然后仅对训练集进行差分?
没有正确答案,也许选择一个对您来说最容易处理且不会导致数据泄露的方法。
你好 Jason,非常感谢您提供的这篇精彩文章。我有一个关于 Persistence Model 的问题,如果它像 naif 模型一样工作,因为它们都要求前一个观测值来预测下一个观测值?
不客气。
什么是“naif”?
我很抱歉,我是说 naive 模型。
你好 Jason,感谢您的精彩帖子。我的问题是,只看回溯一步来使用 LSTM 有意义吗?或者只是为了举例说明。
谢谢
可能不是。总的来说,我建议测试一系列模型,并找出最适合您数据集的模型。
你好 Jason,非常感谢您的精彩帖子。我是一名初学者,如果有三个问题,我是否可以提问?
1. 在特征缩放中,当您进行 scaler_fit(train) 时,这是否意味着您将使用从训练数据拟合的 scaler 来缩放测试数据?
2. 您提到为了达到更好的准确度并最小化损失,我们可以调整我们的 LSTM 模型。如何为您的模型和数据找到最佳配置?
3. 如何添加 Dropout 层(在编码方面)以获得更好的正则化?
谢谢!
当我们用训练数据拟合 scaler 时,我们从训练数据集中估计 scaler 所需的属性。然后我们可以使用 scaler 来转换训练数据集、测试数据集和其他数据集。
https://machinelearning.org.cn/standardscaler-and-minmaxscaler-transforms-in-python/
找到模型好的/最佳配置的唯一方法是进行受控实验并测试许多超参数配置。
这是一个关于为 LSTM 添加 dropout 的示例。
https://machinelearning.org.cn/use-dropout-lstm-networks-time-series-forecasting/
非常感谢您的回复。
我明白测试很多超参数,但也许您有一个关于如何进行受控实验的例子?
谢谢!
是的,您可以在博客上看到许多示例,也许从这里开始。
https://machinelearning.org.cn/how-to-grid-search-deep-learning-models-for-time-series-forecasting/
嘿 Jason,您的网站太棒了!
我尝试将此模型用于更大的数据集(3774 行)并将测试集设置为 20%。但是,当我绘制预测值时,它们就像原始数据一样!这是否意味着模型过拟合了?有什么解决方案吗?干杯!
谢谢。
我建议测试一系列模型、模型配置和数据准备技术,以找出最适合您特定数据集的模型。
你好 Jason,我的问题是,如果我想尝试不同的学习率,我只需要将它放在 adam 旁边吗?例如,optimizer='adam(lr=n)'
谢谢!
您必须使用 SGD 来测试不同的学习率。
你好 Jason,很棒的教程!
我正在努力将您的差分(和逆差分)方法应用于多元数据。当只有一列数据时,它有效,但在有多个列时,我该如何修改?
谢谢,并继续做这项出色的工作!
您可以尝试一次转换一个变量,然后一旦您习惯了,就可以尝试简化代码以一次性完成所有操作。
感谢您的回复 Jason。
我已经弄清楚了如何对所有变量进行差分——使用 .diff(periods=n)。
然后我知道如何进行逆差分
例如,
data_differentiated.iloc[0] = normal_data.iloc[0]
data_inverted_back = data_diff.cumsum()
但是,在进行一步预测并进行缩放回之后,我难以实现这一点。您认为您可以帮助我吗?非常感谢!
谢谢
也许这会有帮助
https://machinelearning.org.cn/machine-learning-data-transforms-for-time-series-forecasting/
感谢您的回复。
我尝试遵循这篇帖子,但在使用我的多元数据时,我得到了与区间相关的内容,但我不知道如何正确修改它。有什么建议吗?
谢谢!
抱歉,我无法为您准备自定义代码。也许您可以从博客上的其他示例中学习,那里有几百个关于这个主题的例子,也许可以从这里开始
https://machinelearning.org.cn/start-here/#deep_learning_time_series
# 我得到
嗨,Jason,
我的数据集包含客户数量、销售额和日期。我同时使用了 LSTM 和 ARIMA,它们都对整个数据集有效,但我想按客户查找。我该如何做到?有其他方法吗?您能就这个问题指点我一下吗?
抱歉,我不明白您的问题,也许您可以重新表述一下?
嗨,Jason,
感谢您发布了这篇详尽且解释得很好的帖子。我想知道是否有办法添加一些协变量来帮助 LSTM 模型进行预测?或者是否有可能在 LSTM 中进行多维时间序列预测?谢谢。
是的,请看这里的例子
https://machinelearning.org.cn/how-to-develop-lstm-models-for-time-series-forecasting/
你好 Jason,
非常棒的帖子!谢谢你!!!
我有一个问题:假设我有以下代码
# 拟合模型
lstm_model = fit_lstm(train_scaled, 1, 3000, 4)
# 预测整个训练数据集以建立预测状态
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
train_predicted = lstm_model.predict(train_reshaped, batch_size=1)
其中 train_predicted 将包含训练数据的预测。现在我们需要进行逆缩放和逆差分。您提供的例程(invert_scale 和 inverse_difference)不能应用于“train_predicted”。您能否向我展示如何对“train_predicted”进行逆缩放和逆差分?
提前感谢!
不客气。
是的,请看这个
https://machinelearning.org.cn/machine-learning-data-transforms-for-time-series-forecasting/
嗨,
我见过一些不重置状态的例子。您推荐哪种?
谢谢。
我建议测试一套算法和算法配置,并找出最适合您特定数据集的方法。
在实践中,我没有在有状态和无状态 LSTM 之间看到太大差异。也许我进行模型训练的方式过于粗暴。
嗨,Jason,
您使用了一个长循环(前向预测)来预测每个输入,而您可以直接将预测函数传递给所有样本,它似乎会循环遍历它们并给出预测。无论循环是否用于遍历测试的每个输入,结果似乎都是相同的。如果我错了,请纠正我。
也许可以,只要数据不被打乱。
嗨,Jason,
非常感谢您的帖子。我想预测未来12个月,所以在我的测试数据中,我只有月份,但没有销售额。它只能预测第一个月,其余的显示为 NAN。所以看起来它也使用期望值作为输入。那么如何预测未来12个步骤而不是只预测1个步骤呢?
好问题。
一种方法是使用相同的模型,并将输出作为输入12次。
另一种方法是更改模型以直接预测12个步骤。
也许可以尝试这两种方法,看看哪种最适合您。
这将帮助您入门
https://machinelearning.org.cn/faq/single-faq/how-do-you-use-lstms-for-multi-step-time-series-forecasting
嗨,Jason,
非常感谢您的回复。我阅读了所有其他人的评论。看起来很多人都有和我相同的问题。我想知道您是否可以发布一个例子来预测未来多个步骤(不是测试数据)。我至少有以下两个问题(还有很多人也有):1. 如何继续使用输出作为输入来连续预测 2. 如何缩放预测数据并进行逆缩放(如果未来数据不在训练数据的缩放范围内怎么办?例如,我预计新冠病毒的总数会不断增长,我想预测的数字可能比训练数据大一百倍。如何进行缩放?)我将非常感谢您发布这样的示例。这将有助于回答许多人的问题。谢谢!
感谢您的建议。
博客上有几十个关于 LSTM 多步预测的例子。我建议您从它们开始。
如果您在数据缩放方面遇到困难,这会有所帮助
https://machinelearning.org.cn/machine-learning-data-transforms-for-time-series-forecasting/
谢谢 Jason。我知道您关于多步预测的精彩帖子。但它们都适用于测试数据。我认为我们正在寻找的是一个预测未来一段时间的示例,无论是单步还是多步方法。
在测试集上进行预测与在样本外数据上进行预测,代码完全相同。
如果对数据进行预测对您来说是新想法,这可能会有帮助
https://machinelearning.org.cn/how-to-make-classification-and-regression-predictions-for-deep-learning-models-in-keras/
你好,Jason。
我有一个相当简单的问题。
我们到底在哪里定义每个 LSTM 层中每个块的单元数?
我在您关于使用 Keras 实现 LSTM 的教程中都没有找到答案。
提前感谢。
LSTM 层有一个单元数,就像“神经元”或“节点”一样。单元和块不再被讨论。
非常感谢您的回复。
您是否有关于上述差异的教程或讨论中有用的链接?
如果没有,那么这些节点在这种情况下是如何相互作用的?
我完全赞赏您的帮助。
在这种情况下,我们将每个 LSTM 层视为一个由具有给定数量神经元的单元组成的块(就块和单元而言)吗?
节点之间不相互作用。
也许这会有帮助。
https://machinelearning.org.cn/faq/single-faq/how-is-data-processed-by-an-lstm
还有这个。
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
还有这些
https://machinelearning.org.cn/start-here/#lstm
非常感谢 Jason。
不客气。
你好 Jason,我有一个问题……
如何固定种子?
棘手的问题,请看这个
https://machinelearning.org.cn/reproducible-results-neural-networks-keras/
你好 Jason,我有一个问题……我对机器学习和 Python 以及 Anaconda 都很陌生……
我尝试了您在机器学习中的第一个例子(鸢尾花),它很容易跟进并在 Anaconda Powershell 提示符上应用命令。
但现在对于时间序列预测,在最开始的阶段,我在打开 .CSV 文件并将其定义为变量(series)时遇到了问题。我已按照您所说的将其保存在当前目录中,并且在提示符中搜索时可以看到它。直到 print(series.head())=> 我才出错,在这里我得到了这个错误
>>> # 总结前几行
>>> print(series.head())
回溯(最近一次调用)
File “”, line 1, in
NameError: name ‘series’ is not defined
我不知道为什么它没有定义包含 shampoosales.csv 值的 series 变量!
值得一提的是,我尝试通过 URL 输入我的 CSV 值,并且它成功显示了数据集的头部。
提前感谢您的回复,
Ronak
错误表明您可能跳过了一些代码行。
也许可以将代码保存在 .py 脚本文件中,并在命令行中运行,这将有所帮助
https://machinelearning.org.cn/faq/single-faq/how-do-i-run-a-script-from-the-command-line
嗨,Jason,
感谢您的教程。
您能(通过代码)解释一下如何使用此示例来预测未来 x 天的销售额,而不是您已知的数据(测试集)吗?
Mark。
是的,调用 model.predict()。
看这里
https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
还有这个。
https://machinelearning.org.cn/how-to-make-classification-and-regression-predictions-for-deep-learning-models-in-keras/
嗨,Jason,
感谢您提供更多链接,也抱歉我的经验不足。
我的做法是这样的
1)我将数据集分成两半(训练+测试)
2)我使用训练数据训练模型,并使用测试数据获得结果
testPredict = model.predict(testX)
结果是这样的:https://ibb.co/7pGQXXL
模型看起来不错。所以我去重新编写代码以能够预测未来值。
3)预测新值:我构建了一个函数,该函数可以获取历史记录(数据集的一半)并通过上述模型预测一个新值,然后获取该值,将其添加到历史记录中并重复,其中 steps_ahead 是我想要进行的预测总数。
for i in range(steps_ahead)
# 预测下一步
prediction = self.perform_prediction(history)
# 存储预测
model_predictions.append(prediction)
# 将预测添加到历史记录
next_index = history.tail(1).index.item() + timedelta(days=1)
history.loc[next_index, ‘Series name’] = round(prediction[-1][0])
不幸的是,结果是这样的:https://ibb.co/2hXZNtn
Q1)我完全困惑了。在 2)中,当您将测试集输入模型时,究竟发生了什么?模型会为测试集中的每个样本运行一次(内部),模拟 3)中的函数吗?
Q2)上面的问题引出了一个新问题。据我理解,预测是根据过去/现在获取未来值的过程。从这个角度来看,将测试集输入模型,会得到一个真正说明不了什么的结果,还是我错了?
任何帮助不胜感激。
抱歉文字太多了。
Mark
是的,模型会为每个样本运行一次。如果您使用的是 LSTM,它会一次处理一批样本,并在批次中的样本之间共享内部状态。
通常我们使用前向验证来评估预测模型
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
你好 Jason,我需要以训练集中的一个样本作为参数进行预测,我该如何进行逆差分?我不知道如何对单个样本进行逆差分。
谢谢你。
本教程有一个计算差分和逆差分的示例
https://machinelearning.org.cn/machine-learning-data-transforms-for-time-series-forecasting/
你好,我明白如何对整个数据集进行差分和逆差分,就像本教程所示。
但我不知道如何对 model.predict() 的结果进行逆差分,我不知道在这种情况下我应该做什么。
谢谢。
我相信您在谈论逆差分。其思想是,数据以 (y1-y0), (y2-y1) 等形式提供。而您想知道 y0, y1, y2, y3 等是什么。因此,要逆转差分,您知道 y0,然后不断加上差分项 (y1-y0) 来得到 y1,加上 (y2-y1) 来得到 y2,依此类推。
你好,我明白如何进行逆差分,但我不太明白这两种情况的区别
1. 对差分值进行逆差分
value = inverse_difference(series, differenced[i], len(series)-i)
(这出现在本博客的“Transform Time Series to Stationary”中)
2. 对预测结果进行逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
(这出现在本博客的 LSTM 完整示例中)
我想知道如何在第二种情况下进行逆差分。
谢谢
如果我理解正确,情况是这样的:我们有从时间 1 到 N 的已知数据,并训练了 LSTM 模型来预测 N+1 及以后的数据,但仅以差分形式。因此,以历史为输入,我们得到差分项(假设只预测下一个周期)。那么 N+1 的值是多少?我们需要取 x[N] 并加上输出,因为 yhat = x[N+1]-x[N]。那么 N+2 呢?如果我们假设我们从逆差分中得到的 x[N+1] 是正确的,并再次输入模型,我们会得到 yhat = x[N+2]-x[N+1],所以我们可以通过再次逆差分来找到 x[N+2]。
希望这有帮助。
你好 Jason,您的 LSTM 教程非常有帮助。我有一个关于 stateful 参数的快速问题。如果预测范围直接跟在用于训练的数据时间段之后,那么在训练和预测之间保持模型状态是否更好?它建立的状态应该对做出预测有用,对吗?
如果是,我是否可以简单地重新排列以下代码
for i in range(nb_epoch)
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
model.reset_states()
将 reset_states 方法调用移到 fit 之前,以便在训练的最后一个 epoch 中,模型只保持状态
for i in range(nb_epoch)
model.reset_states()
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
您的做法是可行的。这样做的问题是,您需要非常小心地控制训练何时结束。通常我们不这样做。因此,更安全的方法是重置状态并为其提供一些数据(即使它已用于训练)以重新建立状态并进行预测。
明白了,谢谢 Adrian。
你好 Jason,我有一个问题,这个例子可以预测 t+1 时刻的值。但如果我想预测从 t+1 到 t+5 的值,我应该如何修改代码?
每次调用 y = model.predict(x),获取输出 y 并将其作为 x 的最后一行,然后再次调用 predict()。这是多步预测最简单的方法。但要注意,当您使用预测输出来作为输入时,预测的时间越长,其准确性就应该越低。
你好,我有一个问题。你能给我们一个预测未来 3 或 6 个时间步的例子吗?我读过这篇帖子很多次了,但仍然不明白如何预测未来值……谢谢
你好,你能帮我反差分预测吗?我不知道我需要求和哪些值。
谢谢
不是求和,而是累积求和。如果您的数据是 x(一个 numpy 数组),那么一阶差分是 np.diff(x),您可以通过 x[0]+y.cumsum() 来获取 x(仅从第二个元素开始)。
我明白这个解决方案是针对正常预测的,但我正在进行一步预测,就像这篇帖子中的一样,所以在我的情况下,“y”将只有一个元素。
在这种情况下,有什么区别?
在进行一步预测时,我遇到了执行逆差分的问题,如果您能帮助我,我将非常感激。
您在那里的 y 将是 y=x(t+1)-x(t),而 x(t+1) 是您正在预测的值。因此,您需要找到 x(t),也就是输入序列中的最后一个值,并将其添加到您的 y 中。
Jason,非常感谢您的课程!
我有一个时间序列数据库,里面是汽车驾驶员(例如银行检查)的汽油消费记录。如何诊断购买行为的长时间中断是因为离开了加油站?
我想预测购买间隔时间。
谢谢。
我不确定是否理解正确,但可以尝试将数据处理为驾驶员访问加油站的次数以及上次访问至今的时间。这可能更容易让模型预测。
换句话说,我有这些买家的系列
买家 1
2018-01-02 100
2018-01-12 155
2018-02-04 150
2018-02-22 115
…
买家 2
2019-11-01 111
2018-11-21 98
2018-11-29 122
2018-12-03 150
…
如果我按日或周汇总,那么就会出现一个带有空格的序列
按月汇总呢?
差分会去除季节性吗?如果不会,我该如何去除它。
如果您谈论的是季节性,那么您已经假设了一个数据模型。如果您想去除季节性,可以通过另一个模型来实现(例如,在使用 LSTM 网络之前,使用 statsmodels 包中的 SARIMAX 函数),然后再输入 LSTM 网络。
你好 Joep…差分是一种流行且广泛使用的数据转换方法,用于使时间序列数据平稳。
请参考以下教程了解更多详情。
https://machinelearning.org.cn/remove-trends-seasonality-difference-transform-python/#:~:text=Differencing%20is%20a%20method%20of,%2C%20so%2Dcalled%20temporal%20dependence.&text=Differencing%20can%20help%20stabilize%20the,or%20reducing)
你好 Jason!感谢精彩的教程!我想知道我们需要对模型进行哪些更改才能在可用数据集之外进行预测?例如,这里有 36 个观测值,其中 24 个用于训练,12 个用于测试模型。那么我们如何进行第 36 个观测值之后的预测?(例如,假设是未来 12 个月)
你好 Anupam…您将修改下面的数字,从 -12 改为其他范围。
# 将数据分割为训练集和测试集 X = series.values train, test = X[0:-12], X[-12:]
你好 James。抱歉,我不太明白你的意思。
你好 Jason,非常感谢您提供的精彩教程,我的问题是在完整的 LSTM 示例的第 116 行:print(‘Month=%d, Predicted=%f, Expected=%f’ % (i+1, yhat, expected))
什么是 %d 和 %f,我该如何向普通人解释?
另外,我该如何从模型中获取预测值和预期值,以便用数字显示 LSTM 的准确性?(我想到的是;Accuracy = Expected/predicted)提前感谢!
你好 Adnan…以下资源可能有助于澄清
https://discuss.codecademy.com/t/how-do-we-use-the-python-string-formatters-d-and-f/357933
你好 James,感谢您提供的主题,这很有帮助。
我还有另一个问题,如果我想保存这个模型,我该怎么做?
我已经阅读了这篇帖子:https://machinelearning.org.cn/make-predictions-long-short-term-memory-models-keras/
但我希望将此帖子中的模型保存为文件。我能否在进行测试数据上的 # 步进验证(第 103 行)之前,直接执行 model.save(‘lstm_model.h5’) 来保存模型?提前感谢!
您好,我对 LSTM 的主题非常感兴趣。您真的帮了我很多。
我有一个问题,如何将 lookback 值从 1 个时间步更改为 3 个或更多?以及如何添加未来值?谢谢。
嗨
此代码现在看来已经相当过时了。很难回头找到所有协同工作的 Python 模块来完成此教程——例如 pandas 版本太旧了。例如,pandas 2.0 中没有 datetime,squeeze 也不是 read_csv 的有效参数等。是否有最新版本的代码?
另外,对于未来的教程,您能否提供 pip requirements.txt 文件,以便我们更容易地复制您的 Python 环境?网络上有很多代码,由于没有说明要使用哪个版本的 Python 模块,已经无法使用了。
谢谢。
您好 Marcus… 如果您在设置环境方面仍然遇到问题,请告知我们。以下资源可能对您有所帮助:
https://machinelearning.org.cn/setup-python-environment-machine-learning-deep-learning-anaconda/
https://machinelearning.org.cn/python-environment-time-series-forecasting/
哦天哪——我可以看到如何创建环境的说明,并且还提到了上面的一些版本——我应该先看的!!我会尝试这些说明。谢谢。
您好 Marcus… 不客气!请告诉我们您设置环境的进展如何。另外,在您设置好本地环境时,您仍然可以使用 Google Colab 继续进行。
在我的情况下,是根据上个月的特征来预测下个月的特征,但是,这些特征来自同一时期的不同观测值。那么,我应该使用哪种 LSTM?还是其他神经网络模型?
您好 jinjia T… 您可以考虑使用多变量 LSTM 模型。
https://machinelearning.org.cn/multivariate-time-series-forecasting-lstms-keras/