Python现代时间序列预测——时间序列简介

欢迎来到《Python现代时间序列预测》! 本书旨在为数据科学家或机器学习(ML)工程师提供提升时间序列分析技能的机会,帮助他们通过学习机器学习领域的新技术和先进方法来提高分析能力。时间序列分析在常见的机器学习书籍、课程等资源中常常被忽视。它们通常从分类开始,稍微提及回归,然后继续讲解其他内容。然而,时间序列分析对于商业来说非常有价值并且无处不在。我们从三维的视角来看待世界,而时间是我们很少考虑的隐藏维度,但它无处不在。既然时间是我们生活中世界的四个维度之一,时间序列数据也是无处不在的。

分析时间序列数据为企业带来了巨大的价值。时间序列分析并不是新兴的,它自20世纪20年代以来就存在了。但是在当前数据时代,企业收集的时间序列数据正以每分钟的速度变得越来越大和广泛。结合数据收集量的激增和对机器学习的重新关注,时间序列分析的格局也发生了显著变化。本书试图将您带出传统的统计方法(如自回归积分滑动平均模型(ARIMA)),并介绍机器学习世界中在时间序列分析方面的最新技术。

我们将从一些基本概念开始,快速深入到更复杂的主题。在本章中,我们将涵盖以下主要内容:

  • 什么是时间序列?
  • 数据生成过程(DGP)
  • 我们能预测什么?
  • 预测术语和符号

技术要求

您需要根据本书前言中的说明设置 Anaconda 环境,以获得一个包含本书中所需所有库和数据集的工作环境。在运行笔记本时,任何额外的库都会被安装。

本章的相关代码可以在以下地址找到:GitHub 链接

什么是时间序列?

简单来说,时间序列是一组按时间顺序依次观察到的数据。重点在于"时间"这一词。如果我们在不同的时间点上持续记录相同的观察数据,我们就得到了一个时间序列。例如,如果你每月记录自己拥有的巧克力块数,你就得到一个关于巧克力消费的时间序列。假设你每个月初都记录一次自己的体重,你又得到了另一个关于体重的时间序列。那么,这两个时间序列之间有关系吗?很可能是的。但到本书的最后,我们将能够从科学的角度来分析它们之间的关系。

其他时间序列的例子包括你关注的某只股票的每周收盘价、你所在城市的每日降水量或降雪量、以及你智能手表记录的每小时脉搏率。

时间序列的类型

根据时间间隔,时间序列数据可以分为两种类型,如下所示:

  • 规则时间序列:这是最常见的时间序列类型,观察数据以固定时间间隔进行收集,如每小时或每月一次。例如,如果我们记录某个城市的温度,我们将得到一个固定间隔的时间序列(根据我们选择的观察频率)。
  • 不规则时间序列:有些时间序列的观察数据并不是以规则的时间间隔收集的。例如,考虑我们从某个病人的实验室测试中获得的一系列读数。我们只有在病人去诊所进行实验室测试时,才会得到观察值,而这种测试并不总是按固定的时间间隔进行。

本书主要关注规则时间序列,它们的时间间隔是均匀的。不规则时间序列稍微复杂一些,需要使用专门的技术来处理它们。如果你有兴趣深入了解不规则时间序列,相关的综述论文是一个很好的入门资料,你可以在本章的进一步阅读部分找到它们。

时间序列分析的主要应用领域

