时间序列预测:使用 LSTM 模型预测股票价格
在这篇文章中,我将向你展示如何使用预测 LSTM 模型来预测股票价格
作者创作的人物。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
1.介绍
1.1.时间序列和预测模型
传统上,大多数机器学习(ML)模型使用一些观察值(样本/例子)作为输入特征,但是在数据中没有时间 维度。
时间序列预测模型是能够根据先前 观测 值预测 未来值的模型。时间序列预测广泛用于非平稳数据。非平稳数据被称为其统计属性(如平均值和标准偏差)不随时间保持不变,而是随时间变化的数据。
这些非平稳输入数据(用作这些模型的输入)通常被称为时间序列。时间序列的一些例子包括随时间变化的温度值、随时间变化的股票价格、随时间变化的房屋价格等。因此,输入是一个信号(时间序列),它是由在时间中连续进行的观察定义的**。**
时间序列是按时间顺序进行的一系列观察。
时间序列的一个例子。作者用 Python 创作的情节。
观察:时序数据记录在离散 时间 刻度上。
免责声明(在我们继续之前):已经有人尝试使用时间序列分析算法来预测股票价格,尽管它们仍然不能用于在真实市场中下注。这只是一篇教程文章,并不打算以任何方式“指导”人们购买股票。
2.LSTM 模式
长短期记忆 ( LSTM )是一种用于深度学习领域的人工递归神经网络(RNN)架构。与标准的前馈神经网络不同,LSTM 有反馈连接。它不仅可以处理单个数据点(例如图像),还可以处理整个数据序列(例如语音或视频输入)。
LSTM 型号能够储存一段时间的信息。
换句话说,它们有记忆能力。记住 LSTM 代表长短期记忆模型。
当我们处理时间序列或顺序数据时,这个特性是非常有用的。当使用 LSTM 模型时,我们可以自由决定存储什么信息,丢弃什么信息。我们使用“门”来实现。对 LSTM 的深入理解超出了这篇文章的范围,但是如果你有兴趣了解更多,看看这篇文章末尾的参考资料。
如果你想在交互式路线图和活跃的学习社区的支持下自学数据科学,看看这个资源:https://aigents.co/learn
3.获取股票价格历史数据
感谢雅虎财经我们可以免费获得的数据。使用以下链接获取特斯拉的股价历史记录:https://finance.yahoo.com/quote/TSLA/history?周期 1=1436486400 &周期 2=1594339200 &间隔=1d &过滤器=历史&频率=1d
您应该看到以下内容:
点击下载并保存**。csv** 文件本地保存在您的计算机上。
数据从 2015 到现在( 2020 )!
4.Python 工作示例
需要的模块:Keras,Tensorflow,Pandas,Scikit-Learn & Numpy
我们将构建一个多层 LSTM 递归神经网络来预测一系列值中的最后一个值,即本例中的特斯拉股票价格。
让加载和数据和检查它们:
import math
import matplotlib.pyplot as plt
import keras
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
from keras.layers import *
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import train_test_split
from keras.callbacks import EarlyStoppingdf=pd.read_csv("TSLA.csv")
print(‘Number of rows and columns:’, df.shape)
df.head(5)
上述代码的输出
下一步是将数据分割成训练和测试集合,以避免过度拟合,并能够调查我们模型的泛化能力。要了解更多关于过度拟合的信息,请阅读本文:
[## 你的模型是否过拟合?或者不合身?python 中使用神经网络的示例
过拟合,欠拟合,泛化能力,交叉验证。一切都简单解释了。我还提供了一个…
towardsdatascience.com](/is-your-model-overfitting-or-maybe-underfitting-an-example-using-a-neural-network-in-python-4faf155398d2)
要预测的目标值将是“收盘时的股价值。
training_set = df.iloc[:800, 1:2].values
test_set = df.iloc[800:, 1:2].values
在模型 拟合之前,归一化数据不失为一个好主意。这将提高性能。您可以在此阅读更多关于最小-最大缩放器的信息:
[## 关于 Python 中的最小-最大规范化,您需要知道的一切
在这篇文章中,我将解释什么是最小-最大缩放,什么时候使用它,以及如何使用 scikit 在 Python 中实现它
towardsdatascience.com](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79)
让我们构建具有 1 天滞后时间**(滞后 1)的输入要素:**
# Feature Scaling
sc = MinMaxScaler(feature_range = (0, 1))
training_set_scaled = sc.fit_transform(training_set)# Creating a data structure with 60 time-steps and 1 output
X_train = []
y_train = []
for i in range(60, 800):
X_train.append(training_set_scaled[i-60:i, 0])
y_train.append(training_set_scaled[i, 0])
X_train, y_train = np.array(X_train), np.array(y_train)X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
#(740, 60, 1)
现在我们已经将数据整形为以下格式(#值、#时间步长、#1 维输出)。
**现在,该建立模型了。**我们将建立有 50 个神经元的 LSTM 和 4 个隐含层。最后,我们将在输出层分配 1 个神经元用于预测标准化的股票价格。我们将使用 MSE 损失函数和 Adam 随机梯度下降优化器。
注意:以下需要一些时间(~ 5 分钟)。
model = Sequential()#Adding the first LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50, return_sequences = True, input_shape = (X_train.shape[1], 1)))
model.add(Dropout(0.2))# Adding a second LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50, return_sequences = True))
model.add(Dropout(0.2))# Adding a third LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50, return_sequences = True))
model.add(Dropout(0.2))# Adding a fourth LSTM layer and some Dropout regularisation
model.add(LSTM(units = 50))
model.add(Dropout(0.2))# Adding the output layer
model.add(Dense(units = 1))# Compiling the RNN
model.compile(optimizer = 'adam', loss = 'mean_squared_error')# Fitting the RNN to the Training set
model.fit(X_train, y_train, epochs = 100, batch_size = 32)
装配完成后,您应该会看到类似这样的内容:
准备测试数据(重塑它们):
# Getting the predicted stock price of 2017
dataset_train = df.iloc[:800, 1:2]
dataset_test = df.iloc[800:, 1:2]dataset_total = pd.concat((dataset_train, dataset_test), axis = 0)inputs = dataset_total[len(dataset_total) - len(dataset_test) - 60:].valuesinputs = inputs.reshape(-1,1)
inputs = sc.transform(inputs)
X_test = []
for i in range(60, 519):
X_test.append(inputs[i-60:i, 0])
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))print(X_test.shape)
# (459, 60, 1)
使用测试集进行预测
predicted_stock_price = model.predict(X_test)
predicted_stock_price = sc.inverse_transform(predicted_stock_price)
现在让我们来看看结果:
# Visualising the results
plt.plot(df.loc[800:, ‘Date’],dataset_test.values, color = ‘red’, label = ‘Real TESLA Stock Price’)
plt.plot(df.loc[800:, ‘Date’],predicted_stock_price, color = ‘blue’, label = ‘Predicted TESLA Stock Price’)
plt.xticks(np.arange(0,459,50))
plt.title('TESLA Stock Price Prediction')
plt.xlabel('Time')
plt.ylabel('TESLA Stock Price')
plt.legend()
plt.show()
5.结果
使用滞后 1(即一天的步长):
观察:2020 年 3 月因新冠肺炎封锁而大幅下跌!
我们可以清楚地看到,我们的模型表现得非常好。它能够准确地跟踪大多数不可接受的上涨/下跌,但是,对于最近的日期戳,我们可以看到,与股票价格的实际值相比,模型预期(预测)的值较低。
关于滞后的一个注记
本文中最初选择的延迟为 1,即使用 1 天的步长。这可以通过修改构建 3D 输入的代码来轻松改变。
示例:可以更改以下两个代码块:
X_train = []
y_train = []
for i in range(60, 800):
X_train.append(training_set_scaled[i-60:i, 0])
y_train.append(training_set_scaled[i, 0])
和
X_test = []
y_test = []
for i in range(60, 519):
X_test.append(inputs[i-60:i, 0])
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
采用以下新代码:
X_train = []
y_train = []
for i in range(60, 800):
X_train.append(training_set_scaled[i-50:i, 0])
y_train.append(training_set_scaled[i, 0])
和
X_test = []
y_test = []
for i in range(60, 519):
X_test.append(inputs[i-50:i, 0])
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
在这种情况下,结果如下所示:
那都是乡亲们!希望你喜欢这篇文章!
看看我在另一篇文章中用来预测谷歌股价的脸书先知模型。
使用可从《先知脸书》公开获得的预测模型预测股票价格
towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-facebooks-prophet-model-9ee1657132b5)
也可以看看我最近用 ARIMA 模型写的文章:
在这篇文章中,我将向你展示如何使用预测 ARIMA 模型来预测特斯拉的股票价格
towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-an-arima-model-2e3b3080bd70)
参考
[1]https://colah.github.io/posts/2015-08-Understanding-LSTMs/
[2]https://en.wikipedia.org/wiki/Long_short-term_memory
敬请关注并支持这一努力
如果你喜欢这篇文章并且觉得它有用,关注我就可以看到我所有的新帖子。
有问题吗?把它们作为评论贴出来,我会尽快回复。
最新帖子
使用可从《先知脸书》公开获得的预测模型预测股票价格
towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-facebooks-prophet-model-9ee1657132b5) [## 最佳免费数据科学资源:免费书籍和在线课程
最有用的免费书籍和在线课程,适合想了解更多数据科学知识的人。
medium.com](https://medium.com/@seralouk/the-best-free-data-science-resources-free-books-online-courses-9c4a2df194e5) [## 用新冠肺炎假设的例子解释 ROC 曲线:二分类和多分类…
在这篇文章中,我清楚地解释了什么是 ROC 曲线以及如何阅读它。我用一个新冠肺炎的例子来说明我的观点,我…
towardsdatascience.com](/roc-curve-explained-using-a-covid-19-hypothetical-example-binary-multi-class-classification-bab188ea869c) [## 支持向量机(SVM)解释清楚:分类问题的 python 教程…
在这篇文章中,我解释了支持向量机的核心,为什么以及如何使用它们。此外,我还展示了如何绘制支持…
towardsdatascience.com](/support-vector-machines-svm-clearly-explained-a-python-tutorial-for-classification-problems-29c539f3ad8) [## PCA 清楚地解释了——如何、何时、为什么使用它以及特性的重要性:Python 指南
在这篇文章中,我解释了什么是 PCA,何时以及为什么使用它,以及如何使用 scikit-learn 在 Python 中实现它。还有…
towardsdatascience.com](/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e) [## 关于 Python 中的最小-最大规范化,您需要知道的一切
在这篇文章中,我将解释什么是最小-最大缩放,什么时候使用它,以及如何使用 scikit 在 Python 中实现它
towardsdatascience.com](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79) [## Scikit-Learn 的标准定标器如何工作
在这篇文章中,我将解释为什么以及如何使用 scikit-learn 应用标准化
towardsdatascience.com](/how-and-why-to-standardize-your-data-996926c2c832)
和我联系
- LinkedIn:https://www.linkedin.com/in/serafeim-loukas/
- 研究之门:https://www.researchgate.net/profile/Serafeim_Loukas
- https://people.epfl.ch/serafeim.loukasEPFL简介 : 美国
- 栈 溢出:【https://stackoverflow.com/users/5025009/seralouk】T4
时间序列预测:用脸书的先知模型预测股票价格
在这篇文章中,我将向你展示如何使用脸书数据科学团队公开发布的预测模型来预测股票价格
作者用 Python 创建的图。
1.介绍
1.1.时间序列和预测模型
传统上,大多数机器学习(ML)模型使用一些观察值(样本/实例)作为输入特征,但数据中没有时间 维度。
时间序列预测模型是能够根据先前 观测 值预测 未来值的模型。时间序列预测广泛用于非平稳数据。非平稳数据被称为统计属性(如平均值和标准偏差)不随时间保持不变,而是随时间变化的数据。
这些非平稳输入数据(用作这些模型的输入)通常被称为时间序列。时间序列的一些例子包括随时间变化的温度值、随时间变化的股票价格、随时间变化的房屋价格等。因此,输入是一个信号(时间序列),它是由在时间中连续获得的观察值定义的。
时间序列是按时间顺序进行的一系列观察。
时间序列的一个例子。作者用 Python 创作的情节。
观察:时序数据记录在离散时间刻度时间刻度上。
免责声明(在我们继续之前):已经有人尝试使用时间序列分析算法来预测股票价格,尽管它们仍然不能用于在真实市场中下注。这只是一篇教程文章,并不打算以任何方式“指导”人们购买股票。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
如果你想在交互式路线图和活跃的学习社区的支持下自学数据科学,看看这个资源:https://aigents.co/learn
1.2 预测模型:脸书的预言家
最常用的预测模型是 自回归 模型。简而言之,自回归模型规定输出变量线性依赖于它自己以前的值和一个随机项(一个不完全可预测的项)。
最近,为了开发一个可以在时间序列数据中捕捉季节性的模型,脸书开发了著名的 Prophet 模型,每个人都可以公开获得。在本文中,我们将使用这个最先进的模型: Prophet 模型。 Prophet 通过实现 加法回归 模型,能够捕捉每日**、每周、每年的季节性以及假日 效果。**
Prophet 模型背后的数学方程式定义为:
y(t) = g(t) + s(t) + h(t) + e(t)
- 其中,g(t)代表趋势。Prophet 使用分段线性模型进行趋势预测。
- s(t)代表周期性变化(每周、每月、每年)。
- h(t)代表假期的影响(回想一下:假期影响业务)。
- e(t)是误差项。
Prophet 模型拟合过程通常非常快(即使对于成千上万的观察),并且不需要任何数据预处理。它还处理缺失数据和异常值。
在本文中,我们将使用先知模式来预测谷歌未来的股价。
我们开始吧!
——我的邮件列表只需 5 秒:https://seralouk.medium.com/subscribe
-成为会员支持我:https://seralouk.medium.com/membership
2.获取股票价格历史数据
感谢雅虎财经我们可以免费获得的数据。使用以下链接获取谷歌的股价历史:https://finance.yahoo.com/quote/GOOG/history?周期 1=1433548800 &周期 2=1591833600 &间隔=1d &过滤器=历史&频率=1d
您应该看到以下内容:
如何下载股价历史?
点击下载并保存**。csv** 文件本地保存在您的计算机上。
数据是从 2015 到现在( 2020 )!
3。Python 工作示例
现在有了数据,就来考察数据,建立模型,预测股价吧!
3.1。加载&检查数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# Load the dataset using pandas
data = pd.read_csv("/Users/loukas/Downloads/GOOG.csv")
data.head(5)
上面的代码应该打印出以下内容:
数据集的前 5 行。
现在,让我们打印一些统计数据,如上述特征(列)的平均值、中值、最小值、最大值和标准偏差值。
data.describe()
过去 5 年(2015–2020)收盘时的均值股价为 983.45!真的很高!
3.2。建立预测模型
现在让我们继续建模。我们将仅使用日期和收盘价格作为我们模型的特征。
# Select only the important features i.e. the date and price
data = data[["Date","Close"]] # select Date and Price# Rename the features: These names are NEEDED for the model fitting
data = data.rename(columns = {"Date":"ds","Close":"y"}) #renaming the columns of the datasetdata.head(5)
最后一个 python 命令应该返回数据集的前 5 行。您应该会看到类似这样的内容:
这里,ds
是日期,y
是谷歌 股票价格。
在本教程中,我们不会将数据分成训练和测试集,而是使用所有数据来拟合模型,然后要求模型预测未来值,即 2021 年的股价。
通常人们将数据分为训练和测试,因为他们不想在测试集上训练模型。如果我们隐藏一个测试集,那么模型将会预测看不见的数据的值。在这种情况下,我们也能够测量模型的误差。
接下来,我们从 fbprophet 模块导入 prophet 类,然后创建一个 Prophet 类的对象。
**旁注:**模型的 github 页面是这样的:https://github.com/facebook/prophet
要在您的控制台上安装模块类型:
pip install fbprophet
。
from fbprophet import Prophetm = Prophet(daily_seasonality = True) # the Prophet class (model)
m.fit(data) # fit the model using all data
安装后,您应该会看到:
优化正常终止:
检测到收敛:相对梯度幅度低于公差
3.3。策划预测
现在,对于最后一步,我们将要求模型预测未来值,然后将预测可视化。
future = m.make_future_dataframe(periods=365) #we need to specify the number of days in future
prediction = m.predict(future)
m.plot(prediction)plt.title("Prediction of the Google Stock Price using the Prophet")
plt.xlabel("Date")
plt.ylabel("Close Stock Price")
plt.show()
该模型使用所有数据进行训练(黑点),并且预测从 2020 年 6 月到 2021 年 6 月的未来股票价格!蓝色阴影是置信区间。
结论:根据模型预测,2021 年 6 月谷歌股价似乎会在 1600 左右。
侧注:在这种情况下,我们无法测量模型的误差。如果有人想这样做,那么他们应该将数据分为训练集和测试集,仅使用训练集拟合模型,预测测试集的价格,然后使用测试集的基本真实价格值来衡量误差。
观察:2020 年 3 月因新冠肺炎封锁而大幅下跌。
奖金
3.4。绘制趋势、周、季、年和日成分图
如果您想要查看预测组件,即趋势、周、季、年和日组件,那么您可以使用以下命令。
m.plot_components(prediction)
plt.show()
结果
根据估计的趋势,我们可以看到,通常股票价格在早早一月(见第 3 副图)最高,多在周三**(见第 2 副图)的**最高。最后,第 1 个子图显示了股票价格在不久的将来(在 2020 年 6 月和 2021 年 6 月之间)的增长。
那都是乡亲们!希望你喜欢这篇文章!
也看看我最近用 LSTM 模型写的文章:
[## LSTM 时间序列预测:使用 LSTM 模型预测股票价格
在这篇文章中,我将向你展示如何使用预测 LSTM 模型来预测股票价格
towardsdatascience.com](/lstm-time-series-forecasting-predicting-stock-prices-using-an-lstm-model-6223e9644a2f)
也可以看看我最近用 ARIMA 模型写的文章:
在这篇文章中,我将向你展示如何使用预测 ARIMA 模型来预测特斯拉的股票价格
towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-an-arima-model-2e3b3080bd70)
参考
[1]https://Facebook . github . io/prophet/docs/quick _ start . html # python-API
https://en.wikipedia.org/wiki/Additive_model
敬请关注并支持这一努力
如果你喜欢这篇文章,并且觉得它有用,那么关注我就可以看到我所有的新帖子。
有问题吗?把它们作为评论贴出来,我会尽快回复。
最新帖子
最有用的免费书籍和在线课程,适合想了解更多数据科学知识的人。
medium.com](https://medium.com/@seralouk/the-best-free-data-science-resources-free-books-online-courses-9c4a2df194e5) [## 用新冠肺炎假设的例子解释 ROC 曲线:二分类和多分类…
在这篇文章中,我清楚地解释了什么是 ROC 曲线以及如何阅读它。我用一个新冠肺炎的例子来说明我的观点,我…
towardsdatascience.com](/roc-curve-explained-using-a-covid-19-hypothetical-example-binary-multi-class-classification-bab188ea869c) [## 支持向量机(SVM)解释清楚:分类问题的 python 教程…
在这篇文章中,我解释了支持向量机的核心,为什么以及如何使用它们。此外,我还展示了如何绘制支持…
towardsdatascience.com](/support-vector-machines-svm-clearly-explained-a-python-tutorial-for-classification-problems-29c539f3ad8) [## PCA 清楚地解释了——如何、何时、为什么使用它以及特性的重要性:Python 指南
在这篇文章中,我解释了什么是 PCA,何时以及为什么使用它,以及如何使用 scikit-learn 在 Python 中实现它。还有…
towardsdatascience.com](/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e) [## 关于 Python 中的最小-最大规范化,您需要知道的一切
在这篇文章中,我将解释什么是最小-最大缩放,什么时候使用它,以及如何使用 scikit 在 Python 中实现它
towardsdatascience.com](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79) [## Scikit-Learn 的标准定标器如何工作
在这篇文章中,我将解释为什么以及如何使用 scikit-learn 应用标准化
towardsdatascience.com](/how-and-why-to-standardize-your-data-996926c2c832)
和我联系
- LinkedIn:【https://www.linkedin.com/in/serafeim-loukas/
- https://www.researchgate.net/profile/Serafeim_Loukas研究之门:
- https://people.epfl.ch/serafeim.loukasEPFL简介:
- 堆栈 溢出:https://stackoverflow.com/users/5025009/seralouk
时间序列预测策略
由 Unsplash 上的 Tabea Damm 拍摄的照片
有大量的文章详细描述了各种数据预处理技术,并解释了如何使用机器学习算法,甚至是关于模型性能估计和选择。在我之前的 帖子 中,我谈到了从头开发一个预测模型,并为参与该主题的项目经理提供了一些提示。然而,当使用测试实例时,我面临着关于什么策略可以预测未来的信息的缺乏。为了填补这个空白,我提供了三种常见方法的解释。希望有用。
因此,在本文中,我们打算跳过数据准备的一部分,直接进入特征生成,因为时间序列分析的前面步骤不依赖于已经选择的策略。
让我们回顾一下他们的拳头。
整个项目的代码可以在 GitHub 资源库 中找到
第一种策略—“基于先前预测值创建新特征”
在那里,我们提前 1 个时间步长进行预测,并根据之前的预测值生成未来的模型特征。只有在前几个预测中,我们使用实际的例子。这种方式使我们能够预测未来的价值,无论我们想要什么。在这种情况下,预测范围变得无限。然而,另一方面,这也有一个缺点,因为每次下一次预测观测都会累积以前观测的误差。因此,进一步的预测值远离历史值,那么模型精度就变得更差。
我们预测一个步骤,然后将预测值添加到数据集中,并重用它来生成新的步骤,就像下图所示。
正如我上面提到的,我们将在数据集的顶部添加每个新的预测值,因此我们必须调整将生成要素的函数以遵循这种方法。
第二种策略—“预测未来 K 个分笔成交点”
我们可以预测向前 K 步。只有当预测范围小于我们拥有的数据时,这才是可能的。这很重要,因为我们将只使用历史观察值来生成未来值。
但是,在我们开始进行预测之前,我们必须定义要预测多少步,并意识到我们拥有为未来值生成特征所需的历史点数量。
这种策略的主要好处是仅使用真实数据来生成预测。与此同时,可以预测的时间步长数量有限。此外,我想你已经猜到,我们越是走向未来,我们的历史观察就变得越没用,这就是这种方法的局限性。
第三个策略——“有创意”
您可以通过结合第一种和第二种策略来创建任何单独的模型。
例如,使用一个模型预测一个步骤,使用另一个模型预测两个时间步骤,依此类推。
在下面的例子中,我们通过重用在第二个策略中训练过的模型来预测 K 步,然后从第一个策略中启动模型。
结论
我认为,首先也是最重要的是,策略选择的偏好应该取决于您想要预测的步骤数量和要达到的预测准确度水平。选择适合你的或者创造你自己的。感谢您的时间,请分享您的想法或任何反馈。
利用季节性 ARIMA 模型进行时间序列预测
Python 教程
时间序列预测中最广泛研究的模型之一是 ARIMA(自回归综合移动平均)模型。ARIMA 模型有许多变体,它们采用相似的概念,但稍有改动。一个特别的例子是季节性 ARIMA (SARIMA)模型。SARIMA 模型在生成时间序列预测时考虑了季节性。本教程涵盖了使用 Python 生成和调整 SARIMA 模型的基础知识,旨在预测具有季节性的时间序列。
算法背景
首先,简单介绍一下 SARIMA 模型的工作原理。由于 ARIMA 模型构成了萨里玛模型的主干,因此理解 ARIMA 模型的工作原理是有益的。它包括以下步骤:
- 差分时间序列中的滞后读数,从而使时间序列平稳。
- 使用时间序列中指定数量的滞后观测值来预测时间序列的未来行为。这一步包括两个模型的组合:自回归(AR)模型和移动平均(MA)模型。每个主题的一些背景:
***AR 模型。***AR 模型使用变量以前值的线性组合来预测变量( 1 )。我们将订单为 p 的 AR 模型描述如下:
自回归(AR)模型。图片由(1*)*提供
在上式中,ε项代表随机误差项。 y(t-p) 项表示时间序列中前一个 p 值。phi 值在每个时间步长都是常数。phi 值随着远离点 t(序列中的最新值)而减小。因此,滞后值越接近预测值(在序号 t 处),phi 值越大,时间步长对预测的影响越大。
【马】马典范。 移动平均模型类似于 AR 模型,只是它是前面误差项的线性组合( 2 )。我们描述如下:
移动平均线(MA)模型,承蒙(3)
在上面的等式中,ε项是误差项,ε(t)是时间步长 t 处的误差项,以此类推。像上面的 AR 方程一样,phi 参数在每个时间步长都是一个常量值。类似地,phi 值随着远离时间 t 移动更多的时间步长而减小。
ARIMA 模型参数
ARIMA 模型包括三个主要参数——p、 q 和 d 。这些参数代表以下内容( 4 ):
- p :自回归模型的阶数(滞后项的个数),在上面的 AR 方程中描述。
- q :移动平均线模型的阶数(滞后项的个数),在上面的 MA 方程中描述。
- d :使时间序列平稳所需的差值数。
SARIMA 模型参数
萨里玛模式建立在 ARIMA 模式的基础上。它包括 p 、 q 和 d 参数,还包括一组额外的参数来说明时间序列的季节性。该参数集— P 、 Q 、 D 和附加参数 m — 定义如下( 5 ):
m :模型的季节性。例如,如果时间序列的季节性每年重复一次,那么 m = 12。如果季节性是每季度一次,那么 m = 4(意味着季节性模式每四个月重复一次)。
P :季节性自回归模型的阶。
Q :季节移动平均线模型的阶。
D :应用于时间序列的季节差异数。
时间序列
在本教程中,我们将使用美国地热能发电的月度时间序列。数据可以通过能源信息管理局(EIA)的 API 直接拉入 Python 中(参见 本教程 了解更多关于使用 EIA 的 API 的背景)。时间序列的快照如下所示,单位为百万千瓦时:
月时间序列,地热能发电净发电量。单位为百万千瓦小时。
我们使用下面的代码来检索和可视化我们的时间序列:
在我们生成 SARIMA 模型之前,让我们分解时间序列以确保它显示季节性。我们使用季节性分解函数,可通过 statsmodels.tsa 包获得。此函数允许我们将时间序列分解为趋势、季节和残差部分:
分解地热能净发电量时间序列
如上图所示,时间序列明确显示了季节性,每 12 个月(每年)重复一次。
构建萨里玛模型
既然我们已经执行了一些初步的数据探索,让我们构建和调整一个 SARIMA 模型来预测时间序列。
超参数选择
我们通过强力选择最适合萨里玛模型的 p 、 d 、 q 、 P 、 D 和 Q 超参数——我们对不同的模型超参数变量进行采样,直到找到最佳的模型组合。在生成每个模型后,我们使用其 AIC 和 BIC 分数来衡量其性能。AIC 或 Akaike 信息标准是一种将一组统计模型的质量相互比较的度量标准( 6 )。类似地,BIC 或贝叶斯信息标准是一种用于比较不同模型的贝叶斯统计。当使用 AIC 或 BIC 指标比较模型时,我们将 AIC 和 BIC 得分最低的模型作为最佳选择。
在下面的代码片段中,我们生成不同的超参数变量来运行 SARIMA 模型,并返回一个列表进行循环:
在上面的代码片段中,我们使用sarima _ parameter _ search()函数生成不同超参数组合的列表,作为 seasonal _ pqd _ combinations和 pdq 变量返回。季节性变量的默认值为 12,表示季节性模式每 12 个月(每年)重复一次。
趋势变量有 4 个可能选项——“n”、“c”、“t”和“ct”。该变量控制时间序列的多项式趋势;’ n ‘表示没有趋势(默认),’ c ‘表示趋势是恒定的,’ t ‘表示随时间的线性趋势,’ ct '既恒定又线性( 8 )。
p 、 d 和 q 变量可以在 0 和 search_range 限制(不含)之间变化。在上面的代码中,我将 search_range 设置为 2,因此参数范围在 0 和 1(含)之间变化。这意味着相关 AR 和 MA 模型的滞后项的最大可能数量是 1,差分的最大可能阶数是 1。
** [## 如何网格搜索 SARIMA 超参数进行时间序列预测
季节性自回归综合移动平均模型是一种模拟单变量时间序列的方法
machinelearningmastery.com](https://machinelearningmastery.com/how-to-grid-search-sarima-model-hyperparameters-for-time-series-forecasting-in-python/) [## 如何使用 SARIMA 模型用 Python 预测销售额
从统计学和 python 到时间序列预测的分步指南
towardsdatascience.com](/how-to-forecast-sales-with-python-using-sarima-model-ba600992fa7d)
培训 SARIMA 模型
让我们首先将数据分成训练集和测试集。这样,我们可以使用训练集构建模型,并使用测试集评估其性能:
在上面的代码片段中,我们使用了标准的 75/25 数据分割(分别是训练和测试)。我们将时间序列中前 75%的数据点作为训练集,后 25%的数据点作为测试集。
注意:当生成我们的训练和测试集时,我们必须只使用一个分割,因为数据必须保持其连续性。这是因为 SARIMA 模型依赖于数据序列来进行预测。
最后,是时候建立我们的 SARIMA 模型了。我们循环遍历每个可能的超参数配置,生成一个 SARIMA 模型。我们使用每个可能模型的 AIC 参数来衡量模型性能。记住——我们想要 AIC 分数最低的模型:
在上面的代码片段中,我们使用了 seasonal_arima_model() 函数来构建 SARIMA 模型。如果模型构建成功,那么模型摘要将打印在控制台中,并返回模型及其相关的 AIC 和 BIC 分数。
我们在一个循环中调用*季节性 arima 模型()*函数,在这里我们对每个超参数配置进行采样。我们设置了一个默认的 AIC 值 100,000,000,000(非常高),当我们找到一个具有较低 AIC 分数的模型时,替换它。当我们在循环中移动时,我们在具有最低相关 AIC 分数的模型上保留一个标签,并保存该模型及其超参数配置(在 best_model 、 best_order 和 best_seasonal_order 变量下)。我们将循环结束时存储在 best_model 下的 SARIMA 模型作为具有最佳超参数配置的最终模型。
解释模型结果
循环完成后,最佳模型配置及其摘要将打印在 Python 控制台中:
最佳 SARIMA 型号配置
萨里玛(1,1,1)x(1,1,1,12)模型摘要
上面的模型摘要包含*“协方差类型”*图,该图描述了每个变量对预测的影响。我们有四个主要的滞后 AR 和 MA 变量。第一组 AR 和 MA 变量滞后 1 个时间步长( ar)。和马。L1 ,而第二组滞后 12 个时间步( ar)。S.L12 和 ma。S.L12 。
查看图中的*P>ABS(z)*项,所有变量读数为 0。这很好,因为我们希望 P 值尽可能接近 0。使用 0.05 作为统计显著性的截止值,我们所有的滞后 AR 和 MA 项都会显著影响模型预测。
测试模型性能
现在我们有了 SARIMA 模型,让我们使用测试数据来评估它的性能!
在下面的代码片段中,我们预测测试集的值,预测出测试集中出现的步骤总数。然后,我们使用均方根误差(RMSE)和平均绝对误差(MAE)指标将预测值与实际值进行比较。RMSE 和梅的分数越低,模型就越适合。如果预测值与实际值完全匹配,则 RMSE 和 MAE 都等于 0。
关于均方根误差和平均绝对误差的更多信息,请查看 此链接 。
预测的 RMSE 和梅产量
运行上面的代码片段,该模型的输出 RMSE 和 MAE 分别约为 868 和 860。
在计算了 RMSE 和梅伊指标后,我们将预测值与实际值进行对比。这为我们提供了模型性能的直观度量:
时间序列指数 t 下的时间序列预测值与实际时间序列值。预测的置信区间用灰色表示。
请看上图,该模型在预测 140 个时间步长的时间序列方面做得很好。这都快十二年了!我们可以看到预测的季节性,这是由 ar 说明的。S.L12 和 ma。模型中的 S.L12 术语。
我的用季节性 ARIMA 模型生成和预测的教程到此结束。
查看本教程中使用的完整代码。
另外,看看我的其他一些时间序列分析文章:
[## 使用 Python 分析电价时间序列数据:时间序列分解和价格…
欢迎来到科技兰多博客!本教程涵盖了时间序列分解和向量自回归(VAR)…
techrando.com](https://techrando.com/2019/07/19/analyzing-electricity-price-time-series-data-using-python-time-series-decomposition-and-price-forecasting-using-a-vector-autoregression-var-model/) [## 使用 Python - Tech Rando 进行变化点检测简介
我的很多工作都大量涉及时间序列分析。我使用的一个很棒但不太为人所知的算法是…
techrando.com](https://techrando.com/2019/08/14/a-brief-introduction-to-change-point-detection-using-python/) [## 时间序列中离群点检测的无监督机器学习方法
在这篇文章中,我将介绍一些我最喜欢的检测时间序列数据中异常值的方法。有许多不同的…
techrando.com](https://techrando.com/2019/08/23/unsupervised-machine-learning-approaches-for-outlier-detection-in-time-series/)
资源
- https://otexts.com/fpp2/AR.html
- https://new online courses . science . PSU . edu/stat 510/lesson/2/2.1
- 【https://otexts.com/fpp2/MA.html
- https://people.duke.edu/~rnau/411arim.htm
- https://new online courses . science . PSU . edu/stat 510/lesson/4/4.1
- https://www . statistics show to . data science central . com/akai KES-information-criterion/
- https://www . statistics show to . data science central . com/Bayesian-information-criterion/
- https://www . stats models . org/dev/generated/stats models . TSA . statespace . sarimax . sarimax . html
最初发表于 2020 年 1 月 4 日https://techrando.comT22。**
python 中自动 ARIMA 的时间序列预测
演示如何利用 python 中的自动 ARIMA 功能,使用“pmdarima”包预测未来
照片由 Isaac Smith 在 Unsplash 上拍摄
时间序列分析是任何数据科学家的核心技能之一,在分析领域工作的任何人经常会遇到根据过去和现在的数据预测未来的情况。
什么是时间序列?
它是在特定时间基本上以相等间隔进行的一系列观察。它用于根据过去的观察值预测未来值。在时间序列分析中,您可能会观察到趋势性、季节性、不规则性和周期性。
在这种数据集的情况下,每次只观察到一个变量被称为“单变量时间序列”,如果每次观察到两个或两个以上的变量被称为“多变量时间序列”。
在本文中,我们将重点关注使用 python 中的自动 ARIMA 功能来预测销售额的单变量时间序列,这与 r 中的自动 ARIMA 功能非常相似
为什么使用汽车 ARIMA?
通常,在基本的 ARIMA 模型中,我们需要提供必要的 p、d 和 q 值。我们使用统计技术,通过执行差分来消除非平稳性并绘制 ACF 和 PACF 图来生成这些值。在自动 ARIMA 中,模型本身将生成适合数据集的最佳 p、d 和 q 值,以提供更好的预测。
让我们开始安装吧…
请注意,这个包最初命名为“金字塔”,后来改为“pmdarima”。确保您正在安装“pmdarima”软件包。
👉步骤 1:安装“pmdarima”包
你可以用下面的命令从你的 Jupyter 单元安装这个包。
!pip 安装 pmdarima
为了确保软件包构建正确,请使用下面的命令进行测试。
从 pmdarima.arima 导入 auto_arima
还要注意,这个包依赖于其他几个 python 包,要了解更多关于设置的信息,请参考这个[ 链接
我们正在使用的数据集是从 1964 年到 1972 年的每月明智香槟销售。你可以在这里得到数据集
👉第二步:准备数据
读取数据集后,确保没有空值,并将“Month”变量的数据类型更改为 datetime 对象。此外,使用 set_index 方法将 dataframe 的索引设置为该变量。
销售数据的前几行
👉第三步:理解模式
为了理解数据的模式,我们可以简单地用。plot()方法。
销售数据中的季节性模式
从上面我们可以观察到,数据存在季节性。从 1964 年到 1972 年,每年都有一个销售高峰。
👉步骤 4:平稳性测试
平稳性是时间序列中的一个重要概念,任何时间序列数据都应该在进行建模之前进行平稳性测试。
我们使用“扩展的 Dickey-Fuller 检验”来检查数据是否是平稳的,这在“pmdarima”包中是可用的。
从上面我们可以得出结论,数据是非平稳的。因此,我们需要使用“综合(I)”概念,在时间序列中用值“d”表示,以使数据在构建自动 ARIMA 模型时保持平稳。
👉第五步:训练和测试分割
拆分为定型数据集和测试数据集,以在定型数据集上构建模型,并使用测试数据集进行预测。
绘制训练和测试数据集
👉第六步:建立汽车 ARIMA 模型
自回归§ - >自回归项数。
积分(d) - >平稳性所需的非季节性差异数。
移动平均(q) - >预测方程中滞后预测误差的个数。
在自动 ARIMA 模型中,注意小的 P,D,Q 值代表非季节性成分,大的 P,D,Q 代表季节性成分。它的工作类似于超调谐技术,以找到不同组合的 p、d 和 q 的最佳值,并且最终值将通过考虑较低的 AIC、BIC 参数来确定。
这里,我们尝试使用范围从 0 到 5 的 p、d、q 值来从模型中获得更好的最优值。该模型中还有许多其他参数,要了解更多功能,请访问此链接[ 此处
自动 ARIMA 模型参数
自动 ARIMA 模型的追踪
下面是模型的总结。
ARIMA 模式概述
👉第七步:测试数据预测
使用在前面步骤中建立的训练模型根据测试数据预测销售。
根据测试数据预测的销售额
绘制培训对比测试对比预测销售
测试数据集的 R2 分数
总结
在本文中,我们学习了如何使用自动 ARIMA 模型的功能,如果您想从模型本身生成 p、d 和 q 值,这种方法将会很方便。在基本的 ARIMA 或萨里玛模型中,您需要进行差分并绘制 ACF 和 PACF 图来确定这些值,这非常耗时。
然而,如果你是时间序列的新手,建议你使用统计技术并实现基本的 ARIMA 模型来理解 p、d 和 q 值背后的直觉。
您可以从我的 GitHub [ here ]获得数据集和完整代码
感谢阅读,快乐学习!🙂
时间序列预测 vs .数据意义上的预测辩论!—行业需求是什么
我如何在预测冠状病毒爆发时实现 1.4%的 MAPE
“每一个在中国和其他地方受苦的人,愿上帝加强受害者和他们的家庭,引导他们度过这段艰难的时光。请遵循世卫组织网站中的建议,保持安全并受到保护
在这个技术和变革的时代,商业智能和数据科学是两个最经常出现的术语。虽然两者都是建立在数据的基础上,但却完全不同。商业智能是收集、整合和分析当前数据以推动未来决策的过程,而数据科学更多的是分析数据以预测未来的结果。关于这两个术语的不同造词有多种版本,然而,归根结底是数学+商业+技术的结合!
我们今天要谈论的四件事
- 问题陈述☄
- 方法-解决方案框架☀
- 验证机制▥
- 什么是对的或错的?☺ ☹
问题陈述☄
“我们都知道 2019-nCoV(冠状病毒)的爆发,以及它的致命性。世界卫生组织目前正在密切监测局势,并努力制定一项全球战略准备。每天发布一份 情况报告 跟踪确诊病例数、死亡数、痊愈数、新增病例数等。想象一下这样一种情景,对未来疫情的估计可以帮助各国在今天实施战略措施。战略措施包括建立保健中心、储备医疗必需品、传播意识等等。我们将努力预测确诊病例的数量,直到下周末”。
世卫组织——给公众的建议
世界卫生组织和 Kaggle 的 2019-nCoV(冠状病毒)数据库如何讲述同一个故事…
towardsdatascience.com](/why-quality-sense-checks-are-so-important-in-data-science-7ef80da760c3)
方法-解决方案框架☀
为了预测确诊病例的数量,了解可能影响疫情的几个因素是很重要的。让我们看看下面的信息图。
“考虑到目前无法获得所需的数据粒度,实施这些因素来开发回归或 ARIMAX 模型似乎很困难”,但是,可以采用基于进展/商业智能的方法来预测未来结果。
上述因素,如果不在模型中使用,也可以用来验证模型结果。例如,我们最终预测武汉的确诊病例数会更高,我们需要验证预测的数字。我们可以对武汉的人口统计进行初步研究。如果我们看到一个确定/证实武汉患有糖尿病和心力衰竭的老年人数量比周围省份高得多的场景,我们肯定可以验证我们的预测值;这两个因素总是高度相关的。
我已经在分析行业工作了 5 年,我看到过这样的场景,当一个简单易懂的解决方案可以轻松实现时,我们却把过程复杂化了。想象一下这样一个场景,您被要求预测销售额,因为您的业务伙伴想要一个基线数字来计划下一年的预算。你可以一直致力于开发一个时间序列模型,但是你的商业伙伴能够理解 P-D-Q 框架意味着什么或者 ACF-PACF 图代表什么吗?
在你开发一个模型☃之前,想简单点
一个模型并不一定意味着,你开始使用复杂的数学来创建一些等式。对于任何时间序列数据,第一步是查看这三个组成部分:
- 趋势 —变量的大小是否随时间线性增加?例如,确诊病例的增长是否会随着时间的推移而增加?
- 水平 —变量在一段时间内的平均值是多少?例如,过去 6 天的平均增长率是多少?
- 季节性*——在特定的时间间隔内,我们会看到类似的价值模式吗?—我们是否在特定日期观察到类似的趋势,即每周一确诊病例/增长数字较高?*
现在怎么办?
- 绘制确诊病例数与时间的关系图。 检查线性、非线性趋势
- 如果趋势存在, 寻找增长的同方差或异方差;增长数字是随时间增长还是像随机噪声一样分布不均
- 如果数字有增长趋势,看看是增加还是减少; 计算 alpha;α可以定义为增长随时间变化的比例
- 任何时间序列数据都应该使用最近的事件进行预测。快速 PACF(部分自相关)图可用于理解从 t(n)到 t(n-1)时间间隔的不同确认数字的相互作用。PACF 图基本上用于理解我们是否可以使用最近值 的组合 的当前值来预测下一个结果
数据分析师的观点—您应该知道的 4 件重要事情
towardsdatascience.com](/how-bad-will-the-coronavirus-outbreak-get-predicting-the-outbreak-figures-f0b8e8b61991)
我通过使用截至 2020 年 1 月 31 日的最近 6 天的数据来调整模型参数,以得出 alpha 值。
验证机制▥
平均绝对百分比误差(MAPE)是我们预测模型精确度的统计度量。它以百分比的形式测量这种精度,并且可以计算为每个时间段的平均绝对百分比误差减去实际值除以实际值。它基本上帮助我们识别
- 我们的预测和实际值有多大的差异?即差异的大小
- 我们是低估了还是高估了?
MAPE 越低,模型结果越好。世界卫生组织每天发布一份情况报告,报告中的数值被用来验证模型数据。
什么是对的或错的?☺ ☹
什么顺利!☺
- 1.4%的 MAPE;适合任何型号的验证
- 简单易懂的解决方案,没有复杂的方法
什么不顺利!☹
- MAPE 随着时间而增加。不适合用于预测长期值的模型
- 无法纳入可能有助于改善预测结果的外部因素*
这种爆发的致命性还有待观察,但利用现有的数据,如果我们能够确定高风险区,我们就可以迅速采取行动,对爆发进行一些抵抗。这就是数据科学家和分析师需要携手合作并帮助社区传播更多意识的地方。
关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的商业、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以和我在 上联系 中。*
用 2D 卷积进行时间序列预测
在本文中,我将向您展示一种我在其他地方没有见过的时间序列预测方法。我怀疑这是一个新方法,但由于我还没有看到一篇关于它的伟大文章,这里是它。
数据集
我在这个项目中使用的数据来自全球能源预测竞赛,由我的家乡大学北卡罗来纳大学夏洛特分校举办。你可以在这里找到更多关于它的信息:【http://www.drhongtao.com/gefcom/2017】T2
你需要知道的是这些数据是来自一个能量网格的各种读数。我们的目标是利用这些数据点预测电网的实时能源需求。数据点还包括露点和干球温度,因为空调是能源消耗的巨大驱动力。
我们的目标变量是 RTDemand:我们正在工作的电网的实时能源需求。数据有明确的每日周期。这是我们三天的数据:
3 天每小时一次
在太阳下山、所有人都睡着的半夜,我们的功耗达到最低。我们早上醒来,开始工作,当太阳达到峰值强度时,我们的功耗达到最大。我认为每天的下降对应于通勤时间。
如果我们再放大一点,我们可以看到清晰的自相关和天数趋势,就像你在天气中看到的一样。这是大约 3 周的数据:
目标变量的 3 周
如果我们进一步缩小,查看一整年的数据,我们还可以注意到一个更大的季节性趋势:
这是一个非常好的时间序列预测数据集。
单变量纯时间序列模型
对于时间序列预测来说,我们将需要做出导致目标结果的时间序列。在我们的例子中,我选择 72 小时作为时间序列的长度。这意味着我们模型的输入是代表过去 72 小时数据的 72 个独立数字,我们希望从我们模型得到的目标输出是第 73 小时的预测。我认为 72 小时是一个很好的长度,因为它可以很好地捕捉当地的趋势和昼夜循环。
让我告诉你我所说的时间顺序是什么意思。这是 X 的前 3 天,我们对模型的输入:
array([[12055., 11430., 10966., 10725., 10672., 10852., 11255., 11583.,
12238., 12877., 13349., 13510., 13492., 13314., 13156., 13364.,
14632., 15653., 15504., 15088., 14579., 13882., 12931., 11883.,
10978., 10406., 10089., 9982., 10031., 10289., 10818., 11444.,
12346., 13274., 13816., 14103., 14228., 14154., 14055., 14197.,
15453., 16531., 16410., 15954., 15337., 14347., 13178., 12106.,
11400., 11059., 10959., 11073., 11485., 12645., 14725., 15863.,
16076., 16222., 16358., 16362., 16229., 16123., 15976., 16127.,
17359., 18818., 18724., 18269., 17559., 16383., 14881., 13520.], [11430., 10966., 10725., 10672., 10852., 11255., 11583., 12238.,
12877., 13349., 13510., 13492., 13314., 13156., 13364., 14632.,
15653., 15504., 15088., 14579., 13882., 12931., 11883., 10978.,
10406., 10089., 9982., 10031., 10289., 10818., 11444., 12346.,
13274., 13816., 14103., 14228., 14154., 14055., 14197., 15453.,
16531., 16410., 15954., 15337., 14347., 13178., 12106., 11400.,
11059., 10959., 11073., 11485., 12645., 14725., 15863., 16076.,
16222., 16358., 16362., 16229., 16123., 15976., 16127., 17359.,
18818., 18724., 18269., 17559., 16383., 14881., 13520., 12630.], [10966., 10725., 10672., 10852., 11255., 11583., 12238., 12877.,
13349., 13510., 13492., 13314., 13156., 13364., 14632., 15653.,
15504., 15088., 14579., 13882., 12931., 11883., 10978., 10406.,
10089., 9982., 10031., 10289., 10818., 11444., 12346., 13274.,
13816., 14103., 14228., 14154., 14055., 14197., 15453., 16531.,
16410., 15954., 15337., 14347., 13178., 12106., 11400., 11059.,
10959., 11073., 11485., 12645., 14725., 15863., 16076., 16222.,
16358., 16362., 16229., 16123., 15976., 16127., 17359., 18818.,
18724., 18269., 17559., 16383., 14881., 13520., 12630., 12223.]])
数组中的每个数字都是 RTDemand 的读数:这个特定的发电站在那个小时需要多少千瓦的电力。三个大阵列中的每一个都有 72 小时的数据。如果你仔细观察这三组 72 个读数的前 8 个左右,你会注意到每组新的 72 个读数都是向前移动了一个小时的系列。因此,这些 72 长度的输入数组中的每一个都代表了该能源电网实时需求的过去 72 小时的读数。
然后,我们希望预测第 73 个小时,因此我们的 y 数组将如下所示:
array([[12630.],
[12223.],
[12070.]])
注意,如果你看上面第二个 X 数组中的最后一个条目,它也是我们 Y 中的第一个条目,第三个 X 数组中的最后一个条目是我们 Y 中的第二个条目。对于第一个 X 数组,我们试图预测 Y 系列中的第二个值。
数据转换
一旦我们加载并窗口化了数据,我们接下来需要将它转换成一个合适的集合来训练机器学习模型。首先,我将缩放所有输入变量。稍后,我们将考虑使用数据集的所有 12 个输入,但现在我将只介绍一个变量。我将而不是缩放我的目标变量,我的 Y,因为我觉得它以最小的成本使得监控模型的进展更容易。接下来,我们将把它分成培训/测试部分:
from sklearn.preprocessing import StandardScalerscaler = StandardScaler()
X = scaler.fit_transform(X)split = int(0.8 * len(X))
X_train = X[: split - 1]
X_test = X[split:]y_train = y[: split - 1]
y_test = y[split:]
最后,我们的形状有点偏离。我们将使用的模型的输入是(样本、时间步长、特征)。在第一个模型中,我们仅使用时间窗口目标变量作为输入。所以,我们只有一个特征。我们的 X_train.shape 当前为(样本,时间步长)。在上面的训练/测试拆分之后,我们现在将重塑它:
X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], 1))
X_test = X_test.reshape((X_test.shape[0], X_test.shape[1], 1))
X_train.shape
(61875, 72, 1)
即 61,875 个样本,每个样本由 72 个每小时读数和 1 个特征组成。准备好摇滚了。
基准车型:
首先,一个基准。我们的优化指标将是均方误差/均方根误差。所以首先我们需要知道这个数字是好是坏。我们还会考虑 R,不过如果有冲突,我们只会使用均方误差作为损失函数和优化目标。
对于基准模型,我们将看到我们得到的均方误差和 R 的读数。这里的基准模型将猜测我们的时间序列中的前一个值。下面是一些代码,可以快速阅读这个模型:
# Benchmark model
prev_val = y_test[0]
sse = 0for n in range(0, len(y_test)-1):
err = y_test[n] — prev_val
sq_err = err ** 2
sse = sse + sq_err
prev_val = y_test[n]mse = sse / n
mse
对于我们的测试数据集,这产生了 411,577.17 的答案,其平方根是 641.54。对此的一种解释是,平均而言,该基准模型在给定的一小时内下降了 641.54 兆瓦。下面是基准模型与真实结果的对比图。
这不是一个容易被击败的模型,尽管它非常简单。
1-可变 LSTM 模型:
现在我们已经建立了数据集,我们可以开始使用机器学习模型进行预测。
预测时间序列的一种常用方法是 LSTM 模型。这将提供一个很好的基准学习模型来与我们的卷积模型进行比较。以下是使用 LSTM 模型进行设置和预测的一些代码:
def basic_LSTM(window_size=5, n_features=1):
new_model = keras.Sequential()
new_model.add(tf.keras.layers.LSTM(100,
input_shape=(window_size, n_features),
return_sequences=True,
activation=’relu’))
new_model.add(tf.keras.layers.Flatten())
new_model.add(tf.keras.layers.Dense(1500, activation=’relu’))
new_model.add(tf.keras.layers.Dense(100, activation=’linear’))
new_model.add(tf.keras.layers.Dense(1))
new_model.compile(optimizer=”adam”, loss=”mean_squared_error”)
return new_modells_model = basic_LSTM(window_size=window_size, n_features=X_train.shape[2])ls_model.summary()Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm (LSTM) (None, 72, 100) 40800
_________________________________________________________________
flatten (Flatten) (None, 7200) 0
_________________________________________________________________
dense (Dense) (None, 1500) 10801500
_________________________________________________________________
dense_1 (Dense) (None, 100) 150100
_________________________________________________________________
dense_2 (Dense) (None, 1) 101
=================================================================
Total params: 10,992,501
Trainable params: 10,992,501
Non-trainable params: 0
训练后,我们可以评估模型:
ls_model.evaluate(X_test, y_test, verbose=0)
1174830.0587427279from sklearn.metrics import r2_score
predictions = ls_model.predict(X_test)
test_r2 = r2_score(y_test, predictions)
test_r2
0.8451637094740732
我们得到的结果还可以,但不是一流的。具体来说,我们得到了比以前的基准模型更高的误差。下面的图表可以让你了解它预测了什么:
如你所见,它预测了相当多的可变性,但最终结果并不理想。问题似乎是在上午的“下降”过程中出现了相对较大的误差。我还发现这个模型非常不可靠,经常将其损失函数降低到 nan,并且不产生任何输出。
引入 1D 卷积方法
另一种预测时间序列的方法是使用 1D 卷积模型。1D 卷积使用滤波窗口,并在数据上循环该窗口以产生新的输出。根据卷积窗的学习参数,它们可以像移动平均线、方向指示器或模式检测器一样随时间变化。我用一些图片来解释一下方法。
第一步
这里我们有一个包含 8 个元素的数据集,过滤器大小为 4。滤波器中的四个数字是 Conv1D 层学习的参数。在第一步中,我们将滤波器的元素乘以输入数据,并将结果相加,产生卷积输出。
第二步
在卷积的第二步中,窗口移动一步,重复相同的过程以产生第二个输出。
1D 卷积的最后一步
这个过程一直持续到窗口到达输入数据的末尾。在我们的例子中,一个输入数据序列是我们之前设置的 72 小时的数据。如果我们添加选项 padding =“same”,我们的输入数据将在开头和结尾用零填充,以保持输出长度等于输入长度。上面的演示使用了线性激活,这意味着最后一个多色数组是我们的输出。但是,您可以在这里使用大量的激活函数,这些函数将通过一个额外的步骤来运行这个数字。因此,在我们下面的例子中,将有一个 ReLU 激活函数应用于这个最后的输出,以产生最终的输出。
给定我们之前描述的数据设置,下面是设置和运行 1D 卷积的代码:
def basic_conv1D(n_filters=10, fsize=5, window_size=5, n_features=2):
new_model = keras.Sequential()
new_model.add(tf.keras.layers.Conv1D(n_filters, fsize, padding=”same”, activation=”relu”, input_shape=(window_size, n_features)))
# Flatten will take our convolution filters and lay them out end to end so our dense layer can predict based on the outcomes of each
new_model.add(tf.keras.layers.Flatten())
new_model.add(tf.keras.layers.Dense(1800, activation=’relu’))
new_model.add(tf.keras.layers.Dense(100))
new_model.add(tf.keras.layers.Dense(1))
new_model.compile(optimizer=”adam”, loss=”mean_squared_error”)
return new_model
我们的数据集看起来是这样的:
univar_model = basic_conv1D(n_filters=24, fsize=8, window_size=window_size, n_features=X_train.shape[2])univar_model.summary()Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d (Conv1D) (None, 72, 24) 216
_________________________________________________________________
flatten_1 (Flatten) (None, 1728) 0
_________________________________________________________________
dense_3 (Dense) (None, 1800) 3112200
_________________________________________________________________
dense_4 (Dense) (None, 100) 180100
_________________________________________________________________
dense_5 (Dense) (None, 1) 101
=================================================================
Total params: 3,292,617
Trainable params: 3,292,617
Non-trainable params: 0
注意这里我有 24 个卷积窗,滤波器大小是 8。因此,在我们的例子中,输入数据将是 72 小时,这将创建一个大小为 8 的窗口,并且将有 24 个这样的过滤器。因为我使用了 padding="same ",所以每个过滤器的输出宽度将是 72,就像我们的输入数据一样,输出的数量将是 24 个卷积数组。展平产生 72 * 24 = 1,728 长度数组输出。从上面继续我们的样本卷积,它看起来像这样:
展平如何工作
那么,相对于一个 LSTM 和一个愚蠢的模型,这个方法是如何工作的呢?
好吧,所以它比 LSTM 好一点,但它仍然达不到最初的基准模型“只是猜测以前的值”。当我们看这个图表时,我们可以看到这个模型中明显的偏差:
1 变量 Conv1D
添加更多数据
在我们的例子中,我们只使用我们想要预测的特征作为输入变量。然而,我们的数据集有 12 个可能的输入变量。我们可以把所有的输入变量叠加在一起,用它们来做一个预测。由于许多输入变量与我们的输出变量有中度到强烈的相关性,所以应该可以用更多的数据做出更好的预测,对吗?嗯,在 1D 卷积中有一点问题。
多元 Conv1D
我相信这就是 1D 卷积窗应用于多序列输入的情况。如果我是对的,那么添加更多的数据集将会“模糊”任何一个特定输入变化的影响,反而会产生一个不太准确的模型。
如果我想将不同的数据序列堆叠到我的模型中,我首先必须通过相同的窗口处理来运行它,以产生一组观察值,每个观察值包含变量的最后 72 个读数。例如,如果我想在第 1 列中添加变量 DADemand(提前一天的需求,此时来自前一天的需求),我将对其执行以下操作:
(DADemand, _) = window_data(gc_df, window_size, 1, 1)scaler = StandardScaler()DADemand = scaler.fit_transform(DADemand)split = int(0.8 * len(X))DADemand_train = DADemand[: split — 1]DADemand_test = DADemand[split:]DADemand_test.shape
(61875, 72, 1)
然后,我可以对我的所有 12 个变量继续这个过程,并像这样把它们堆成一个集合:
data_train = np.concatenate((X_train, db_train, dew_train, DADemand_train, DALMP_train, DAEC_train, DACC_train, DAMLC_train, RTLMP_train, RTEC_train, RTCC_train, RTMLC_train), axis=2)data_test = np.concatenate((X_test, db_test, dew_test, DADemand_test, DALMP_test, DAEC_test, DACC_test, DAMLC_test, RTLMP_test, RTEC_test, RTCC_test, RTMLC_test), axis=2)data_train.shape(61875, 72, 12)
这是 61,875 个例子,每个例子都是 12 个不同时间序列的 72 小时单独读数。我们现在将通过一个 Conv1D 网络来运行它,看看我们会得到什么结果。如果回顾一下我们用于创建这些模型的函数,您会注意到其中一个变量是要素的数量,因此运行该函数和 LSTM 的代码与使用现有代码创建模型一样简单,只是使用了新的堆叠数据、拟合、评估和绘制。这就是事情的经过:
呦喂。
正如所料,我们在这里的表现实际上随着额外的变量而下降,我相信是因为模糊效应。当我坐在一个沉闷的午夜,虚弱而疲惫地沉思时,我找到了解决这个问题的办法。
2D 卷积
好了,这里我们需要的是一个卷积窗口,它可以查看我们的特征,并找出哪些特征是好的。它基本上应该是这样的:
我需要什么
在做了一些研究后,这个形状可以通过一个形状为(1,filter_size)的 2D 卷积窗口来实现,在上图中,filter_size=3。回到我们的能源预测问题,我们有 12 个特征。为了让它进入 2D 卷积窗,我们实际上需要它有 4 个维度。我们可以得到另一个维度:
data_train_wide = data_train.reshape((data_train.shape[0], data_train.shape[1], data_train.shape[2], 1))
data_test_wide = data_test.reshape((data_test.shape[0], data_test.shape[1], data_test.shape[2], 1))data_train_wide.shape(61875, 72, 12, 1)
我对这个 2D 窗口的各种形状做了一些测试,发现一次做两个功能效果最好:
def basic_conv2D(n_filters=10, fsize=5, window_size=5, n_features=2):
new_model = keras.Sequential()
new_model.add(tf.keras.layers.Conv2D(n_filters, (1,fsize), padding=”same”, activation=”relu”, input_shape=(window_size, n_features, 1)))
new_model.add(tf.keras.layers.Flatten())
new_model.add(tf.keras.layers.Dense(1000, activation=’relu’))
new_model.add(tf.keras.layers.Dense(100))
new_model.add(tf.keras.layers.Dense(1))
new_model.compile(optimizer=”adam”, loss=”mean_squared_error”)
return new_modelm2 = basic_conv2D(n_filters=24, fsize=2, window_size=window_size, n_features=data_train_wide.shape[2])m2.summary()Model: "sequential_4"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 72, 12, 24) 72
_________________________________________________________________
flatten_4 (Flatten) (None, 20736) 0
_________________________________________________________________
dense_12 (Dense) (None, 1000) 20737000
_________________________________________________________________
dense_13 (Dense) (None, 100) 100100
_________________________________________________________________
dense_14 (Dense) (None, 1) 101
=================================================================
Total params: 20,837,273
Trainable params: 20,837,273
Non-trainable params: 0
好的,这个模型非常庞大。在我的普通 CPU 上,每个纪元花了大约 4 分钟进行训练。当它完成后,我对它进行了评估并绘制了图表,我的朋友像买彩票一样得到了回报:
YOWZA
这款车型与我们之前的车型相比如何?
布丁中的证据
因此,这个模型远远优于所有以前的模型,并以巨大的优势击败了我们的基准“哑模型”。
但是等等,还有更多!
好吧,就像你没有想到的奖金模型:如果我们使用类似的想法,但也是一次卷积超过 8 小时,过滤形状为(8,1),会怎么样?
下面是下一个更深层的代码:
def deeper_conv2D(n_filters=10, fsize=5, window_size=5, n_features=2, hour_filter=8):
new_model = keras.Sequential()
new_model.add(tf.keras.layers.Conv2D(n_filters, (1,fsize), padding=”same”, activation=”linear”, input_shape=(window_size, n_features, 1)))
new_model.add(tf.keras.layers.Conv2D(n_filters, (hour_filter, 1), padding=”same”, activation=”relu”))
new_model.add(tf.keras.layers.Flatten())
new_model.add(tf.keras.layers.Dense(1000, activation=’relu’))
new_model.add(tf.keras.layers.Dense(100))
new_model.add(tf.keras.layers.Dense(1))
new_model.compile(optimizer=”adam”, loss=”mean_squared_error”)
return new_model
这种模式表现也很好:
根据我们的损失指标/优化目标,该模型的表现优于任何其他模型:
我们的最终结果!
您可以在以下位置找到所有相关代码以及样本数据集:【https://github.com/walesdata/2Dconv_pub
你可以在这里找到更多关于我和我在做什么的信息:【https://www.linkedin.com/in/john-wales-62832b5/
基于 SARIMA 模型的时间序列预测
预测加州大学伯克利分校一栋建筑的每日电力负荷
图片来源:艾琳娜·朱科娃
背景
你好。在本文中,我将使用 SARIMA 模型运行一个电力负荷预测示例。为加州大学伯克利分校的一栋建筑收集了三年的每日电力负荷数据,以根据该建筑从 2016 年 1 月到 2019 年 10 月的电力使用情况创建模型。该模型将预测 2019 年 11 月的日负荷,其有效性将使用平均绝对百分比误差来衡量。详细介绍该流程时,将涵盖以下主题:
- 平稳性(差分和增强的 Dickey-Fuller 检验)
- ACF 和 PACF 图
- 网格搜索和 AIC
- 向前走验证
- MAPE
- 外生变量
EDA 和平稳性检查
在建模之前,我们先来看看一些数据,看能不能提取出什么有意义的信息。
图 1:每日电力负荷示例
看上面的图 1,数据中有一个非常清晰的周趋势。当一周中上课时,电力负荷很高,而在周末,电力负荷较低。在确定 SARIMA 参数时,这一见解将会派上用场。
对于许多类型的时间序列模型,验证您的数据是平稳的是很重要的。简而言之,数据需要满足以下要求,以确保稳定性:
- 常数平均值
- 恒定方差
- 恒定自相关结构(当前值取决于过去值)
- 没有周期性成分
从上面的 EDA 中可以清楚地看到,数据包含周期性的成分,因此需要应用转换来使数据保持稳定。在这种情况下,我们将应用第一个差异和每周季节差异。下面的图 2 显示了对数据进行差异处理后的相同日期范围;它不再包含周趋势。
图 2:首次差异和季节差异后的日负荷
验证数据平稳性的一种快速简单的方法是通过扩展的 Dickey-Fuller 检验。这可以通过下面的代码来完成:
from statsmodels.tsa.stattools import adfulleradf, pvalue, usedlag_, nobs_, critical_values_, icbest_ = adfuller(train)
该测试的零假设(p 值> 0.05)是数据不是稳定的。根据上面代码的输出,p 值被计算为~ 0,所以我们可以拒绝零假设,说数据实际上是稳定的。开始做模特!
萨里玛模型参数— ACF 和 PACF 图
简单介绍一下, SARIMA 款是带有季节性元素的 ARIMA 款。根据公式萨里玛( p 、 d 、 q )x( P 、 D 、 Q、s ),这些型号的参数如下:
- p 和季节性 P :表示自回归项的个数(平稳序列的滞后)
- d 和季节性 D :表示为了平稳化系列必须进行的差分
- q 和季节性 Q :表示移动平均项的个数(预测误差的滞后)
- s :表示数据中的季节长度
采用两种方法来确定理想的萨里玛参数: ACF 和 PACF 图,以及网格搜索。使用 ACF 和 PACF 图作为起点,缩小到几个潜在参数,然后使用网格搜索来确定最佳参数。我们来看看吧!
ACF 和 PACF 图是使用下面的代码生成的,可以在下面的图 3 中看到。
import matplotlib.pyplot as plt
import statsmodels.api as smfig, ax = plt.subplots(2,1)
fig = sm.graphics.tsa.plot_acf(train, lags=50, ax=ax[0])
fig = sm.graphics.tsa.plot_pacf(train, lags=50, ax=ax[1])
plt.show()
图 3: ACF 和 PACF 图(x 轴=滞后数,y 轴=相关性)
可以看出,在滞后 1 和滞后 7(每周季节性成分)的 ACF 图中有显著的负尖峰。在 PACF 图中,在滞后 1 和 2 处有显著的负尖峰(即滞后衰减较慢),在滞后 7、14、21 等处也有显著的负尖峰。这些特征暗示了一个潜在的参数起点 SARIMA(0,1,1)x(0,1,1,7)
- p 和 P 都等于 0(在 ACF 和 PACF 图中没有显著的正尖峰)
- d 和 D 都等于 1(首差和季节差)
- q 和 Q 都等于 1(显著的负尖峰,PACF 衰减更平缓)
- s 等于 7(每周季节性成分)
使用这些参数,模型与数据拟合,然后评估模型残差的一组新的 ACF 和 PACF 图。参见下面的代码:
model = sm.tsa.statespace.SARIMAX(train, order=(0,1,1),
seasonal_order(0,1,1,7))
.fit(max_iter=50, method='powell')res = model.residfig, ax = plt.subplots(2,1)
fig = sm.graphics.tsa.plot_acf(res, lags=50, ax=ax[0])
fig = sm.graphics.tsa.plot_pacf(res, lags=50, ax=ax[1])
plt.show()
残差的 ACF 和 PACF 图见下图 4。除了在滞后 7 时,没有显著的峰值。这些参数是模型的一个可接受的起点,可以使用网格搜索进一步改进。
图 4:模型残差的 ACF 和 PACF 图
SARIMA 模型参数—网格搜索
以(0,1,1)x(0,1,1,7)为起点,建立网格搜索来测试许多不同的参数组合。值得关注的是那些 p = 0、1 或 2,q = 1 或 2 的模型。可以用来比较各模型相对质量的一个度量是 AIC (阿凯克信息准则),这是一个样本外预测误差的估计量;较低的 AIC 分数表明模型更具预测性。参见下面生成不同参数组合列表的代码,以及测试每个组合并打印相应 AIC 分数的 SARIMA 模型管道:
import itertools#set parameter range
p = range(0,3)
q = range(1,3)
d = range(1,2)
s = range(7,8)# list of all parameter combos
pdq = list(itertools.product(p, d, q))
seasonal_pdq = list(itertools.product(p, d, q, s))# SARIMA model pipeline
for param in pdq:
for param_seasonal in seasonal_pdq:
try:
mod = sm.tsa.statespace.SARIMAX(train,
order=param,
seasonal_order=param_seasonal)
results = mod.fit(max_iter = 50, method = 'powell')print('SARIMA{},{} - AIC:{}'.format(param, param_seasonal, results.aic))
except:
continue
在这种情况下,用 p , P = 1 和 q , Q = 2 获得了最低的 AIC 分数,因此要使用的最终 SARIMA 模型参数是 SARIMA(1,1,2)x(1,1,2,7) 。
与 MAPE 一起进行验证和评估
如本文背景所述,SARIMA 模型正在预测 2019 年 11 月的日用电负荷。虽然简单的训练/测试分割对于时间序列是可能的(在我们的例子中,测试数据是 2019 年 11 月的实际负荷数据),但更可靠的选择是向前行走验证,其中测试数据被分割多次。参见下面的代码;在第一次遍历中,根据模型对训练数据的拟合,预测 11 月第一周的日负荷。在第二次遍历中,将 11 月第一周的实际日负荷添加到训练数据中,重新调整模型,并预测 11 月第二周的负荷。11 月的第三和第四周遵循同样的程序。
平均绝对百分比误差(MAPE)是一个可用于评估 SARIMA 模型的指标。对于每个预测数据点,计算与相应测试点的绝对差值,然后除以测试点。平均百分比给出了 MAPE。请参见下面的代码,了解向前遍历验证和 MAPE 计算。
# data = entire dataset
# n_test = point where data is split into training and test setsdef walk_forward_validation(data, n_test): predictions = np.array([])
mape_list = []
train, test = data[:n_test], data[n_test:]
day_list = [7,14,21,28] # weeks 1,2,3,4 for i in day_list:
# Fit model to training data
model = sm.tsa.statespace.SARIMAX(train, order=(1,1,2),
seasonal_order(1,1,2,7))
.fit(max_iter = 50,
method = 'powell')
# Forecast daily loads for week i
forecast = model.get_forecast(steps = 7)
predictions = np.concatenate(predictions, forecast,
axis=None) # Calculate MAPE and add to mape_list
j = i-7
mape_score = (abs(test[j:i]-predictions[j:i])/test[j:i])*100
mape_mean = mape_score.mean()
mape_list.append(mape_mean) # Add week i to training data for next loop
train = np.concatenate((train, test[j:i]), axis=None)return predictions, mape_list
我们的模型预测的 MAPE 为 9.74%。还不错!让我们将预测和实际数据一起绘制出来,看看它们在视觉上是如何比较的。请参见下面的图 5。
图 5:每日负载预测与实际每日负载
预测似乎很好地遵循了每周的趋势,尽管在一个月中的一些日子里有相当大的误差。仔细看看,这些都是假期(特别是 11 日的退伍军人节,以及月底的感恩节假期)。
外变量
提高模型性能的一个快速方法是添加一个外生变量,该变量考虑了全年的假期。Python 有一个“假日”包,可以导入并用于确定日期是否为假日(可以指定美国假日)。
到目前为止,我们一直使用的 SARIMAX 模型只是将外生变量作为一个额外的参数。请参见下面的代码摘录:
model2 = sm.tsa.statespace.SARIMAX(train, holiday_ex_var,
order=(1,1,2),
seasonal_order(1,1,2,7))
.fit(max_iter = 50,
method = 'powell')
通过 walk_forward_validation 函数运行这个模型,我们得到的 MAPE 为 7.04% 。这比最初的型号提高了 25%以上!请参见下图 6,了解与实际日负荷相比的最新预测。退伍军人节和感恩节负荷预测有了明显的改进;加入假日变量是有益的!然而,仍有改进的余地,因为在感恩节假期的其他日子里仍有明显的误差。这里不探讨减少这些误差的方法。
图 6:每日负荷预测(带有外部变量)与实际每日负荷的对比
结论
总的来说,我们经历了一个电力负荷预测问题,并涵盖了一些重要的时间序列主题。检验平稳性、分析 ACF 和 PACF 图、执行验证以及考虑外生变量都是实现 SARIMA 模型时必不可少的。
这个项目扩展到 70 多栋加州大学伯克利分校的建筑,并创建了一个交互式 Tableau 仪表板来显示预测;这里可以查看。下面还可以看到一段录制的演示。点击此处进入该项目的 github repo。
希望这个概述是有帮助的。下次见!
R 中 ARIMA 模型的时间序列预测
帕特里克·亨德利在 Unsplash 上的照片
从勘探到预测 1970 年至 2015 年的二氧化碳排放数据。
C 气候变化是真实的。更糟糕的是,人类的活动对环境并不友好,例如使用化石燃料作为交通工具、燃煤发电机、水泥生产等。这些活动的影响之一是气温上升和臭氧层消耗。
众所周知,发达国家,尤其是欧洲,正在减少导致气候变化的排放量。如果我们想象一些欧洲国家的时间序列,它没有显示出明显的增长,它有同样的排放量,甚至在某些情况下排放量减少,特别是俄罗斯联邦在 1991 年苏联解体后。它显示几乎没有明显的增长。
当我们看发展中国家时,情况就不同了。如果我们从东盟国家的角度来看这个图,它不时地显示出轻微的线性增长。正如你在下面看到的,
基于这个问题,本文将向您展示如何使用 R 中的 ARIMA 模型来预测欧盟委员会的 CO2 排放时间序列数据,您可以在此处获得数据以及我们为什么要使用该模型。
通过分析和预测排放物的产生量,我们可以知道已经产生了多少排放物,这对于制定什么样的政策来减少其增长是非常有用的。
注意:
这与我之前的文章不同,我之前的文章预测印度尼西亚的 CPI 是一个平稳的数据。在这种情况下,我将使用印度尼西亚的二氧化碳排放量向您展示如何处理非平稳数据。
但是等等,平稳和非平稳数据有什么区别?
平稳与非平稳数据
平稳数据和非平稳数据的区别在于时间的均值和方差。
静态数据在时间上具有恒定的均值、方差和相关性。而非平稳数据具有随时间变化的均值、方差和相关性。
还是一点想法都没有?好吧,看看这些可视化的东西:
回想一下我上一篇文章中的 CPI 图,这是一个平稳的数据。原因是 CPI 值不会随着时间的推移而增加,换句话说,无论它是否增加,都不存在趋势。
这是马来西亚随着时间的推移产生的二氧化碳排放量。正如我们所见,它显示了一些线性趋势。我们可以说,均值、方差和相关性随着时间的推移而增加。这就是为什么它是非平稳数据。
我希望你现在至少能理解平稳和非平稳时间序列数据之间的区别。
行动(或活动、袭击)计划
在我们进行分析之前,我会告诉你我是如何处理这些数据的。以下是我完成的步骤:
- 数据探索
- 型号识别和诊断
- 预测
分析
介绍
在建立模型之前,我们首先要知道数据。它看起来如何,与其他国家的模式有何不同,等等。我将描述什么是真正的数据集以及数据集中包含的信息。
该数据集代表了从 1970 年到 2015 年的二氧化碳排放总量。它记录了世界上所有国家的数量。欧洲委员会联合研究中心记录的 CO2 量是来自化石燃料使用和工业过程使用的排放,例如水泥生产、化学过程、非能源使用等等。这不包括生物质燃烧和其他农业相关活动,如森林火灾和农业废物燃烧。
探测
因为我已经告诉过你们一些国家的二氧化碳排放量,我将向你们具体展示印度尼西亚的二氧化碳排放量。这里展示了它的可视化,
正如我们在这里看到的,它随时间呈线性趋势。这是一个不稳定的数据,因为均值、方差和相关性会随着时间而变化。在 1970 年,二氧化碳排放量仅为 30.066 千吨,而在 2015 年,二氧化碳排放量为 502.961 千吨。
这是一个很大的变化。根据这些数据,我们希望使用 ARIMA 模型进行预测,以了解如果政府政策不变,未来几年的排放量是多少。
模型识别
因为这不是一个平稳的时间序列,我们必须找到与以前的值有差异的数据。
如果差分数据具有平稳特性,则可以使用 ARMA 模型对其建模。因此,我们可以从中找到模型的完美滞后。
为此,我们必须将该值作为一个时间序列对象,然后查看应用于 diff 函数的时间序列的结果。下面是代码的样子,
**indo <- df %>%
filter(nation == "Indonesia") %>%
pivot_longer(2:47, names_to = "year", values_to = "co2")indo.ts <- ts(indo$co2, frequency = 1, start = 1970)
indo.ts # Create Time Series Plot from
plot(diff(indo.ts))**
这是它的可视化结果,
基于这种可视化,我们可以看到差异数据具有稍微更稳定的属性,并且没有趋势。因此,我们可以使用这些差异数据来找出哪些 AR 和 MA 参数适合我们的 ARIMA 模型。
为了找到适合我们的 ARIMA 模型的 AR 和 MA 的参数值,我们可以使用 ACF 和 PACF 函数来找到最佳值,
这是一个函数,我们可以看到 ACF 和 PACF 图,
**library(astsa)
acf2(diff(indo.ts), max.lag = 40)**
这是结果,
根据这个图,我们知道,ACF 和 PACF 函数略有下降,不会很快达到 0。因此,我们可以假设它将参数 p 与 1 一起使用,参数 q 也与 1 一起使用。所以,适合的 ARMA 模型是 ARMA(1,1)。
为了使模型成为 ARIMA 模型,我们只需添加另一个参数,即代表数据差异的 d。因此,我们的 ARIMA 模型将是 ARIMA(1,1,1),其中每个参数代表 p、d 和 q。p 是 AR 模型参数,d 是数据的差异量,q 是 MA 模型参数。
模型诊断
如果其他模型之间没有显著变化,ARIMA(1,1,1)将是我们的模型。在这种情况下,我们将尝试 ARIMA(2,1,1)和 ARIMA(1,1,2)来查看参数是否具有显著的 p 值。
我们可以简单地通过使用下面的函数来诊断这个模型,
**# ARIMA(1, 1, 1)
sarima(indo.ts, 1, 1, 1)# ARIMA(2, 1, 1)
sarima(indo.ts, 2, 1, 1)# ARIMA(1, 1, 2)
sarima(indo.ts, 1, 1, 2)**
这是每个参数的 p 值,
从左到右:ARIMA(1,1,1),ARIMA(1,1,2),ARIMA(2,1,1)
正如我们在这里看到的,ARIMA(1,1,1)在其参数上具有显著的 p 值。那么,ARIMA(1,1,2)和 ARIMA(2,1,1)这两个模型的 p 值都不显著。通过改变它的参数对模型没有任何影响。因此,我们可以用 ARIMA(1,1,1) 模型。
在我们为数据选择了最佳模型之后,我们还要诊断另一件事,那就是残差。以下是 sarima 函数的残差分析结果。
如果我们要使用这个模型,残差必须具有正态分布,并且其值的每个滞后之间没有相关性。基于这一可视化,我们可以看到残差没有任何显著的自相关性,正如我们从 ACF 图中看到的那样,大多数点也在直线上对齐,正如我们从 Q-Q 图中看到的那样,并且 Ljung-Box 统计 p 值没有越过蓝线。因此,我们可以用这个模型来做预测。
预测
如果我们想做一些预测,我们可以使用 sarima.for 函数来做。这个函数的每个参数都包括数据、我们要预测的时间,然后设置代表我们的 ARIMA 模型的 p、d 和 q 参数。
在本例中,我们想知道未来 35 年的二氧化碳排放量是多少,以及 2050 年的二氧化碳排放量是多少。
这是用来做预测的函数,
**sarima.for(indo.ts, n.ahead = 35, 1, 1, 1)**
这是它的视觉效果,
正如我们在这里看到的,黑点代表我们的数据,红色代表预测结果。正如我们在这里看到的,预测结果也显示了红线之间的灰色边界。它基本上表示预测结果的标准误差。该边界上没有大的边界,因此该模型具有良好的结果。
根据预测结果,我们知道 2050 年将产生约 904.186 千吨的二氧化碳排放量。这是一个巨大的二氧化碳排放量。因此,政府应该考虑如何减少排放的政策,这样才能对抗气候变化,使我们的地球更适合居住,而不是因为我们的活动而破坏地球的状况。
结论
总之,ARIMA 模型是对非平稳时间序列数据进行预测的良好模型。
我知道,这个模型并不完美,但至少它给出了未来的价值。知道这一点真的很重要,尤其是如果你是一个政策制定者,通过知道这个结果,你将知道制定什么样的政策。
我将引用这段话来结束这篇文章,以提醒我们,
“所有的模型都是错误的,但有些是有用的”——乔治·博克斯
参考
[1] Stoffer,D. S. & Shumway,R. H. 时间序列:一种使用 R (2019)的数据分析方法,Taylor & Francis Group。
【2】Hyndman,R.J. & Athanasopoulos,G. 预测:原理与实践 (2018),第 2 版,OTexts。
感谢您阅读我的文章,您也可以在下面查看我以前的文章:
从探索,到预测。使用印度尼西亚 2002 年 12 月至 2020 年 4 月的消费者价格指数(CPI)数据
towardsdatascience.com](/introduction-to-time-series-analysis-with-r-a2f97650baa3) [## 我推荐你先学习 Python 的 3 个理由
如果你想从数据科学开始而不是先学 R
towardsdatascience.com](/3-reasons-why-i-recommend-you-to-learn-python-first-8e72ed4a6c65) [## 更高的准确性并不意味着更好的机器学习模型性能
我们可以定量地衡量机器学习模型的性能,但不仅仅是准确性,还有很多…
towardsdatascience.com](/greater-accuracy-does-not-mean-greater-machine-learning-model-performance-771222345e61)****
具有自回归过程的时间序列预测
Python 中时间序列分析的 AR§过程实践教程
伊莲娜·科伊切娃在 Unsplash 上的照片
介绍
在本实践教程中,我们将讨论使用自回归过程进行时间序列建模的主题。
本文将涵盖时间序列分析中的以下关键要素:
- 自回归过程
- 尤尔-沃克方程
- 平稳性
- 扩充的迪克-富勒试验
确保准备好 Jupyter 笔记本,以便跟进。代码和数据集可在这里获得。
我们开始吧!
了解如何使用更复杂的模型,如 SARIMAX、VARMAX,并应用深度学习模型(LSTM、CNN、ResNet、自回归 LSTM)进行时间序列分析,并使用 Python 中的应用时间序列分析!
自回归过程
一个自回归模型使用目标过去值的线性组合进行预测。当然,回归是针对目标本身进行的。数学上,AR§模型表示为:
自回归模型
其中:
- p:这是命令吗
- c:是常数
- ε:噪声
AR§模型非常灵活,可以模拟许多不同类型的时间序列模式。当我们模拟自回归过程时,这是很容易想象的。
通常,自回归模型仅适用于平稳时间序列。这限制了参数φ的范围。
例如,AR(1)模型会将 phi 限制在-1 和 1 之间。随着模型阶数的增加,这些约束变得更加复杂,但是在 Python 中建模时会自动考虑这些约束。
AR(2)过程的模拟
让我们用 Python 模拟一个 AR(2)流程。
我们从导入一些库开始。并非所有这些都将用于模拟,但它们将是本教程其余部分所必需的。
from statsmodels.graphics.tsaplots import plot_pacf
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.tsa.arima_process import ArmaProcess
from statsmodels.tsa.stattools import pacf
from statsmodels.regression.linear_model import yule_walker
from statsmodels.tsa.stattools import adfuller
import matplotlib.pyplot as plt
import numpy as np%matplotlib inline
我们将使用 ArmaProcess 库来模拟时间序列。它要求我们定义我们的参数。
我们将模拟以下过程:
AR(2)过程
因为我们正在处理一个 2 阶的自回归模型,我们需要定义滞后 0,1 和 2 的系数。
此外,我们将取消移动平均线过程的影响。
最后,我们将生成 10 000 个数据点。
在代码中:
ar2 = np.array([1, 0.33, 0.5])
ma = np.array([1])simulated_AR2_data = ArmaProcess(ar2, ma).generate_sample(nsample=10000)
我们可以绘制时间序列:
plt.figure(figsize=[10, 7.5]); # Set dimensions for figure
plt.plot(simulated_AR2_data)
plt.title("Simulated AR(2) Process")
plt.show()
您应该会得到类似这样的结果:
模拟 AR(2)过程的图
现在,让我们来看看自相关图(相关图):
plot_acf(simulated_AR2_data);
AR(2)过程的相关图
你可以看到系数在慢慢衰减。这意味着它不太可能是一个移动平均过程,这表明时间序列可能可以用一个自回归过程来建模(这是有意义的,因为这正是我们正在模拟的)。
为了确保这是正确的,让我们绘制偏自相关图:
plot_pacf(simulated_AR2_data);
AR(2)过程的偏自相关图
正如你所看到的,滞后 2 之后,系数并不显著。因此,部分自相关图对于确定 AR§过程的阶数是有用的。
您还可以通过运行以下命令来检查每个系数的值:
pacf_coef_AR2 = pacf(simulated_AR2_data)
print(pacf_coef_AR2)
现在,在真实的项目设置中,可以很容易地找到 AR§过程的阶,但是我们需要找到一种方法来估计系数φ。
为此,我们使用了尤尔-沃克方程。这个方程允许我们在已知阶数的情况下估计 AR§模型的系数。
rho, sigma = yule_walker(simulated_AR2_data, 2, method='mle')
print(f'rho: {-rho}')
print(f'sigma: {sigma}')
尤尔-沃克系数估计
如你所见,Yule-Walker 方程在估算我们的系数方面做得不错,非常接近 0.33 和 0.5。
AR(3)过程的模拟
现在,让我们模拟一个 AR(3)过程。具体来说,我们将模拟:
AR(3)过程模拟
类似于之前所做的,让我们定义我们的系数并生成 10 000 个数据点:
ar3 = np.array([1, 0.33, 0.5, 0.07])
ma = np.array([1])simulated_AR3_data = ArmaProcess(ar3,ma).generate_sample(nsample=10000)
然后,我们可以将时间序列可视化:
plt.figure(figsize=[10, 7.5]); # Set dimensions for figure
plt.plot(simulated_AR3_data)
plt.title("Simulated AR(3) Process")
plt.show()
您应该会看到类似如下的内容:
模拟 AR(3)过程
现在,看看 PACF 和 ACF:
plot_pacf(simulated_AR3_data);
plot_acf(simulated_AR3_data);
AR(3)流程的 PACF 和 ACF
你可以看到,对于 PACF 函数来说,滞后 3 之后的系数并不像预期的那样显著。
最后,让我们使用尤尔-沃克方程来估计系数:
rho, sigma = yule_walker(simulated_AR3_data, 3, method='mle')
print(f'rho: {-rho}')
print(f'sigma: {sigma}')
尤尔-沃克系数估计
同样,估计值相当接近实际值。
项目—预测强生公司的季度每股收益
现在,让我们将自回归过程的知识应用到项目设置中。
目标是模拟强生公司 1960 年至 1980 年间的每股季度收益(EPS)。
首先,我们来读一下数据集:
import pandas as pddata = pd.read_csv('jj.csv')
data.head()
数据集的前五行
现在,前五行对我们来说不是很有用。让我们绘制整个数据集,以获得更好的可视化表示。
plt.figure(figsize=[15, 7.5]); # Set dimensions for figure
plt.scatter(data['date'], data['data'])
plt.title('Quaterly EPS for Johnson & Johnson')
plt.ylabel('EPS per share ($)')
plt.xlabel('Date')
plt.xticks(rotation=90)
plt.grid(True)
plt.show()
强生公司 1960 年至 1980 年间的每股收益
厉害!现在我们可以看到数据有明显的上升趋势。虽然这对公司来说可能是一个好迹象,但就时间序列建模而言,这并不好,因为这意味着时间序列不是平稳的。
如前所述,AR§过程仅适用于平稳序列。
因此,我们必须对数据进行一些转换,使其保持稳定。
在这种情况下,将取对数差。这相当于取每个值的对数,减去前一个值。
# Take the log difference to make data stationarydata['data'] = np.log(data['data'])
data['data'] = data['data'].diff()
data = data.drop(data.index[0])
data.head()
绘制转换后的时间序列:
plt.figure(figsize=[15, 7.5]); # Set dimensions for figure
plt.plot(data['data'])
plt.title("Log Difference of Quaterly EPS for Johnson & Johnson")
plt.show()
强生公司季度每股收益的对数差异
现在,似乎我们消除了这种趋势。然而,在用 AR§过程建模之前,我们必须确保我们的序列是平稳的。
因此,我们将使用扩展的 Dicker-Fuller 检验。这将给我们统计上的信心,我们的时间序列确实是平稳的。
ad_fuller_result = adfuller(data['data'])
print(f'ADF Statistic: {ad_fuller_result[0]}')
print(f'p-value: {ad_fuller_result[1]}')
ADF 测试的结果
由于我们得到一个大的负 ADF 统计量和小于 0.05 的 p 值,我们可以拒绝零假设,说我们的时间序列是平稳的。
现在,让我们通过绘制 PACF 来找到该过程的顺序:
plot_pacf(data['data']);
plot_acf(data['data']);
PACF 和 ACF
正如你所看到的,在滞后 4 之后,PACF 系数不再重要。因此,我们将假设一个 4 阶的自回归过程。
现在,我们将利用这些信息,通过 Yule-Walker 方程来估算系数:
# Try a AR(4) model
rho, sigma = yule_walker(data['data'], 4)
print(f'rho: {-rho}')
print(f'sigma: {sigma}')
尤尔-沃克系数估计
因此,该函数近似为:
请注意,此等式模拟了转换后的序列。
结论
恭喜你!您现在了解了什么是自回归模型,如何识别自回归过程,如何确定其顺序,以及如何使用它来模拟现实生活中的时间序列。
提高您的时间序列分析技能,并学习 Python 中时间序列分析的最新最佳实践:
干杯🍺
基于深度学习和注意机制的时间序列预测
入门指南
用于时间序列预测的最重要的深度学习算法的架构和实现细节的概述
动机
时间序列预测在许多领域一直是一个非常重要的研究领域,因为许多不同类型的数据都存储为时间序列。例如,我们可以在医学、天气预报、生物学、供应链管理和股票价格预测等领域找到大量的时间序列数据。
鉴于近年来数据可用性和计算能力的不断增长,深度学习已成为新一代时间序列预测模型的基础部分,并取得了优异的效果。
虽然在经典的机器学习模型(如自回归模型(AR)或指数平滑)中,特征工程是手动执行的,并且通常还会考虑领域知识来优化一些参数,但深度学习模型仅直接从数据中学习特征和动态。得益于此,他们加快了数据准备的过程,并能够以更完整的方式学习更复杂的数据模式。
随着不同时间序列问题在许多不同领域的研究,近年来开发了大量新的体系结构。开源框架的日益普及也简化了这一过程,它使得新的定制网络组件的开发更加容易和快速。在这篇文章中,我们总结了时间序列预测最常见的深度学习方法。
应用程序
让我们看看时间序列预测的一些重要应用。
股票价格预测- 许多先进的时间序列预测模型被用于预测股票价格,因为在历史序列中存在大量噪声和高度不确定性的信息,这些信息可能依赖于不总是与股票市场密切相关的几个因素。
天气预测——时间序列预测模型被广泛用于
提高天气预测的准确性。
预测交通 -旅行规划应用程序使用时间序列预测模型来预测道路上的交通,以便更准确地决定到达所选目的地的最快方式。
许多公司使用时间序列预测模型来预测他们在哪个月可以预期更高的流动率,以便他们可以实施最佳的员工保留计划。
文本生成- 当我们在智能手机上写文本时,它会查看最后写的单词和键入的字母,并建议接下来的字母甚至整个单词。
时间序列组件
首先,解释时间序列的主要组成部分是很重要的。
长期趋势
长期趋势是数据的总体方向,忽略任何短期影响,如季节变化或噪音。
季节性
季节性是指在整个时间序列期间重复的周期性波动。
平稳性
平稳性是时间序列的一个重要特征。如果时间序列的均值、方差和协方差不随时间发生显著变化,则称该时间序列是平稳的。有许多变换可以提取非平稳过程的平稳部分。
噪音
每组数据都有噪声,即由于不可控因素导致的随机波动或变化。
自相关
自相关是时间序列与其自身的滞后版本之间的相关性,用于识别时间序列数据中的季节性和趋势。
基于传统机器学习的时间序列预测
在谈论时间序列预测的深度学习方法之前,回忆一下用于解决这个问题的最经典的机器学习模型是 ARIMA 模型和指数平滑是有用的。
ARIMA 主张在建立时间序列的复合模型时结合自回归(AR)和移动平均(MA)方法。这个模型非常简单,但可能会有好的结果。它包括说明季节性、长期趋势、自回归和移动平均项的参数,以便处理数据中嵌入的自相关。
在指数平滑法中,预报是在加权平均值的基础上进行的,就像在 ARIMA 模型中一样,但是在这种情况下,不同的递减权重被分配给每个观测值,随着我们离现在越来越远,对观测值的重视程度越来越低。
传统机器学习的劣势
众所周知,这些传统的机器学习模型有许多局限性:
- 缺少值确实会影响模型的性能;
- 他们不能识别数据中的复杂模式;
- 它们通常只在分步预报中有效,在长期预报中无效。
时间序列预测的深度学习
使用深度学习进行时间序列预测克服了许多不同方法的传统机器学习缺点。本文提出了 5 种不同的时间序列预测深度学习架构:
- *递归神经网络(RNNs),*时间序列预测问题最经典、最常用的架构;
- 长短期记忆(LSTM) ,其是为了克服消失梯度问题而开发的 RNNs 的进化;
- 门控循环单元(GRU) ,那是 RNNs 的另一种进化,类似于LSTM;
- 编码器-解码器模型,这是为了解决输入序列与输出序列长度不同的问题而引入的 RNNs 模型;
- 注意机制,它是编码器-解码器模型的一种进化,其开发是为了避免忘记序列的较早部分。
递归神经网络
递归神经网络是组织成连续层的神经元样节点的网络,具有类似于标准神经网络的架构。事实上,像在标准神经网络中一样,神经元被分为输入层、隐藏层和输出层。神经元之间的每个连接都有相应的可训练权重。
不同之处在于,在这种情况下,每个神经元都被分配到一个固定的时间步长。隐藏层中的神经元也在时间相关的方向上被转发,这意味着它们中的每一个都仅与具有相同分配时间步长的隐藏层中的神经元完全连接,并且与分配到下一个时间步长的每一个神经元单向连接。输入和输出神经元仅连接到具有相同指定时间步长的隐藏层。
由于一个时间步长的隐藏层的输出是下一个时间步长的输入的一部分,神经元的激活是按时间顺序计算的:在任何给定的时间步长,只有分配给该时间步长的神经元计算它们的激活。
体系结构
作者图片
权重- 在 *RNNs 中,*时刻 t 的输入向量通过权重矩阵 U 连接到时刻 t 的隐层神经元,隐层神经元通过权重矩阵 W 连接到时刻 t-1 和 t+1 的神经元,隐层神经元连接到输出所有权重矩阵在每个时间步都是常数
输入- 向量 x(t) 是网络在时间步长t的输入
隐藏状态- 向量 h(t) 是时间处的隐藏状态,是网络的一种内存y;它是基于当前输入和前一时间步的隐藏状态计算的:
输出— 矢量 y^(t) 是网络在时间 t 的输出:
学习算法
学习过程的目标是从真实值 y(t) 的输入 x(t) 开始,找到给出 y^(t) 的最佳预测的最佳权重矩阵 U 、 V 和 W 。
为了实现这一点,我们定义了一个目标函数,称为损失函数并表示为 J,,它量化了整个训练集的实际值和预测值之间的距离。它是由
在哪里
- 成本函数 L 评估单个时间步长上的实际值和预测值之间的距离;
- m 是训练集的大小;
- θ 模型参数的向量。
使用这两个主要步骤使损失函数 J 最小化:通过时间的向前传播和向后传播**。这些步骤迭代多次,迭代次数称为历元数。
前向传播 -使用固定参数 U 、 W 和 V ,数据通过网络传播,在每个时刻 t ,我们使用之前定义的公式计算 y^ (t) 。最后计算损失函数。
通过时间的反向传播- 相对于不同的参数计算成本函数的梯度,然后应用下降算法以便更新它们。每个输出端的梯度既取决于同一时间步的元素,也取决于前一时间步的存储器状态。
递归神经网络的优势
一般来说,RNNs 解决了时间序列预测的传统机器学习模型的许多问题。
- RNNs 的性能不会受到丢失值的显著影响。
- RNNs 可以发现输入时间序列中的复杂模式。
- RNNs 在预测多于几步的情况下给出了良好的结果。
- RNNs 可以对数据序列进行建模,以便可以假设每个样本都依赖于前一个样本。
递归神经网络的缺点
- 当在长时间序列上训练时,rnn 通常会遭受消失梯度或爆炸梯度*问题,这意味着隐藏层中的参数要么不会改变太多,要么会导致数值不稳定和混沌行为。这是因为成本函数的梯度包括影响其记忆能力的 *W、的幂。
- 上面描述的内在循环网络存在记忆力差的问题,在预测未来时不能考虑过去的几个因素。
- 递归神经网络的训练很难并行化,并且计算量也很大。
鉴于这些缺点,RNNs 的各种扩展被设计来修整内部存储器:双向神经网络、LSTM、GRU、注意力机制。在金融等特定领域,扩大记忆可能至关重要,在这些领域,最基本的是尽可能多地记忆历史,以便预测接下来的步骤。
长短期记忆(LSTM)
长短期记忆网络(LSTM)已经被开发出来,通过改善网络内的梯度流来克服标准 RNN 中的梯度消失问题。这是通过使用 LSTM 单元代替隐藏层来实现的。如下图所示,一个 LSTM 单元包括:
- 一个信元状态*,它带来整个序列的信息并代表网络的存储;*
- 一个忘记门*,它决定从先前的时间步骤中保留什么;*
- 一个输入门*,它决定从当前时间步长添加什么相关信息;*
- 一个输出门*,决定当前时间步长的输出值。*
类似于 RNNs,时间 t 的输入向量通过权重矩阵 U 连接到时间 t 的 LSTM 单元,LSTM 单元通过权重矩阵 W 连接到时间 t-1 和 t+1 的 LSTM 单元,LSTM 单元连接到时间t的输出向量矩阵 W 和 U 被分成子矩阵( Wf 、 Wi 、 Wg 、Wo;Uf 、 Ui 、 Ug 、 Uo )连接到 LSTM 单元的不同元件,如下图所示。所有权重矩阵在时间上是共享的。
作者图片
细胞状态在处理过程中传递相关信息,因此来自前一时间步的信息也会到达每个时间步,从而减少短期记忆的影响。在所有时间步骤的训练中,门学习哪些信息是重要的,应该保留或忘记,并将它们添加到细胞状态中,或从细胞状态中删除。
通过这种方式,LSTM 允许恢复内存中传输的数据,解决了消失梯度问题。LSTM 可用于分类、处理和预测具有未知持续时间的时间滞后的时间序列。
忘记大门
第一道门是遗忘之门。这个入口决定哪些信息应该被删除或保存。来自先前隐藏状态的信息和来自当前输入的信息通过 sigmoid 函数传递。输出接近 0 意味着信息可以被遗忘,而输出接近 1 意味着信息必须被保存。
输入门
第二个门是输入门。这用于更新单元状态。最初,先前的隐藏状态和当前输入作为输入被给定到 sigmoid 函数(输出越接近 1,信息越重要)。它还将隐藏状态和当前输入传递给一个 tanh 函数,以将值压缩在-1 和 1 之间,从而改善网络的调谐。然后, tanh 和 sigmoid 的输出被逐元素相乘(在下面的公式中,符号表示两个矩阵的逐元素相乘)。 sigmoid 输出决定哪些信息对 tanh 输出是重要的。*
细胞状态
输入门激活后,可以计算单元状态。首先,前一时间步的单元状态按元素乘以遗忘门的输出。当单元状态中的值乘以接近 0 的值时,这提供了忽略这些值的可能性。然后,输入门的输出被逐元素添加到单元状态。输出是新的单元状态。
输出门
第三个也是最后一个门是输出门,它决定下一个隐藏状态的值,该值包含有关先前输入的信息。首先,将先前的隐藏状态和当前输入相加,并传递给一个 sigmoid 函数。然后,新的单元状态被传递给 tanh 函数。最后, tanh 输出与 sigmoid 输出相乘,以决定隐藏状态应该包含什么信息。输出是新的隐藏状态。然后,新的单元状态和新的隐藏状态被带到下一个时间步骤。
门控循环单元(GRU)
GRU 是新一代的递归神经网络,非常类似于 LSTM。为了解决标准 RNN 的消失梯度问题,GRU 使用了更新门和重置门*。这两个门决定什么信息应该被传递到输出。这两个门可以被训练以保持来自实际时间步长之前的许多时间步长的信息,而不随时间推移清洗它,或者移除与预测无关的信息。如果仔细训练,GRU 甚至可以在复杂的情况下表现得非常好。*
如下图所示,一个 GRU 单元包括:
- 一个复位门*,它决定有多少来自先前时间步骤的信息可以被遗忘;*
- 一个更新门*,它决定必须保存多少来自先前时间步骤的信息;*
- 一个存储器*,它携带整个序列的信息并代表网络的存储器。*
作者图片
复位门
第一个门是复位门。它决定了如何将新的输入与以前的记忆结合起来,决定了可以忘记多少以前时间步骤的信息。首先,执行输入 x(t) 和存储器h(t-1)之间的加权和,该存储器保存先前 t-1 步骤的信息。然后应用 sigmoid 激活函数将结果压缩在 0 和 1 之间。
更新门
第二个门是更新门。它有助于模型确定有多少来自先前时间步骤的信息需要传递到未来。这真的很强大,因为模型可以决定复制过去的所有信息,并消除消失梯度问题的风险。计算它的公式类似于复位门的公式,但是不同之处在于权重和门的用途(在存储器的计算中会很清楚)。
当前内存
存储器内容使用复位门来存储来自过去的相关信息。为了获得它,首先计算复位门 r(t) 的输出与前一时间步 h(t-1) 的最终存储器之间的逐元素乘法,然后执行结果与输入 x(t) 之间的加权和。最后,应用非线性激活函数 tanh 。
最终记忆
作为最后一步,网络需要计算 h(t) ,即保存当前单元信息的向量,并将其传递到下一个时间步骤。它决定了从当前内存内容 h ~ (t) 中收集什么,从前面的步骤 h(t-1) 中收集什么。它是通过在更新门 z_t 和 h_(t-1) 之间以及 (1-z_t) 和 h~(t) 之间应用逐元素乘法来计算的,最后在两个结果之间执行 yhr 加权求和。**
RNN、LSTM、GRU 的执行情况
RNN、LSTM 和 GRU 可以使用 Keras API 实现,该 API 旨在易于使用和定制。Keras 中存在以下 3 个 RNN 层:
- keras.layers.SimpleRNN
- keras.layers.LSTM
- keras.layers.GRU
它们允许您快速创建重复模板,而不必做出困难的配置选择。此外,可以定义一个具有所需行为的自定义 RNN 细胞层,允许以最少的代码灵活地快速测试各种不同的原型。在 Tensorflow 网站上,可以找到使用这些图层的说明和许多示例。
编码器-解码器模型
在 RNN、LSTM 和 GRU,每个输入对应于同一时间步的一个输出。然而,在许多实际情况下,我们希望在给定不同长度的输入序列的情况下预测输出序列,而不需要每个输入和每个输出之间的对应关系。这种情况称为序列到序列映射模型,是众多常用应用的基础,例如语言翻译、语音设备和在线聊天机器人。
为了解决序列到序列* 映射模型,引入了递归神经网络的编码器-解码器模型。编码器-解码器将一个序列作为输入,并生成最可能的下一个序列作为输出。顾名思义,该模型由两个子模型组成:*
- 编码器,负责逐步通过输入时间步骤,并将整个序列编码成称为上下文向量的固定长度向量;
- 解码器,负责在从上下文向量中读取时步进输出时间步长。
作者图片
编码器
编码器是几个递归单元的堆叠,这些递归单元可以是简单的 rnn、LSTM 单元或 GRU 单元。每个单元接受输入序列的单个元素,从该元素收集信息并将其向前传播。
使用所选择的递归单元的函数来计算隐藏状态向量 h(t) 。该函数以适当的权重应用于先前的隐藏状态 h(t-1) 和输入向量x(t)**
最终隐藏状态向量 h(t) 包含来自先前隐藏表示和先前输入的所有编码信息。
上下文向量
上下文向量是从模型的编码器部分产生的最终隐藏状态,并表示解码器的初始隐藏状态。它封装了所有输入元素的信息,以帮助解码器做出准确的预测。
解码器
解码器由几个循环单元的堆栈组成。每个递归单元从前一个单元接受一个隐藏状态 s(t-1) ,并产生和输出 y^(t) 以及它自己的隐藏状态 s(t) 。
隐藏状态 s(t) 是根据所选递归单元的功能计算的:
使用当前时间步 s(t) 处的隐藏状态以及相应的权重,使用 softmax 函数来计算输出 y^(t) ,以便创建概率向量:
优点和缺点
该模型的强大之处在于它可以将不同长度的序列相互映射,因为输入和输出是不相关的,它们的长度可以不同。这开启了一系列全新的问题,现在可以使用这种架构来解决。
这种技术适用于小序列,但是当序列的长度增加时,很难将长序列总结成单个向量,然后 model 在处理最后部分时经常忘记输入序列的前面部分。这就是为什么许多实验表明,随着序列大小的增加,该模型的性能下降。
注意机制
注意机制是深度学习中的主要前沿之一,并且是编码器-解码器模型的进化,开发该模型是为了提高对长输入序列的性能。
主要思想是允许解码器在解码期间选择性地访问编码器信息。这是通过为解码器的每个时间步长构建不同的上下文向量、根据编码器的前一隐藏状态和所有隐藏状态来计算它、为它们分配可训练的权重来实现的。
这样,注意机制对输入序列的不同元素赋予不同的重要性,对更相关的输入给予更多的注意* 。这解释了模型的名称)。*
作者图片
编码器
编码器操作非常类似于编码器-解码器模型的相同操作。在每个时间步长,每个输入序列的表示作为前一个时间步长和当前输入的隐藏状态的函数进行计算。最终隐藏状态包含来自先前隐藏表示和先前输入的所有编码信息。
上下文向量
注意机制和编码器-解码器模型之间的主要区别在于,为解码器的每个时间步长 t 计算不同的上下文向量 c(t) 。
为了计算时间步长 t 的上下文向量 c(t) ,我们进行如下。首先,对于编码器的时间步长 j 和解码器的时间步长 t 的每个组合,所谓的对准分数 e(j,t)* 用以下加权和计算:*
*在这个方程中, *Wₐ,uₐ, Vₐ 为可训练权重,称为注意力权重。权重 Wₐ 与编码器的隐藏状态相关联,权重 Uₐ 与解码器的隐藏状态相关联,权重 Vₐ 定义计算校准分数的函数。
对于每个时间步长 t ,在编码器时间步长 j 上使用 softmax 函数对分数 e(j,t) 进行归一化,得到注意力权重* α(j,t)*
注意力权重α(j,t) 捕捉时间步长 j 的输入对于解码时间步长 t 的输出的重要性。上下文向量 c(t) 根据注意力权重计算为编码器所有隐藏值的加权和:
该上下文向量允许对输入句子中更相关的输入给予更多关注* 。*
解码器
现在上下文向量 c(t) 被传递给解码器,解码器计算下一个可能输出的概率分布。这种解码操作适用于输入中出现的所有时间步长。
然后根据递归单元函数计算当前隐藏状态 s(t) ,输入上下文向量 c(t) ,隐藏状态 s(t-1) 和输出前一时间步的 y^(t-1) :
因此,使用这种机制,该模型能够找到输入序列的不同部分和输出序列的相应部分之间的相关性。
对于每个时间步长,将 softmax 函数应用于加权隐藏状态来计算解码器的输出:
优势
- 正如已经提到的,注意机制在存在长输入序列的情况下也给出了好的结果。
- 由于注意力权重,注意力机制还具有比其他深度学习模型更易解释的优势,其他深度学习模型通常被认为是黑盒,因为它们不具有解释其输出的能力。
- 此外,注意机制在 NLP 模型中给出了突出的结果,因为它允许记住输入中的所有单词,并在制定响应时识别最相关的单词。
履行
注意机制可以使用 TensorFlow 和 Keras 开发,并很容易与其他 Keras 层集成。在 Github 上可以找到许多实现,例如:
https://github.com/uzaymacar/attention-mechanisms
https://github.com/philipperemy/keras-attention-mechanism
在这些环节,也有很多关于情感分类、文本生成、文档分类、机器翻译的例子。
结论
递归神经网络是用于时间序列预测的最流行的深度学习技术,因为它们允许在许多不同的问题中对时间序列进行可靠的预测。rnn 的主要问题是,当应用于长序列时,它们遭受消失梯度问题。
LSTM 和 GRU 是为了通过使用门来减轻 RNNs 的消失梯度问题而创建的,门通过序列链来调节信息流。LSTM 和 GRU 的使用在诸如语音识别、语音合成、自然语言理解等应用中给出了显著的结果。
递归神经网络的编码器-解码器模型是序列到序列映射问题中最常见的技术,其中输入序列与输出序列的长度不同。
注意机制是编码器-解码器模型的发展,其诞生是为了解决编码器-解码器模型在长序列存在时的性能下降,对每个时间步长使用不同的上下文向量。它在许多领域都取得了显著的效果,例如自然语言处理、文本分类、文档分类等。
作者
我关于走向数据科学的文章:https://medium.com/@marcodelpra
*我的 LinkedIn 个人资料:【https://www.linkedin.com/in/marco-del-pra-7179516/ *
领英集团 AI 学习:https://www.linkedin.com/groups/8974511/
基于图卷积神经网络的时间序列预测
结合图和递归结构的商店物品需求预测
米歇尔·比特托在 Unsplash 上的照片
时间序列预测任务可以通过以下不同的方法来完成。最经典的是基于统计和自回归方法。更棘手的是基于 boosting 和 ensemble 的算法,在这些算法中,我们必须产生大量有用的手工制作的滚动周期特征。另一方面,我们可以找到神经网络模型,使其开发更加自由,提供可定制的顺序建模和更多。
递归和卷积结构在时间序列预测中取得了巨大成功。该领域中有趣的方法是通过采用最初在 NLP 中固有的转换器和注意力架构来给出的。图形结构的使用似乎不常见,其中我们有一个由不同节点组成的网络,这些节点通过某种链接相互关联。我们试图用时间序列的图形表示来预测未来。
在本文中,我们执行了一项销售预测任务,其中我们利用图形卷积神经网络,利用我们的数据的嵌套结构,这些数据由不同商店中各种商品的不同销售系列组成。
数据
该数据集是从 Kaggle 上过去的比赛中收集的。商店商品需求预测挑战赛以每日格式提供了各商店销售的不同商品的 4 整年的销售数据。我们有 10 家商店和 50 种产品,总共 500 个系列。每个产品在每个商店都有销售。我们的范围是每天为所有项目提供准确的未来预测。
每个商店中商品 10 的销售额
我们掌握的数据很少:只有销售额以及商品和商店的数字编码。这仍然足以让我们强调一个基本的层次结构。我们需要做的就是在项目级别对系列进行分组,这样我们最终得到 50 个组(项目),每个组由 10 个系列组成(每个商店销售的项目);上图描述了一个组的示例。
在经典图网络中,所有相关信息都存储在一个名为邻接矩阵的对象中。这是数据中所有关联的数字表示。我们上下文中的相邻矩阵可以通过根据所有商店中给定商品的销售序列计算的相关矩阵来检索。
序列重新划分在我们的方法中是基本的,因为我们决定像递归架构一样处理数据,这也将是我们模型的一部分。
模型
我们的模型接收来自所有商店的销售序列和从相同序列获得的相邻矩阵作为输入。序列通过 LSTM 层,而相关矩阵由图卷积层处理。它们在 Spektral 中实现,这是一个基于 Tensorflow 构建的很酷的图形深度学习库。它提供了各种类型的图层。我们使用最基本的一种,图卷积。它在可学习的权重、外部节点特征(与相邻矩阵一起提供)和我们的相关矩阵之间进行一系列卷积运算。不太可能,目前 Spektral 不支持 Window,所以我必须手动提取我感兴趣的类并创建我的 Python 可执行文件。
我们的网络看起来如下:
def get_model(): opt = Adam(lr=0.001) inp_seq = Input((sequence_length, 10))
inp_lap = Input((10, 10))
inp_feat = Input((10, X_train_feat.shape[-1])) x = GraphConv(32, activation='relu')([inp_feat, inp_lap])
x = GraphConv(16, activation='relu')([x, inp_lap])
x = Flatten()(x) xx = LSTM(128, activation='relu',return_sequences=True)(inp_seq)
xx = LSTM(32, activation='relu')(xx) x = Concatenate()([x,xx])
x = BatchNormalization()(x)
x = Dropout(0.5)(x)
x = Dense(128, activation='relu')(x)
x = Dense(32, activation='relu')(x)
x = Dropout(0.3)(x)
out = Dense(1)(x) model = Model([inp_seq, inp_lap, inp_feat], out)
model.compile(optimizer=opt, loss='mse',
metrics=[tf.keras.metrics.RootMeanSquaredError()]) return model
如前所述,在开发递归网络时,数据的处理一如既往。这些序列是固定时间段内所有商店中所考虑商品的销售情况的集合。
在我们的例子中,下一步是在相同的序列上计算商店间销售额的相关矩阵,它代表我们的相邻矩阵。与它们一起提供了一些手工制作的特征(如平均值、标准偏差、偏斜度、峰度、回归系数),这些特征由我们根据每个序列的存储进行计算,代表我们在网络中的节点特征。
给定样本协方差或相关矩阵,我们可以基于频谱卷积的一阶近似,应用拉普拉斯归一化来估计邻接矩阵,这使得能够使用高效的逐层传播规则(如这里的所述和在频谱中实现的)。
给定相关矩阵的拉普拉斯归一化过程
训练是用前两年的数据计算的,而剩下的两年分别用于验证和测试。我为每个商店训练了一个模型,所以我们最终得到了总共 10 个不同的神经网络。
在训练程序结束时,悬挂物的预测由相关模型检索。误差计算为测试数据的 RMSE,报告如下。
RMSE 为每个商店计算了测试集上的所有项目
同样,很容易提取 desired stores 中商品的预测,直接操作我们的嵌套数据结构。
测试数据预测
摘要
在这篇文章中,我在一个不常见的场景中采用了图形神经网络,比如时间序列预测。在我们的深度学习模型中,图依赖将自身与循环部分相结合,试图提供更准确的预测。这种方法似乎很适合我们的问题,因为我们可以强调我们的数据中的基本层次结构,我们用相关矩阵进行数字编码。
保持联系: Linkedin
参考文献
- Spektral:带有 Keras 和 Tensorflow 的图形神经网络
- 图卷积网络的半监督分类