购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第2章
对未来的简单预测

在第1章中,我们介绍了什么是时间序列,以及预测时间序列与传统的回归任务有何不同。你还学习了构建成功的预测项目所需的必要步骤,从定义目标到构建模型、部署模型以及在收集到新数据时更新模型。现在你已经准备好开始预测时间序列了。

你将首先学习如何对未来进行简单预测,这将作为基线。基线模型是一种简单的解决方案,它使用试探法或简单的统计数据来计算预测。开发基线模型并不总是一门精确的科学。它通常需要一些直觉,我们将通过可视化数据和检测可用于预测的模式来获得这些直觉。在任何建模项目中,有一个基线是很重要的,因为你可以使用它来比较你将要构建的更复杂模型的性能。理解模型的性能是否良好的唯一方法是将其与基线进行比较。

在本章中,假设我们希望预测强生公司的季度每股收益。我们可以查看图2.1中的数据集,它与你在第1章中看到的相同。具体来说,我们将使用1960~1979年底的数据来预测1980年四个季度的每股收益。预测期如图2.1中的灰色区域所示。

你可以在图2.1中看到,我们的数据有一个趋势,因为它随着时间的推移而增加。此外,我们有一个季节性模式,因为在一年或四个季度的过程中,我们可以反复观察波峰和波谷。这意味着我们有季节性。

回想一下,我们在第1章分解时间序列时识别了这些分量。这些分量如图2.2所示。我们将在本章后面详细研究其中的一些分量,因为它们将帮助我们获得一些关于数据行为的直觉,这反过来将帮助我们开发一个良好的基线模型。

我们将首先定义什么是基线模型,然后我们将开发4种不同的基线来预测强生公司的季度每股收益。最后用Python和时间序列预测来动手实践。

图2.1 强生公司从1960~1980年季度每股收益(美元)。我们将使用从1960~1979年最后一个季度的数据来建立一个基线模型,该模型将预测1980年季度的每股收益(如灰色区域所示)

图2.2 强生公司1960~1980年季度收益的分解图

2.1 定义基线模型

一个基线模型是我们问题的一个简单解决方案。它通常使用启发式方法或简单的统计数据来生成预测。基线模型是你能够想到的最简单解决方案,它不需要任何训练,并且实施成本应该非常低。

你能思考出我们项目的基线吗

已知我们想要预测强生公司的每股收益,你能做的最基本、最简单的预测是什么?

在时间序列的上下文中,我们可以用来建立基线的一个简单统计数据是算术平均数。我们可以简单地计算一段时间内这些值的均值,并假设未来的值将等于该均值。在预测强生公司每股收益的背景下,这就像是在说:

1960~1979年间的平均每股收益为4.31美元。因此,我预计1980年未来四个季度的每股收益将相当于每季度4.31美元。

另一种可能的基线是简单地预测最后记录的数据点。在强生公司的背景下,这就像是在说:

如果本季度的每股收益为0.71美元,那么下个季度的每股收益也将为0.71美元。

或者,如果我们在数据中看到周期性模式,我们可以简单地在未来重复该模式。在强生公司的背景下,这就像是在说:

如果1979年第一季度的每股收益为14.04美元,那么1980年第一季度的每股收益也将为14.04美元。

你可以看到,这三个可能的基线依赖于在我们的数据集中观测到的简单统计数据、启发式方法和模式。

基线模型

基线模型是预测问题的一个简单的解决方案。它依赖于启发式或简单的统计,通常是最简单的解决方案。它不需要模型拟合,易于实现。

你可能想知道这些基线模型是否有用。这些简单的方法能在多大程度上预测未来?我们可以通过对1980年进行预测,并用1980年的观测数据检验预测,来回答这个问题。这被称为非样本预测,因为我们在开发模型时未考虑周期进行预测。通过这种方式,我们可以衡量模型的性能,并理解当我们预测超出我们所拥有的数据时,它们的表现如何,在这种情况下是1981年及以后。

接下来你将学习如何制定此处提到的不同基线,以预测强生公司的季度每股收益。

2.2 预测历史均值