时间序列分析的主要应用领域大致可以分为三个重要方向,如下所述:

  • 时间序列预测:给定时间序列的历史数据,预测未来的数值。例如,使用过去5年的温度数据预测下一天的温度。这个应用场景是最受欢迎和最重要的,因为任何类型的计划都需要对未来有一定的预见性。例如,计划下个月生产多少巧克力,就需要预测预期的需求。
  • 时间序列分类:有时我们不仅仅是预测时间序列的未来值,还可能需要根据过去的值预测某个行动。例如,给定脑电图(EEG,跟踪大脑电活动)或心电图(EKG,跟踪心脏电活动)的历史数据,我们需要预测EEG或EKG的结果是正常还是异常。
  • 异常检测:在一些情况下,我们只想检测某件事是否出现问题,或是否有异常情况。在这种情况下,我们不需要使用分类或预测方法,而是可以进行异常检测。例如,身上佩戴的技术设备可以记录加速度计的时间序列数据,并利用异常检测来识别跌倒或事故。
  • 解释与因果关系:你可以利用时间序列分析来理解时间序列的"是什么"和"为什么",理解多个相关时间序列之间的关系,或基于时间序列数据推导出因果推论。例如,我们有一个品牌的市场份额时间序列和一个广告支出时间序列。通过使用解释与因果关系技术,我们可以开始理解广告投资对市场份额的影响,并可能采取相应的行动。

本书的重点主要是时间序列预测,但你所学的技术也将帮助你解决时间序列分类问题,只需做一些方法上的调整。解释方面也有所涉及,虽然只是简短地提及,但因果关系是本书不涉及的领域,因为它需要一种完全不同的方法。

现在,我们已经对时间序列的整体情况有了一个概览,让我们建立一个关于时间序列数据如何生成的思维模型。

数据生成过程(DGP)

我们已经看到,时间序列数据是一组按时间维度顺序进行的观察值。每个时间序列背后,都会有某种机制在生成。例如,您最喜欢的巧克力从制造厂到日常发货的数据,受多种因素的影响,比如季节(例如假期季节)、可用的可可豆、工厂机器的正常运转时间等等。在统计学中,生成时间序列的这个基础过程被称为数据生成过程(DGP)。时间序列数据可以由随机过程和确定性过程生成。确定性过程涉及那些随着时间推移以可预测方式发展的量。一个例子是元素的放射性衰变,其中剩余的数量按照精确的数学公式减少,导致量的持续减少。但大多数有趣的时间序列(从预测的角度来看)是由随机过程生成的。随机过程是一种描述事物如何随时间变化的方式,这种变化是随机的,但在某种程度上是可预测的,就像天气每天都有一定的变化模式和概率。

因此,让我们进一步讨论由随机过程生成的时间序列。

如果我们对现实有完整和完美的了解,那么我们只需要将这个数据生成过程(DGP)转化为数学形式,就能得到最精确的预测。但不幸的是,没有人能完全和完美地了解现实。因此,我们尝试尽可能地在数学上近似DGP,以便我们对DGP的模拟能够给出最好的预测(或任何我们希望从分析中得到的结果)。这种模拟被称为模型,它提供了DGP的有用近似。

但我们必须记住,模型不是DGP,而是现实中某些重要方面的表现。例如,我们可以考虑班加罗尔的空中视角和班加罗尔的地图,如下所示:

班加罗尔的地图无疑是有用的------我们可以用它从A点到B点。但班加罗尔的地图与班加罗尔的照片并不相同。它没有展示繁忙的夜生活或让人无法忍受的交通。地图只是一个模型,代表了一个地点的某些有用特征,如道路和地标。下面的图示可能帮助我们更好地理解这一概念并记住它:

当然,接下来的问题是:我们是否有一个有用的模型?每个模型都有其局限性和挑战。如我们所见,班加罗尔的地图并不能完美地代表班加罗尔。但如果我们的目的是导航班加罗尔,那么地图就是一个非常有用的模型。那么,如果我们想了解文化呢?地图并不能给你带来这种感觉。所以,在新的情境下,原本有用的模型变得完全没有用了。

不同的情境和不同的目标需要不同类型的模型。例如,最适合预测的模型可能与最适合进行因果推断的模型不同。

我们可以使用DGP的概念来生成多个具有不同复杂度的合成时间序列。

生成合成时间序列

合成时间序列(或人工时间序列)是理解时间序列空间、实验不同技术,甚至测试新模型或建模设置的极好工具。这些时间序列被设计成可预测的,即使它们有一定的挑战性。让我们看几个实际的例子,我们可以通过一些基本构建块生成时间序列。你可以发挥创造力,混合搭配这些组件,甚至将它们组合起来,生成任意复杂度的时间序列。

