# 如何开发单变量时间序列预测的深度学习模型
> 原文: [https://machinelearningmastery.com/how-to-develop-deep-learning-models-for-univariate-time-series-forecasting/](https://machinelearningmastery.com/how-to-develop-deep-learning-models-for-univariate-time-series-forecasting/)
深度学习神经网络能够自动学习和从原始数据中提取特征。
神经网络的这一特征可用于时间序列预测问题,其中模型可以直接在原始观测上开发,而不需要使用归一化和标准化来扩展数据或通过差分使数据静止。
令人印象深刻的是,简单的深度学习神经网络模型能够进行熟练的预测,与朴素模型和调整 SARIMA 模型相比,单变量时间序列预测存在趋势和季节性成分且无需预处理的问题。
在本教程中,您将了解如何开发一套用于单变量时间序列预测的深度学习模型。
完成本教程后,您将了解:
* 如何使用前向验证开发一个强大的测试工具来评估神经网络模型的表现。
* 如何开发和评估简单多层感知器和卷积神经网络的时间序列预测。
* 如何开发和评估 LSTM,CNN-LSTM 和 ConvLSTM 神经网络模型用于时间序列预测。
让我们开始吧。
![How to Develop Deep Learning Models for Univariate Time Series Forecasting](https://img.kancloud.cn/79/a6/79a64b43dbf2aed03ffcbb82791087d8_640x277.jpg)
如何开发单变量时间序列预测的深度学习模型
照片由 [Nathaniel McQueen](https://www.flickr.com/photos/nmcqueenphotography/40518405705/) ,保留一些权利。
## 教程概述
本教程分为五个部分;他们是:
1. 问题描述
2. 模型评估测试线束
3. 多层感知器模型
4. 卷积神经网络模型
5. 循环神经网络模型
## 问题描述
'_ 月度汽车销售 _'数据集总结了 1960 年至 1968 年间加拿大魁北克省的月度汽车销量。
您可以从 [DataMarket](https://datamarket.com/data/set/22n4/monthly-car-sales-in-quebec-1960-1968#!ds=22n4&display=line) 了解有关数据集的更多信息。
直接从这里下载数据集:
* [month-car-sales.csv](https://raw.githubusercontent.com/jbrownlee/Datasets/master/monthly-car-sales.csv)
在当前工作目录中使用文件名“ _monthly-car-sales.csv_ ”保存文件。
我们可以使用函数 _read_csv()_ 将此数据集作为 Pandas 系列加载。
```py
# load
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
```
加载后,我们可以总结数据集的形状,以确定观察的数量。
```py
# summarize shape
print(series.shape)
```
然后我们可以创建该系列的线图,以了解该系列的结构。
```py
# plot
pyplot.plot(series)
pyplot.show()
```
我们可以将所有这些结合在一起;下面列出了完整的示例。
```py
# load and plot dataset
from pandas import read_csv
from matplotlib import pyplot
# load
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
# summarize shape
print(series.shape)
# plot
pyplot.plot(series)
pyplot.show()
```
首先运行该示例将打印数据集的形状。
```py
(108, 1)
```
该数据集是每月一次,有 9 年或 108 次观测。在我们的测试中,将使用去年或 12 个观测值作为测试集。
创建线图。数据集具有明显的趋势和季节性成分。季节性成分的期限可能是六个月或 12 个月。
![Line Plot of Monthly Car Sales](https://img.kancloud.cn/79/4e/794e2be5483d741bc2f967eb2e8b9722_1280x960.jpg)
月度汽车销售线图
从之前的实验中,我们知道一个幼稚的模型可以通过取预测月份的前三年的观测值的中位数来实现 1841.155 的均方根误差或 RMSE;例如:
```py
yhat = median(-12, -24, -36)
```
负指数是指相对于预测月份的历史数据末尾的序列中的观察值。
从之前的实验中,我们知道 SARIMA 模型可以达到 1551.842 的 RMSE,其配置为 SARIMA(0,0,0),(1,1,0),12 其中没有为趋势指定元素和季节性差异计算周期为 12,并使用一个季节的 AR 模型。
朴素模型的表现为被认为熟练的模型提供了下限。任何在过去 12 个月内达到低于 1841.155 的预测表现的模型都具有技巧。
SARIMA 模型的表现可以衡量问题的良好模型。任何在过去 12 个月内达到预测表现低于 1551.842 的模型都应采用 SARIMA 模型。
现在我们已经定义了模型技能的问题和期望,我们可以看看定义测试工具。
## 模型评估测试线束
在本节中,我们将开发一个测试工具,用于开发和评估不同类型的神经网络模型,用于单变量时间序列预测。
本节分为以下几部分:
1. 训练 - 测试分裂
2. 系列作为监督学习
3. 前瞻性验证
4. 重复评估
5. 总结表现
6. 工作示例
### 训练 - 测试分裂
第一步是将加载的系列分成训练和测试集。
我们将使用前八年(96 个观测值)进行训练,最后 12 个用于测试集。
下面的 _train_test_split()_ 函数将拆分系列,将原始观察值和在测试集中使用的观察数作为参数。
```py
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test], data[-n_test:]
```
### 系列作为监督学习
接下来,我们需要能够将单变量观测系列框架化为监督学习问题,以便我们可以训练神经网络模型。
系列的监督学习框架意味着需要将数据拆分为模型从中学习和概括的多个示例。
每个样本必须同时具有输入组件和输出组件。
输入组件将是一些先前的观察,例如三年或 36 个时间步骤。
输出组件将是下个月的总销售额,因为我们有兴趣开发一个模型来进行一步预测。
我们可以使用 pandas DataFrame 上的 [shift()函数](http://pandas-docs.github.io/pandas-docs-travis/generated/pandas.DataFrame.shift.html)来实现它。它允许我们向下移动一列(向前移动)或向后移动(向后移动)。我们可以将该系列作为一列数据,然后创建列的多个副本,向前或向后移动,以便使用我们需要的输入和输出元素创建样本。
当一个系列向下移动时,会引入 _NaN_ 值,因为我们没有超出系列开头的值。
例如,系列定义为列:
```py
(t)
1
2
3
4
```
可以预先移位和插入列:
```py
(t-1), (t)
Nan, 1
1, 2
2, 3
3, 4
4 NaN
```
我们可以看到,在第二行,值 1 作为输入提供,作为前一时间步的观察,2 是系列中可以预测的下一个值,或者当 1 是预测模型时要学习的值作为输入呈现。
可以去除具有 _NaN_ 值的行。
下面的 _series_to_supervised()_ 函数实现了这种行为,允许您指定输入中使用的滞后观察数和每个样本的输出中使用的数。它还将删除具有 _NaN_ 值的行,因为它们不能用于训练或测试模型。
```py
# transform list into supervised learning format
def series_to_supervised(data, n_in=1, n_out=1):
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
agg.dropna(inplace=True)
return agg.values
```
### 前瞻性验证
可以使用[前进验证](https://machinelearningmastery.com/backtest-machine-learning-models-time-series-forecasting/)在测试集上评估时间序列预测模型。
前瞻性验证是一种方法,其中模型一次一个地对测试数据集中的每个观察进行预测。在对测试数据集中的时间步长进行每个预测之后,将预测的真实观察结果添加到测试数据集并使其可用于模型。
在进行后续预测之前,可以使用观察结果更简单的模型。考虑到更高的计算成本,更复杂的模型,例如神经网络,不会被改装。
然而,时间步骤的真实观察可以用作输入的一部分,用于在下一个时间步骤上进行预测。
首先,数据集分为训练集和测试集。我们将调用 _train_test_split()_ 函数来执行此拆分并传入预先指定数量的观察值以用作测试数据。
对于给定配置,模型将适合训练数据集一次。
我们将定义一个通用的 _model_fit()_ 函数来执行此操作,可以为我们稍后可能感兴趣的给定类型的神经网络填充该操作。该函数获取训练数据集和模型配置,并返回准备好进行预测的拟合模型。
```py
# fit a model
def model_fit(train, config):
return None
```
枚举测试数据集的每个时间步。使用拟合模型进行预测。
同样,我们将定义一个名为 _model_predict()_ 的通用函数,它采用拟合模型,历史和模型配置,并进行单个一步预测。
```py
# forecast with a pre-fit model
def model_predict(model, history, config):
return 0.0
```
将预测添加到预测列表中,并将来自测试集的真实观察结果添加到用训练数据集中的所有观察结果播种的观察列表中。此列表在前向验证的每个步骤中构建,允许模型使用最新历史记录进行一步预测。
然后可以将所有预测与测试集中的真实值进行比较,并计算误差测量值。
我们将计算预测和真实值之间的均方根误差或 RMSE。
RMSE 计算为预测值与实际值之间的平方差的平均值的平方根。 _measure_rmse()_ 使用 [mean_squared_error()scikit-learn 函数](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html)在计算平方根之前首先计算均方误差或 MSE。
```py
# root mean squared error or rmse
def measure_rmse(actual, predicted):
return sqrt(mean_squared_error(actual, predicted))
```
下面列出了将所有这些联系在一起的完整 _walk_forward_validation()_ 函数。
它采用数据集,用作测试集的观察数量以及模型的配置,并返回测试集上模型表现的 RMSE。
```py
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test, cfg):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# fit model
model = model_fit(train, cfg)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# fit model and make forecast for history
yhat = model_predict(model, history, cfg)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# estimate prediction error
error = measure_rmse(test, predictions)
print(' > %.3f' % error)
return error
```
### 重复评估
神经网络模型是随机的。
这意味着,在给定相同的模型配置和相同的训练数据集的情况下,每次训练模型时将产生不同的内部权重集,这反过来将具有不同的表现。
这是一个好处,允许模型自适应并找到复杂问题的高表现配置。
在评估模型的表现和选择用于进行预测的最终模型时,这也是一个问题。
为了解决模型评估问题,我们将通过前向验证多次评估模型配置,并将错误报告为每次评估的平均误差。
对于大型神经网络而言,这并不总是可行的,并且可能仅适用于能够在几分钟或几小时内完成的小型网络。
下面的 _repeat_evaluate()_ 函数实现了这一点,并允许将重复次数指定为默认为 30 的可选参数,并返回模型表现得分列表:在本例中为 RMSE 值。
```py
# repeat evaluation of a config
def repeat_evaluate(data, config, n_test, n_repeats=30):
# fit and evaluate the model n times
scores = [walk_forward_validation(data, n_test, config) for _ in range(n_repeats)]
return scores
```
### 总结表现
最后,我们需要从多个重复中总结模型的表现。
我们将首先使用汇总统计汇总表现,特别是平均值和标准差。
我们还将使用盒子和须状图绘制模型表现分数的分布,以帮助了解表现的传播。
下面的 _summarize_scores()_ 函数实现了这一点,取了评估模型的名称和每次重复评估的分数列表,打印摘要并显示图表。
```py
# summarize model performance
def summarize_scores(name, scores):
# print a summary
scores_m, score_std = mean(scores), std(scores)
print('%s: %.3f RMSE (+/- %.3f)' % (name, scores_m, score_std))
# box and whisker plot
pyplot.boxplot(scores)
pyplot.show()
```
### 工作示例
现在我们已经定义了测试工具的元素,我们可以将它们绑定在一起并定义一个简单的持久性模型。
具体而言,我们将计算先前观察的子集相对于预测时间的中值。
我们不需要拟合模型,因此 _model_fit()_ 函数将被实现为简单地返回 _ 无 _。
```py
# fit a model
def model_fit(train, config):
return None
```
我们将使用配置来定义先前观察中的索引偏移列表,该列表相对于将被用作预测的预测时间。例如,12 将使用 12 个月前(-12)相对于预测时间的观察。
```py
# define config
config = [12, 24, 36]
```
可以实现 model_predict()函数以使用此配置来收集观察值,然后返回这些观察值的中值。
```py
# forecast with a pre-fit model
def model_predict(model, history, config):
values = list()
for offset in config:
values.append(history[-offset])
return median(values)
```
下面列出了使用简单持久性模型使用框架的完整示例。
```py
# persistence
from math import sqrt
from numpy import mean
from numpy import std
from pandas import DataFrame
from pandas import concat
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from matplotlib import pyplot
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test], data[-n_test:]
# transform list into supervised learning format
def series_to_supervised(data, n_in=1, n_out=1):
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
agg.dropna(inplace=True)
return agg.values
# root mean squared error or rmse
def measure_rmse(actual, predicted):
return sqrt(mean_squared_error(actual, predicted))
# difference dataset
def difference(data, interval):
return [data[i] - data[i - interval] for i in range(interval, len(data))]
# fit a model
def model_fit(train, config):
return None
# forecast with a pre-fit model
def model_predict(model, history, config):
values = list()
for offset in config:
values.append(history[-offset])
return median(values)
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test, cfg):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# fit model
model = model_fit(train, cfg)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# fit model and make forecast for history
yhat = model_predict(model, history, cfg)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# estimate prediction error
error = measure_rmse(test, predictions)
print(' > %.3f' % error)
return error
# repeat evaluation of a config
def repeat_evaluate(data, config, n_test, n_repeats=30):
# fit and evaluate the model n times
scores = [walk_forward_validation(data, n_test, config) for _ in range(n_repeats)]
return scores
# summarize model performance
def summarize_scores(name, scores):
# print a summary
scores_m, score_std = mean(scores), std(scores)
print('%s: %.3f RMSE (+/- %.3f)' % (name, scores_m, score_std))
# box and whisker plot
pyplot.boxplot(scores)
pyplot.show()
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
data = series.values
# data split
n_test = 12
# define config
config = [12, 24, 36]
# grid search
scores = repeat_evaluate(data, config, n_test)
# summarize scores
summarize_scores('persistence', scores)
```
运行该示例将打印在最近 12 个月的数据中使用前向验证评估的模型的 RMSE。
该模型被评估 30 次,但由于该模型没有随机元素,因此每次得分相同。
```py
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
> 1841.156
persistence: 1841.156 RMSE (+/- 0.000)
```
我们可以看到模型的 RMSE 是 1841,提供了表现的下限,通过它我们可以评估模型是否熟练掌握问题。
![Box and Whisker Plot of Persistence RMSE Forecasting Car Sales](https://img.kancloud.cn/d4/e1/d4e126114218898e9a884b734ae36dce_1280x960.jpg)
持久性 RMSE 预测汽车销售的盒子和晶须图
既然我们拥有强大的测试工具,我们就可以用它来评估一套神经网络模型。
## 多层感知器模型
我们将评估的第一个网络是多层感知器,简称 MLP。
这是一个简单的前馈神经网络模型,应该在考虑更复杂的模型之前进行评估。
MLP 可用于时间序列预测,方法是在先前时间步骤中进行多次观测,称为滞后观测,并将其用作输入要素并根据这些观测预测一个或多个时间步长。
这正是上一节中 _series_to_supervised()_ 函数提供的问题的框架。
因此,训练数据集是样本列表,其中每个样本在预测时间之前的几个月具有一定数量的观察,并且预测是序列中的下个月。例如:
```py
X, y
month1, month2, month3, month4
month2, month3, month4, month5
month3, month4, month5, month6
...
```
该模型将尝试概括这些样本,以便当提供超出模型已知的新样本时,它可以预测有用的东西;例如:
```py
X, y
month4, month5, month6, ???
```
我们将使用 Keras 深度学习库实现一个简单的 MLP。
该模型将具有输入层,其具有一些先前的观察结果。当我们定义第一个隐藏层时,可以使用 _input_dim_ 参数指定。该模型将具有单个隐藏层,其具有一定数量的节点,然后是单个输出层。
我们将在隐藏层上使用经过校正的线性激活函数,因为它表现良好。我们将在输出层使用线性激活函数(默认值),因为我们正在预测连续值。
网络的损失函数将是均方误差损失或 MSE,我们将使用随机梯度下降的高效 [Adam 风格来训练网络。](https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/)
```py
# define model
model = Sequential()
model.add(Dense(n_nodes, activation='relu', input_dim=n_input))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
```
该模型将适合一些训练时期(对训练数据的暴露),并且可以指定批量大小以定义在每个时期内权重的更新频率。
下面列出了用于在训练数据集上拟合 MLP 模型的 _model_fit()_ 函数。
该函数要求配置为具有以下配置超参数的列表:
* **n_input** :用作模型输入的滞后观察数。
* **n_nodes** :隐藏层中使用的节点数。
* **n_epochs** :将模型公开给整个训练数据集的次数。
* **n_batch** :更新权重的时期内的样本数。
```py
# fit a model
def model_fit(train, config):
# unpack config
n_input, n_nodes, n_epochs, n_batch = config
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
# define model
model = Sequential()
model.add(Dense(n_nodes, activation='relu', input_dim=n_input))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
```
使用拟合 MLP 模型进行预测与调用 _predict()_ 函数并传入进行预测所需的一个样本值输入值一样简单。
```py
yhat = model.predict(x_input, verbose=0)
```
为了使预测超出已知数据的限制,这要求将最后 n 个已知观察值作为数组并用作输入。
_predict()_ 函数在进行预测时需要一个或多个输入样本,因此提供单个样本需要阵列具有[ _1,n_input_ ]形状,其中 _] n_input_ 是模型期望作为输入的时间步数。
类似地, _predict()_ 函数返回一个预测数组,每个样本一个作为输入提供。在一个预测的情况下,将存在具有一个值的数组。
下面的 _model_predict()_ 函数实现了这种行为,将模型,先前观察和模型配置作为参数,制定输入样本并进行一步预测,然后返回。
```py
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_input, _, _, _ = config
# prepare data
x_input = array(history[-n_input:]).reshape(1, n_input)
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
```
我们现在拥有在月度汽车销售数据集上评估 MLP 模型所需的一切。
进行模型超参数的简单网格搜索,并选择下面的配置。这可能不是最佳配置,但却是最好的配置。
* **n_input** :24(例如 24 个月)
* **n_nodes** :500
* **n_epochs** :100
* **n_batch** :100
此配置可以定义为列表:
```py
# define config
config = [24, 500, 100, 100]
```
请注意,当训练数据被构建为监督学习问题时,只有 72 个样本可用于训练模型。
使用 72 或更大的批量大小意味着使用批量梯度下降而不是小批量梯度下降来训练模型。这通常用于小数据集,并且意味着在每个时期结束时执行权重更新和梯度计算,而不是在每个时期内多次执行。
完整的代码示例如下所示。
```py
# evaluate mlp
from math import sqrt
from numpy import array
from numpy import mean
from numpy import std
from pandas import DataFrame
from pandas import concat
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from matplotlib import pyplot
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test], data[-n_test:]
# transform list into supervised learning format
def series_to_supervised(data, n_in=1, n_out=1):
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
agg.dropna(inplace=True)
return agg.values
# root mean squared error or rmse
def measure_rmse(actual, predicted):
return sqrt(mean_squared_error(actual, predicted))
# fit a model
def model_fit(train, config):
# unpack config
n_input, n_nodes, n_epochs, n_batch = config
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
# define model
model = Sequential()
model.add(Dense(n_nodes, activation='relu', input_dim=n_input))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_input, _, _, _ = config
# prepare data
x_input = array(history[-n_input:]).reshape(1, n_input)
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test, cfg):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# fit model
model = model_fit(train, cfg)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# fit model and make forecast for history
yhat = model_predict(model, history, cfg)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# estimate prediction error
error = measure_rmse(test, predictions)
print(' > %.3f' % error)
return error
# repeat evaluation of a config
def repeat_evaluate(data, config, n_test, n_repeats=30):
# fit and evaluate the model n times
scores = [walk_forward_validation(data, n_test, config) for _ in range(n_repeats)]
return scores
# summarize model performance
def summarize_scores(name, scores):
# print a summary
scores_m, score_std = mean(scores), std(scores)
print('%s: %.3f RMSE (+/- %.3f)' % (name, scores_m, score_std))
# box and whisker plot
pyplot.boxplot(scores)
pyplot.show()
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
data = series.values
# data split
n_test = 12
# define config
config = [24, 500, 100, 100]
# grid search
scores = repeat_evaluate(data, config, n_test)
# summarize scores
summarize_scores('mlp', scores)
```
运行该示例为模型的 30 次重复评估中的每一次打印 RMSE。
在运行结束时,报告的平均和标准偏差 RMSE 约为 1,526 销售。
我们可以看到,平均而言,所选配置的表现优于朴素模型(1841.155)和 SARIMA 模型(1551.842)。
这是令人印象深刻的,因为该模型直接对原始数据进行操作而不进行缩放或数据静止。
```py
> 1629.203
> 1642.219
> 1472.483
> 1662.055
> 1452.480
> 1465.535
> 1116.253
> 1682.667
> 1642.626
> 1700.183
> 1444.481
> 1673.217
> 1602.342
> 1655.895
> 1319.387
> 1591.972
> 1592.574
> 1361.607
> 1450.348
> 1314.529
> 1549.505
> 1569.750
> 1427.897
> 1478.926
> 1474.990
> 1458.993
> 1643.383
> 1457.925
> 1558.934
> 1708.278
mlp: 1526.688 RMSE (+/- 134.789)
```
创建 RMSE 分数的方框和胡须图,以总结模型表现的传播。
这有助于理解分数的传播。我们可以看到,尽管平均而言模型的表现令人印象深刻,但传播幅度很大。标准偏差略大于 134 销售额,这意味着更糟糕的案例模型运行,误差与平均误差相差 2 或 3 个标准差可能比朴素模型差。
使用 MLP 模型的一个挑战是如何利用更高的技能并在多次运行中最小化模型的方差。
该问题通常适用于神经网络。您可以使用许多策略,但最简单的方法可能就是在所有可用数据上训练多个最终模型,并在进行预测时在集合中使用它们,例如:预测是 10 到 30 个模型的平均值。
![Box and Whisker Plot of Multilayer Perceptron RMSE Forecasting Car Sales](https://img.kancloud.cn/27/aa/27aa1b2ac190be534d507a8f7b5f9351_1280x960.jpg)
多层感知器 RMSE 预测汽车销售的盒子和晶须图
## 卷积神经网络模型
卷积神经网络(CNN)是为二维图像数据开发的一种神经网络,尽管它们可用于一维数据,例如文本序列和时间序列。
当对一维数据进行操作时,CNN 读取一系列滞后观察并学习提取与进行预测相关的特征。
我们将定义具有两个卷积层的 CNN,用于从输入序列中提取特征。每个都将具有可配置数量的滤波器和内核大小,并将使用经过整流的线性激活功能。滤波器的数量决定了读取和投影加权输入的并行字段的数量。内核大小定义了网络沿输入序列读取时每个快照内读取的时间步数。
```py
model.add(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu', input_shape=(n_input, 1)))
model.add(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu'))
```
在卷积层之后使用最大池化层将加权输入特征提取为最显着的特征,将输入大小减小 1/4。汇总输入在被解释之前被平展为一个长向量,并用于进行一步预测。
```py
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(1))
```
CNN 模型期望输入数据采用多个样本的形式,其中每个样本具有多个输入时间步长,与上一节中的 MLP 相同。
一个区别是 CNN 可以在每个时间步骤支持多个特征或类型的观察,其被解释为图像的通道。我们在每个时间步都只有一个特征,因此输入数据所需的三维形状将是[ _n_samples,n_input,1_ ]。
```py
train_x = train_x.reshape((train_x.shape[0], train_x.shape[1], 1))
```
下面列出了用于在训练数据集上拟合 CNN 模型的 _model_fit()_ 函数。
该模型将以下五个配置参数作为列表:
* **n_input** :用作模型输入的滞后观察数。
* **n_filters** :并行滤波器的数量。
* **n_kernel** :每次读取输入序列时考虑的时间步数。
* **n_epochs** :将模型公开给整个训练数据集的次数。
* **n_batch** :更新权重的时期内的样本数。
```py
# fit a model
def model_fit(train, config):
# unpack config
n_input, n_filters, n_kernel, n_epochs, n_batch = config
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], train_x.shape[1], 1))
# define model
model = Sequential()
model.add(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu', input_shape=(n_input, 1)))
model.add(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
```
使用拟合 CNN 模型进行预测非常类似于使用上一节中的拟合 MLP 模型进行预测。
一个区别在于我们要求我们指定在每个时间步骤观察到的特征数量,在这种情况下为 1.因此,当进行单个一步预测时,输入数组的形状必须是:
```py
[1, n_input, 1]
```
下面的 _model_predict()_ 函数实现了这种行为。
```py
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_input, _, _, _, _ = config
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_input, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
```
进行模型超参数的简单网格搜索,并选择下面的配置。这不是最佳配置,但却是最好的配置。
所选配置如下:
* **n_input** :36(例如 3 年或 3 * 12)
* **n_filters** :256
* **n_kernel** :3
* **n_epochs** :100
* **n_batch** :100(例如批量梯度下降)
这可以指定为如下列表:
```py
# define config
config = [36, 256, 3, 100, 100]
```
将所有这些结合在一起,下面列出了完整的示例。
```py
# evaluate cnn
from math import sqrt
from numpy import array
from numpy import mean
from numpy import std
from pandas import DataFrame
from pandas import concat
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers.convolutional import Conv1D
from keras.layers.convolutional import MaxPooling1D
from matplotlib import pyplot
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test], data[-n_test:]
# transform list into supervised learning format
def series_to_supervised(data, n_in=1, n_out=1):
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
agg.dropna(inplace=True)
return agg.values
# root mean squared error or rmse
def measure_rmse(actual, predicted):
return sqrt(mean_squared_error(actual, predicted))
# fit a model
def model_fit(train, config):
# unpack config
n_input, n_filters, n_kernel, n_epochs, n_batch = config
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], train_x.shape[1], 1))
# define model
model = Sequential()
model.add(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu', input_shape=(n_input, 1)))
model.add(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_input, _, _, _, _ = config
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_input, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test, cfg):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# fit model
model = model_fit(train, cfg)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# fit model and make forecast for history
yhat = model_predict(model, history, cfg)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# estimate prediction error
error = measure_rmse(test, predictions)
print(' > %.3f' % error)
return error
# repeat evaluation of a config
def repeat_evaluate(data, config, n_test, n_repeats=30):
# fit and evaluate the model n times
scores = [walk_forward_validation(data, n_test, config) for _ in range(n_repeats)]
return scores
# summarize model performance
def summarize_scores(name, scores):
# print a summary
scores_m, score_std = mean(scores), std(scores)
print('%s: %.3f RMSE (+/- %.3f)' % (name, scores_m, score_std))
# box and whisker plot
pyplot.boxplot(scores)
pyplot.show()
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
data = series.values
# data split
n_test = 12
# define config
config = [36, 256, 3, 100, 100]
# grid search
scores = repeat_evaluate(data, config, n_test)
# summarize scores
summarize_scores('cnn', scores)
```
首先运行该示例,为每次重复的模型评估打印 RMSE。
在运行结束时,我们可以看到模型确实熟练,达到平均 RMSE 1,524.067,这比朴素模型,SARIMA 模型,甚至上一节中的 MLP 模型更好。
这是令人印象深刻的,因为该模型直接对原始数据进行操作而不进行缩放或数据静止。
分数的标准偏差很大,约为 57 个销售额,但却是前一部分 MLP 模型观察到的方差大小的 1/3。我们有信心在坏情况下(3 个标准偏差),模型 RMSE 将保持低于(优于)朴素模型的表现。
```py
> 1551.031
> 1495.743
> 1449.408
> 1526.017
> 1466.118
> 1566.535
> 1649.204
> 1455.782
> 1574.214
> 1541.790
> 1489.140
> 1506.035
> 1513.197
> 1530.714
> 1511.328
> 1471.518
> 1555.596
> 1552.026
> 1531.727
> 1472.978
> 1620.242
> 1424.153
> 1456.393
> 1581.114
> 1539.286
> 1489.795
> 1652.620
> 1537.349
> 1443.777
> 1567.179
cnn: 1524.067 RMSE (+/- 57.148)
```
创建分数的框和胡须图以帮助理解运行中的错误传播。
我们可以看到,差价看起来似乎偏向于更大的误差值,正如我们所预期的那样,尽管图的上部胡须(在这种情况下,最大误差不是异常值)仍然受限于 1,650 销售的 RMSE 。
![Box and Whisker Plot of Convolutional Neural Network RMSE Forecasting Car Sales](https://img.kancloud.cn/92/48/924879581330351e7d4981fdb7f3ea86_1280x960.jpg)
卷积神经网络 RMSE 预测汽车销售的盒子和晶须图
## 循环神经网络模型
循环神经网络或 RNN 是那些类型的神经网络,其使用来自先前步骤的网络输出作为输入以尝试跨序列数据自动学习。
长短期内存或 LSTM 网络是一种 RNN,其实现解决了在序列数据上训练 RNN 导致稳定模型的一般困难。它通过学习控制每个节点内的循环连接的内部门的权重来实现这一点。
尽管针对序列数据进行了开发, [LSTM 尚未证明在时间序列预测问题上有效](https://machinelearningmastery.com/suitability-long-short-term-memory-networks-time-series-forecasting/),其中输出是近期观测的函数,例如自动回归类型预测问题,例如汽车销售数据集。
然而,我们可以开发用于自回归问题的 LSTM 模型,并将其用作与其他神经网络模型进行比较的点。
在本节中,我们将探讨 LSTM 模型的三变量,用于单变量时间序列预测;他们是:
* **LSTM** :LSTM 网络原样。
* **CNN-LSTM** :学习输入功能的 CNN 网络和解释它们的 LSTM。
* **ConvLSTM** :CNN 和 LSTM 的组合,其中 LSTM 单元使用 CNN 的卷积过程读取输入数据。
### LSTM
LSTM 神经网络可用于单变量时间序列预测。
作为 RNN,它将一次一步地读取输入序列的每个时间步长。 LSTM 具有内部存储器,允许它在读取给定输入序列的步骤时累积内部状态。
在序列结束时,隐藏 LSTM 单元层中的每个节点将输出单个值。该值向量总结了 LSTM 从输入序列中学习或提取的内容。这可以在完成最终预测之前由完全连接的层解释。
```py
# define model
model = Sequential()
model.add(LSTM(n_nodes, activation='relu', input_shape=(n_input, 1)))
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
```
与 CNN 一样,LSTM 可以在每个时间步骤支持多个变量或功能。由于汽车销售数据集在每个时间步都只有一个值,我们可以将其固定为 1,既可以在 input_shape 参数[ _n_input,1_ ]中定义网络输入,也可以定义形状输入样本。
```py
train_x = train_x.reshape((train_x.shape[0], train_x.shape[1], 1))
```
与不一次一步读取序列数据的 MLP 和 CNN 不同,如果数据是静止的,LSTM 确实表现更好。这意味着执行差异操作以消除趋势和季节性结构。
对于汽车销售数据集,我们可以通过执行季节性调整来制作数据信息,即从每个观察值中减去一年前的值。
```py
adjusted = value - value[-12]
```
这可以针对整个训练数据集系统地执行。这也意味着必须放弃观察的第一年,因为我们没有前一年的数据来区分它们。
下面的 _ 差异()_ 函数将使提供的数据集与提供的偏移量不同,称为差异顺序,例如差异顺序。 12 前一个月的一年。
```py
# difference dataset
def difference(data, interval):
return [data[i] - data[i - interval] for i in range(interval, len(data))]
```
我们可以使差值顺序成为模型的超参数,并且只有在提供非零值的情况下才执行操作。
下面提供了用于拟合 LSTM 模型的 _model_fit()_ 函数。
该模型需要一个包含五个模型超参数的列表;他们是:
* **n_input** :用作模型输入的滞后观察数。
* **n_nodes** :隐藏层中使用的 LSTM 单元数。
* **n_epochs** :将模型公开给整个训练数据集的次数。
* **n_batch** :更新权重的时期内的样本数。
* **n_diff** :差值顺序或 0 如果不使用。
```py
# fit a model
def model_fit(train, config):
# unpack config
n_input, n_nodes, n_epochs, n_batch, n_diff = config
# prepare data
if n_diff > 0:
train = difference(train, n_diff)
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], train_x.shape[1], 1))
# define model
model = Sequential()
model.add(LSTM(n_nodes, activation='relu', input_shape=(n_input, 1)))
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
```
使用 LSTM 模型进行预测与使用 CNN 模型进行预测相同。
单个输入必须具有样本,时间步长和特征的三维结构,在这种情况下,我们只有 1 个样本和 1 个特征:[ _1,n_input,1_ ]。
如果执行差异操作,我们必须添加模型进行预测后减去的值。在制定用于进行预测的单个输入之前,我们还必须区分历史数据。
下面的 _model_predict()_ 函数实现了这种行为。
```py
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_input, _, _, _, n_diff = config
# prepare data
correction = 0.0
if n_diff > 0:
correction = history[-n_diff]
history = difference(history, n_diff)
x_input = array(history[-n_input:]).reshape((1, n_input, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return correction + yhat[0]
```
进行模型超参数的简单网格搜索,并选择下面的配置。这不是最佳配置,但却是最好的配置。
所选配置如下:
* **n_input** :36(即 3 年或 3 * 12)
* **n_nodes** :50
* **n_epochs** :100
* **n_batch** :100(即批量梯度下降)
* **n_diff** :12(即季节性差异)
这可以指定为一个列表:
```py
# define config
config = [36, 50, 100, 100, 12]
```
将所有这些结合在一起,下面列出了完整的示例。
```py
# evaluate lstm
from math import sqrt
from numpy import array
from numpy import mean
from numpy import std
from pandas import DataFrame
from pandas import concat
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from matplotlib import pyplot
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test], data[-n_test:]
# transform list into supervised learning format
def series_to_supervised(data, n_in=1, n_out=1):
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
agg.dropna(inplace=True)
return agg.values
# root mean squared error or rmse
def measure_rmse(actual, predicted):
return sqrt(mean_squared_error(actual, predicted))
# difference dataset
def difference(data, interval):
return [data[i] - data[i - interval] for i in range(interval, len(data))]
# fit a model
def model_fit(train, config):
# unpack config
n_input, n_nodes, n_epochs, n_batch, n_diff = config
# prepare data
if n_diff > 0:
train = difference(train, n_diff)
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], train_x.shape[1], 1))
# define model
model = Sequential()
model.add(LSTM(n_nodes, activation='relu', input_shape=(n_input, 1)))
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_input, _, _, _, n_diff = config
# prepare data
correction = 0.0
if n_diff > 0:
correction = history[-n_diff]
history = difference(history, n_diff)
x_input = array(history[-n_input:]).reshape((1, n_input, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return correction + yhat[0]
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test, cfg):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# fit model
model = model_fit(train, cfg)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# fit model and make forecast for history
yhat = model_predict(model, history, cfg)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# estimate prediction error
error = measure_rmse(test, predictions)
print(' > %.3f' % error)
return error
# repeat evaluation of a config
def repeat_evaluate(data, config, n_test, n_repeats=30):
# fit and evaluate the model n times
scores = [walk_forward_validation(data, n_test, config) for _ in range(n_repeats)]
return scores
# summarize model performance
def summarize_scores(name, scores):
# print a summary
scores_m, score_std = mean(scores), std(scores)
print('%s: %.3f RMSE (+/- %.3f)' % (name, scores_m, score_std))
# box and whisker plot
pyplot.boxplot(scores)
pyplot.show()
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
data = series.values
# data split
n_test = 12
# define config
config = [36, 50, 100, 100, 12]
# grid search
scores = repeat_evaluate(data, config, n_test)
# summarize scores
summarize_scores('lstm', scores)
```
运行该示例,我们可以看到每次重复评估模型的 RMSE。
在运行结束时,我们可以看到平均 RMSE 约为 2,109,这比朴素模型更差。这表明所选择的模型并不熟练,并且鉴于前面部分中用于查找模型配置的相同资源,它是最好的。
这提供了进一步的证据(虽然证据不足),LSTM,至少单独,可能不适合自回归型序列预测问题。
```py
> 2129.480
> 2169.109
> 2078.290
> 2257.222
> 2014.911
> 2197.283
> 2028.176
> 2110.718
> 2100.388
> 2157.271
> 1940.103
> 2086.588
> 1986.696
> 2168.784
> 2188.813
> 2086.759
> 2128.095
> 2126.467
> 2077.463
> 2057.679
> 2209.818
> 2067.082
> 1983.346
> 2157.749
> 2145.071
> 2266.130
> 2105.043
> 2128.549
> 1952.002
> 2188.287
lstm: 2109.779 RMSE (+/- 81.373)
```
还创建了一个盒子和胡须图,总结了 RMSE 分数的分布。
甚至模型的基本情况也没有达到朴素模型的表现。
![Box and Whisker Plot of Long Short-Term Memory Neural Network RMSE Forecasting Car Sales](https://img.kancloud.cn/6e/90/6e90c41d93fc7b98412846786a6534af_1280x960.jpg)
长短期记忆神经网络 RMSE 预测汽车销售的盒子和晶须图
### CNN LSTM
我们已经看到 CNN 模型能够自动学习和从原始序列数据中提取特征而无需缩放或差分。
我们可以将此功能与 LSTM 结合使用,其中 CNN 模型应用于输入数据的子序列,其结果一起形成可由 LSTM 模型解释的提取特征的时间序列。
用于通过 LSTM 随时间读取多个子序列的 CNN 模型的这种组合称为 CNN-LSTM 模型。
该模型要求每个输入序列,例如, 36 个月,分为多个子序列,每个子序列由 CNN 模型读取,例如, 12 个时间步骤的 3 个子序列。将子序列划分多年可能是有意义的,但这只是一个假设,可以使用其他分裂,例如六个时间步骤的六个子序列。因此,对于子序列的数量和每个子序列参数的步数,使用 _n_seq_ 和 _n_steps_ 参数化该分裂。
```py
train_x = train_x.reshape((train_x.shape[0], n_seq, n_steps, 1))
```
每个样本的滞后观察数量简单( _n_seq * n_steps_ )。
这是一个 4 维输入数组,现在尺寸为:
```py
[samples, subsequences, timesteps, features]
```
必须对每个输入子序列应用相同的 CNN 模型。
我们可以通过将整个 CNN 模型包装在 _TimeDistributed_ 层包装器中来实现这一点。
```py
model = Sequential()
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu', input_shape=(None,n_steps,1))))
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(pool_size=2)))
model.add(TimeDistributed(Flatten()))
```
CNN 子模型的一个应用程序的输出将是向量。子模型到每个输入子序列的输出将是可由 LSTM 模型解释的时间序列的解释。接下来是完全连接的层,用于解释 LSTM 的结果,最后是输出层,用于进行一步预测。
```py
model.add(LSTM(n_nodes, activation='relu'))
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
```
完整的 _model_fit()_ 功能如下所示。
该模型需要一个包含七个超参数的列表;他们是:
* **n_seq** :样本中的子序列数。
* **n_steps** :每个子序列中的时间步数。
* **n_filters** :并行滤波器的数量。
* **n_kernel** :每次读取输入序列时考虑的时间步数。
* **n_nodes** :隐藏层中使用的 LSTM 单元数。
* **n_epochs** :将模型公开给整个训练数据集的次数。
* **n_batch** :更新权重的时期内的样本数。
```py
# fit a model
def model_fit(train, config):
# unpack config
n_seq, n_steps, n_filters, n_kernel, n_nodes, n_epochs, n_batch = config
n_input = n_seq * n_steps
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], n_seq, n_steps, 1))
# define model
model = Sequential()
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu', input_shape=(None,n_steps,1))))
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(pool_size=2)))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(n_nodes, activation='relu'))
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
```
使用拟合模型进行预测与 LSTM 或 CNN 大致相同,尽管添加了将每个样本分成具有给定数量的时间步长的子序列。
```py
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_seq, n_steps, 1))
```
更新后的 _model_predict()_ 功能如下所示。
```py
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_seq, n_steps, _, _, _, _, _ = config
n_input = n_seq * n_steps
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_seq, n_steps, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
```
进行模型超参数的简单网格搜索,并选择下面的配置。这可能不是最佳配置,但它是最好的配置。
* **n_seq** :3(即 3 年)
* **n_steps** :12(即 1 个月)
* **n_filters** :64
* **n_kernel** :3
* **n_nodes** :100
* **n_epochs** :200
* **n_batch** :100(即批量梯度下降)
我们可以将配置定义为列表;例如:
```py
# define config
config = [3, 12, 64, 3, 100, 200, 100]
```
下面列出了评估用于预测单变量月度汽车销售的 CNN-LSTM 模型的完整示例。
```py
# evaluate cnn lstm
from math import sqrt
from numpy import array
from numpy import mean
from numpy import std
from pandas import DataFrame
from pandas import concat
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import TimeDistributed
from keras.layers import Flatten
from keras.layers.convolutional import Conv1D
from keras.layers.convolutional import MaxPooling1D
from matplotlib import pyplot
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test], data[-n_test:]
# transform list into supervised learning format
def series_to_supervised(data, n_in=1, n_out=1):
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
agg.dropna(inplace=True)
return agg.values
# root mean squared error or rmse
def measure_rmse(actual, predicted):
return sqrt(mean_squared_error(actual, predicted))
# fit a model
def model_fit(train, config):
# unpack config
n_seq, n_steps, n_filters, n_kernel, n_nodes, n_epochs, n_batch = config
n_input = n_seq * n_steps
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], n_seq, n_steps, 1))
# define model
model = Sequential()
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu', input_shape=(None,n_steps,1))))
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(pool_size=2)))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(n_nodes, activation='relu'))
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_seq, n_steps, _, _, _, _, _ = config
n_input = n_seq * n_steps
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_seq, n_steps, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test, cfg):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# fit model
model = model_fit(train, cfg)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# fit model and make forecast for history
yhat = model_predict(model, history, cfg)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# estimate prediction error
error = measure_rmse(test, predictions)
print(' > %.3f' % error)
return error
# repeat evaluation of a config
def repeat_evaluate(data, config, n_test, n_repeats=30):
# fit and evaluate the model n times
scores = [walk_forward_validation(data, n_test, config) for _ in range(n_repeats)]
return scores
# summarize model performance
def summarize_scores(name, scores):
# print a summary
scores_m, score_std = mean(scores), std(scores)
print('%s: %.3f RMSE (+/- %.3f)' % (name, scores_m, score_std))
# box and whisker plot
pyplot.boxplot(scores)
pyplot.show()
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
data = series.values
# data split
n_test = 12
# define config
config = [3, 12, 64, 3, 100, 200, 100]
# grid search
scores = repeat_evaluate(data, config, n_test)
# summarize scores
summarize_scores('cnn-lstm', scores)
```
运行该示例为每次重复的模型评估打印 RMSE。
最终平均 RMSE 报告在约 1,626 的末尾,低于幼稚模型,但仍高于 SARIMA 模型。该分数的标准偏差也非常大,表明所选配置可能不如独立 CNN 模型稳定。
```py
> 1543.533
> 1421.895
> 1467.927
> 1441.125
> 1750.995
> 1321.498
> 1571.657
> 1845.298
> 1621.589
> 1425.065
> 1675.232
> 1807.288
> 2922.295
> 1391.861
> 1626.655
> 1633.177
> 1667.572
> 1577.285
> 1590.235
> 1557.385
> 1784.982
> 1664.839
> 1741.729
> 1437.992
> 1772.076
> 1289.794
> 1685.976
> 1498.123
> 1618.627
> 1448.361
cnn-lstm: 1626.735 RMSE (+/- 279.850)
```
还创建了一个盒子和胡须图,总结了 RMSE 分数的分布。
该图显示了一个非常差的表现异常值,仅低于 3,000 个销售额。
![Box and Whisker Plot of CNN-LSTM RMSE Forecasting Car Sales](https://img.kancloud.cn/ac/73/ac73235e54d1672b20f36b43031ed759_1280x960.jpg)
CNN-LSTM RMSE 预测汽车销售的盒子和晶须图
### ConvLSTM
作为读取每个 LSTM 单元内的输入序列的一部分,可以执行卷积运算。
这意味着,LSTM 不是一次一步地读取序列,而是使用卷积过程(如 CNN)一次读取观察的块或子序列。
这与使用 LSTM 首先读取提取特征并使用 LSTM 解释结果不同;这是作为 LSTM 的一部分在每个时间步执行 CNN 操作。
这种类型的模型称为卷积 LSTM,简称 ConvLSTM。它在 Keras 中作为 2D 数据称为 ConvLSTM2D 的层提供。我们可以通过假设我们有一行包含多列来配置它以用于 1D 序列数据。
与 CNN-LSTM 一样,输入数据被分成子序列,其中每个子序列具有固定数量的时间步长,尽管我们还必须指定每个子序列中的行数,在这种情况下固定为 1。
```py
train_x = train_x.reshape((train_x.shape[0], n_seq, 1, n_steps, 1))
```
形状是五维的,尺寸为:
```py
[samples, subsequences, rows, columns, features]
```
与 CNN 一样,ConvLSTM 层允许我们指定过滤器映射的数量以及读取输入序列时使用的内核的大小。
```py
model.add(ConvLSTM2D(filters=n_filters, kernel_size=(1,n_kernel), activation='relu', input_shape=(n_seq, 1, n_steps, 1)))
```
层的输出是一系列过滤器映射,在解释之前必须首先将其展平,然后是输出层。
该模型需要一个包含七个超参数的列表,与 CNN-LSTM 相同;他们是:
* **n_seq** :样本中的子序列数。
* **n_steps** :每个子序列中的时间步数。
* **n_filters** :并行滤波器的数量。
* **n_kernel** :每次读取输入序列时考虑的时间步数。
* **n_nodes** :隐藏层中使用的 LSTM 单元数。
* **n_epochs** :将模型公开给整个训练数据集的次数。
* **n_batch** :更新权重的时期内的样本数。
下面列出了实现所有这些功能的 _model_fit()_ 函数。
```py
# fit a model
def model_fit(train, config):
# unpack config
n_seq, n_steps, n_filters, n_kernel, n_nodes, n_epochs, n_batch = config
n_input = n_seq * n_steps
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], n_seq, 1, n_steps, 1))
# define model
model = Sequential()
model.add(ConvLSTM2D(filters=n_filters, kernel_size=(1,n_kernel), activation='relu', input_shape=(n_seq, 1, n_steps, 1)))
model.add(Flatten())
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
```
使用拟合模型以与 CNN-LSTM 相同的方式进行预测,尽管我们将附加行维度固定为 1。
```py
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_seq, 1, n_steps, 1))
```
下面列出了用于进行单个一步预测的 _model_predict()_ 函数。
```py
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_seq, n_steps, _, _, _, _, _ = config
n_input = n_seq * n_steps
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_seq, 1, n_steps, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
```
进行模型超参数的简单网格搜索,并选择下面的配置。
这可能不是最佳配置,但却是最好的配置。
* **n_seq** :3(即 3 年)
* **n_steps** :12(即 1 个月)
* **n_filters** :256
* **n_kernel** :3
* **n_nodes** :200
* **n_epochs** :200
* **n_batch** :100(即批量梯度下降)
我们可以将配置定义为列表;例如:
```py
# define config
config = [3, 12, 256, 3, 200, 200, 100]
```
我们可以将所有这些结合在一起。下面列出了评估每月汽车销售数据集一步预测的 ConvLSTM 模型的完整代码清单。
```py
# evaluate convlstm
from math import sqrt
from numpy import array
from numpy import mean
from numpy import std
from pandas import DataFrame
from pandas import concat
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Flatten
from keras.layers import ConvLSTM2D
from matplotlib import pyplot
# split a univariate dataset into train/test sets
def train_test_split(data, n_test):
return data[:-n_test], data[-n_test:]
# transform list into supervised learning format
def series_to_supervised(data, n_in=1, n_out=1):
df = DataFrame(data)
cols = list()
# input sequence (t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
# forecast sequence (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
# put it all together
agg = concat(cols, axis=1)
# drop rows with NaN values
agg.dropna(inplace=True)
return agg.values
# root mean squared error or rmse
def measure_rmse(actual, predicted):
return sqrt(mean_squared_error(actual, predicted))
# difference dataset
def difference(data, interval):
return [data[i] - data[i - interval] for i in range(interval, len(data))]
# fit a model
def model_fit(train, config):
# unpack config
n_seq, n_steps, n_filters, n_kernel, n_nodes, n_epochs, n_batch = config
n_input = n_seq * n_steps
# prepare data
data = series_to_supervised(train, n_in=n_input)
train_x, train_y = data[:, :-1], data[:, -1]
train_x = train_x.reshape((train_x.shape[0], n_seq, 1, n_steps, 1))
# define model
model = Sequential()
model.add(ConvLSTM2D(filters=n_filters, kernel_size=(1,n_kernel), activation='relu', input_shape=(n_seq, 1, n_steps, 1)))
model.add(Flatten())
model.add(Dense(n_nodes, activation='relu'))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
# fit
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch, verbose=0)
return model
# forecast with a pre-fit model
def model_predict(model, history, config):
# unpack config
n_seq, n_steps, _, _, _, _, _ = config
n_input = n_seq * n_steps
# prepare data
x_input = array(history[-n_input:]).reshape((1, n_seq, 1, n_steps, 1))
# forecast
yhat = model.predict(x_input, verbose=0)
return yhat[0]
# walk-forward validation for univariate data
def walk_forward_validation(data, n_test, cfg):
predictions = list()
# split dataset
train, test = train_test_split(data, n_test)
# fit model
model = model_fit(train, cfg)
# seed history with training dataset
history = [x for x in train]
# step over each time-step in the test set
for i in range(len(test)):
# fit model and make forecast for history
yhat = model_predict(model, history, cfg)
# store forecast in list of predictions
predictions.append(yhat)
# add actual observation to history for the next loop
history.append(test[i])
# estimate prediction error
error = measure_rmse(test, predictions)
print(' > %.3f' % error)
return error
# repeat evaluation of a config
def repeat_evaluate(data, config, n_test, n_repeats=30):
# fit and evaluate the model n times
scores = [walk_forward_validation(data, n_test, config) for _ in range(n_repeats)]
return scores
# summarize model performance
def summarize_scores(name, scores):
# print a summary
scores_m, score_std = mean(scores), std(scores)
print('%s: %.3f RMSE (+/- %.3f)' % (name, scores_m, score_std))
# box and whisker plot
pyplot.boxplot(scores)
pyplot.show()
series = read_csv('monthly-car-sales.csv', header=0, index_col=0)
data = series.values
# data split
n_test = 12
# define config
config = [3, 12, 256, 3, 200, 200, 100]
# grid search
scores = repeat_evaluate(data, config, n_test)
# summarize scores
summarize_scores('convlstm', scores)
```
运行该示例为每次重复的模型评估打印 RMSE。
最终的平均 RMSE 报告在约 1,660 结束时,低于幼稚模型,但仍高于 SARIMA 模型。
这个结果可能与 CNN-LSTM 模型相当。该分数的标准偏差也非常大,表明所选配置可能不如独立 CNN 模型稳定。
```py
> 1825.246
> 1862.674
> 1684.313
> 1310.448
> 2109.668
> 1507.912
> 1431.118
> 1442.692
> 1400.548
> 1732.381
> 1523.824
> 1611.898
> 1805.970
> 1616.015
> 1649.466
> 1521.884
> 2025.655
> 1622.886
> 2536.448
> 1526.532
> 1866.631
> 1562.625
> 1491.386
> 1506.270
> 1843.981
> 1653.084
> 1650.430
> 1291.353
> 1558.616
> 1653.231
convlstm: 1660.840 RMSE (+/- 248.826)
```
还创建了一个盒子和胡须图,总结了 RMSE 分数的分布。
![Box and Whisker Plot of ConvLSTM RMSE Forecasting Car Sales](https://img.kancloud.cn/3c/83/3c833ac433c04b874be233bd8c47ffab_1280x960.jpg)
ConvLSTM RMSE 预测汽车销售的盒子和晶须图
## 扩展
本节列出了一些扩展您可能希望探索的教程的想法。
* **数据准备**。探索数据准备(例如规范化,标准化和/或差异化)是否可以列出任何模型的表现。
* **网格搜索超参数**。对一个模型实施超参数的网格搜索,以查看是否可以进一步提升表现。
* **学习曲线诊断**。创建一个模型的单一拟合并查看数据集的训练和验证分割的学习曲线,然后使用学习曲线的诊断来进一步调整模型超参数以提高模型表现。
* **历史规模**。探索一种模型的不同数量的历史数据(滞后输入),以了解您是否可以进一步提高模型表现
* **减少最终模型的差异**。探索一种或多种策略来减少其中一种神经网络模型的方差。
* **前进期间更新**。探索作为前进验证的一部分重新拟合或更新神经网络模型是否可以进一步提高模型表现。
* **更多参数化**。探索为一个模型添加更多模型参数化,例如使用其他层。
如果你探索任何这些扩展,我很想知道。
## 进一步阅读
如果您希望深入了解,本节将提供有关该主题的更多资源。
* [pandas.DataFrame.shift API](http://pandas-docs.github.io/pandas-docs-travis/generated/pandas.DataFrame.shift.html)
* [sklearn.metrics.mean_squared_error API](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html)
* [matplotlib.pyplot.boxplot API](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.boxplot.html)
* [Keras 序列模型 API](https://keras.io/models/sequential/)
## 摘要
在本教程中,您了解了如何开发一套用于单变量时间序列预测的深度学习模型。
具体来说,你学到了:
* 如何使用前向验证开发一个强大的测试工具来评估神经网络模型的表现。
* 如何开发和评估简单多层感知器和卷积神经网络的时间序列预测。
* 如何开发和评估 LSTM,CNN-LSTM 和 ConvLSTM 神经网络模型用于时间序列预测。
你有任何问题吗?
在下面的评论中提出您的问题,我会尽力回答。
- Machine Learning Mastery 应用机器学习教程
- 5竞争机器学习的好处
- 过度拟合的简单直觉,或者为什么测试训练数据是一个坏主意
- 特征选择简介
- 应用机器学习作为一个搜索问题的温和介绍
- 为什么应用机器学习很难
- 为什么我的结果不如我想的那么好?你可能过度拟合了
- 用ROC曲线评估和比较分类器表现
- BigML评论:发现本机学习即服务平台的聪明功能
- BigML教程:开发您的第一个决策树并进行预测
- 构建生产机器学习基础设施
- 分类准确性不够:可以使用更多表现测量
- 一种预测模型的巧妙应用
- 机器学习项目中常见的陷阱
- 数据清理:将凌乱的数据转换为整洁的数据
- 机器学习中的数据泄漏
- 数据,学习和建模
- 数据管理至关重要以及为什么需要认真对待它
- 将预测模型部署到生产中
- 参数和超参数之间有什么区别?
- 测试和验证数据集之间有什么区别?
- 发现特征工程,如何设计特征以及如何获得它
- 如何开始使用Kaggle
- 超越预测
- 如何在评估机器学习算法时选择正确的测试选项
- 如何定义机器学习问题
- 如何评估机器学习算法
- 如何获得基线结果及其重要性
- 如何充分利用机器学习数据
- 如何识别数据中的异常值
- 如何提高机器学习效果
- 如何在竞争机器学习中踢屁股
- 如何知道您的机器学习模型是否具有良好的表现
- 如何布局和管理您的机器学习项目
- 如何为机器学习准备数据
- 如何减少最终机器学习模型中的方差
- 如何使用机器学习结果
- 如何解决像数据科学家这样的问题
- 通过数据预处理提高模型精度
- 处理机器学习的大数据文件的7种方法
- 建立机器学习系统的经验教训
- 如何使用机器学习清单可靠地获得准确的预测(即使您是初学者)
- 机器学习模型运行期间要做什么
- 机器学习表现改进备忘单
- 来自世界级从业者的机器学习技巧:Phil Brierley
- 模型预测精度与机器学习中的解释
- 竞争机器学习的模型选择技巧
- 机器学习需要多少训练数据?
- 如何系统地规划和运行机器学习实验
- 应用机器学习过程
- 默认情况下可重现的机器学习结果
- 10个实践应用机器学习的标准数据集
- 简单的三步法到最佳机器学习算法
- 打击机器学习数据集中不平衡类的8种策略
- 模型表现不匹配问题(以及如何处理)
- 黑箱机器学习的诱惑陷阱
- 如何培养最终的机器学习模型
- 使用探索性数据分析了解您的问题并获得更好的结果
- 什么是数据挖掘和KDD
- 为什么One-Hot在机器学习中编码数据?
- 为什么你应该在你的机器学习问题上进行抽样检查算法
- 所以,你正在研究机器学习问题......
- Machine Learning Mastery Keras 深度学习教程
- Keras 中神经网络模型的 5 步生命周期
- 在 Python 迷你课程中应用深度学习
- Keras 深度学习库的二元分类教程
- 如何用 Keras 构建多层感知器神经网络模型
- 如何在 Keras 中检查深度学习模型
- 10 个用于 Amazon Web Services 深度学习的命令行秘籍
- 机器学习卷积神经网络的速成课程
- 如何在 Python 中使用 Keras 进行深度学习的度量
- 深度学习书籍
- 深度学习课程
- 你所知道的深度学习是一种谎言
- 如何设置 Amazon AWS EC2 GPU 以训练 Keras 深度学习模型(分步)
- 神经网络中批量和迭代之间的区别是什么?
- 在 Keras 展示深度学习模型训练历史
- 基于 Keras 的深度学习模型中的dropout正则化
- 评估 Keras 中深度学习模型的表现
- 如何评价深度学习模型的技巧
- 小批量梯度下降的简要介绍以及如何配置批量大小
- 在 Keras 中获得深度学习帮助的 9 种方法
- 如何使用 Keras 在 Python 中网格搜索深度学习模型的超参数
- 用 Keras 在 Python 中使用卷积神经网络进行手写数字识别
- 如何用 Keras 进行预测
- 用 Keras 进行深度学习的图像增强
- 8 个深度学习的鼓舞人心的应用
- Python 深度学习库 Keras 简介
- Python 深度学习库 TensorFlow 简介
- Python 深度学习库 Theano 简介
- 如何使用 Keras 函数式 API 进行深度学习
- Keras 深度学习库的多类分类教程
- 多层感知器神经网络速成课程
- 基于卷积神经网络的 Keras 深度学习库中的目标识别
- 流行的深度学习库
- 用深度学习预测电影评论的情感
- Python 中的 Keras 深度学习库的回归教程
- 如何使用 Keras 获得可重现的结果
- 如何在 Linux 服务器上运行深度学习实验
- 保存并加载您的 Keras 深度学习模型
- 用 Keras 逐步开发 Python 中的第一个神经网络
- 用 Keras 理解 Python 中的有状态 LSTM 循环神经网络
- 在 Python 中使用 Keras 深度学习模型和 Scikit-Learn
- 如何使用预训练的 VGG 模型对照片中的物体进行分类
- 在 Python 和 Keras 中对深度学习模型使用学习率调度
- 如何在 Keras 中可视化深度学习神经网络模型
- 什么是深度学习?
- 何时使用 MLP,CNN 和 RNN 神经网络
- 为什么用随机权重初始化神经网络?
- Machine Learning Mastery 深度学习 NLP 教程
- 深度学习在自然语言处理中的 7 个应用
- 如何实现自然语言处理的波束搜索解码器
- 深度学习文档分类的最佳实践
- 关于自然语言处理的热门书籍
- 在 Python 中计算文本 BLEU 分数的温和介绍
- 使用编码器 - 解码器模型的用于字幕生成的注入和合并架构
- 如何用 Python 清理机器学习的文本
- 如何配置神经机器翻译的编码器 - 解码器模型
- 如何开始深度学习自然语言处理(7 天迷你课程)
- 自然语言处理的数据集
- 如何开发一种深度学习的词袋模型来预测电影评论情感
- 深度学习字幕生成模型的温和介绍
- 如何在 Keras 中定义神经机器翻译的编码器 - 解码器序列 - 序列模型
- 如何利用小实验在 Keras 中开发字幕生成模型
- 如何从头开发深度学习图片标题生成器
- 如何在 Keras 中开发基于字符的神经语言模型
- 如何开发用于情感分析的 N-gram 多通道卷积神经网络
- 如何从零开始开发神经机器翻译系统
- 如何在 Python 中用 Keras 开发基于单词的神经语言模型
- 如何开发一种预测电影评论情感的词嵌入模型
- 如何使用 Gensim 在 Python 中开发词嵌入
- 用于文本摘要的编码器 - 解码器深度学习模型
- Keras 中文本摘要的编码器 - 解码器模型
- 用于神经机器翻译的编码器 - 解码器循环神经网络模型
- 浅谈词袋模型
- 文本摘要的温和介绍
- 编码器 - 解码器循环神经网络中的注意力如何工作
- 如何利用深度学习自动生成照片的文本描述
- 如何开发一个单词级神经语言模型并用它来生成文本
- 浅谈神经机器翻译
- 什么是自然语言处理?
- 牛津自然语言处理深度学习课程
- 如何为机器翻译准备法语到英语的数据集
- 如何为情感分析准备电影评论数据
- 如何为文本摘要准备新闻文章
- 如何准备照片标题数据集以训练深度学习模型
- 如何使用 Keras 为深度学习准备文本数据
- 如何使用 scikit-learn 为机器学习准备文本数据
- 自然语言处理神经网络模型入门
- 对自然语言处理的深度学习的承诺
- 在 Python 中用 Keras 进行 LSTM 循环神经网络的序列分类
- 斯坦福自然语言处理深度学习课程评价
- 统计语言建模和神经语言模型的简要介绍
- 使用 Keras 在 Python 中进行 LSTM 循环神经网络的文本生成
- 浅谈机器学习中的转换
- 如何使用 Keras 将词嵌入层用于深度学习
- 什么是用于文本的词嵌入
- Machine Learning Mastery 深度学习时间序列教程
- 如何开发人类活动识别的一维卷积神经网络模型
- 人类活动识别的深度学习模型
- 如何评估人类活动识别的机器学习算法
- 时间序列预测的多层感知器网络探索性配置
- 比较经典和机器学习方法进行时间序列预测的结果
- 如何通过深度学习快速获得时间序列预测的结果
- 如何利用 Python 处理序列预测问题中的缺失时间步长
- 如何建立预测大气污染日的概率预测模型
- 如何开发一种熟练的机器学习时间序列预测模型
- 如何构建家庭用电自回归预测模型
- 如何开发多步空气污染时间序列预测的自回归预测模型
- 如何制定多站点多元空气污染时间序列预测的基线预测
- 如何开发时间序列预测的卷积神经网络模型
- 如何开发卷积神经网络用于多步时间序列预测
- 如何开发单变量时间序列预测的深度学习模型
- 如何开发 LSTM 模型用于家庭用电的多步时间序列预测
- 如何开发 LSTM 模型进行时间序列预测
- 如何开发多元多步空气污染时间序列预测的机器学习模型
- 如何开发多层感知器模型进行时间序列预测
- 如何开发人类活动识别时间序列分类的 RNN 模型
- 如何开始深度学习的时间序列预测(7 天迷你课程)
- 如何网格搜索深度学习模型进行时间序列预测
- 如何对单变量时间序列预测的网格搜索朴素方法
- 如何在 Python 中搜索 SARIMA 模型超参数用于时间序列预测
- 如何在 Python 中进行时间序列预测的网格搜索三次指数平滑
- 一个标准的人类活动识别问题的温和介绍
- 如何加载和探索家庭用电数据
- 如何加载,可视化和探索复杂的多变量多步时间序列预测数据集
- 如何从智能手机数据模拟人类活动
- 如何根据环境因素预测房间占用率
- 如何使用脑波预测人眼是开放还是闭合
- 如何在 Python 中扩展长短期内存网络的数据
- 如何使用 TimeseriesGenerator 进行 Keras 中的时间序列预测
- 基于机器学习算法的室内运动时间序列分类
- 用于时间序列预测的状态 LSTM 在线学习的不稳定性
- 用于罕见事件时间序列预测的 LSTM 模型体系结构
- 用于时间序列预测的 4 种通用机器学习数据变换
- Python 中长短期记忆网络的多步时间序列预测
- 家庭用电机器学习的多步时间序列预测
- Keras 中 LSTM 的多变量时间序列预测
- 如何开发和评估朴素的家庭用电量预测方法
- 如何为长短期记忆网络准备单变量时间序列数据
- 循环神经网络在时间序列预测中的应用
- 如何在 Python 中使用差异变换删除趋势和季节性
- 如何在 LSTM 中种子状态用于 Python 中的时间序列预测
- 使用 Python 进行时间序列预测的有状态和无状态 LSTM
- 长短时记忆网络在时间序列预测中的适用性
- 时间序列预测问题的分类
- Python 中长短期记忆网络的时间序列预测
- 基于 Keras 的 Python 中 LSTM 循环神经网络的时间序列预测
- Keras 中深度学习的时间序列预测
- 如何用 Keras 调整 LSTM 超参数进行时间序列预测
- 如何在时间序列预测训练期间更新 LSTM 网络
- 如何使用 LSTM 网络的 Dropout 进行时间序列预测
- 如何使用 LSTM 网络中的特征进行时间序列预测
- 如何在 LSTM 网络中使用时间序列进行时间序列预测
- 如何利用 LSTM 网络进行权重正则化进行时间序列预测
- Machine Learning Mastery 线性代数教程
- 机器学习数学符号的基础知识
- 用 NumPy 阵列轻松介绍广播
- 如何从 Python 中的 Scratch 计算主成分分析(PCA)
- 用于编码器审查的计算线性代数
- 10 机器学习中的线性代数示例
- 线性代数的温和介绍
- 用 NumPy 轻松介绍 Python 中的 N 维数组
- 机器学习向量的温和介绍
- 如何在 Python 中为机器学习索引,切片和重塑 NumPy 数组
- 机器学习的矩阵和矩阵算法简介
- 温和地介绍机器学习的特征分解,特征值和特征向量
- NumPy 对预期价值,方差和协方差的简要介绍
- 机器学习矩阵分解的温和介绍
- 用 NumPy 轻松介绍机器学习的张量
- 用于机器学习的线性代数中的矩阵类型简介
- 用于机器学习的线性代数备忘单
- 线性代数的深度学习
- 用于机器学习的线性代数(7 天迷你课程)
- 机器学习的线性代数
- 机器学习矩阵运算的温和介绍
- 线性代数评论没有废话指南
- 学习机器学习线性代数的主要资源
- 浅谈机器学习的奇异值分解
- 如何用线性代数求解线性回归
- 用于机器学习的稀疏矩阵的温和介绍
- 机器学习中向量规范的温和介绍
- 学习线性代数用于机器学习的 5 个理由
- Machine Learning Mastery LSTM 教程
- Keras中长短期记忆模型的5步生命周期
- 长短时记忆循环神经网络的注意事项
- CNN长短期记忆网络
- 逆向神经网络中的深度学习速成课程
- 可变长度输入序列的数据准备
- 如何用Keras开发用于Python序列分类的双向LSTM
- 如何开发Keras序列到序列预测的编码器 - 解码器模型
- 如何诊断LSTM模型的过度拟合和欠拟合
- 如何开发一种编码器 - 解码器模型,注重Keras中的序列到序列预测
- 编码器 - 解码器长短期存储器网络
- 神经网络中爆炸梯度的温和介绍
- 对时间反向传播的温和介绍
- 生成长短期记忆网络的温和介绍
- 专家对长短期记忆网络的简要介绍
- 在序列预测问题上充分利用LSTM
- 编辑器 - 解码器循环神经网络全局注意的温和介绍
- 如何利用长短时记忆循环神经网络处理很长的序列
- 如何在Python中对一个热编码序列数据
- 如何使用编码器 - 解码器LSTM来回显随机整数序列
- 具有注意力的编码器 - 解码器RNN体系结构的实现模式
- 学习使用编码器解码器LSTM循环神经网络添加数字
- 如何学习长短时记忆循环神经网络回声随机整数
- 具有Keras的长短期记忆循环神经网络的迷你课程
- LSTM自动编码器的温和介绍
- 如何用Keras中的长短期记忆模型进行预测
- 用Python中的长短期内存网络演示内存
- 基于循环神经网络的序列预测模型的简要介绍
- 深度学习的循环神经网络算法之旅
- 如何重塑Keras中长短期存储网络的输入数据
- 了解Keras中LSTM的返回序列和返回状态之间的差异
- RNN展开的温和介绍
- 5学习LSTM循环神经网络的简单序列预测问题的例子
- 使用序列进行预测
- 堆叠长短期内存网络
- 什么是教师强制循环神经网络?
- 如何在Python中使用TimeDistributed Layer for Long Short-Term Memory Networks
- 如何准备Keras中截断反向传播的序列预测
- 如何在使用LSTM进行训练和预测时使用不同的批量大小
- Machine Learning Mastery 机器学习算法教程
- 机器学习算法之旅
- 用于机器学习的装袋和随机森林集合算法
- 从头开始实施机器学习算法的好处
- 更好的朴素贝叶斯:从朴素贝叶斯算法中获取最多的12个技巧
- 机器学习的提升和AdaBoost
- 选择机器学习算法:Microsoft Azure的经验教训
- 机器学习的分类和回归树
- 什么是机器学习中的混淆矩阵
- 如何使用Python从头开始创建算法测试工具
- 通过创建机器学习算法的目标列表来控制
- 从头开始停止编码机器学习算法
- 在实现机器学习算法时,不要从开源代码开始
- 不要使用随机猜测作为基线分类器
- 浅谈机器学习中的概念漂移
- 温和介绍机器学习中的偏差 - 方差权衡
- 机器学习的梯度下降
- 机器学习算法如何工作(他们学习输入到输出的映射)
- 如何建立机器学习算法的直觉
- 如何实现机器学习算法
- 如何研究机器学习算法行为
- 如何学习机器学习算法
- 如何研究机器学习算法
- 如何研究机器学习算法
- 如何在Python中从头开始实现反向传播算法
- 如何用Python从头开始实现Bagging
- 如何用Python从头开始实现基线机器学习算法
- 如何在Python中从头开始实现决策树算法
- 如何用Python从头开始实现学习向量量化
- 如何利用Python从头开始随机梯度下降实现线性回归
- 如何利用Python从头开始随机梯度下降实现Logistic回归
- 如何用Python从头开始实现机器学习算法表现指标
- 如何在Python中从头开始实现感知器算法
- 如何在Python中从零开始实现随机森林
- 如何在Python中从头开始实现重采样方法
- 如何用Python从头开始实现简单线性回归
- 如何用Python从头开始实现堆栈泛化(Stacking)
- K-Nearest Neighbors for Machine Learning
- 学习机器学习的向量量化
- 机器学习的线性判别分析
- 机器学习的线性回归
- 使用梯度下降进行机器学习的线性回归教程
- 如何在Python中从头开始加载机器学习数据
- 机器学习的Logistic回归
- 机器学习的Logistic回归教程
- 机器学习算法迷你课程
- 如何在Python中从头开始实现朴素贝叶斯
- 朴素贝叶斯机器学习
- 朴素贝叶斯机器学习教程
- 机器学习算法的过拟合和欠拟合
- 参数化和非参数机器学习算法
- 理解任何机器学习算法的6个问题
- 在机器学习中拥抱随机性
- 如何使用Python从头开始扩展机器学习数据
- 机器学习的简单线性回归教程
- 有监督和无监督的机器学习算法
- 用于机器学习的支持向量机
- 在没有数学背景的情况下理解机器学习算法的5种技术
- 最好的机器学习算法
- 教程从头开始在Python中实现k-Nearest Neighbors
- 通过从零开始实现它们来理解机器学习算法(以及绕过坏代码的策略)
- 使用随机森林:在121个数据集上测试179个分类器
- 为什么从零开始实现机器学习算法
- Machine Learning Mastery 机器学习入门教程
- 机器学习入门的四个步骤:初学者入门与实践的自上而下策略
- 你应该培养的 5 个机器学习领域
- 一种选择机器学习算法的数据驱动方法
- 机器学习中的分析与数值解
- 应用机器学习是一种精英政治
- 机器学习的基本概念
- 如何成为数据科学家
- 初学者如何在机器学习中弄错
- 机器学习的最佳编程语言
- 构建机器学习组合
- 机器学习中分类与回归的区别
- 评估自己作为数据科学家并利用结果建立惊人的数据科学团队
- 探索 Kaggle 大师的方法论和心态:对 Diogo Ferreira 的采访
- 扩展机器学习工具并展示掌握
- 通过寻找地标开始机器学习
- 温和地介绍预测建模
- 通过提供结果在机器学习中获得梦想的工作
- 如何开始机器学习:自学蓝图
- 开始并在机器学习方面取得进展
- 应用机器学习的 Hello World
- 初学者如何使用小型项目开始机器学习并在 Kaggle 上进行竞争
- 我如何开始机器学习? (简短版)
- 我是如何开始机器学习的
- 如何在机器学习中取得更好的成绩
- 如何从在银行工作到担任 Target 的高级数据科学家
- 如何学习任何机器学习工具
- 使用小型目标项目深入了解机器学习工具
- 获得付费申请机器学习
- 映射机器学习工具的景观
- 机器学习开发环境
- 机器学习金钱
- 程序员的机器学习
- 机器学习很有意思
- 机器学习是 Kaggle 比赛
- 机器学习现在很受欢迎
- 机器学习掌握方法
- 机器学习很重要
- 机器学习 Q& A:概念漂移,更好的结果和学习更快
- 缺乏自学机器学习的路线图
- 机器学习很重要
- 快速了解任何机器学习工具(即使您是初学者)
- 机器学习工具
- 找到你的机器学习部落
- 机器学习在一年
- 通过竞争一致的大师 Kaggle
- 5 程序员在机器学习中开始犯错误
- 哲学毕业生到机器学习从业者(Brian Thomas 采访)
- 机器学习入门的实用建议
- 实用机器学习问题
- 使用来自 UCI 机器学习库的数据集练习机器学习
- 使用秘籍的任何机器学习工具快速启动
- 程序员可以进入机器学习
- 程序员应该进入机器学习
- 项目焦点:Shashank Singh 的人脸识别
- 项目焦点:使用 Mahout 和 Konstantin Slisenko 进行堆栈交换群集
- 机器学习自学指南
- 4 个自学机器学习项目
- ÁlvaroLemos 如何在数据科学团队中获得机器学习实习
- 如何思考机器学习
- 现实世界机器学习问题之旅
- 有关机器学习的有用知识
- 如果我没有学位怎么办?
- 如果我不是一个优秀的程序员怎么办?
- 如果我不擅长数学怎么办?
- 为什么机器学习算法会处理以前从未见过的数据?
- 是什么阻碍了你的机器学习目标?
- 什么是机器学习?
- 机器学习适合哪里?
- 为什么要进入机器学习?
- 研究对您来说很重要的机器学习问题
- 你这样做是错的。为什么机器学习不必如此困难
- Machine Learning Mastery Sklearn 教程
- Scikit-Learn 的温和介绍:Python 机器学习库
- 使用 Python 管道和 scikit-learn 自动化机器学习工作流程
- 如何以及何时使用带有 scikit-learn 的校准分类模型
- 如何比较 Python 中的机器学习算法与 scikit-learn
- 用于机器学习开发人员的 Python 崩溃课程
- 用 scikit-learn 在 Python 中集成机器学习算法
- 使用重采样评估 Python 中机器学习算法的表现
- 使用 Scikit-Learn 在 Python 中进行特征选择
- Python 中机器学习的特征选择
- 如何使用 scikit-learn 在 Python 中生成测试数据集
- scikit-learn 中的机器学习算法秘籍
- 如何使用 Python 处理丢失的数据
- 如何开始使用 Python 进行机器学习
- 如何使用 Scikit-Learn 在 Python 中加载数据
- Python 中概率评分方法的简要介绍
- 如何用 Scikit-Learn 调整算法参数
- 如何在 Mac OS X 上安装 Python 3 环境以进行机器学习和深度学习
- 使用 scikit-learn 进行机器学习简介
- 从 shell 到一本带有 Fernando Perez 单一工具的书的 IPython
- 如何使用 Python 3 为机器学习开发创建 Linux 虚拟机
- 如何在 Python 中加载机器学习数据
- 您在 Python 中的第一个机器学习项目循序渐进
- 如何使用 scikit-learn 进行预测
- 用于评估 Python 中机器学习算法的度量标准
- 使用 Pandas 为 Python 中的机器学习准备数据
- 如何使用 Scikit-Learn 为 Python 机器学习准备数据
- 项目焦点:使用 Artem Yankov 在 Python 中进行事件推荐
- 用于机器学习的 Python 生态系统
- Python 是应用机器学习的成长平台
- Python 机器学习书籍
- Python 机器学习迷你课程
- 使用 Pandas 快速和肮脏的数据分析
- 使用 Scikit-Learn 重新调整 Python 中的机器学习数据
- 如何以及何时使用 ROC 曲线和精确调用曲线进行 Python 分类
- 使用 scikit-learn 在 Python 中保存和加载机器学习模型
- scikit-learn Cookbook 书评
- 如何使用 Anaconda 为机器学习和深度学习设置 Python 环境
- 使用 scikit-learn 在 Python 中进行 Spot-Check 分类机器学习算法
- 如何在 Python 中开发可重复使用的抽样检查算法框架
- 使用 scikit-learn 在 Python 中进行 Spot-Check 回归机器学习算法
- 使用 Python 中的描述性统计来了解您的机器学习数据
- 使用 OpenCV,Python 和模板匹配来播放“哪里是 Waldo?”
- 使用 Pandas 在 Python 中可视化机器学习数据
- Machine Learning Mastery 统计学教程
- 浅谈计算正态汇总统计量
- 非参数统计的温和介绍
- Python中常态测试的温和介绍
- 浅谈Bootstrap方法
- 浅谈机器学习的中心极限定理
- 浅谈机器学习中的大数定律
- 机器学习的所有统计数据
- 如何计算Python中机器学习结果的Bootstrap置信区间
- 浅谈机器学习的Chi-Squared测试
- 机器学习的置信区间
- 随机化在机器学习中解决混杂变量的作用
- 机器学习中的受控实验
- 机器学习统计学速成班
- 统计假设检验的关键值以及如何在Python中计算它们
- 如何在机器学习中谈论数据(统计学和计算机科学术语)
- Python中数据可视化方法的简要介绍
- Python中效果大小度量的温和介绍
- 估计随机机器学习算法的实验重复次数
- 机器学习评估统计的温和介绍
- 如何计算Python中的非参数秩相关性
- 如何在Python中计算数据的5位数摘要
- 如何在Python中从头开始编写学生t检验
- 如何在Python中生成随机数
- 如何转换数据以更好地拟合正态分布
- 如何使用相关来理解变量之间的关系
- 如何使用统计信息识别数据中的异常值
- 用于Python机器学习的随机数生成器简介
- k-fold交叉验证的温和介绍
- 如何计算McNemar的比较两种机器学习量词的测试
- Python中非参数统计显着性测试简介
- 如何在Python中使用参数统计显着性测试
- 机器学习的预测间隔
- 应用统计学与机器学习的密切关系
- 如何使用置信区间报告分类器表现
- 统计数据分布的简要介绍
- 15 Python中的统计假设检验(备忘单)
- 统计假设检验的温和介绍
- 10如何在机器学习项目中使用统计方法的示例
- Python中统计功效和功耗分析的简要介绍
- 统计抽样和重新抽样的简要介绍
- 比较机器学习算法的统计显着性检验
- 机器学习中统计容差区间的温和介绍
- 机器学习统计书籍
- 评估机器学习模型的统计数据
- 机器学习统计(7天迷你课程)
- 用于机器学习的简明英语统计
- 如何使用统计显着性检验来解释机器学习结果
- 什么是统计(为什么它在机器学习中很重要)?
- Machine Learning Mastery 时间序列入门教程
- 如何在 Python 中为时间序列预测创建 ARIMA 模型
- 用 Python 进行时间序列预测的自回归模型
- 如何回溯机器学习模型的时间序列预测
- Python 中基于时间序列数据的基本特征工程
- R 的时间序列预测热门书籍
- 10 挑战机器学习时间序列预测问题
- 如何将时间序列转换为 Python 中的监督学习问题
- 如何将时间序列数据分解为趋势和季节性
- 如何用 ARCH 和 GARCH 模拟波动率进行时间序列预测
- 如何将时间序列数据集与 Python 区分开来
- Python 中时间序列预测的指数平滑的温和介绍
- 用 Python 进行时间序列预测的特征选择
- 浅谈自相关和部分自相关
- 时间序列预测的 Box-Jenkins 方法简介
- 用 Python 简要介绍时间序列的时间序列预测
- 如何使用 Python 网格搜索 ARIMA 模型超参数
- 如何在 Python 中加载和探索时间序列数据
- 如何使用 Python 对 ARIMA 模型进行手动预测
- 如何用 Python 进行时间序列预测的预测
- 如何使用 Python 中的 ARIMA 进行样本外预测
- 如何利用 Python 模拟残差错误来纠正时间序列预测
- 使用 Python 进行数据准备,特征工程和时间序列预测的移动平均平滑
- 多步时间序列预测的 4 种策略
- 如何在 Python 中规范化和标准化时间序列数据
- 如何利用 Python 进行时间序列预测的基线预测
- 如何使用 Python 对时间序列预测数据进行功率变换
- 用于时间序列预测的 Python 环境
- 如何重构时间序列预测问题
- 如何使用 Python 重新采样和插值您的时间序列数据
- 用 Python 编写 SARIMA 时间序列预测
- 如何在 Python 中保存 ARIMA 时间序列预测模型
- 使用 Python 进行季节性持久性预测
- 基于 ARIMA 的 Python 历史规模敏感性预测技巧分析
- 简单的时间序列预测模型进行测试,这样你就不会欺骗自己
- 标准多变量,多步骤和多站点时间序列预测问题
- 如何使用 Python 检查时间序列数据是否是固定的
- 使用 Python 进行时间序列数据可视化
- 7 个机器学习的时间序列数据集
- 时间序列预测案例研究与 Python:波士顿每月武装抢劫案
- Python 的时间序列预测案例研究:巴尔的摩的年度用水量
- 使用 Python 进行时间序列预测研究:法国香槟的月销售额
- 使用 Python 的置信区间理解时间序列预测不确定性
- 11 Python 中的经典时间序列预测方法(备忘单)
- 使用 Python 进行时间序列预测表现测量
- 使用 Python 7 天迷你课程进行时间序列预测
- 时间序列预测作为监督学习
- 什么是时间序列预测?
- 如何使用 Python 识别和删除时间序列数据的季节性
- 如何在 Python 中使用和删除时间序列数据中的趋势信息
- 如何在 Python 中调整 ARIMA 参数
- 如何用 Python 可视化时间序列残差预测错误
- 白噪声时间序列与 Python
- 如何通过时间序列预测项目
- Machine Learning Mastery XGBoost 教程
- 通过在 Python 中使用 XGBoost 提前停止来避免过度拟合
- 如何在 Python 中调优 XGBoost 的多线程支持
- 如何配置梯度提升算法
- 在 Python 中使用 XGBoost 进行梯度提升的数据准备
- 如何使用 scikit-learn 在 Python 中开发您的第一个 XGBoost 模型
- 如何在 Python 中使用 XGBoost 评估梯度提升模型
- 在 Python 中使用 XGBoost 的特征重要性和特征选择
- 浅谈机器学习的梯度提升算法
- 应用机器学习的 XGBoost 简介
- 如何在 macOS 上为 Python 安装 XGBoost
- 如何在 Python 中使用 XGBoost 保存梯度提升模型
- 从梯度提升开始,比较 165 个数据集上的 13 种算法
- 在 Python 中使用 XGBoost 和 scikit-learn 进行随机梯度提升
- 如何使用 Amazon Web Services 在云中训练 XGBoost 模型
- 在 Python 中使用 XGBoost 调整梯度提升的学习率
- 如何在 Python 中使用 XGBoost 调整决策树的数量和大小
- 如何在 Python 中使用 XGBoost 可视化梯度提升决策树
- 在 Python 中开始使用 XGBoost 的 7 步迷你课程