如本章开头所述,我们将使用强生公司1960~1980年以美元(USD)计算的季度每股收益。我们的目标是使用1960~1979年底的数据来预测1980年的四个季度。我们将讨论的第一个基线使用历史均值,即过去数值的算术平均数。它的实现很简单:计算训练集的均值,这将是我们对1980年四个季度的预测。不过,首先,我们需要做一些准备工作,我们将在所有基线实现中使用这些准备工作。

2.2.1 基线实现准备

第一步是加载数据集。为此,我们将使用pandas库,并使用read_csv方法将数据集加载到DataFrame中。你可以将该文件下载到本地计算机上,并将该文件的路径传递给read_csv方法,或者只需输入托管在GitHub上的CSV文件的URL。在这种情况下,我们将使用文件:

本章的完整代码可以在GitHub上找到:https://github.com/marcopeix/TimeSeriesForecasting InPython/tree/master/CH02。

DataFrame是pandas中最常用的数据结构。它是一种二维标签数据结构,其中的列可以保存不同类型的数据,如字符串、整数、浮点数或日期。

第二步是将数据拆分为用于训练的训练集和用于测试的测试集。鉴于我们的预测期是1年,我们的训练集将从1960年开始,一直到1979年底。我们将为我们的测试集保存1980年收集的数据。你可以将DataFrame视为具有列名和行索引的表格或电子表格。

使用DataFrame中的数据集,我们可以通过运行以下命令来显示前5个条目:

这将为我们提供如图2.3所示的输出。

图2.3将帮助你更好地理解DataFrame所保存的数据类型。当计算EPS时,我们有日期列,它指定每个季度的结束。数据列以美元(USD)为单位保存EPS的值。

我们可以选择显示数据集的最后5个条目,并获得图2.4中的输出:

图2.3 强生公司数据集的季度每股收益的前5个条目。注意我们的DataFrame有两列:date和data。它还具有从0开始的行索引

图2.4 数据集的最后5个条目。在这里,我们可以看到1980年的四个季度,我们将尝试使用不同的基线模型进行预测。我们将把预测与1980年的观测数据进行比较,以评估每个基线的性能

在图2.4中,我们看到了1980年的四个季度,这是我们将试图使用基线模型预测的。我们将通过比较预测与1980年四个季度的数据栏中的值来评估基线的性能。预测与观测值越接近越好。

在开发我们的基线模型之前,最后一步是将数据集拆分为训练集和测试集。如前所述,训练集将由1960~1979年底的数据组成,而测试集将由1980年的四个季度组成。训练集将是我们用于开发模型的唯一信息。一旦建立了模型,我们将预测接下来的四个时间步长,这将对应于我们测试集中1980年的四个季度。这样,我们就可以将预测与观测数据进行比较,并评估基线的性能。

为了进行拆分,我们将指定训练集将包含保存在df中除最后4个条目之外的所有数据。测试集将仅由最后4个条目组成。这是由下面代码块来做的:

2.2.2 实现历史均值基线

现在我们准备实施基线。我们将首先使用整个训练集的算术平均数。为了计算均值,我们将使用numpy库,因为它是一个非常快速的Python科学计算包,可以很好地处理DataFrame:

在前面的代码块中,我们首先导入numPy库,然后计算整个训练集的EPS的均值,并将其打印在屏幕上。这给出了4.31美元的数值。这意味着1960~1979年底,强生公司的季度每股收益平均为4.31美元。

现在,我们将简单地预测1980年每个季度的这个值。为此,我们只需创建一个新列pred_mean,它将训练集的历史平均值作为预测:

接下来,我们需要定义并计算误差度量,以便评估预测在测试集上的性能。在这种情况下,我们将使用平均绝对百分比误差(Mean Absolute Percentage Error,MAPE)。它是一种预测方法的预测准确性的衡量标准,易于解释,并且独立于数据规模。这意味着,无论我们使用的是两位数的数值还是六位数的数值,MAPE都将始终以百分比表示。因此,MAPE返回预测值与观测值或实际值平均偏差的百分比,无论预测值高于观测值还是低于观测值。MAPE的定义见式2.1。

在式2.1中, A i 为第 i 时间点的实际值, F i 为第 i 时间点的预测值, n 只是预测的数量。在我们的例子中,因为我们预测的是1980年的四个季度,所以 n =4。在求和中,从实际值中减去预测值,然后将结果除以实际值,这就给出了百分比误差。然后我们取百分比误差的绝对值。对 n 个时间点中的每个时间点重复该操作,并将结果加在一起。最后,我们将总和除以 n (即时间点的数量),这有效地给出了平均绝对百分比误差。