白噪声与红噪声

生成时间序列的一个极端案例是白噪声过程。它由一系列具有零均值和恒定方差的随机数构成。这也是时间序列中最常见的噪声假设之一。

让我们看看如何生成这样的时间序列并将其绘制出来:

perl 复制代码
# 生成时间轴,序列号直到200
time = np.arange(200)
# 从正态分布中随机采样200个值,并乘以100
values = np.random.randn(200)*100
plot_time_series(time, values, "White Noise")

这是输出结果:

红噪声则与白噪声不同,它具有零均值和恒定方差,但在时间上是序列相关的。这种序列相关性或"红色性"通过相关系数 r 来参数化,公式如下:

其中,w 是来自白噪声分布的随机样本。

让我们看看如何生成红噪声,具体代码如下:

ini 复制代码
# 设置相关系数
r = 0.4
# 生成时间轴
time = np.arange(200)
# 生成白噪声
white_noise = np.random.randn(200)*100
# 通过在白噪声中引入后续值之间的相关性来创建红噪声
values = np.zeros(200)
for i, v in enumerate(white_noise):
    if i == 0:
        values[i] = v
    else:
        values[i] = r * values[i - 1] + np.sqrt((1 - np.power(r, 2))) * v
plot_time_series(time, values, "Red Noise Process")

这是输出结果:

周期性或季节性信号

在时间序列中,最常见的信号之一是季节性或周期性信号。因此,你可以通过几种方式将季节性引入你生成的时间序列。

让我们借助一个非常有用的库来生成其余的时间序列------TimeSynth。有关更多信息,请参考 TimeSynth GitHub

这个库非常适合生成时间序列。它包含了各种数据生成过程(DGP),你可以混合搭配,创建一个真实的合成时间序列。

笔记本提示: 有关确切的代码和用法,请参阅关联的 Jupyter 笔记本。

让我们看看如何使用正弦函数来创建周期性。TimeSynth 中有一个有用的函数 generate_timeseries,它帮助我们组合信号并生成时间序列。请看以下代码片段:

ini 复制代码
# 振幅=1.5,频率=0.25的正弦信号
signal_1 = ts.signals.Sinusoidal(amplitude=1.5, frequency=0.25)
# 振幅=1,频率=0.5的正弦信号
signal_2 = ts.signals.Sinusoidal(amplitude=1, frequency=0.5)
# 生成时间序列
samples_1, regular_time_samples, signals_1, errors_1 = generate_timeseries(signal=signal_1)
samples_2, regular_time_samples, signals_2, errors_2 = generate_timeseries(signal=signal_2)
plot_time_series(regular_time_samples,
                 [samples_1, samples_2],
                 "Sinusoidal Waves",
                 legends=["Amplitude = 1.5 | Frequency = 0.25", "Amplitude = 1 | Frequency = 0.5"])

这是输出结果:

请注意,这两条正弦波在频率(时间序列穿越零点的速度)和振幅(时间序列离零点的距离)上有所不同。

TimeSynth 还具有另一种信号,称为 PseudoPeriodic(伪周期信号)。它类似于 Sinusoidal 类,但频率和振幅具有一定的随机性。我们可以通过以下代码片段看到,伪周期信号比 Sinusoidal 类中的普通正弦波和余弦波更具现实性:

ini 复制代码
# 振幅=1,频率=0.25的伪周期信号
signal = ts.signals.PseudoPeriodic(amplitude=1, frequency=0.25)
# 生成时间序列
samples, regular_time_samples, signals, errors = generate_timeseries(signal=signal)
plot_time_series(regular_time_samples,
                 samples,
                 "Pseudo Periodic")

这是输出结果:

自回归信号

另一个在现实世界中非常常见的信号是自回归(AR)信号。我们将在第4章《建立强有力的基准预测》中详细讨论这一点,但现在可以简要了解,AR 信号是指时间序列当前时间步的值依赖于前几个时间步的值。这种序列相关性是 AR 信号的一个关键特性,并通过以下几个参数进行参数化:

  • 序列相关性顺序------换句话说,信号依赖于前几个时间步的数量。
  • 用于组合前几个时间步的系数

