# 如何开发多步空气污染时间序列预测的自回归预测模型
> 原文: [https://machinelearningmastery.com/how-to-develop-autoregressive-forecasting-models-for-multi-step-air-pollution-time-series-forecasting/](https://machinelearningmastery.com/how-to-develop-autoregressive-forecasting-models-for-multi-step-air-pollution-time-series-forecasting/)
实时世界时间序列预测具有挑战性,其原因不仅限于问题特征,例如具有多个输入变量,需要预测多个时间步骤,以及需要对多个物理站点执行相同类型的预测。
EMC Data Science Global Hackathon 数据集或简称“空气质量预测”数据集描述了多个站点的天气状况,需要预测随后三天的空气质量测量结果。
在深入研究时间序列预测的复杂机器学习和深度学习方法之前,重要的是要找到经典方法的局限性,例如使用 AR 或 ARIMA 方法开发自回归模型。
在本教程中,您将了解如何为多变量空气污染时间序列开发多步时间序列预测的自回归模型。
完成本教程后,您将了解:
* 如何分析和计算时间序列数据的缺失值。
* 如何开发和评估多步时间序列预测的自回归模型。
* 如何使用备用数据插补方法改进自回归模型。
让我们开始吧。
![Impact of Dataset Size on Deep Learning Model Skill And Performance Estimates](https://img.kancloud.cn/5f/40/5f4085505d615d32103aea399e02c1ca_640x425.jpg)
数据集大小对深度学习模型技能和表现估计的影响
照片由 [Eneas De Troya](https://www.flickr.com/photos/eneas/13632855754/) ,保留一些权利。
## 教程概述
本教程分为六个部分;他们是:
1. 问题描述
2. 模型评估
3. 数据分析
4. 开发自回归模型
5. 具有全球归因策略的自回归模型
## 问题描述
空气质量预测数据集描述了多个地点的天气状况,需要预测随后三天的空气质量测量结果。
具体而言,对于多个站点,每小时提供 8 天的温度,压力,风速和风向等天气观测。目标是预测未来 3 天在多个地点的空气质量测量。预测的提前期不是连续的;相反,必须在 72 小时预测期内预测特定提前期。他们是:
```py
+1, +2, +3, +4, +5, +10, +17, +24, +48, +72
```
此外,数据集被划分为不相交但连续的数据块,其中 8 天的数据随后是需要预测的 3 天。
并非所有站点或块都可以获得所有观察结果,并且并非所有站点和块都可以使用所有输出变量。必须解决大部分缺失数据。
该数据集被用作 2012 年 Kaggle 网站上[短期机器学习竞赛](https://www.kaggle.com/c/dsg-hackathon)(或黑客马拉松)的基础。
根据从参与者中扣留的真实观察结果评估竞赛的提交,并使用平均绝对误差(MAE)进行评分。提交要求在由于缺少数据而无法预测的情况下指定-1,000,000 的值。实际上,提供了一个插入缺失值的模板,并且要求所有提交都采用(模糊的是什么)。
获胜者在滞留测试集([私人排行榜](https://www.kaggle.com/c/dsg-hackathon/leaderboard))上使用随机森林在滞后观察中获得了 0.21058 的 MAE。该帖子中提供了此解决方案的说明:
* [把所有东西都扔进随机森林:Ben Hamner 赢得空气质量预测黑客马拉松](http://blog.kaggle.com/2012/05/01/chucking-everything-into-a-random-forest-ben-hamner-on-winning-the-air-quality-prediction-hackathon/),2012。
在本教程中,我们将探索如何为可用作基线的问题开发朴素预测,以确定模型是否具有该问题的技能。
## 模型评估
在我们评估朴素的预测方法之前,我们必须开发一个测试工具。
这至少包括如何准备数据以及如何评估预测。
### 加载数据集
第一步是下载数据集并将其加载到内存中。
数据集可以从 Kaggle 网站免费下载。您可能必须创建一个帐户并登录才能下载数据集。
下载整个数据集,例如“_ 将所有 _”下载到您的工作站,并使用名为' _AirQualityPrediction_ '的文件夹解压缩当前工作目录中的存档。
* [EMC 数据科学全球黑客马拉松(空气质量预测)数据](https://www.kaggle.com/c/dsg-hackathon/data)
我们的重点将是包含训练数据集的' _TrainingData.csv_ '文件,特别是块中的数据,其中每个块是八个连续的观察日和目标变量。
我们可以使用 Pandas [read_csv()函数](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html)将数据文件加载到内存中,并在第 0 行指定标题行。
```py
# load dataset
dataset = read_csv('AirQualityPrediction/TrainingData.csv', header=0)
```
我们可以通过'chunkID'变量(列索引 1)对数据进行分组。
首先,让我们获取唯一的块标识符列表。
```py
chunk_ids = unique(values[:, 1])
```
然后,我们可以收集每个块标识符的所有行,并将它们存储在字典中以便于访问。
```py
chunks = dict()
# sort rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks[chunk_id] = values[selection, :]
```
下面定义了一个名为 _to_chunks()_ 的函数,它接受加载数据的 NumPy 数组,并将 _chunk_id_ 的字典返回到块的行。
```py
# split the dataset by 'chunkID', return a dict of id to rows
def to_chunks(values, chunk_ix=1):
chunks = dict()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks[chunk_id] = values[selection, :]
return chunks
```
下面列出了加载数据集并将其拆分为块的完整示例。
```py
# load data and split into chunks
from numpy import unique
from pandas import read_csv
# split the dataset by 'chunkID', return a dict of id to rows
def to_chunks(values, chunk_ix=1):
chunks = dict()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks[chunk_id] = values[selection, :]
return chunks
# load dataset
dataset = read_csv('AirQualityPrediction/TrainingData.csv', header=0)
# group data by chunks
values = dataset.values
chunks = to_chunks(values)
print('Total Chunks: %d' % len(chunks))
```
运行该示例将打印数据集中的块数。
```py
Total Chunks: 208
```
### 数据准备
既然我们知道如何加载数据并将其拆分成块,我们就可以将它们分成训练和测试数据集。
尽管每个块内的实际观测数量可能差异很大,但每个块的每小时观察间隔为 8 天。
我们可以将每个块分成前五天的训练观察和最后三天的测试。
每个观察都有一行称为' _position_within_chunk_ ',从 1 到 192(8 天* 24 小时)不等。因此,我们可以将此列中值小于或等于 120(5 * 24)的所有行作为训练数据,将任何大于 120 的值作为测试数据。
此外,任何在训练或测试分割中没有任何观察的块都可以被丢弃,因为不可行。
在使用朴素模型时,我们只对目标变量感兴趣,而不对输入的气象变量感兴趣。因此,我们可以删除输入数据,并使训练和测试数据仅包含每个块的 39 个目标变量,以及块和观察时间内的位置。
下面的 _split_train_test()_ 函数实现了这种行为;给定一个块的字典,它将每个分成训练和测试块数据。
```py
# split each chunk into train/test sets
def split_train_test(chunks, row_in_chunk_ix=2):
train, test = list(), list()
# first 5 days of hourly observations for train
cut_point = 5 * 24
# enumerate chunks
for k,rows in chunks.items():
# split chunk rows by 'position_within_chunk'
train_rows = rows[rows[:,row_in_chunk_ix] <= cut_point, :]
test_rows = rows[rows[:,row_in_chunk_ix] > cut_point, :]
if len(train_rows) == 0 or len(test_rows) == 0:
print('>dropping chunk=%d: train=%s, test=%s' % (k, train_rows.shape, test_rows.shape))
continue
# store with chunk id, position in chunk, hour and all targets
indices = [1,2,5] + [x for x in range(56,train_rows.shape[1])]
train.append(train_rows[:, indices])
test.append(test_rows[:, indices])
return train, test
```
我们不需要整个测试数据集;相反,我们只需要在三天时间内的特定提前期进行观察,特别是提前期:
```py
+1, +2, +3, +4, +5, +10, +17, +24, +48, +72
```
其中,每个提前期相对于训练期结束。
首先,我们可以将这些提前期放入函数中以便于参考:
```py
# return a list of relative forecast lead times
def get_lead_times():
return [1, 2 ,3, 4, 5, 10, 17, 24, 48, 72]
```
接下来,我们可以将测试数据集缩减为仅在首选提前期的数据。
我们可以通过查看' _position_within_chunk_ '列并使用提前期作为距离训练数据集末尾的偏移量来实现,例如: 120 + 1,120 +2 等
如果我们在测试集中找到匹配的行,则保存它,否则生成一行 NaN 观测值。
下面的函数 _to_forecasts()_ 实现了这一点,并为每个块的每个预测提前期返回一行 NumPy 数组。
```py
# convert the rows in a test chunk to forecasts
def to_forecasts(test_chunks, row_in_chunk_ix=1):
# get lead times
lead_times = get_lead_times()
# first 5 days of hourly observations for train
cut_point = 5 * 24
forecasts = list()
# enumerate each chunk
for rows in test_chunks:
chunk_id = rows[0, 0]
# enumerate each lead time
for tau in lead_times:
# determine the row in chunk we want for the lead time
offset = cut_point + tau
# retrieve data for the lead time using row number in chunk
row_for_tau = rows[rows[:,row_in_chunk_ix]==offset, :]
# check if we have data
if len(row_for_tau) == 0:
# create a mock row [chunk, position, hour] + [nan...]
row = [chunk_id, offset, nan] + [nan for _ in range(39)]
forecasts.append(row)
else:
# store the forecast row
forecasts.append(row_for_tau[0])
return array(forecasts)
```
我们可以将所有这些组合在一起并将数据集拆分为训练集和测试集,并将结果保存到新文件中。
完整的代码示例如下所示。
```py
# split data into train and test sets
from numpy import unique
from numpy import nan
from numpy import array
from numpy import savetxt
from pandas import read_csv
# split the dataset by 'chunkID', return a dict of id to rows
def to_chunks(values, chunk_ix=1):
chunks = dict()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks[chunk_id] = values[selection, :]
return chunks
# split each chunk into train/test sets
def split_train_test(chunks, row_in_chunk_ix=2):
train, test = list(), list()
# first 5 days of hourly observations for train
cut_point = 5 * 24
# enumerate chunks
for k,rows in chunks.items():
# split chunk rows by 'position_within_chunk'
train_rows = rows[rows[:,row_in_chunk_ix] <= cut_point, :]
test_rows = rows[rows[:,row_in_chunk_ix] > cut_point, :]
if len(train_rows) == 0 or len(test_rows) == 0:
print('>dropping chunk=%d: train=%s, test=%s' % (k, train_rows.shape, test_rows.shape))
continue
# store with chunk id, position in chunk, hour and all targets
indices = [1,2,5] + [x for x in range(56,train_rows.shape[1])]
train.append(train_rows[:, indices])
test.append(test_rows[:, indices])
return train, test
# return a list of relative forecast lead times
def get_lead_times():
return [1, 2 ,3, 4, 5, 10, 17, 24, 48, 72]
# convert the rows in a test chunk to forecasts
def to_forecasts(test_chunks, row_in_chunk_ix=1):
# get lead times
lead_times = get_lead_times()
# first 5 days of hourly observations for train
cut_point = 5 * 24
forecasts = list()
# enumerate each chunk
for rows in test_chunks:
chunk_id = rows[0, 0]
# enumerate each lead time
for tau in lead_times:
# determine the row in chunk we want for the lead time
offset = cut_point + tau
# retrieve data for the lead time using row number in chunk
row_for_tau = rows[rows[:,row_in_chunk_ix]==offset, :]
# check if we have data
if len(row_for_tau) == 0:
# create a mock row [chunk, position, hour] + [nan...]
row = [chunk_id, offset, nan] + [nan for _ in range(39)]
forecasts.append(row)
else:
# store the forecast row
forecasts.append(row_for_tau[0])
return array(forecasts)
# load dataset
dataset = read_csv('AirQualityPrediction/TrainingData.csv', header=0)
# group data by chunks
values = dataset.values
chunks = to_chunks(values)
# split into train/test
train, test = split_train_test(chunks)
# flatten training chunks to rows
train_rows = array([row for rows in train for row in rows])
# print(train_rows.shape)
print('Train Rows: %s' % str(train_rows.shape))
# reduce train to forecast lead times only
test_rows = to_forecasts(test)
print('Test Rows: %s' % str(test_rows.shape))
# save datasets
savetxt('AirQualityPrediction/naive_train.csv', train_rows, delimiter=',')
savetxt('AirQualityPrediction/naive_test.csv', test_rows, delimiter=',')
```
运行该示例首先评论了从数据集中移除了块 69 以获得不足的数据。
然后我们可以看到每个训练和测试集中有 42 列,一个用于块 ID,块内位置,一天中的小时和 39 个训练变量。
我们还可以看到测试数据集的显着缩小版本,其中行仅在预测前置时间。
新的训练和测试数据集分别保存在' _naive_train.csv_ '和' _naive_test.csv_ '文件中。
```py
>dropping chunk=69: train=(0, 95), test=(28, 95)
Train Rows: (23514, 42)
Test Rows: (2070, 42)
```
### 预测评估
一旦做出预测,就需要对它们进行评估。
在评估预测时,使用更简单的格式会很有帮助。例如,我们将使用 _[chunk] [变量] [时间]_ 的三维结构,其中变量是从 0 到 38 的目标变量数,time 是从 0 到 9 的提前期索引。
模型有望以这种格式进行预测。
我们还可以重新构建测试数据集以使此数据集进行比较。下面的 _prepare_test_forecasts()_ 函数实现了这一点。
```py
# convert the test dataset in chunks to [chunk][variable][time] format
def prepare_test_forecasts(test_chunks):
predictions = list()
# enumerate chunks to forecast
for rows in test_chunks:
# enumerate targets for chunk
chunk_predictions = list()
for j in range(3, rows.shape[1]):
yhat = rows[:, j]
chunk_predictions.append(yhat)
chunk_predictions = array(chunk_predictions)
predictions.append(chunk_predictions)
return array(predictions)
```
我们将使用平均绝对误差或 MAE 来评估模型。这是在竞争中使用的度量,并且在给定目标变量的非高斯分布的情况下是合理的选择。
如果提前期不包含测试集中的数据(例如 _NaN_ ),则不会计算该预测的错误。如果提前期确实在测试集中有数据但预测中没有数据,那么观察的全部大小将被视为错误。最后,如果测试集具有观察值并进行预测,则绝对差值将被记录为误差。
_calculate_error()_ 函数实现这些规则并返回给定预测的错误。
```py
# calculate the error between an actual and predicted value
def calculate_error(actual, predicted):
# give the full actual value if predicted is nan
if isnan(predicted):
return abs(actual)
# calculate abs difference
return abs(actual - predicted)
```
错误在所有块和所有提前期之间求和,然后取平均值。
将计算总体 MAE,但我们还将计算每个预测提前期的 MAE。这通常有助于模型选择,因为某些模型在不同的提前期可能会有不同的表现。
下面的 evaluate_forecasts()函数实现了这一点,计算了 _[chunk] [variable] [time]_ 格式中提供的预测和期望值的 MAE 和每个引导时间 MAE。
```py
# evaluate a forecast in the format [chunk][variable][time]
def evaluate_forecasts(predictions, testset):
lead_times = get_lead_times()
total_mae, times_mae = 0.0, [0.0 for _ in range(len(lead_times))]
total_c, times_c = 0, [0 for _ in range(len(lead_times))]
# enumerate test chunks
for i in range(len(test_chunks)):
# convert to forecasts
actual = testset[i]
predicted = predictions[i]
# enumerate target variables
for j in range(predicted.shape[0]):
# enumerate lead times
for k in range(len(lead_times)):
# skip if actual in nan
if isnan(actual[j, k]):
continue
# calculate error
error = calculate_error(actual[j, k], predicted[j, k])
# update statistics
total_mae += error
times_mae[k] += error
total_c += 1
times_c[k] += 1
# normalize summed absolute errors
total_mae /= total_c
times_mae = [times_mae[i]/times_c[i] for i in range(len(times_mae))]
return total_mae, times_mae
```
一旦我们对模型进行评估,我们就可以呈现它。
下面的 _summarize_error()_ 函数首先打印模型表现的一行摘要,然后创建每个预测提前期的 MAE 图。
```py
# summarize scores
def summarize_error(name, total_mae, times_mae):
# print summary
lead_times = get_lead_times()
formatted = ['+%d %.3f' % (lead_times[i], times_mae[i]) for i in range(len(lead_times))]
s_scores = ', '.join(formatted)
print('%s: [%.3f MAE] %s' % (name, total_mae, s_scores))
# plot summary
pyplot.plot([str(x) for x in lead_times], times_mae, marker='.')
pyplot.show()
```
我们现在准备开始探索朴素预测方法的表现。
## 数据分析
将经典时间序列模型拟合到这些数据的第一步是仔细研究数据。
有 208 个(实际上是 207 个)可用的数据块,每个块有 39 个时间序列适合;这是总共 8,073 个需要适合数据的独立模型。这是很多模型,但模型是在相对少量的数据上进行训练,最多(5 * 24)或 120 次观测,并且模型是线性的,因此它可以快速找到拟合。
我们可以选择如何为数据配置模型;例如:
* 所有时间序列的一种模型配置(最简单)。
* 跨块的所有变量的一个模型配置(合理)。
* 每个块的每个变量一个模型配置(最复杂)。
我们将研究所有系列的一种模型配置的最简单方法,但您可能想要探索一种或多种其他方法。
本节分为三个部分;他们是:
1. 缺失数据
2. 归咎于缺失数据
3. 自相关图
### 缺失数据
经典时间序列方法要求时间序列完整,例如,没有遗漏的价值。
因此,第一步是研究目标变量的完整性或不完整性。
对于给定变量,可能缺少由缺失行定义的观察值。具体地,每个观察具有' _position_within_chunk_ '。我们期望训练数据集中的每个块有 120 个观察值,其中“ _positions_within_chunk_ ”从 1 到 120 包含。
因此,我们可以为每个变量创建一个 120 纳米值的数组,使用' _positions_within_chunk_ '值标记块中的所有观察值,剩下的任何内容都将标记为 _NaN_ 。然后我们可以绘制每个变量并寻找差距。
下面的 _variable_to_series()_ 函数将获取目标变量的块和给定列索引的行,并将为变量返回一系列 120 个时间步长,所有可用数据都标记为来自块。
```py
# layout a variable with breaks in the data for missing positions
def variable_to_series(chunk_train, col_ix, n_steps=5*24):
# lay out whole series
data = [nan for _ in range(n_steps)]
# mark all available data
for i in range(len(chunk_train)):
# get position in chunk
position = int(chunk_train[i, 1] - 1)
# store data
data[position] = chunk_train[i, col_ix]
return data
```
然后我们可以在一个块中为每个目标变量调用此函数并创建一个线图。
下面名为 _plot_variables()_ 的函数将实现此功能并创建一个图形,其中 39 个线图水平堆叠。
```py
# plot variables horizontally with gaps for missing data
def plot_variables(chunk_train, n_vars=39):
pyplot.figure()
for i in range(n_vars):
# convert target number into column number
col_ix = 3 + i
# mark missing obs for variable
series = variable_to_series(chunk_train, col_ix)
# plot
ax = pyplot.subplot(n_vars, 1, i+1)
ax.set_xticklabels([])
ax.set_yticklabels([])
pyplot.plot(series)
# show plot
pyplot.show()
```
将这些结合在一起,下面列出了完整的示例。创建第一个块中所有变量的图。
```py
# plot missing
from numpy import loadtxt
from numpy import nan
from numpy import unique
from matplotlib import pyplot
# split the dataset by 'chunkID', return a list of chunks
def to_chunks(values, chunk_ix=0):
chunks = list()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks.append(values[selection, :])
return chunks
# layout a variable with breaks in the data for missing positions
def variable_to_series(chunk_train, col_ix, n_steps=5*24):
# lay out whole series
data = [nan for _ in range(n_steps)]
# mark all available data
for i in range(len(chunk_train)):
# get position in chunk
position = int(chunk_train[i, 1] - 1)
# store data
data[position] = chunk_train[i, col_ix]
return data
# plot variables horizontally with gaps for missing data
def plot_variables(chunk_train, n_vars=39):
pyplot.figure()
for i in range(n_vars):
# convert target number into column number
col_ix = 3 + i
# mark missing obs for variable
series = variable_to_series(chunk_train, col_ix)
# plot
ax = pyplot.subplot(n_vars, 1, i+1)
ax.set_xticklabels([])
ax.set_yticklabels([])
pyplot.plot(series)
# show plot
pyplot.show()
# load dataset
train = loadtxt('AirQualityPrediction/naive_train.csv', delimiter=',')
# group data by chunks
train_chunks = to_chunks(train)
# pick one chunk
rows = train_chunks[0]
# plot variables
plot_variables(rows)
```
运行该示例将创建一个包含 39 个线图的图形,一个用于第一个块中的每个目标变量。
我们可以在许多变量中看到季节性结构。这表明在建模之前对每个系列执行 24 小时季节差异可能是有益的。
这些图很小,您可能需要增加图的大小以清楚地看到数据。
我们可以看到有些变量我们没有数据。这些可以被检测和忽略,因为我们无法建模或预测它们。
我们可以看到许多系列中的差距,但差距很短,最多只能持续几个小时。这些可以通过在同一系列中的相同时间持续存在先前值或值来估算。
![Line Plots for All Targets in Chunk 1 With Missing Values Marked](https://img.kancloud.cn/05/40/05407887de2425974b919e3c8f8c2dd6_1280x960.jpg)
具有缺失值的块 1 中所有目标的线图
随机查看其他几个块,许多块会产生具有大致相同观察结果的图。
但情况并非总是如此。
更新示例以绘制数据集中的第 4 个块(索引 3)。
```py
# pick one chunk
rows = train_chunks[3]
```
结果是一个人物讲述了一个非常不同的故事。
我们发现数据中存在持续数小时的差距,可能长达一天或更长时间。
这些系列在用于装配经典型号之前需要进行大幅修复。
使用同一小时内系列内的持久性或观察来输入缺失的数据可能是不够的。它们可能必须填充整个训练数据集中的平均值。
![Line Plots for All Targets in Chunk 4 With Missing Values Marked](https://img.kancloud.cn/c5/c7/c5c721d555cf16d3aa67793007285d18_1280x960.jpg)
具有缺失值的块 4 中所有目标的线图
### 归咎于缺失数据
有许多方法来估算缺失的数据,我们无法知道哪个是最好的先验。
一种方法是使用多种不同的插补方法准备数据,并使用适合数据的模型技能来帮助指导最佳方法。
已经提出的一些估算方法包括:
* 坚持系列中的最后一次观察,也称为线性插值。
* 使用相同的小时填写系列中的值或平均值。
* 在训练数据集中填写一天中相同小时的值或平均值。
使用组合也可能是有用的,例如,从系列中保留或填充小间隙,并从整个数据集中提取大间隙。
我们还可以通过填写缺失数据并查看图表以查看该系列是否合理来研究输入方法的效果。它原始,有效,快速。
首先,我们需要为每个块计算一个小时的并行序列,我们可以使用它来为块中的每个变量计算特定于小时的数据。
给定一系列部分填充的小时,下面的 _interpolate_hours()_ 函数将填充一天中缺少的小时数。它通过找到第一个标记的小时,然后向前计数,填写一天中的小时,然后向后执行相同的操作来完成此操作。
```py
# interpolate series of hours (in place) in 24 hour time
def interpolate_hours(hours):
# find the first hour
ix = -1
for i in range(len(hours)):
if not isnan(hours[i]):
ix = i
break
# fill-forward
hour = hours[ix]
for i in range(ix+1, len(hours)):
# increment hour
hour += 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# fill-backward
hour = hours[ix]
for i in range(ix-1, -1, -1):
# decrement hour
hour -= 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
```
我确信有更多的 Pythonic 方式来编写这个函数,但是我想把它全部用来使它显而易见。
我们可以在缺少数据的模拟小时列表上测试它。下面列出了完整的示例。
```py
# interpolate hours
from numpy import nan
from numpy import isnan
# interpolate series of hours (in place) in 24 hour time
def interpolate_hours(hours):
# find the first hour
ix = -1
for i in range(len(hours)):
if not isnan(hours[i]):
ix = i
break
# fill-forward
hour = hours[ix]
for i in range(ix+1, len(hours)):
# increment hour
hour += 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# fill-backward
hour = hours[ix]
for i in range(ix-1, -1, -1):
# decrement hour
hour -= 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# define hours with missing data
data = [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0, nan, 2, nan, nan, nan, nan, nan, nan, 9, 10, 11, 12, 13, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]
print(data)
# fill in missing hours
interpolate_hours(data)
print(data)
```
首先运行示例打印带有缺失值的小时数据,然后正确填写所有小时数的相同序列。
```py
[nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 0, nan, 2, nan, nan, nan, nan, nan, nan, 9, 10, 11, 12, 13, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0, 1]
```
我们可以使用此函数为一个块准备一系列小时,这些块可用于使用特定于小时的信息填充块的缺失值。
我们可以从上一节中调用相同的 _variable_to_series()_ 函数来创建具有缺失值的小时系列(列索引 2),然后调用 _interpolate_hours()_ 来填补空白。
```py
# prepare sequence of hours for the chunk
hours = variable_to_series(rows, 2)
# interpolate hours
interpolate_hours(hours)
```
然后我们可以将时间传递给可以使用它的任何 impute 函数。
让我们尝试在相同系列中使用相同小时填充值中的缺失值。具体来说,我们将在系列中找到所有具有相同小时的行并计算中值。
下面的 _impute_missing()_ 获取块中的所有行,准备好的块的一天中的小时数,以及具有变量的缺失值和变量的列索引的系列。
它首先检查系列是否全部缺失数据,如果是这种情况则立即返回,因为不能执行任何插补。然后,它会在系列的时间步骤中进行枚举,当它检测到没有数据的时间步长时,它会收集序列中所有行,并使用相同小时的数据并计算中值。
```py
# impute missing data
def impute_missing(rows, hours, series, col_ix):
# count missing observations
n_missing = count_nonzero(isnan(series))
# calculate ratio of missing
ratio = n_missing / float(len(series)) * 100
# check for no data
if ratio == 100.0:
return series
# impute missing using the median value for hour in the series
imputed = list()
for i in range(len(series)):
if isnan(series[i]):
# get all rows with the same hour
matches = rows[rows[:,2]==hours[i]]
# fill with median value
value = nanmedian(matches[:, col_ix])
imputed.append(value)
else:
imputed.append(series[i])
return imputed
```
要查看此推算策略的影响,我们可以更新上一节中的 _plot_variables()_ 函数,首先绘制插补系列,然后绘制具有缺失值的原始系列。
这将允许插补值在原始系列的间隙中闪耀,我们可以看到结果是否合理。
_plot_variables()_ 函数的更新版本在下面列出了此更改,调用 _impute_missing()_ 函数来创建系列的推算版本并将小时系列作为参数。
```py
# plot variables horizontally with gaps for missing data
def plot_variables(chunk_train, hours, n_vars=39):
pyplot.figure()
for i in range(n_vars):
# convert target number into column number
col_ix = 3 + i
# mark missing obs for variable
series = variable_to_series(chunk_train, col_ix)
ax = pyplot.subplot(n_vars, 1, i+1)
ax.set_xticklabels([])
ax.set_yticklabels([])
# imputed
imputed = impute_missing(chunk_train, hours, series, col_ix)
# plot imputed
pyplot.plot(imputed)
# plot with missing
pyplot.plot(series)
# show plot
pyplot.show()
```
将所有这些结合在一起,下面列出了完整的示例。
```py
# impute missing
from numpy import loadtxt
from numpy import nan
from numpy import isnan
from numpy import count_nonzero
from numpy import unique
from numpy import nanmedian
from matplotlib import pyplot
# split the dataset by 'chunkID', return a list of chunks
def to_chunks(values, chunk_ix=0):
chunks = list()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks.append(values[selection, :])
return chunks
# impute missing data
def impute_missing(rows, hours, series, col_ix):
# count missing observations
n_missing = count_nonzero(isnan(series))
# calculate ratio of missing
ratio = n_missing / float(len(series)) * 100
# check for no data
if ratio == 100.0:
return series
# impute missing using the median value for hour in the series
imputed = list()
for i in range(len(series)):
if isnan(series[i]):
# get all rows with the same hour
matches = rows[rows[:,2]==hours[i]]
# fill with median value
value = nanmedian(matches[:, col_ix])
imputed.append(value)
else:
imputed.append(series[i])
return imputed
# interpolate series of hours (in place) in 24 hour time
def interpolate_hours(hours):
# find the first hour
ix = -1
for i in range(len(hours)):
if not isnan(hours[i]):
ix = i
break
# fill-forward
hour = hours[ix]
for i in range(ix+1, len(hours)):
# increment hour
hour += 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# fill-backward
hour = hours[ix]
for i in range(ix-1, -1, -1):
# decrement hour
hour -= 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# layout a variable with breaks in the data for missing positions
def variable_to_series(chunk_train, col_ix, n_steps=5*24):
# lay out whole series
data = [nan for _ in range(n_steps)]
# mark all available data
for i in range(len(chunk_train)):
# get position in chunk
position = int(chunk_train[i, 1] - 1)
# store data
data[position] = chunk_train[i, col_ix]
return data
# plot variables horizontally with gaps for missing data
def plot_variables(chunk_train, hours, n_vars=39):
pyplot.figure()
for i in range(n_vars):
# convert target number into column number
col_ix = 3 + i
# mark missing obs for variable
series = variable_to_series(chunk_train, col_ix)
ax = pyplot.subplot(n_vars, 1, i+1)
ax.set_xticklabels([])
ax.set_yticklabels([])
# imputed
imputed = impute_missing(chunk_train, hours, series, col_ix)
# plot imputed
pyplot.plot(imputed)
# plot with missing
pyplot.plot(series)
# show plot
pyplot.show()
# load dataset
train = loadtxt('AirQualityPrediction/naive_train.csv', delimiter=',')
# group data by chunks
train_chunks = to_chunks(train)
# pick one chunk
rows = train_chunks[0]
# prepare sequence of hours for the chunk
hours = variable_to_series(rows, 2)
# interpolate hours
interpolate_hours(hours)
# plot variables
plot_variables(rows, hours)
```
运行该示例将创建一个包含 39 个线图的单个图形:一个用于训练数据集中第一个块中的每个目标变量。
我们可以看到该系列是橙色的,显示原始数据,并且已经估算了间隙并标记为蓝色。
蓝色部分看似合理。
![Line Plots for All Targets in Chunk 1 With Imputed Missing Values](https://img.kancloud.cn/c9/55/c955f04853bc8a51d8e1d5dc1bd67b82_1280x960.jpg)
带有插补缺失值的块 1 中所有目标的线图
我们可以在数据集中具有更多缺失数据的第 4 个块上尝试相同的方法。
```py
# pick one chunk
rows = train_chunks[0]
```
运行该示例会创建相同类型的图形,但在这里我们可以看到填充了估算值的大缺失段。
同样,序列看似合理,甚至在适当的时候显示每日季节周期结构。
![Line Plots for All Targets in Chunk 4 With Imputed Missing Values](https://img.kancloud.cn/71/70/717037a08e68fa54536a197d43af5f25_1280x960.jpg)
带有插补缺失值的块 4 中所有目标的线图
这似乎是一个好的开始;您可以探索其他估算策略,并了解它们如何在线图或最终模型技能方面进行比较。
### 自相关图
现在我们知道如何填写缺失值,我们可以看一下系列数据的自相关图。
自相关图总结了每个观察结果与先前时间步骤的观察结果之间的关系。与部分自相关图一起,它们可用于确定 ARMA 模型的配置。
statsmodels 库提供 [plot_acf()](http://www.statsmodels.org/dev/generated/statsmodels.graphics.tsaplots.plot_acf.html)和 [plot_pacf()](http://www.statsmodels.org/dev/generated/statsmodels.graphics.tsaplots.plot_pacf.html)函数,可分别用于绘制 ACF 和 PACF 图。
我们可以更新 _plot_variables()_ 来创建这些图,这些图是 39 系列中每一个的每种类型之一。这是很多情节。
我们将垂直向左堆叠所有 ACF 图,并在右侧垂直堆叠所有 PACF 图。这是两列 39 个图。我们将绘图所考虑的滞后时间限制为 24 个时间步长(小时),并忽略每个变量与其自身的相关性,因为它是多余的。
下面列出了用于绘制 ACF 和 PACF 图的更新的 _plot_variables()_ 函数。
```py
# plot acf and pacf plots for each imputed variable series
def plot_variables(chunk_train, hours, n_vars=39):
pyplot.figure()
n_plots = n_vars * 2
j = 0
lags = 24
for i in range(1, n_plots, 2):
# convert target number into column number
col_ix = 3 + j
j += 1
# get series
series = variable_to_series(chunk_train, col_ix)
imputed = impute_missing(chunk_train, hours, series, col_ix)
# acf
axis = pyplot.subplot(n_vars, 2, i)
plot_acf(imputed, ax=axis, lags=lags, zero=False)
axis.set_title('')
axis.set_xticklabels([])
axis.set_yticklabels([])
# pacf
axis = pyplot.subplot(n_vars, 2, i+1)
plot_pacf(imputed, ax=axis, lags=lags, zero=False)
axis.set_title('')
axis.set_xticklabels([])
axis.set_yticklabels([])
# show plot
pyplot.show()
```
下面列出了完整的示例。
```py
# acf and pacf plots
from numpy import loadtxt
from numpy import nan
from numpy import isnan
from numpy import count_nonzero
from numpy import unique
from numpy import nanmedian
from matplotlib import pyplot
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf
# split the dataset by 'chunkID', return a list of chunks
def to_chunks(values, chunk_ix=0):
chunks = list()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks.append(values[selection, :])
return chunks
# impute missing data
def impute_missing(rows, hours, series, col_ix):
# count missing observations
n_missing = count_nonzero(isnan(series))
# calculate ratio of missing
ratio = n_missing / float(len(series)) * 100
# check for no data
if ratio == 100.0:
return series
# impute missing using the median value for hour in the series
imputed = list()
for i in range(len(series)):
if isnan(series[i]):
# get all rows with the same hour
matches = rows[rows[:,2]==hours[i]]
# fill with median value
value = nanmedian(matches[:, col_ix])
imputed.append(value)
else:
imputed.append(series[i])
return imputed
# interpolate series of hours (in place) in 24 hour time
def interpolate_hours(hours):
# find the first hour
ix = -1
for i in range(len(hours)):
if not isnan(hours[i]):
ix = i
break
# fill-forward
hour = hours[ix]
for i in range(ix+1, len(hours)):
# increment hour
hour += 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# fill-backward
hour = hours[ix]
for i in range(ix-1, -1, -1):
# decrement hour
hour -= 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# layout a variable with breaks in the data for missing positions
def variable_to_series(chunk_train, col_ix, n_steps=5*24):
# lay out whole series
data = [nan for _ in range(n_steps)]
# mark all available data
for i in range(len(chunk_train)):
# get position in chunk
position = int(chunk_train[i, 1] - 1)
# store data
data[position] = chunk_train[i, col_ix]
return data
# plot acf and pacf plots for each imputed variable series
def plot_variables(chunk_train, hours, n_vars=39):
pyplot.figure()
n_plots = n_vars * 2
j = 0
lags = 24
for i in range(1, n_plots, 2):
# convert target number into column number
col_ix = 3 + j
j += 1
# get series
series = variable_to_series(chunk_train, col_ix)
imputed = impute_missing(chunk_train, hours, series, col_ix)
# acf
axis = pyplot.subplot(n_vars, 2, i)
plot_acf(imputed, ax=axis, lags=lags, zero=False)
axis.set_title('')
axis.set_xticklabels([])
axis.set_yticklabels([])
# pacf
axis = pyplot.subplot(n_vars, 2, i+1)
plot_pacf(imputed, ax=axis, lags=lags, zero=False)
axis.set_title('')
axis.set_xticklabels([])
axis.set_yticklabels([])
# show plot
pyplot.show()
# load dataset
train = loadtxt('AirQualityPrediction/naive_train.csv', delimiter=',')
# group data by chunks
train_chunks = to_chunks(train)
# pick one chunk
rows = train_chunks[0]
# prepare sequence of hours for the chunk
hours = variable_to_series(rows, 2)
# interpolate hours
interpolate_hours(hours)
# plot variables
plot_variables(rows, hours)
```
运行该示例会在训练数据集的第一个块中为目标变量创建一个包含大量图的图形。
您可能需要增加绘图窗口的大小以更好地查看每个绘图的详细信息。
我们可以在左侧看到,大多数 ACF 图在滞后 1-2 步时显示出显着的相关性(高于显着性区域的点),在某些情况下可能滞后 1-3 步,在滞后时缓慢,稳定地减少
同样,在右边,我们可以看到 PACF 图中 1-2 个时间步长的显着滞后,陡峭的下降。
这有力地暗示了自相关过程,其顺序可能是 1,2 或 3,例如 AR(3)。
在左侧的 ACF 图中,我们还可以看到相关性中的每日周期。这可能表明在建模之前对数据进行季节性差异或使用能够进行季节性差异的 AR 模型的一些益处。
![ACF and PACF Plots for Target Variables in Chunk 1](https://img.kancloud.cn/be/8b/be8b59181abc71b8186070d88f7088a2_1280x2018.jpg)
块 1 中目标变量的 ACF 和 PACF 图
我们可以重复对其他块的目标变量的分析,我们看到的图片大致相同。
它表明我们可以通过所有块的所有系列的一般 AR 模型配置逃脱。
## 开发自回归模型
在本节中,我们将为估算的目标序列数据开发一个自回归模型。
第一步是实现一个通用函数,用于为每个块进行预测。
该功能为训练数据集和测试集的输入列(块 ID,块和小时的位置)执行任务,并返回具有 _[chunk] [变量] [时间]的预期 3D 格式的所有块的预测 _。
该函数枚举预测中的块,然后枚举 39 个目标列,调用另一个名为 _forecast_variable()_ 的新函数,以便对给定目标变量的每个提前期进行预测。
完整的功能如下所列。
```py
# forecast for each chunk, returns [chunk][variable][time]
def forecast_chunks(train_chunks, test_input):
lead_times = get_lead_times()
predictions = list()
# enumerate chunks to forecast
for i in range(len(train_chunks)):
# prepare sequence of hours for the chunk
hours = variable_to_series(train_chunks[i], 2)
# interpolate hours
interpolate_hours(hours)
# enumerate targets for chunk
chunk_predictions = list()
for j in range(39):
yhat = forecast_variable(hours, train_chunks[i], test_input[i], lead_times, j)
chunk_predictions.append(yhat)
chunk_predictions = array(chunk_predictions)
predictions.append(chunk_predictions)
return array(predictions)
```
我们现在可以实现 _forecast_variable()_ 的一个版本。
对于每个变量,我们首先检查是否没有数据(例如所有 NaN),如果是,我们返回每个预测提前期的 NaN 预测。
然后我们使用 _variable_to_series()_ 从变量创建一个系列,然后通过调用 _impute_missing()_ 使用系列中的中位数来计算缺失值,两者都是在上一节。
最后,我们调用一个名为 _fit_and_forecast()_ 的新函数,该函数适合模型并预测 10 个预测前置时间。
```py
# forecast all lead times for one variable
def forecast_variable(hours, chunk_train, chunk_test, lead_times, target_ix):
# convert target number into column number
col_ix = 3 + target_ix
# check for no data
if not has_data(chunk_train[:, col_ix]):
forecast = [nan for _ in range(len(lead_times))]
return forecast
# get series
series = variable_to_series(chunk_train, col_ix)
# impute
imputed = impute_missing(chunk_train, hours, series, col_ix)
# fit AR model and forecast
forecast = fit_and_forecast(imputed)
return forecast
```
我们将 AR 模型适用于给定的推算系列。为此,我们将使用 [statsmodels ARIMA 类](http://www.statsmodels.org/dev/generated/statsmodels.tsa.arima_model.ARIMA.html)。如果您想探索任何 ARIMA 模型系列,我们将使用 ARIMA 代替 AR 来提供一些灵活性。
首先,我们必须定义模型,包括自回归过程的顺序,例如 AR(1)。
```py
# define the model
model = ARIMA(series, order=(1,0,0))
```
接下来,该模型适用于推算系列。我们通过将 _disp_ 设置为 _False_ 来关闭拟合期间的详细信息。
```py
# fit the model
model_fit = model.fit(disp=False)
```
然后使用拟合模型预测系列结束后的 72 小时。
```py
# forecast 72 hours
yhat = model_fit.predict(len(series), len(series)+72)
```
我们只对特定的提前期感兴趣,因此我们准备一系列提前期,减 1 以将它们转换为数组索引,然后使用它们选择我们感兴趣的 10 个预测提前期的值。
```py
# extract lead times
lead_times = array(get_lead_times())
indices = lead_times - 1
return yhat[indices]
```
statsmodels ARIMA 模型使用线性代数库来拟合封面下的模型,有时适合过程在某些数据上可能不稳定。因此,它可以抛出异常或报告大量警告。
我们将捕获异常并返回 _NaN_ 预测,并在拟合和评估期间忽略所有警告。
下面的 _fit_and_forecast()_ 函数将所有这些联系在一起。
```py
# fit AR model and generate a forecast
def fit_and_forecast(series):
# define the model
model = ARIMA(series, order=(1,0,0))
# return a nan forecast in case of exception
try:
# ignore statsmodels warnings
with catch_warnings():
filterwarnings("ignore")
# fit the model
model_fit = model.fit(disp=False)
# forecast 72 hours
yhat = model_fit.predict(len(series), len(series)+72)
# extract lead times
lead_times = array(get_lead_times())
indices = lead_times - 1
return yhat[indices]
except:
return [nan for _ in range(len(get_lead_times()))]
```
我们现在准备评估 207 个训练块中每个系列中 39 个系列中每个系列的自回归过程。
我们将从测试 AR(1)过程开始。
完整的代码示例如下所示。
```py
# autoregression forecast
from numpy import loadtxt
from numpy import nan
from numpy import isnan
from numpy import count_nonzero
from numpy import unique
from numpy import array
from numpy import nanmedian
from statsmodels.tsa.arima_model import ARIMA
from matplotlib import pyplot
from warnings import catch_warnings
from warnings import filterwarnings
# split the dataset by 'chunkID', return a list of chunks
def to_chunks(values, chunk_ix=0):
chunks = list()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks.append(values[selection, :])
return chunks
# return a list of relative forecast lead times
def get_lead_times():
return [1, 2, 3, 4, 5, 10, 17, 24, 48, 72]
# interpolate series of hours (in place) in 24 hour time
def interpolate_hours(hours):
# find the first hour
ix = -1
for i in range(len(hours)):
if not isnan(hours[i]):
ix = i
break
# fill-forward
hour = hours[ix]
for i in range(ix+1, len(hours)):
# increment hour
hour += 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# fill-backward
hour = hours[ix]
for i in range(ix-1, -1, -1):
# decrement hour
hour -= 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# return true if the array has any non-nan values
def has_data(data):
return count_nonzero(isnan(data)) < len(data)
# impute missing data
def impute_missing(rows, hours, series, col_ix):
# impute missing using the median value for hour in the series
imputed = list()
for i in range(len(series)):
if isnan(series[i]):
# get all rows with the same hour
matches = rows[rows[:,2]==hours[i]]
# fill with median value
value = nanmedian(matches[:, col_ix])
if isnan(value):
value = 0.0
imputed.append(value)
else:
imputed.append(series[i])
return imputed
# layout a variable with breaks in the data for missing positions
def variable_to_series(chunk_train, col_ix, n_steps=5*24):
# lay out whole series
data = [nan for _ in range(n_steps)]
# mark all available data
for i in range(len(chunk_train)):
# get position in chunk
position = int(chunk_train[i, 1] - 1)
# store data
data[position] = chunk_train[i, col_ix]
return data
# fit AR model and generate a forecast
def fit_and_forecast(series):
# define the model
model = ARIMA(series, order=(1,0,0))
# return a nan forecast in case of exception
try:
# ignore statsmodels warnings
with catch_warnings():
filterwarnings("ignore")
# fit the model
model_fit = model.fit(disp=False)
# forecast 72 hours
yhat = model_fit.predict(len(series), len(series)+72)
# extract lead times
lead_times = array(get_lead_times())
indices = lead_times - 1
return yhat[indices]
except:
return [nan for _ in range(len(get_lead_times()))]
# forecast all lead times for one variable
def forecast_variable(hours, chunk_train, chunk_test, lead_times, target_ix):
# convert target number into column number
col_ix = 3 + target_ix
# check for no data
if not has_data(chunk_train[:, col_ix]):
forecast = [nan for _ in range(len(lead_times))]
return forecast
# get series
series = variable_to_series(chunk_train, col_ix)
# impute
imputed = impute_missing(chunk_train, hours, series, col_ix)
# fit AR model and forecast
forecast = fit_and_forecast(imputed)
return forecast
# forecast for each chunk, returns [chunk][variable][time]
def forecast_chunks(train_chunks, test_input):
lead_times = get_lead_times()
predictions = list()
# enumerate chunks to forecast
for i in range(len(train_chunks)):
# prepare sequence of hours for the chunk
hours = variable_to_series(train_chunks[i], 2)
# interpolate hours
interpolate_hours(hours)
# enumerate targets for chunk
chunk_predictions = list()
for j in range(39):
yhat = forecast_variable(hours, train_chunks[i], test_input[i], lead_times, j)
chunk_predictions.append(yhat)
chunk_predictions = array(chunk_predictions)
predictions.append(chunk_predictions)
return array(predictions)
# convert the test dataset in chunks to [chunk][variable][time] format
def prepare_test_forecasts(test_chunks):
predictions = list()
# enumerate chunks to forecast
for rows in test_chunks:
# enumerate targets for chunk
chunk_predictions = list()
for j in range(3, rows.shape[1]):
yhat = rows[:, j]
chunk_predictions.append(yhat)
chunk_predictions = array(chunk_predictions)
predictions.append(chunk_predictions)
return array(predictions)
# calculate the error between an actual and predicted value
def calculate_error(actual, predicted):
# give the full actual value if predicted is nan
if isnan(predicted):
return abs(actual)
# calculate abs difference
return abs(actual - predicted)
# evaluate a forecast in the format [chunk][variable][time]
def evaluate_forecasts(predictions, testset):
lead_times = get_lead_times()
total_mae, times_mae = 0.0, [0.0 for _ in range(len(lead_times))]
total_c, times_c = 0, [0 for _ in range(len(lead_times))]
# enumerate test chunks
for i in range(len(test_chunks)):
# convert to forecasts
actual = testset[i]
predicted = predictions[i]
# enumerate target variables
for j in range(predicted.shape[0]):
# enumerate lead times
for k in range(len(lead_times)):
# skip if actual in nan
if isnan(actual[j, k]):
continue
# calculate error
error = calculate_error(actual[j, k], predicted[j, k])
# update statistics
total_mae += error
times_mae[k] += error
total_c += 1
times_c[k] += 1
# normalize summed absolute errors
total_mae /= total_c
times_mae = [times_mae[i]/times_c[i] for i in range(len(times_mae))]
return total_mae, times_mae
# summarize scores
def summarize_error(name, total_mae, times_mae):
# print summary
lead_times = get_lead_times()
formatted = ['+%d %.3f' % (lead_times[i], times_mae[i]) for i in range(len(lead_times))]
s_scores = ', '.join(formatted)
print('%s: [%.3f MAE] %s' % (name, total_mae, s_scores))
# plot summary
pyplot.plot([str(x) for x in lead_times], times_mae, marker='.')
pyplot.show()
# load dataset
train = loadtxt('AirQualityPrediction/naive_train.csv', delimiter=',')
test = loadtxt('AirQualityPrediction/naive_test.csv', delimiter=',')
# group data by chunks
train_chunks = to_chunks(train)
test_chunks = to_chunks(test)
# forecast
test_input = [rows[:, :3] for rows in test_chunks]
forecast = forecast_chunks(train_chunks, test_input)
# evaluate forecast
actual = prepare_test_forecasts(test_chunks)
total_mae, times_mae = evaluate_forecasts(forecast, actual)
# summarize forecast
summarize_error('AR', total_mae, times_mae)
```
首先运行示例报告测试集的总体 MAE,然后是每个预测提前期的 MAE。
我们可以看到该模型实现了约 0.492 的 MAE,小于通过朴素持久模型实现的 MAE 0.520。这表明该方法确实具有一定的技巧。
```py
AR: [0.492 MAE] +1 0.225, +2 0.342, +3 0.410, +4 0.475, +5 0.512, +10 0.593, +17 0.586, +24 0.588, +48 0.588, +72 0.604
```
创建每个预测提前期的 MAE 线图,显示预测误差随预测提前期的增加而线性增加。
![MAE vs Forecast Lead Time for AR(1)](https://img.kancloud.cn/d8/64/d86450b7405cb679010c66b857a56d7a_1280x960.jpg)
AR 与预测 AR 的预测时间(1)
我们可以更改代码以测试其他 AR 模型。具体是 _fit_and_forecast()_ 函数中 ARIMA 模型的顺序。
AR(2)模型可以定义为:
```py
model = ARIMA(series, order=(2,0,0))
```
使用此更新运行代码显示错误进一步下降到总体 MAE 约 0.490。
```py
AR: [0.490 MAE] +1 0.229, +2 0.342, +3 0.412, +4 0.470, +5 0.503, +10 0.563, +17 0.576, +24 0.605, +48 0.597, +72 0.608
```
我们也可以尝试 AR(3):
```py
model = ARIMA(series, order=(3,0,0))
```
使用更新重新运行示例显示与 AR(2)相比整体 MAE 增加。
AR(2)可能是一个很好的全局级配置,尽管预计为每个变量或每个系列量身定制的模型可能总体上表现更好。
```py
AR: [0.491 MAE] +1 0.232, +2 0.345, +3 0.412, +4 0.472, +5 0.504, +10 0.556, +17 0.575, +24 0.607, +48 0.599, +72 0.611
```
## 具有全球归因策略的自回归模型
我们可以使用替代插补策略来评估 AR(2)模型。
我们可以计算所有块中变量的相同值,而不是计算块中系列中相同小时的中值。
我们可以更新 _impute_missing()_ 以将所有训练块作为参数,然后从给定小时的所有块收集行,以计算用于估算的中值。下面列出了该功能的更新版本。
```py
# impute missing data
def impute_missing(train_chunks, rows, hours, series, col_ix):
# impute missing using the median value for hour in all series
imputed = list()
for i in range(len(series)):
if isnan(series[i]):
# collect all rows across all chunks for the hour
all_rows = list()
for rows in train_chunks:
[all_rows.append(row) for row in rows[rows[:,2]==hours[i]]]
# calculate the central tendency for target
all_rows = array(all_rows)
# fill with median value
value = nanmedian(all_rows[:, col_ix])
if isnan(value):
value = 0.0
imputed.append(value)
else:
imputed.append(series[i])
return imputed
```
为了将 train_chunks 传递给 _impute_missing()_ 函数,我们必须更新 _forecast_variable()_ 函数以将 _train_chunks_ 作为参数并传递给它,然后更新 _forecast_chunks()_ 函数以传递 _train_chunks_ 。
下面列出了使用全局插补策略的完整示例。
```py
# autoregression forecast with global impute strategy
from numpy import loadtxt
from numpy import nan
from numpy import isnan
from numpy import count_nonzero
from numpy import unique
from numpy import array
from numpy import nanmedian
from statsmodels.tsa.arima_model import ARIMA
from matplotlib import pyplot
from warnings import catch_warnings
from warnings import filterwarnings
# split the dataset by 'chunkID', return a list of chunks
def to_chunks(values, chunk_ix=0):
chunks = list()
# get the unique chunk ids
chunk_ids = unique(values[:, chunk_ix])
# group rows by chunk id
for chunk_id in chunk_ids:
selection = values[:, chunk_ix] == chunk_id
chunks.append(values[selection, :])
return chunks
# return a list of relative forecast lead times
def get_lead_times():
return [1, 2, 3, 4, 5, 10, 17, 24, 48, 72]
# interpolate series of hours (in place) in 24 hour time
def interpolate_hours(hours):
# find the first hour
ix = -1
for i in range(len(hours)):
if not isnan(hours[i]):
ix = i
break
# fill-forward
hour = hours[ix]
for i in range(ix+1, len(hours)):
# increment hour
hour += 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# fill-backward
hour = hours[ix]
for i in range(ix-1, -1, -1):
# decrement hour
hour -= 1
# check for a fill
if isnan(hours[i]):
hours[i] = hour % 24
# return true if the array has any non-nan values
def has_data(data):
return count_nonzero(isnan(data)) < len(data)
# impute missing data
def impute_missing(train_chunks, rows, hours, series, col_ix):
# impute missing using the median value for hour in all series
imputed = list()
for i in range(len(series)):
if isnan(series[i]):
# collect all rows across all chunks for the hour
all_rows = list()
for rows in train_chunks:
[all_rows.append(row) for row in rows[rows[:,2]==hours[i]]]
# calculate the central tendency for target
all_rows = array(all_rows)
# fill with median value
value = nanmedian(all_rows[:, col_ix])
if isnan(value):
value = 0.0
imputed.append(value)
else:
imputed.append(series[i])
return imputed
# layout a variable with breaks in the data for missing positions
def variable_to_series(chunk_train, col_ix, n_steps=5*24):
# lay out whole series
data = [nan for _ in range(n_steps)]
# mark all available data
for i in range(len(chunk_train)):
# get position in chunk
position = int(chunk_train[i, 1] - 1)
# store data
data[position] = chunk_train[i, col_ix]
return data
# fit AR model and generate a forecast
def fit_and_forecast(series):
# define the model
model = ARIMA(series, order=(2,0,0))
# return a nan forecast in case of exception
try:
# ignore statsmodels warnings
with catch_warnings():
filterwarnings("ignore")
# fit the model
model_fit = model.fit(disp=False)
# forecast 72 hours
yhat = model_fit.predict(len(series), len(series)+72)
# extract lead times
lead_times = array(get_lead_times())
indices = lead_times - 1
return yhat[indices]
except:
return [nan for _ in range(len(get_lead_times()))]
# forecast all lead times for one variable
def forecast_variable(hours, train_chunks, chunk_train, chunk_test, lead_times, target_ix):
# convert target number into column number
col_ix = 3 + target_ix
# check for no data
if not has_data(chunk_train[:, col_ix]):
forecast = [nan for _ in range(len(lead_times))]
return forecast
# get series
series = variable_to_series(chunk_train, col_ix)
# impute
imputed = impute_missing(train_chunks, chunk_train, hours, series, col_ix)
# fit AR model and forecast
forecast = fit_and_forecast(imputed)
return forecast
# forecast for each chunk, returns [chunk][variable][time]
def forecast_chunks(train_chunks, test_input):
lead_times = get_lead_times()
predictions = list()
# enumerate chunks to forecast
for i in range(len(train_chunks)):
# prepare sequence of hours for the chunk
hours = variable_to_series(train_chunks[i], 2)
# interpolate hours
interpolate_hours(hours)
# enumerate targets for chunk
chunk_predictions = list()
for j in range(39):
yhat = forecast_variable(hours, train_chunks, train_chunks[i], test_input[i], lead_times, j)
chunk_predictions.append(yhat)
chunk_predictions = array(chunk_predictions)
predictions.append(chunk_predictions)
return array(predictions)
# convert the test dataset in chunks to [chunk][variable][time] format
def prepare_test_forecasts(test_chunks):
predictions = list()
# enumerate chunks to forecast
for rows in test_chunks:
# enumerate targets for chunk
chunk_predictions = list()
for j in range(3, rows.shape[1]):
yhat = rows[:, j]
chunk_predictions.append(yhat)
chunk_predictions = array(chunk_predictions)
predictions.append(chunk_predictions)
return array(predictions)
# calculate the error between an actual and predicted value
def calculate_error(actual, predicted):
# give the full actual value if predicted is nan
if isnan(predicted):
return abs(actual)
# calculate abs difference
return abs(actual - predicted)
# evaluate a forecast in the format [chunk][variable][time]
def evaluate_forecasts(predictions, testset):
lead_times = get_lead_times()
total_mae, times_mae = 0.0, [0.0 for _ in range(len(lead_times))]
total_c, times_c = 0, [0 for _ in range(len(lead_times))]
# enumerate test chunks
for i in range(len(test_chunks)):
# convert to forecasts
actual = testset[i]
predicted = predictions[i]
# enumerate target variables
for j in range(predicted.shape[0]):
# enumerate lead times
for k in range(len(lead_times)):
# skip if actual in nan
if isnan(actual[j, k]):
continue
# calculate error
error = calculate_error(actual[j, k], predicted[j, k])
# update statistics
total_mae += error
times_mae[k] += error
total_c += 1
times_c[k] += 1
# normalize summed absolute errors
total_mae /= total_c
times_mae = [times_mae[i]/times_c[i] for i in range(len(times_mae))]
return total_mae, times_mae
# summarize scores
def summarize_error(name, total_mae, times_mae):
# print summary
lead_times = get_lead_times()
formatted = ['+%d %.3f' % (lead_times[i], times_mae[i]) for i in range(len(lead_times))]
s_scores = ', '.join(formatted)
print('%s: [%.3f MAE] %s' % (name, total_mae, s_scores))
# plot summary
pyplot.plot([str(x) for x in lead_times], times_mae, marker='.')
pyplot.show()
# load dataset
train = loadtxt('AirQualityPrediction/naive_train.csv', delimiter=',')
test = loadtxt('AirQualityPrediction/naive_test.csv', delimiter=',')
# group data by chunks
train_chunks = to_chunks(train)
test_chunks = to_chunks(test)
# forecast
test_input = [rows[:, :3] for rows in test_chunks]
forecast = forecast_chunks(train_chunks, test_input)
# evaluate forecast
actual = prepare_test_forecasts(test_chunks)
total_mae, times_mae = evaluate_forecasts(forecast, actual)
# summarize forecast
summarize_error('AR', total_mae, times_mae)
```
运行该示例显示整体 MAE 进一步下降至约 0.487。
探索插补策略可能会很有趣,这种策略可以根据系列中缺少的数据量或填充的间隙来替换用于填充缺失值的方法。
```py
AR: [0.487 MAE] +1 0.228, +2 0.339, +3 0.409, +4 0.469, +5 0.499, +10 0.560, +17 0.573, +24 0.600, +48 0.595, +72 0.606
```
还创建了 MAE 与预测提前期的线图。
![MAE vs Forecast Lead Time for AR(2) Impute With Global Strategy](https://img.kancloud.cn/7c/2a/7c2a4e0ce5d6a5e9a0eea517654d2bf5_1280x960.jpg)
MAE 与 AR 的预测提前期(2)对全球战略的影响
## 扩展
本节列出了一些扩展您可能希望探索的教程的想法。
* **估算策略**。为每个系列中缺失的数据开发并评估另一种替代插补策略。
* **数据准备**。探索应用于每种技术的数据准备技术是否可以提高模型技能,例如标准化,标准化和功率变换。
* **差异**。探索差分(例如 1 步或 24 步(季节差分))是否可以使每个系列静止,从而产生更好的预测。
如果你探索任何这些扩展,我很想知道。
## 进一步阅读
如果您希望深入了解,本节将提供有关该主题的更多资源。
### 帖子
* [标准多变量,多步骤和多站点时间序列预测问题](https://machinelearningmastery.com/standard-multivariate-multi-step-multi-site-time-series-forecasting-problem/)
* [自相关和部分自相关的温和介绍](https://machinelearningmastery.com/gentle-introduction-autocorrelation-partial-autocorrelation/)
* [如何使用 Python 网格搜索 ARIMA 模型超参数](https://machinelearningmastery.com/grid-search-arima-hyperparameters-with-python/)
### API
* [statsmodels.graphics.tsaplots.plot_acf API](http://www.statsmodels.org/dev/generated/statsmodels.graphics.tsaplots.plot_acf.html)
* [statsmodels.graphics.tsaplots.plot_pacf API](http://www.statsmodels.org/dev/generated/statsmodels.graphics.tsaplots.plot_pacf.html)
* [statsmodels.tsa.arima_model.ARIMA API](http://www.statsmodels.org/dev/generated/statsmodels.tsa.arima_model.ARIMA.html)
### 用品
* [EMC 数据科学全球黑客马拉松(空气质量预测)](https://www.kaggle.com/c/dsg-hackathon/data)
* [将所有东西放入随机森林:Ben Hamner 赢得空气质量预测黑客马拉松](http://blog.kaggle.com/2012/05/01/chucking-everything-into-a-random-forest-ben-hamner-on-winning-the-air-quality-prediction-hackathon/)
* [EMC 数据科学全球黑客马拉松(空气质量预测)的获奖代码](https://github.com/benhamner/Air-Quality-Prediction-Hackathon-Winning-Model)
* [分区模型的一般方法?](https://www.kaggle.com/c/dsg-hackathon/discussion/1821)
## 摘要
在本教程中,您了解了如何为多变量空气污染时间序列开发多步时间序列预测的自回归模型。
具体来说,你学到了:
* 如何分析和计算时间序列数据的缺失值。
* 如何开发和评估多步时间序列预测的自回归模型。
* 如何使用备用数据插补方法改进自回归模型。
你有任何问题吗?
在下面的评论中提出您的问题,我会尽力回答。
- 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&amp; 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 步迷你课程