让我们用Python实现这个函数。我们将定义一个mape函数,该函数接受两个向量:测试集中观察到的实际值y_true和预测值y_pred。在这种情况下,因为numpy允许我们使用数组,所以我们不需要循环来对所有值求和。我们可以简单地从y_true数组中减去y_pred数组,然后除以y_true,以获得百分比误差,然后我们可以取绝对值。之后,我们求出这个结果的均值,即小心翼翼地对向量中的每个值求和,并除以预测的数量。最后,我们将结果乘以100,以便将输出表示为百分比而不是十进制数:

现在我们可以计算基线的MAPE。实际值在test数据列中,因此它将是传递给mape函数的第一个参数。预测值在test的pred_mean列中,因此它将是函数的第二个参数:

运行该函数得到的MAPE为70.00%。这意味着基线与强生公司1980年观察到的季度每股收益平均偏离70%。

让我们将预测可视化,以便更好地理解70%的MAPE,如清单2.1所示。

清单2.1 可视化我们的预测

在清单2.1中,我们使用matplotlib库(它是在Python中生成可视化的最流行的库)来生成一个图形,显示训练数据、预测范围、测试集的观测值以及1980年每个季度的预测。

第一,我们初始化一个figure和一个ax对象。一个图形可以包含许多ax对象,这允许我们在一个图像上可以创建两个、三个或更多图像。在这种情况下,我们创建单个图像的图形,因此我们只需要一个ax。

第二,我们在ax对象上绘制数据。我们使用点划线绘制训练数据,并将此曲线标记为“训练”。该标签稍后将用于生成图表的图例。然后我们使用连续线绘制测试数据,标记为“测试”。最后,我们使用虚线绘制预测结果,标记为“预测”。

第三,我们标记 x 轴和 y 轴,并绘制一个矩形区域来说明预测范围。由于我们的预测范围是1980年的四个季度,因此该区域从索引80开始,到索引83结束,跨越整个1980年。请记住,我们通过运行df.tail()获得了1980年最后一个季度的指数,结果如图2.5所示。

图2.5 数据集的最后5个条目

我们将此区域设置为灰色,并使用alpha参数指定不透明度。当alpha为1时,形状完全不透明;当alpha为0时,形状完全透明。在我们的例子中,我们将使用20%(或0.2)的不透明度。

然后,我们为 x 轴上的记号指定标签。默认情况下,标签将显示数据集的每个季度的数据,这将创建一个带有无法读取的标签的拥挤的 x 轴。相反,我们将每两年显示一次年份。为此,我们将生成一个数组,指定标签必须出现的索引。这就是np.arange(0, 81, 8)所做的:它生成一个从0开始,到80结束的数组,因为不包括结束索引(81);步长为8,因为2年中有8个季度。这将有效地生成以下数组:[0,8,16,…,72,80]。然后,我们指定一个包含每个索引处的标签的数组,因此它必须以1960开始,以1980结束,就像我们的数据集一样。

最后,我们使用fig.automft_xdate()来自动格式化 x 轴上的刻度线标签。它将稍微旋转它们,并确保它们清晰可辨。最后的修饰是使用plt.tight_layout()来删除图形周围任何多余的空白。

最终结果见图2.6。显然,该基线没有生成准确的预测,因为预测线离测试线非常远。现在我们知道,预测平均比1980年每个季度的实际每股收益低70%。1980年的每股收益一直高于10美元,而我们预测每个季度的每股收益仅为4.31美元。

尽管如此,我们可以从中可以学到什么呢?查看训练集,我们可以看到一个积极的趋势,因为EPS随着时间的推移而增加。如图2.7所示,来自数据集分解的趋势分量进一步支持了这一点。

正如你所看到的,我们不仅有一个趋势,而且这个趋势在1960~1980年并不是恒定的——它变得越来越陡峭。因此,1960年观察到的每股收益可能不能预测1980年的每股收益,因为我们有一个积极的趋势,每股收益值随着时间的推移而增加,并且以更快的速度增加。

你能改进我们的基线吗