让我们看看如何生成 AR 信号,并查看其样式,代码如下:

scss 复制代码
# 我们重新实现了这个类,因为 TimeSynth 中存在一个 bug
from src.synthetic_ts.autoregressive import AutoRegressive
# 参数为 1.5 和 -0.75 的自回归信号
# y(t) = 1.5*y(t-1) - 0.75*y(t-2)
signal = AutoRegressive(ar_param=[1.5, -0.75])
# 生成时间序列
samples, regular_time_samples, signals, errors = generate_timeseries(signal=signal)
plot_time_series(regular_time_samples,
                 samples,
                 "Auto Regressive")

这是输出结果:

混合搭配

你可以使用更多的组件来创建你的数据生成过程(DGP),从而生成一个时间序列。现在,让我们快速看看如何将我们已经看到的组件组合在一起,生成一个真实的时间序列。

让我们使用一个伪周期信号与白噪声,并将其与自回归(AR)信号结合,代码如下:

ini 复制代码
# 生成伪周期信号
pseudo_samples, regular_time_samples, _, _ = generate_timeseries(signal=ts.signals.PseudoPeriodic(amplitude=1, frequency=0.25), noise=ts.noise.GaussianNoise(std=0.3))
# 生成自回归信号
ar_samples, regular_time_samples, _, _ = generate_timeseries(signal=AutoRegressive(ar_param=[1.5, -0.75]))
# 使用数学方程将这两个信号结合起来
ts = pseudo_samples * 2 + ar_samples
plot_time_series(regular_time_samples,
                 ts,
                 "Pseudo Periodic with AutoRegression and White Noise")

这是输出结果:

平稳和非平稳时间序列

在时间序列分析中,平稳性具有重要意义,是许多建模方法中的一个关键假设。具有讽刺意味的是,许多(如果不是大多数的话)现实世界中的时间序列是非平稳的。那么,让我们从一个外行的角度来理解什么是平稳时间序列。

理解平稳性有多种方式,但最清晰和最直观的方法之一是从时间序列的概率分布或数据分布来思考。当时间序列的概率分布在每个时间点上保持不变时,我们称之为平稳时间序列。换句话说,如果你选择不同的时间窗口,这些窗口中的数据分布应该是相同的。

标准的高斯分布由两个参数定义------均值和方差。因此,平稳性假设可以被打破的方式有两种,分别是:

  • 均值随时间变化
  • 方差随时间变化

让我们详细看一下这些假设,并更好地理解它们。

均值随时间变化

这是非平稳时间序列最常见的表现方式。如果时间序列中有上升或下降的趋势,那么在两个时间窗口之间,均值将不相同。

非平稳性的另一种表现形式是季节性。假设我们正在观察过去5年每月的平均温度时间序列。根据我们的经验,我们知道温度在夏季达到高峰,而在冬季则下降。因此,当我们计算冬季的平均温度和夏季的平均温度时,它们会有所不同。

让我们生成一个包含趋势和季节性的时间序列,并看看它如何表现:

ini 复制代码
# 振幅=1,频率=0.25的正弦信号
signal = ts.signals.Sinusoidal(amplitude=1, frequency=0.25)
# 标准差为0.3的白噪声
noise = ts.noise.GaussianNoise(std=0.3)
# 生成时间序列
sinusoidal_samples, regular_time_samples, _, _ = generate_timeseries(signal=signal, noise=noise)
# regular_time_samples 是一个线性递增的时间轴,可以用作趋势
trend = regular_time_samples * 0.4
# 结合信号和趋势
ts = sinusoidal_samples + trend
plot_time_series(regular_time_samples,
                 ts,
                 "Sinusoidal with Trend and White Noise")

这是输出结果:

