一个时间序列由各种数据点组成,这些数据点在一段时间内以相等的间隔依次排列。一个模型将分析时间序列中的复杂模式和关系,并预测未来的价值。
一个时间序列模型可以执行各种任务:天气预报、股票价格预测和加密货币预测。例如,一个时间序列模型将分析过去的比特币价格并预测未来的价格。它帮助投资者知道何时购买和出售比特币以获得利润。
一个单变量的时间序列只有一个单一的变量来训练这个模型。例如,一个天气预报模型使用过去记录的温度值来预测未来的温度。我们将建立一个单变量时间序列模型,预测每月的牛奶产量。我们将使用一个循环神经网络(RNN)来实现这个模型。
有各种类型的RNN。我们将专注于长短时记忆(LSTM),它最适合于时间序列建模。
前提条件
- 在实施时间序列模型之前,读者应该对以下内容有基本的了解和认识。
- 时间序列术语和概念
- 简要介绍神经网络的结构和概念
- 知道如何用Keras构建一个人工神经网络
- 如何在Google Colab中运行一个Python项目
开始使用递归神经网络(RNN)。
递归神经网络是典型的人工神经网络的一个变种,可以对连续数据进行建模。顺序数据依赖于历史/过去的数据点来进行未来预测。
循环神经网络使用一个内部存储器,帮助它们存储从以前的数据点检索的信息,并使用这些信息来生成其他数据点。递归神经网络在隐蔽层内实施反馈回路,这使它们与传统的人工神经网络有所区别。
下图显示了传统人工神经网络和递归神经网络之间的区别。

隐蔽层中的反馈环帮助递归神经网络处理和分析连续的数据,以进行模型预测。反馈环路还引入了顺序记忆,帮助确定数据值被输入到递归神经网络的顺序。尽管递归神经网络比传统的人工神经网络有更好的改进,但它也存在着长期依赖性问题。
当递归神经网络的顺序记忆失效时,就会出现长期依赖性问题,而RNN不能确定数据点的顺序。当递归神经网络使用长时间记录的序列数据时,顺序记忆就会失效,例如,记录了多年的时间序列。
递归神经网络不会长期记住这些信息,因此会失去对输入的顺序以及数据点如何相互依赖的追踪。它无法处理和分析具有较长期依赖性的数据集。
解决这个问题的方法是引入长短期记忆(LSTM)。下面的图片显示了LSTM的基本结构。

LSTM实现了一个被称为门的概念,解决了长期依赖的问题。因此,它解决了复杂的深度学习问题,这些问题是内存密集型的,如语音识别、时间序列分析、机器翻译和其他复杂的自然语言处理,而不会损失其内部内存。
要详细了解LSTM的结构,请阅读这篇文章。在本教程中,我们将实现LSTM用于时间序列建模。LSTM的速度更快,使用的计算能力更少。我们将用它来处理时间序列中的复杂模式。
月度牛奶产量数据集
我们将使用月度牛奶产量数据集来建立时间序列模型。该数据集是单变量的,因为它只有一个训练时间序列模型的变量。你可以在这里下载月度牛奶产量数据集。
我们将使用Pandas加载月度牛奶产量数据集。让我们来导入这个必要的库。
import pandas as pd
为了加载月度牛奶产量数据集,请输入以下代码。
df = pd.read_csv('monthly-milk-production-dataset.csv',index_col='Date',parse_dates=True)
我们使用parse_dates 参数,使Pandas库能够识别Date 列中的DateTime。因此,我们可以进行时间序列分析和操作。
然后我们将数据集转换为有月度间隔,如下所示。
df.index.freq='MS'
为了打印月度牛奶产量数据集中的一些数据点,应用这段代码。
df.head()
它打印出以下数据点。

图片显示了Date 列和其相应的月度产量。然后我们用Matplotlib绘制月度牛奶产量数据集。
导入Matplotlib
要导入Matplotlib库,应用这个命令。
import matplotlib.pyplot as plt
然后,我们可以通过应用这段代码绘制月度牛奶产量数据集。
df.plot(figsize=(12,6))
它显示了以下的图。

从上面的图中,我们可以看到月度牛奶产量数据集具有季节性或重复模式。它也有一个随时间增长的总趋势。
将时间序列分解为组成部分
一个时间序列有各种成分,构成了一般的时间序列模式。我们使用seasonal_decompose 进行时间序列分解。
from statsmodels.tsa.seasonal import seasonal_decompose
为了将时间序列分解成成分,应用这段代码。
decomposable_components = seasonal_decompose(df['Production'])
decomposable_components.plot()
该代码绘制了以下分量。

该代码产生了Observed 、Trend 、Seasonal 、Residual 等分量。
Observed:它显示了每月牛奶生产数据集的一般模式。Trend:它显示了时间序列随时间的上升趋势。Seasonal:显示时间序列中的季节性或重复性模式。Residual:它显示了去除季节性和趋势成分后的时间序列。
将时间序列数据集分割成训练和测试日期
我们必须把时间序列数据集分成训练和测试日期。我们将使用训练日期和其相应的月度产量进行模型训练。然后我们将使用测试日期进行模型预测。
train_dates = df.iloc[:156]
test_dates = df.iloc[156:]
我们将使用前156个月作为训练日期。其余的月份将是测试日期。
缩放时间序列数据集
我们必须将时间序列数据集转换成0和1之间的比例,这将确保所有的数据点适合LSTM。我们将使用MinMaxScaler 进行缩放。
from sklearn.preprocessing import MinMaxScaler
为了初始化缩放方法,执行这段代码。
scaler = MinMaxScaler()
我们对训练和测试日期都适合我们的缩放器。
scaler.fit(train_dates)
scaler.fit(test_dates)
然后我们调用transform 方法来转换训练和测试日期。
scaled_train_dates = scaler.transform(train_dates)
scaled_test_dates = scaler.transform(test_dates)
要看到一些缩放的时间序列值,执行这段代码。
scaled_train_dates[:10]
该代码显示了以下的标度点。