在进入2.3节之前,你能想出一种方法(同时仍然使用均值)来改进我们的基线吗?你认为取一个更短更近的时间段的均值会有帮助吗(例如,1970~1979年)?

图2.6 预测历史均值作为基线。你可以看到,预测与测试集中的实际值相差甚远。该基线给出的MAPE为70%

图2.7 时间序列的趋势分量。你可以看到数据有一个积极的趋势,因为它随着时间的推移而增加

2.3 预测最后一年的均值

从以前的基线中吸取的教训是,由于数据集中的正向趋势分量,早期的数值似乎在长期内不能预测未来值。早期的数值似乎太小,不能代表每股收益在1979年底和1980年达到的新水平。

如果我们使用训练集中最后一年的均值来预测下一年呢?这意味着我们将计算1979年的平均每股收益,并对1980年的每个季度进行预测——随着时间的推移而增加的更近的值可能更接近1980年观察到的值。目前,这只是一个假设,因此让我们实施此基线并进行测试,以理解其表现如何。

我们的数据已经拆分为测试集和训练集(在2.2.1节中完成),因此我们可以继续计算训练集中最后一年的均值,它对应于1979年的最后四个数据点:

这使平均每股收益为12.96美元。因此,我们将预测强生公司在1980年四个季度的EPS为12.96美元。使用与之前基线相同的过程,我们将创建一个新的pred__last_yr_mean列,以保存去年的均值作为预测:

然后,使用我们之前定义的mape函数,我们可以评估新基线的性能。请记住,第一个参数是观测值,保存在测试集中。然后,我们传入预测值,这些位于pred__last_yr_mean列中:

这给了我们15.60%的MAPE值。我们可以在图2.8中看到预测。

你能重新创建图2.8吗

作为练习,尝试重新创建图2.8,以使用1979年的季度均值来可视化预测。代码应与清单2.1相同,只是这次预测在不同的列中。

图2.8 预测训练集最后一年(1979)的均值作为基线模型。你可以看到,与之前我们在图2.6中构建的基线相比,预测更接近测试集的实际值

这个新的基线比以前的基线有了明显的改进,尽管它的实施同样简单,因为我们将MAPE从70%降低到了15.6%。这意味着预测值平均偏离观测值15.6%。使用去年的均值是朝着正确方向迈出的一大步。我们希望获得尽可能接近0%的MAPE,因为这将转化为更接近我们预测范围内实际值的预测。

我们可以从这个基线中理解到,未来的数值很可能取决于历史上不太久远的过去的数值。这是自相关的标志,我们将在第5章深入探讨这一主题。现在,让我们看看可以为这种情况开发的另一个基线。

2.4 使用最后已知数值进行预测

前面我们使用不同时期的均值来开发基线模型。到目前为止,最好的基线是我们训练集中最近一年记录的均值,因为它产生了最低的MAPE。我们从这个基线中理解到,未来的数值取决于过去的数值,但不是那些太遥远的。事实上,预测1960~1979年的平均每股收益比预测1979年的平均每股收益更糟糕。

因此,我们可以假设使用训练集的最后已知数值作为基线模型能提供更好的预测,这将转化为更接近0%的MAPE。让我们来验证一下这个假设。

第一步是提取训练集的最后已知数值,它对应于1979年最后一个季度记录的EPS:

当我们检索1979年最后一个季度记录的每股收益时,我们得到的数值为9.99美元。因此,我们预测强生公司1980年四个季度的每股收益为9.99美元。

同样,我们将追加一个名为pred_last的新列来保存预测。

然后,使用我们之前定义的相同MAPE函数,我们可以评估这个新基线模型的性能。同样,我们把来自test的实际值和来自test的pred_last列的预测值传递给函数:

这样MAPE值为30.45%。我们可以在图2.9中看到预测。

你能重新创建图2.9吗

尝试自己制作图2.9!作为数据科学家,以易于理解的方式向非领域内人员传达结果非常重要。因此,绘制显示预测结果的图表是一项需要培养的重要技能。

新假设似乎并没有改善我们建立的上一个基线,因为MAPE为30.45%,而我们使用1979年的平均每股收益获得的MAPE为15.60%。因此,这些新的预测与观测值在1980年相差甚远。