如果你检查图1.9中的时间序列,你将能够看到明显的趋势和季节性,二者共同作用使得数据分布的均值在不同时间窗口之间剧烈变化。

方差随时间变化

非平稳性还可以表现为时间序列方差的波动。如果时间序列一开始方差较小,而随着时间的推移,方差不断增大,那么我们就得到了一个非平稳的时间序列。在统计学中,这种现象有一个令人害怕的名称------异方差性(heteroscedasticity)。Air Passengers 数据集(即时间序列中的"鸢尾花数据集"------最受欢迎、过度使用且无用的)是异方差性时间序列的经典例子。让我们来看一下这个图:

在图中,你可以看到季节性峰值随着时间的推移越来越宽,这表明时间序列具有典型的异方差性特征。但并不是所有的异方差性时间序列都容易识别。我们有统计检验方法来检查每一种平稳性情况,我们将在第7章《时间序列预测的目标转换》中详细介绍。

本书的目标是帮助你理解平稳和非平稳时间序列。这个讨论涉及到很多统计理论和深度内容,我们为了保持关注实际应用的重点而跳过了这些内容。

掌握了数据生成过程(DGP)的思维模型后,我们已经准备好思考另一个重要问题:我们可以预测什么?

我们可以预测什么?

在继续之前,我们必须理解时间序列预测的另一个方面------时间序列的可预测性。我们在预测时间序列时的基本假设是,未来依赖于过去。但并不是所有的时间序列都有相同的可预测性。

让我们看几个例子,并尝试按可预测性(从最容易到最难)对它们进行排序,如下所示:

  • 下周一的高潮
  • 下周日的彩票号码
  • 下周五特斯拉的股价

直观上,我们很容易给这些排序。下周一的高潮是最容易预测的,因为它是非常可预测的;下周五特斯拉的股价预测起来会很难,但不是不可能;而彩票号码几乎是随机的,所以预测起来非常困难。

然而,对于那些认为可以通过本书中介绍的先进技术预测股价并因此致富的人来说,这(很可能)不会发生。虽然这是一个值得深入讨论的话题,但我们可以用一段简短的文字来总结要点。

股价不是其过去值的函数,而是对未来值的预期,这违反了我们在预测时的第一个假设。而且,股价通常具有非常低的信噪比。最终的问题是有效市场假说(EMH)。这个看似无害的假设宣称,关于股价的所有已知信息都已经反映在股价中。该假说的含义是,如果你能准确预测,很多其他人也能做到这一点,因此股票的市场价格已经反映了这一预测所带来的价格变化。

M6 竞赛选择正面解决这个问题,评估有效市场假说是否成立,通过进行为期一年的预测和投资策略竞赛。虽然结果并不具有决定性,但数据显示,对于绝大多数参与者来说,有效市场假说是成立的,只有少数顶级团队有所不同。即使在这些顶级团队中,他们发现预测准确性与股票选择进入投资组合之间并没有显著相关性,也就是说,团队并没有选择那些他们能更好预测的股票(完整报告的链接可在本章的进一步阅读部分找到)。

回到我们正在讨论的主题------可预测性------有三个主要因素构成了这一思维模型,如下所示:

  • 理解数据生成过程(DGP) :你对DGP理解得越透彻,时间序列的可预测性就越高。
  • 数据量:你拥有的数据越多,可预测性就越强。
  • 模式的充分重复:任何数学模型要发挥良好作用,都应当在时间序列中存在充分重复的模式。模式的重复性越强,可预测性越好。

尽管你已经有了关于如何思考可预测性的思维模型,我们将在第3章《分析和可视化时间序列数据》中探讨更具体的方法来评估时间序列的可预测性,但关键要点是,并非所有的时间序列都是同样可预测的。

为了完全跟上接下来的讨论,我们需要建立标准的符号表示法并学习时间序列分析中使用的专有术语。

预测术语

有一些术语将帮助你理解本书以及其他关于时间序列的文献。这些术语在这里有更详细的描述:

预测

预测是使用已知的时间序列过去值和/或其他相关变量来预测时间序列未来值的过程。这与机器学习中的预测非常相似,我们使用模型来预测看不见的数据。