输出显示了位于0和1之间的经过缩放的数据点。
将缩放后的数据点格式化为批次
我们必须把按比例排列的数据点分成几批。这些批次是LSTM在训练阶段作为输入使用的数值序列。我们使用TimeseriesGenerator 类来生成数据集的批次。
我们可以按以下方式导入这个必要的库。
from keras.preprocessing.sequence import TimeseriesGenerator
我们定义每个批次的大小如下。
n_input = 12
n_features = 1
每个批次将有12个缩放的数据点(n_input = 12)。然后我们用n_features ,设置时间序列数据集的变量数量。由于我们处理的是一个单变量时间序列,所以我们将该值设置为1。
让我们将TimeseriesGenerator 到我们的缩放数据点。
generated_batches = TimeseriesGenerator(scaled_train_dates, scaled_test_dates, length=n_input, batch_size=1)
该代码将对训练和测试日期应用类函数。每个批次将有一个特定的大小。
建立时间序列模型
我们将使用LSTM建立一个顺序的时间序列模型。顺序模型将使我们能够一个接一个地添加多个层(逐层)。LSTM将是顺序模型的输入层。
我们将从Keras中导入LSTM,并直接将其添加为顺序模型的输入层。然后,我们将使用Dense 层添加顺序模型的输出层。让我们从Keras中导入LSTM、顺序模型和密集层。
from keras.layers import LSTM
from keras.models import Sequential
from keras.layers import Dense
让我们将顺序模型初始化如下。
lstm_model = Sequential()
之后,我们添加LSTM 层,如下所示。
lstm_model.add(LSTM(100, activation='relu', input_shape=(n_input, n_features)))
LSTM层将有100个神经元。它使用relu 作为激活函数,因为该层的输出将在0和无限的正时间序列值之间。它使用生成的数据集批次作为输入。然后,该模型将使用Dense 层来输出预测的时间序列值。
让我们添加Dense 层,如下所示。
lstm_model.add(Dense(1))
密集层将只有一个神经元来输出预测的每月牛奶产量。
编译顺序时间序列模型
为了编译顺序时间序列模型,应用这个代码。
lstm_model.compile(optimizer='adam', loss='mse')
我们使用compile 函数编译顺序时间序列模型。为了使编译过程顺利进行,我们传入了以下参数。
-
优化器。它将改善和提高顺序时间序列模型的性能。我们把
adam作为模型编译过程中的优化器,以便工作。 -
损失。它将跟踪和计算所有的模型误差。我们传递
mse作为参数值。
打印顺序时间序列模型的摘要
为了打印顺序时间序列模型的摘要,应用这段代码。
lstm_model.summary()
该代码显示如下。

摘要显示了编译后的连续时间序列模型中的各层以及参数。让我们将顺序模型拟合到生成的批次上。
拟合生成的批次的顺序模型
为了拟合顺序模型,应用这段代码。
lstm_model.fit(generated_batches,epochs=100)
生成的批次将训练和测试序列模型。我们应用100个epochs来减少序列模型的错误(损失)。顺序模型将在生成的批次中运行100次。
上面的代码将给出以下输出。

我们已经用生成的批次训练了顺序模型。从输出结果来看,模型的损失已经随着时间的推移而减少。让我们使用训练好的顺序模型来进行预测。
使用训练好的顺序模型进行预测
经过训练的顺序模型将使用测试日期来预测每月的牛奶产量。我们必须重塑按比例的测试时间序列值,使其具有原始格式。
prediction_result = []
test_batches = scaled_train_dates[-n_input:]
reshaping_batches = test_batches.reshape((1, n_input, n_features))
reshape 方法将对测试时间序列值进行重塑。然后,我们将把预测的输出保存在prediction_result 变量中。然后,我们使用下面的for 循环函数来循环浏览测试数据集。它将分析数据点并进行预测。
for i in range(len(test_dates)):
predicted_output = lstm_model.predict(reshaping_batches )[0]
prediction_result.append(predicted_output)
reshaping_batches = np.append(reshaping_batches [:,1:,:],[[predicted_output]],axis=1)
检查预测的结果,应用这段代码。
prediction_result
该代码显示以下预测值。

最后一步是使用Matplotlib绘制线图,显示测试数据集中的实际数据点和预测的数据点。该折线图将评估顺序时间序列模型的性能。
绘制折线图
要绘制折线图,请执行此代码段。
actual_values = scaler.inverse_transform(prediction_result)
test_dates['Predictions'] = actual_values
test_dates.plot(figsize=(14,5))
上面的代码片断绘制了以下折线图。

该折线图显示了每月的实际牛奶产量和预测的每月牛奶产量。
- 橙色线显示预测的牛奶产量。
- 蓝线表示实际牛奶产量。
如果我们观察这两条线,它们保持相同的模式。此外,这些线也是相互接近的。这意味着顺序时间序列模型训练有素,可以做出准确的预测(预测值位于实际值之内)。
总结
在本教程中,我们建立了一个预测每月牛奶产量的单变量时间序列。我们使用LSTM实现了这个模型,因为它最适合于时间序列建模。
我们解释了RNN和LSTM的区别,以及LSTM如何解决长期依赖性问题。我们从Keras中导入LSTM,并使用它来建立顺序时间序列模型。最后我们用线图来评估顺序时间序列模型的性能。
请在这里查看单变量时间序列模型的完整Python代码。
编码愉快!