这可以解释为,每股收益表现出周期性行为,在前三个季度较高,然后在最后一个季度下降。使用最后一个已知数值不会考虑季节性,因此我们需要使用另一种简单的预测技术,看看是否可以产生更好的基线。

图2.9 预测作为基线模型的训练集的最后已知值。我们可以看到,这个基线的MAPE为30.45%,比我们的第一个基线要好,但性能不如我们的第二个基线

2.5 实现简单的季节性预测

在本章中,我们考虑了前两个基线的趋势分量,但我们没有研究数据集中的另一个重要分量,即图2.10所示的季节性分量。我们的数据中有明显的周期性模式,我们可以用这些信息来构建最后一个基线:简单的季节性预测。

图2.10 时间序列的季节性分量。我们可以在这里看到周期性波动,这表明季节性的存在

简单的季节性预测采用上一个观测周期,并将其重复到未来。在我们的例子中,一个完整的周期发生在四个季度中,因此我们将从1979年第一季度的每股收益中提取并预测1980年第一季度的值,然后我们将从1979年第二季度的每股收益中提取并预测1980年第二季度的值。这个过程将在第三和第四季度重复。

在Python中,我们可以通过简单地获取训练集的最后四个值(对应于1979年的四个季度),并将其分配给1980年的相应季度来实现此基线。以下代码附加了pred_last_season列,以保存我们对简单的季节性预测方法的预测:

然后,我们按照与前几节相同的方式计算MAPE:

这给出了11.56%的MAPE,这是本章所有基线中最小的MAPE。图2.11说明了我们的预测与测试集中观测数据的比较。作为练习,我强烈建议你尝试自己重新创建它。

图2.11 测试集的原始季节性预测结果。这一预测与测试集中观测到的数据更相似,并导致最小的MAPE。显然,该数据集的季节性对未来值有影响,在预测时必须考虑这一点

正如你所看到的,在本章我们建立的所有基线中,简单的季节性预测结果MAPE是最小的。这意味着季节性对未来数值有重大影响,因为将上个季节重复到未来会产生相当准确的预测。客观地说,这是有意义的,因为在图2.11中我们可以清楚地观测到每年重复的循环模式。当我们为这个问题开发一个更复杂的预测模型时,必须考虑季节性效应。我将在第8章中详细解释如何使用它们。

2.6 下一步

在本章中,我们为预测项目开发了四个不同的基线。我们使用了整个训练集的算术平均值、训练集的最后一年的均值、训练集的最后已知数值和简单的季节性数据进行预测。然后使用MAPE指标在测试集上评估每个基线。图2.12总结了我们在本章中开发的每个基线的MAPE。正如你所看到的,使用简单的季节性预测的基线具有最小的MAPE,因此性能最佳。

图2.12 本章中开发的四个基线的MAPE。MAPE越小,基线越好,因此,我们将选择简单的季节性基线作为我们的基准,并将其与我们更复杂的模型进行比较

请记住,基线模型是比较的基础。我们将通过应用统计学习或深度学习技术来开发更复杂的模型,当我们针对测试集评估更复杂的解决方案并记录误差指标时,我们可以将它们与基线进行比较。在我们的例子中,我们将把复杂模型的MAPE与我们简单的季节性预测的MAPE进行比较。如果一个复杂模型的MAPE小于11.56%,那么我们就知道我们有一个表现更好的模型。

在某些特殊情况下,只能使用简单的方法来预测时间序列。这些是过程随机移动并且不能使用统计学习方法预测的特殊情况。这意味着我们处于随机游走的状态——我们将在第3章中对此进行研究。

小结

❍时间序列预测从基线模型开始,作为与更复杂模型进行比较的基准。

❍对于我们的预测问题,基线模型是一个微不足道的解决方案,因为它只使用启发式或简单的统计数据,如均值。

❍MAPE代表平均绝对百分比误差,它是预测值偏离实际值多少的直观度量。

❍有许多方法可以开发基线。在本章中,你了解了如何使用均值、最后一个已知值或上一个季度数据来开发基线。 PuM3Wk2A/ZfnjPgaUnIEZ0uhT8LCVniwrlewKqNnSuZ+4tKPjg8Aw3Z4ileqGbjr

点击中间区域
呼出菜单
上一章
目录
下一章
×