多变量预测

多变量时间序列包含多个时间序列变量,这些变量不仅依赖于它们的过去值,还与其他变量有一定的依赖关系。例如,一个国家的宏观经济指标集合,如国内生产总值(GDP)和通货膨胀,可以视为一个多变量时间序列。多变量预测的目标是建立一个模型,捕捉不同变量之间的相互关系及其与过去的关系,并在未来一起预测所有时间序列。

解释性预测

除了时间序列的过去值外,我们可能还会使用一些其他信息来预测时间序列的未来值。例如,在预测零售店销售时,关于促销活动的信息(无论是历史数据还是未来的活动)通常是有帮助的。这种类型的预测,利用除历史数据之外的其他信息,称为解释性预测。

回测

将验证集从训练数据中分离出来以评估模型是机器学习中常见的做法。回测是时间序列中与验证等效的过程,即使用历史数据来评估已训练的模型。我们将在后续章节中介绍时间序列数据验证和交叉验证的不同方法。

样本内和样本外

与机器学习相类似,样本内指的是训练数据,样本外指的是看不见的或测试数据。当你听到"样本内指标"时,这指的是在训练数据上计算的指标,而"样本外指标"指的是在测试数据上计算的指标。

外生变量与内生变量

外生变量是平行的时间序列变量,它们不会直接影响输出,但用于帮助我们建模感兴趣的时间序列。通常,外生变量不受系统中其他变量的影响。内生变量是受系统中其他变量影响的变量。一个纯粹的内生变量是完全依赖于系统中其他变量的变量。如果放宽一些严格假设,我们可以将目标变量视为内生变量,并将我们在模型中包含的解释性回归变量视为外生变量。

预测组合

时间序列中的预测组合类似于机器学习中的集成方法。预测组合是通过使用一个函数(可以是学习的或启发式的,例如三个预测模型的简单平均值)将多个预测组合在一起的过程。

时间序列中有许多特有的术语,其中一些我们将在本书中讨论。但这些术语应该是一个很好的起点,帮助你对该领域有基本的熟悉。

总结

在本章中,我们首次了解了时间序列,讨论了不同类型的时间序列,查看了数据生成过程(DGP)如何生成时间序列,并思考了一个重要的问题:我们能多好地预测时间序列?我们还简要回顾了理解本书其余部分所需的术语。在下一章中,我们将动手操作,学习如何获取和处理时间序列数据。如果你还没有设置好环境,可以休息一下,把时间投入到这个任务中。

进一步阅读

  • S.N. Shukla 和 B.M. Marlin (2020) 的《A Survey on Principles, Models and Methods for Learning from Irregularly Sampled Time Series: From Discretization to Attention and Invariance》:链接
  • S.C. Li 和 B.M. Marlin (2020),ICML 会议的《Learning from Irregularly-Sampled Time Series: A Missing Data Perspective》:链接
  • Spyros Makridakis 等人 (2023) 的《The M6 forecasting competition: Bridging the gap between forecasting and investment decisions》:链接
相关推荐
深圳南柯电子12 分钟前
深圳南柯电子|电子设备EMC测试整改:常见问题与解决方案
人工智能
Kai HVZ13 分钟前
《OpenCV计算机视觉》--介绍及基础操作
人工智能·opencv·计算机视觉
_WndProc15 分钟前
C++ 日志输出
开发语言·c++·算法
biter008818 分钟前
opencv(15) OpenCV背景减除器(Background Subtractors)学习
人工智能·opencv·学习
吃个糖糖24 分钟前
35 Opencv 亚像素角点检测
人工智能·opencv·计算机视觉
努力学习编程的伍大侠28 分钟前
基础排序算法
数据结构·c++·算法
qq_5290252942 分钟前
Torch.gather
python·深度学习·机器学习
XiaoLeisj1 小时前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
IT古董1 小时前
【漫话机器学习系列】017.大O算法(Big-O Notation)
人工智能·机器学习