目录

引言

Holt 模型,也称为双指数平滑法,是时间序列分析中广泛使用的预测技术。它由 Charles Holt 于 1957 年开发,是对 Brown 的简单指数平滑法的改进。

Holt 模型用于预测呈现趋势的时间序列的未来值。该模型使用两个平滑参数,一个用于估计趋势,另一个用于估计时间序列的水平或基准水平。这些参数分别称为 α\alphaβ\beta

Holt 模型是 Brown 的简单指数平滑法的扩展,后者仅使用一个平滑参数来估计时间序列的趋势和基准水平。Holt 模型通过为趋势添加第二个平滑参数来提高预测的准确性。

Holt 模型的主要优点之一是易于实现,并且不需要大量的历史数据即可生成准确的预测。此外,该模型具有高度适应性,可以根据各种时间序列进行定制。

然而,Holt 模型也存在一些局限性。例如,该模型假设时间序列是平稳的,并且趋势是线性的。如果时间序列不平稳或具有非线性趋势,则 Holt 模型可能不是最合适的。

总的来说,Holt 模型是时间序列分析中一种有用且广泛使用的技术,尤其是在序列预期呈现线性趋势时。

Holt 方法

当数据存在趋势时,简单指数平滑法 的效果不佳。在这种情况下,我们可以使用 双指数平滑法。与其它方法相比,这是一种更可靠的处理无季节性趋势数据的方法。该方法在公式中增加了一个时间 趋势 方程。使用两种不同的权重或平滑参数,同时更新这两个分量。

Holt 的指数平滑法有时也称为 双指数平滑法。其主要思想是使用 SES(简单指数平滑法)并进行改进以捕捉 趋势 分量。

Holt (1957) 扩展了简单指数平滑法,使其能够预测带有 趋势 的数据。该方法包括一个预测方程和两个平滑方程(一个用于 水平,一个用于 趋势

假设一个序列具有以下特征

  • 水平
  • 趋势
  • 无季节性
  • 噪声

其中 t\ell_{t} 表示序列在时间 t,btt, b_t 的水平估计值,t,αt, \alpha 表示序列在时间 t,btt, b_t 的趋势(斜率)估计值,α\alpha 是水平的平滑参数,0α10\le\alpha\le1β\beta^{*} 是趋势的平滑参数,0β10\le\beta^*\le1

与简单指数平滑法一样,此处的水平方程表明 t\ell_{t} 是观测值 yty_{t} 和时间 tt 的一步向前训练预测值的加权平均值,此处由 t1+bt1\ell_{t-1} + b_{t-1} 给出。趋势方程表明 btb_t 是基于 tt1\ell_{t} - \ell_{t-1}bt1b_{t-1}(先前的趋势估计值)的时间 tt 估计趋势的加权平均值。

预测函数不再是平坦的,而是呈现趋势。向前 hh 步预测值等于最后一个估计水平值加上 hh 乘以最后一个估计趋势值。因此,预测值是 hh 的线性函数。

指数平滑的创新状态空间模型

表 7.6 中介绍的指数平滑方法是生成点预测的算法。本教程中的统计模型生成相同的点预测,但也可以生成预测区间。统计模型是一个随机数据生成过程,可以产生完整的预测分布。

每个模型都包含一个描述观测数据的测量方程,以及一些描述未观测分量或状态(水平、趋势、季节性)如何随时间变化的状态方程。因此,这些模型被称为状态空间模型。

对于每种方法,都存在两种模型:一种是加性误差模型,另一种是乘性误差模型。如果模型使用相同的平滑参数值,则生成的点预测是相同的。然而,它们将生成不同的预测区间。

为了区分加性误差模型和乘性误差模型。我们将每个状态空间模型标记为 ETS( .,.,.),分别代表 (Error, Trend, Seasonal)。这个标签也可以理解为指数平滑 (ExponenTial Smoothing)。使用与表 7.5 中相同的符号表示,每个分量的可能性为:Error={A,M}Error=\{A,M\}Trend={N,A,Ad}Trend=\{N,A,A_d\}Seasonal={N,A,M}Seasonal=\{N,A,M\}

对于我们这里带有趋势的线性 Holt 模型,我们将看到两种情况,分别对应于加性误差和乘性误差

ETS(A,A,N):带有加性误差的 Holt 线性方法

对于此模型,我们假设一步向前训练误差由 εt=ytt1bt1NID(0,σ2)\varepsilon_t=y_t-\ell_{t-1}-b_{t-1} \sim \text{NID}(0,\sigma^2) 给出。将其代入 Holt 线性方法的误差修正方程,我们得到

其中,为简单起见,我们设置了 β=αβ\beta=\alpha \beta^*

ETS(M,A,N):带有乘性误差的 Holt 线性方法

将一步向前训练误差指定为相对误差,使得

εt=yt(t1+bt1)(t1+bt1)\varepsilon_t=\frac{y_t-(\ell_{t-1}+b_{t-1})}{(\ell_{t-1}+b_{t-1})}

并采用与上述类似的方法,指定带有乘性误差的 Holt 线性方法基础上的创新状态空间模型为

其中同样 β=αβ\beta=\alpha \beta^*εtNID(0,σ2)\varepsilon_t \sim \text{NID}(0,\sigma^2)

指数平滑方法的分类

基于时间序列分量的思想,我们可以转向 ETS 分类法。ETS 代表“误差-趋势-季节性”(Error-Trend-Seasonality),它具体定义了分量如何相互作用。基于误差、趋势和季节性的类型,Pegels (1969) 提出了一个分类法,随后由 Hyndman et al. (2002) 进一步发展,并由 Hyndman et al. (2008) 进行完善。根据此分类法,误差、趋势和季节性可以是

  1. 误差:“加性”(A) 或 “乘性”(M);
  2. 趋势:“无”(N)、“加性”(A)、“加性阻尼”(Ad)、“乘性”(M) 或 “乘性阻尼”(Md);
  3. 季节性:“无”(N)、“加性”(A) 或 “乘性”(M)。

ETS 分类法中的分量具有清晰的解释:水平显示每个时间段的平均值,趋势反映值的变化,而季节性对应于周期性波动(例如每年一月的销量增加)。根据上述分量的类型,理论上可以设计出 30 种具有不同误差、趋势和季节性类型的 ETS 模型。图 1 显示了具有确定性(不随时间变化)水平、趋势、季节性以及加性误差项的不同时间序列示例。

图 4.1:对应于加性误差 ETS 模型的时间序列

图 1 中图表需要注意的事项

  1. 当季节性为乘性时,其振幅随数据水平的增加而增加,而加性季节性的振幅是恒定的。例如,比较 ETS(A,A,A) 和 ETS(A,A,M):对于前者,第一年最高点和最低点之间的距离与去年大致相同。在 ETS(A,A,M) 的情况下,该距离随着序列水平的增加而增加;
  2. 当趋势为乘性时,数据显示出指数增长/衰减;
  3. 阻尼趋势会减缓加性趋势和乘性趋势;
  4. 如果序列水平不变,则实际上无法区分加性季节性和乘性季节性,因为在这两种情况下季节性的振幅都是恒定的(比较 ETS(A,N,A) 和 ETS(A,N,M))。

图 2:对应于乘性误差 ETS 模型的时间序列

图 2 中的图表显示了与加性情况大致相同的思想,主要区别在于误差方差随着数据水平的增加而增加;这在 ETS(M,A,N) 和 ETS(M,M,N) 数据中变得更清晰。这种属性在统计学中称为异方差性,Hyndman et al. (2008) 认为乘性误差模型的主要优点在于捕捉这种特征。

ETS 分类法中的数学模型

我希望读者能更清楚地了解 ETS 框架是如何建立在时间序列分解的思想之上的。通过引入不同的分量,定义它们的类型,并添加它们的更新方程,我们可以构建能够更好地捕捉时间序列关键特征的模型。但我们也应该考虑分量随时间推移的潜在变化。“转移”或“状态”方程应该反映这种变化:它们解释了水平、趋势或季节性分量是如何演变的。

如第 2.2 节所述,考虑到不同类型分量及其相互作用,我们最终得到了图 1 和图 2 中以图形方式展示的 30 种 ETS 模型,这些模型提供了测量方程和转移方程的公式。

Table 1: Additive error ETS models | | Nonseasonal |Additive |Multiplicative| |—-|———–|———–|————–| |No trend|yt=lt1+ϵtlt=lt1+αϵt\begin{aligned} &y_{t} = l_{t-1} + \epsilon_t \\ &l_t = l_{t-1} + \alpha \epsilon_t \end{aligned} |yt=lt1+stm+ϵtlt=lt1+αϵtst=stm+γϵt\begin{aligned} &y_{t} = l_{t-1} + s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} + \alpha \epsilon_t \\ &s_t = s_{t-m} + \gamma \epsilon_t \end{aligned} |yt=lt1stm+ϵtlt=lt1+αϵtstmst=stm+γϵtlt1\begin{aligned} &y_{t} = l_{t-1} s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} + \alpha \frac{\epsilon_t}{s_{t-m}} \\ &s_t = s_{t-m} + \gamma \frac{\epsilon_t}{l_{t-1}} \end{aligned}| |Additive| yt=lt1+bt1+ϵtlt=lt1+bt1+αϵtbt=bt1+βϵt\begin{aligned} &y_{t} = l_{t-1} + b_{t-1} + \epsilon_t \\ &l_t = l_{t-1} + b_{t-1} + \alpha \epsilon_t \\ &b_t = b_{t-1} + \beta \epsilon_t \end{aligned} | yt=lt1+bt1+stm+ϵtlt=lt1+bt1+αϵtbt=bt1+βϵtst=stm+γϵt\begin{aligned} &y_{t} = l_{t-1} + b_{t-1} + s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} + b_{t-1} + \alpha \epsilon_t \\ &b_t = b_{t-1} + \beta \epsilon_t \\ &s_t = s_{t-m} + \gamma \epsilon_t \end{aligned} | yt=(lt1+bt1)stm+ϵtlt=lt1+bt1+αϵtstmbt=bt1+βϵtstmst=stm+γϵtlt1+bt1\begin{aligned} &y_{t} = (l_{t-1} + b_{t-1}) s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} + b_{t-1} + \alpha \frac{\epsilon_t}{s_{t-m}} \\ &b_t = b_{t-1} + \beta \frac{\epsilon_t}{s_{t-m}} \\ &s_t = s_{t-m} + \gamma \frac{\epsilon_t}{l_{t-1} + b_{t-1}} \end{aligned}| |Additive damped| yt=lt1+ϕbt1+ϵtlt=lt1+ϕbt1+αϵtbt=ϕbt1+βϵt\begin{aligned} &y_{t} = l_{t-1} + \phi b_{t-1} + \epsilon_t \\ &l_t = l_{t-1} + \phi b_{t-1} + \alpha \epsilon_t \\ &b_t = \phi b_{t-1} + \beta \epsilon_t \end{aligned} | yt=lt1+ϕbt1+stm+ϵtlt=lt1+ϕbt1+αϵtbt=ϕbt1+βϵtst=stm+γϵt\begin{aligned} &y_{t} = l_{t-1} + \phi b_{t-1} + s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} + \phi b_{t-1} + \alpha \epsilon_t \\ &b_t = \phi b_{t-1} + \beta \epsilon_t \\ &s_t = s_{t-m} + \gamma \epsilon_t \end{aligned} | yt=(lt1+ϕbt1)stm+ϵtlt=lt1+ϕbt1+αϵtstmbt=ϕbt1+βϵtstmst=stm+γϵtlt1+ϕbt1\begin{aligned} &y_{t} = (l_{t-1} + \phi b_{t-1}) s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} + \phi b_{t-1} + \alpha \frac{\epsilon_t}{s_{t-m}} \\ &b_t = \phi b_{t-1} + \beta \frac{\epsilon_t}{s_{t-m}} \\ &s_t = s_{t-m} + \gamma \frac{\epsilon_t}{l_{t-1} + \phi b_{t-1}} \end{aligned}| |Multiplicative| yt=lt1bt1+ϵtlt=lt1bt1+αϵtbt=bt1+βϵtlt1\begin{aligned} &y_{t} = l_{t-1} b_{t-1} + \epsilon_t \\ &l_t = l_{t-1} b_{t-1} + \alpha \epsilon_t \\ &b_t = b_{t-1} + \beta \frac{\epsilon_t}{l_{t-1}} \end{aligned} | yt=lt1bt1+stm+ϵtlt=lt1bt1+αϵtbt=bt1+βϵtlt1st=stm+γϵt\begin{aligned} &y_{t} = l_{t-1} b_{t-1} + s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} b_{t-1} + \alpha \epsilon_t \\ &b_t = b_{t-1} + \beta \frac{\epsilon_t}{l_{t-1}} \\ &s_t = s_{t-m} + \gamma \epsilon_t \end{aligned} | yt=lt1bt1stm+ϵtlt=lt1bt1+αϵtstmbt=bt1+βϵtlt1stmst=stm+γϵtlt1bt1\begin{aligned} &y_{t} = l_{t-1} b_{t-1} s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} b_{t-1} + \alpha \frac{\epsilon_t}{s_{t-m}} \\ &b_t = b_{t-1} + \beta \frac{\epsilon_t}{l_{t-1}s_{t-m}} \\ &s_t = s_{t-m} + \gamma \frac{\epsilon_t}{l_{t-1} b_{t-1}} \end{aligned}| |Multiplicative damped| yt=lt1bt1ϕ+ϵtlt=lt1bt1ϕ+αϵtbt=bt1ϕ+βϵtlt1\begin{aligned} &y_{t} = l_{t-1} b_{t-1}^\phi + \epsilon_t \\ &l_t = l_{t-1} b_{t-1}^\phi + \alpha \epsilon_t \\ &b_t = b_{t-1}^\phi + \beta \frac{\epsilon_t}{l_{t-1}} \end{aligned} | yt=lt1bt1ϕ+stm+ϵtlt=lt1bt1ϕ+αϵtbt=bt1ϕ+βϵtlt1st=stm+γϵt\begin{aligned} &y_{t} = l_{t-1} b_{t-1}^\phi + s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} b_{t-1}^\phi + \alpha \epsilon_t \\ &b_t = b_{t-1}^\phi + \beta \frac{\epsilon_t}{l_{t-1}} \\ &s_t = s_{t-m} + \gamma \epsilon_t \end{aligned} | yt=lt1bt1ϕstm+ϵtlt=lt1bt1ϕ+αϵtstmbt=bt1ϕ+βϵtlt1stmst=stm+γϵtlt1bt1\begin{aligned} &y_{t} = l_{t-1} b_{t-1}^\phi s_{t-m} + \epsilon_t \\ &l_t = l_{t-1} b_{t-1}^\phi + \alpha \frac{\epsilon_t}{s_{t-m}} \\ &b_t = b_{t-1}^\phi + \beta \frac{\epsilon_t}{l_{t-1}s_{t-m}} \\ &s_t = s_{t-m} + \gamma \frac{\epsilon_t}{l_{t-1} b_{t-1}} \end{aligned}|

Table 2: Multiplicative error ETS models | |Nonseasonal |Additive |Multiplicative| |——|————-|———-|————–| |No trend| yt=lt1(1+ϵt)lt=lt1(1+αϵt)\begin{aligned} &y_{t} = l_{t-1}(1 + \epsilon_t) \\ &l_t = l_{t-1}(1 + \alpha \epsilon_t) \end{aligned} | yt=(lt1+stm)(1+ϵt)lt=lt1+αμy,tϵtst=stm+γμy,tϵt\begin{aligned} &y_{t} = (l_{t-1} + s_{t-m})(1 + \epsilon_t) \\ &l_t = l_{t-1} + \alpha \mu_{y,t} \epsilon_t \\ &s_t = s_{t-m} + \gamma \mu_{y,t} \epsilon_t \end{aligned} | yt=lt1stm(1+ϵt)lt=lt1(1+αϵt)st=stm(1+γϵt)\begin{aligned} &y_{t} = l_{t-1} s_{t-m}(1 + \epsilon_t) \\ &l_t = l_{t-1}(1 + \alpha \epsilon_t) \\ &s_t = s_{t-m}(1 + \gamma \epsilon_t) \end{aligned}| |Additive| yt=(lt1+bt1)(1+ϵt)lt=(lt1+bt1)(1+αϵt)bt=bt1+βμy,tϵt\begin{aligned} &y_{t} = (l_{t-1} + b_{t-1})(1 + \epsilon_t) \\ &l_t = (l_{t-1} + b_{t-1})(1 + \alpha \epsilon_t) \\ &b_t = b_{t-1} + \beta \mu_{y,t} \epsilon_t \end{aligned} | yt=(lt1+bt1+stm)(1+ϵt)lt=lt1+bt1+αμy,tϵtbt=bt1+βμy,tϵtst=stm+γμy,tϵt\begin{aligned} &y_{t} = (l_{t-1} + b_{t-1} + s_{t-m})(1 + \epsilon_t) \\ &l_t = l_{t-1} + b_{t-1} + \alpha \mu_{y,t} \epsilon_t \\ &b_t = b_{t-1} + \beta \mu_{y,t} \epsilon_t \\ &s_t = s_{t-m} + \gamma \mu_{y,t} \epsilon_t \end{aligned} | yt=(lt1+bt1)stm(1+ϵt)lt=(lt1+bt1)(1+αϵt)bt=bt1+β(lt1+bt1)ϵtst=stm(1+γϵt)\begin{aligned} &y_{t} = (l_{t-1} + b_{t-1}) s_{t-m}(1 + \epsilon_t) \\ &l_t = (l_{t-1} + b_{t-1})(1 + \alpha \epsilon_t) \\ &b_t = b_{t-1} + \beta (l_{t-1} + b_{t-1}) \epsilon_t \\ &s_t = s_{t-m} (1 + \gamma \epsilon_t) \end{aligned}| |Additive damped| yt=(lt1+ϕbt1)(1+ϵt)lt=(lt1+ϕbt1)(1+αϵt)bt=ϕbt1+βμy,tϵt\begin{aligned} &y_{t} = (l_{t-1} + \phi b_{t-1})(1 + \epsilon_t) \\ &l_t = (l_{t-1} + \phi b_{t-1})(1 + \alpha \epsilon_t) \\ &b_t = \phi b_{t-1} + \beta \mu_{y,t} \epsilon_t \end{aligned} | yt=(lt1+ϕbt1+stm)(1+ϵt)lt=lt1+ϕbt1+αμy,tϵtbt=ϕbt1+βμy,tϵtst=stm+γμy,tϵt\begin{aligned} &y_{t} = (l_{t-1} + \phi b_{t-1} + s_{t-m})(1 + \epsilon_t) \\ &l_t = l_{t-1} + \phi b_{t-1} + \alpha \mu_{y,t} \epsilon_t \\ &b_t = \phi b_{t-1} + \beta \mu_{y,t} \epsilon_t \\ &s_t = s_{t-m} + \gamma \mu_{y,t} \epsilon_t \end{aligned} | yt=(lt1+ϕbt1)stm(1+ϵt)lt=lt1+ϕbt1(1+αϵt)bt=ϕbt1+β(lt1+ϕbt1)ϵtst=stm(1+γϵt)\begin{aligned} &y_{t} = (l_{t-1} + \phi b_{t-1}) s_{t-m}(1 + \epsilon_t) \\ &l_t = l_{t-1} + \phi b_{t-1} (1 + \alpha \epsilon_t) \\ &b_t = \phi b_{t-1} + \beta (l_{t-1} + \phi b_{t-1}) \epsilon_t \\ &s_t = s_{t-m}(1 + \gamma \epsilon_t) \end{aligned}| |Multiplicative| yt=lt1bt1(1+ϵt)lt=lt1bt1(1+αϵt)bt=bt1(1+βϵt)\begin{aligned} &y_{t} = l_{t-1} b_{t-1} (1 + \epsilon_t) \\ &l_t = l_{t-1} b_{t-1} (1 + \alpha \epsilon_t) \\ &b_t = b_{t-1} (1 + \beta \epsilon_t) \end{aligned} | yt=(lt1bt1+stm)(1+ϵt)lt=lt1bt1+αμy,tϵtbt=bt1+βμy,tlt1ϵtst=stm+γμy,tϵt\begin{aligned} &y_{t} = (l_{t-1} b_{t-1} + s_{t-m})(1 + \epsilon_t) \\ &l_t = l_{t-1} b_{t-1} + \alpha \mu_{y,t} \epsilon_t \\ &b_t = b_{t-1} + \beta \frac{\mu_{y,t}}{l_{t-1}} \epsilon_t \\ &s_t = s_{t-m} + \gamma \mu_{y,t} \epsilon_t \end{aligned}| yt=lt1bt1stm(1+ϵt)lt=lt1bt1(1+αϵt)bt=bt1(1+βϵt)st=stm(1+γϵt)\begin{aligned} &y_{t} = l_{t-1} b_{t-1} s_{t-m} (1 + \epsilon_t) \\ &l_t = l_{t-1} b_{t-1} (1 + \alpha \epsilon_t) \\ &b_t = b_{t-1} (1 + \beta \epsilon_t) \\ &s_t = s_{t-m} (1 + \gamma \epsilon_t) \end{aligned}| |Multiplicative damped| yt=lt1bt1ϕ(1+ϵt)lt=lt1bt1ϕ(1+αϵt)bt=bt1ϕ(1+βϵt)\begin{aligned} &y_{t} = l_{t-1} b_{t-1}^\phi (1 + \epsilon_t) \\ &l_t = l_{t-1} b_{t-1}^\phi (1 + \alpha \epsilon_t) \\ &b_t = b_{t-1}^\phi (1 + \beta \epsilon_t) \end{aligned}| yt=(lt1bt1ϕ+stm)(1+ϵt)lt=lt1bt1ϕ+αμy,tϵtbt=bt1ϕ+βμy,tlt1ϵtst=stm+γμy,tϵt\begin{aligned} &y_{t} = (l_{t-1} b_{t-1}^\phi + s_{t-m})(1 + \epsilon_t) \\ &l_t = l_{t-1} b_{t-1}^\phi + \alpha \mu_{y,t} \epsilon_t \\ &b_t = b_{t-1}^\phi + \beta \frac{\mu_{y,t}}{l_{t-1}} \epsilon_t \\ &s_t = s_{t-m} + \gamma \mu_{y,t} \epsilon_t \end{aligned} | yt=lt1bt1ϕstm(1+ϵt)lt=lt1bt1ϕ(1+αϵt)bt=bt1ϕ(1+βϵt)st=stm(1+γϵt)\begin{aligned} &y_{t} = l_{t-1} b_{t-1}^\phi s_{t-m} (1 + \epsilon_t) \\ &l_t = l_{t-1} b_{t-1}^\phi \left(1 + \alpha \epsilon_t\right) \\ &b_t = b_{t-1}^\phi \left(1 + \beta \epsilon_t\right) \\ &s_t = s_{t-m} \left(1 + \gamma \epsilon_t\right) \end{aligned}|

从统计学的角度来看,表 1 和表 2 中的公式对应于“真实模型”,它们解释了潜在数据的基础模型,但在构建和估计这些模型时,ϵt\epsilon_t 被估计的 ete_t 取代(其计算方式取决于误差类型),并且时间序列分量和平滑参数也被它们的估计值取代(例如 α^\hat \alpha 而不是 α\alpha)。然而,如果这些模型参数的值是已知的,就可以从这些模型中生成点预测和条件 h 步向前期望值。

Holt 线性趋势方法的属性

Holt 线性趋势方法是一种时间序列预测技术,它使用指数平滑来估计时间序列的水平和趋势分量。该方法具有多个属性,包括

  1. 加性模型:Holt 线性趋势方法假设时间序列可以分解为加性模型,其中观测值是水平、趋势和误差分量之和。

  2. 平滑参数:该方法使用两个平滑参数 α 和 β 来估计时间序列的水平和趋势分量。这些参数分别控制应用于水平和趋势分量的平滑程度。

  3. 线性趋势:Holt 线性趋势方法假设时间序列的趋势分量遵循一条直线。这意味着该方法适用于随时间呈现恒定线性趋势的时间序列数据。

  4. 预测:该方法使用估计的水平和趋势分量来预测时间序列的未来值。下一期的预测值由水平分量和趋势分量之和给出。

  5. 优化:通过最小化预测值和观测值之间平方误差和的优化过程来估计平滑参数 α 和 β。这涉及迭代不同平滑参数值,直到找到最优值。

  6. 季节性:Holt 线性趋势方法可以扩展以包含季节性分量。这需要在模型中添加一个季节性分量,该分量捕捉时间序列中定期发生的任何系统性变化。

总的来说,Holt 线性趋势方法是一种强大且广泛使用的预测技术,可用于生成具有恒定线性趋势的时间序列数据的准确预测。该方法易于实现,并且可以扩展以处理带有季节性变化的时间序列数据。

加载库和数据

提示

需要 Statsforecast。要安装,请参阅说明

接下来,我们导入绘图库并配置绘图风格。

import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plt.style.use('grayscale') # fivethirtyeight  grayscale  classic
plt.rcParams['lines.linewidth'] = 1.5
dark_style = {
    'figure.facecolor': '#008080',  # #212946
    'axes.facecolor': '#008080',
    'savefig.facecolor': '#008080',
    'axes.grid': True,
    'axes.grid.which': 'both',
    'axes.spines.left': False,
    'axes.spines.right': False,
    'axes.spines.top': False,
    'axes.spines.bottom': False,
    'grid.color': '#000000',  #2A3459
    'grid.linewidth': '1',
    'text.color': '0.9',
    'axes.labelcolor': '0.9',
    'xtick.color': '0.9',
    'ytick.color': '0.9',
    'font.size': 12 }
plt.rcParams.update(dark_style)


from pylab import rcParams
rcParams['figure.figsize'] = (18,7)

读取数据

import pandas as pd

df=pd.read_csv("https://raw.githubusercontent.com/Naren8520/Serie-de-tiempo-con-Machine-Learning/main/Data/ads.csv")
df.head()
时间广告
02017-09-13T00:00:0080115
12017-09-13T01:00:0079885
22017-09-13T02:00:0089325
32017-09-13T03:00:00101930
42017-09-13T04:00:00121630

StatsForecast 的输入始终是一个长格式的数据框,包含三列:unique_id, ds 和 y

  • unique_id(字符串、整数或类别)表示序列的标识符。

  • ds(日期戳)列的格式应符合 Pandas 的要求,日期格式最好为 YYYY-MM-DD,时间戳格式最好为 YYYY-MM-DD HH:MM:SS。

  • y(数值)表示我们希望预测的测量值。

df["unique_id"]="1"
df.columns=["ds", "y", "unique_id"]
df.head()
dsyunique_id
02017-09-13T00:00:00801151
12017-09-13T01:00:00798851
22017-09-13T02:00:00893251
32017-09-13T03:00:001019301
42017-09-13T04:00:001216301
print(df.dtypes)
ds           object
y             int64
unique_id    object
dtype: object

我们可以看到我们的时间变量 (ds) 是对象格式,我们需要将其转换为日期格式

df["ds"] = pd.to_datetime(df["ds"])

使用绘图方法探索数据

使用 StatsForecast 类中的绘图方法绘制一些序列。此方法会从数据集中打印一个随机序列,对于基本 EDA 非常有用。

from statsforecast import StatsForecast

StatsForecast.plot(df)

增广迪基-福勒检验

增广迪基-福勒 (ADF) 检验是一种统计检验,用于确定时间序列数据中是否存在单位根。单位根可能导致时间序列分析中出现不可预测的结果。单位根检验会形成一个零假设,以确定时间序列数据受趋势影响的强度。通过接受零假设,我们接受时间序列数据是非平稳的证据。通过拒绝零假设或接受备择假设,我们接受时间序列数据是由平稳过程生成的证据。此过程也称为平稳趋势。ADF 检验统计量的值为负数。较低的 ADF 值表明对零假设的拒绝更强烈。

增广迪基-福勒检验是一种常用的统计检验,用于检验给定时间序列是否平稳。我们可以通过定义零假设和备择假设来实现这一点。

  • 零假设:时间序列是非平稳的。它呈现一个与时间相关的趋势。

  • 备择假设:时间序列是平稳的。换句话说,该序列不依赖于时间。

  • ADF 或 t 统计量 < 临界值:拒绝零假设,时间序列是平稳的。

  • ADF 或 t 统计量 > 临界值:未能拒绝零假设,时间序列是非平稳的。

from statsmodels.tsa.stattools import adfuller

def Augmented_Dickey_Fuller_Test_func(series , column_name):
    print (f'Dickey-Fuller test results for columns: {column_name}')
    dftest = adfuller(series, autolag='AIC')
    dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','No Lags Used','Number of observations used'])
    for key,value in dftest[4].items():
       dfoutput['Critical Value (%s)'%key] = value
    print (dfoutput)
    if dftest[1] <= 0.05:
        print("Conclusion:====>")
        print("Reject the null hypothesis")
        print("The data is stationary")
    else:
        print("Conclusion:====>")
        print("The null hypothesis cannot be rejected")
        print("The data is not stationary")
Augmented_Dickey_Fuller_Test_func(df["y"],'Ads')
Dickey-Fuller test results for columns: Ads
Test Statistic         -7.089634e+00
p-value                 4.444804e-10
No Lags Used            9.000000e+00
                            ...     
Critical Value (1%)    -3.462499e+00
Critical Value (5%)    -2.875675e+00
Critical Value (10%)   -2.574304e+00
Length: 7, dtype: float64
Conclusion:====>
Reject the null hypothesis
The data is stationary

自相关图

自相关函数

定义 1.{xt;1tn}\{x_t;1 ≤ t ≤ n\} 为来自 {Xt}\{X_t\} 的大小为 n 的时间序列样本。1. xˉ=t=1nxtn\bar x = \sum_{t=1}^n \frac{x_t}{n} 称为 {Xt}\{X_t\} 的样本均值。2. ck=t=1nk(xt+kxˉ)(xtxˉ)/nc_k =\sum_{t=1}^{n−k} (x_{t+k}- \bar x)(x_t−\bar x)/n 称为 {Xt}\{X_t\} 的样本自协方差函数。3. rk=ck/c0r_k = c_k /c_0 称为 {Xt}\{X_t\} 的样本自相关函数。

关于此定义的注意事项

  • 与大多数文献一样,本指南使用 ACF 同时表示样本自相关函数和自相关函数。ACF 所表示的内容可以很容易地根据上下文确定。

  • 显然 c0 是 {Xt}\{X_t\} 的样本方差。此外,r0=c0/c0=1r_0 = c_0/c_0 = 1 对于任何整数 k,rk1k, |r_k| ≤ 1

  • 当我们计算任何固定长度为 nn 的样本序列的 ACF 时,对于较大的 k 值,我们不能对其值 rkr_k 给予太多信心,因为用于计算 rkr_k(xt+k,xt)(x_{t +k }, x_t ) 对数较少。一个经验法则是对于 k>n/3k > n/3 不估计 rkr_k,另一个是 n50,kn/4n ≥ 50, k ≤ n/4。无论如何,小心总是好的。

  • 我们还通过定义 1 计算非平稳时间序列样本的 ACF。然而,在这种情况下,ACF 或 rkr_k 随着 kk 的增加而非常缓慢或几乎不衰减。

  • 绘制 ACF (rk)(r_k) 对滞后 kk 的图很容易,但在分析时间序列样本时非常有用。这样的 ACF 图称为相关图。

  • 如果 {Xt}\{X_t\} 是平稳的,且 E(Xt)=0E(X_t)=0 且对于所有 k0k \neq 0ρk=0\rho_k =0,也就是说,它是一个白噪声序列,那么 rkr_k 的抽样分布渐近正态,均值为 0,方差为 1/n1/n。因此,rkr_k 大约有 95% 的概率落在区间 [1.96/n,1.96/n][−1.96/\sqrt{n}, 1.96/\sqrt{n}] 中。

现在我们可以总结如下:(1) 如果时间序列的时间序列图清晰地显示出趋势和/或季节性,那么它肯定是非平稳的;(2) 如果自相关函数 (ACF) rkr_k 随着滞后 kk 的增加衰减得非常慢或几乎不衰减,那么时间序列也应该是非平稳的。

偏自相关函数

{Xt}\{X_t\} 是一个平稳时间序列,且 E(Xt)=0E(X_t) = 0。这里的假设 E(Xt)=0E(X_t ) = 0 仅是为了简洁。如果 E(Xt)=μ0E(X_t) = \mu \neq 0,则可以用 {Xtμ}\{X_t −\mu \} 替换 {Xt}\{X_t\}。现在考虑 Xt 对于 {Xtk+1:t1}\{X_{t−k+1:t−1}\} 的线性回归(预测),其中 k 是任意大于或等于 2 的整数。我们用 X^t\hat X_t 来表示这个回归(预测):X^t=α1Xt1++αk1Xtk+1\hat X_t =\alpha_1 X_{t−1}+···+\alpha_{k−1} X_{t−k+1}

其中 {α1,,αk1}\{\alpha_1, · · · , \alpha_{k−1} \} 满足

{α1,,αk1}=arg minβ1,,βk1E[Xt(β1Xt1++βk1Xtk+1)]2\{\alpha_1, · · · , \alpha_{k−1} \}=\argmin_{\beta_1,···,\beta{k−1}} E[X_t −(\beta_1 X_{t−1} +···+\beta_{k−1} X_{t−k+1})]^2

也就是说,{α1,,αk1}\{\alpha_1, · · · , \alpha_{k−1} \} 是通过最小化预测的均方误差来选择的。类似地,设 X^tk\hat X_{t −k} 表示 XtkX_{t −k} 对于 {Xtk+1:t1}\{X_{t −k+1:t −1}\} 的回归(预测)。

X^tk=η1Xt1++ηk1Xtk+1\hat X_{t−k} =\eta_1 X_{t−1}+···+\eta_{k−1} X_{t−k+1}

注意,如果 {Xt}\{X_t\} 是平稳的,则 {α1:k1}={η1:k1}\{\alpha_{1:k−1} \} = \{\eta_{1:k−1} \}。现在设 Z^tk=XtkX^tk\hat Z_{t−k} = X_{t−k} − \hat X_{t−k}Z^t=XtX^t\hat Z_t = X_t − \hat X_t。那么 Z^tk\hat Z_{t−k} 是从 XtkX_{t−k} 中去除中间变量 {Xtk+1:t1}\{X_{t−k+1:t−1} \} 影响后的残差,而 Z^t\hat Z_t 是从 XtX_t 中去除 {Xtk+1:t1}\{X_{t −k+1:t −1} \} 影响后的残差。

定义 2. 平稳时间序列 {Xt}\{X_t \} 在滞后 kk 时的偏自相关函数 (PACF),其中 E(Xt)=0E(X_t ) = 0,定义为

ϕ11=Corr(Xt1,Xt)=Cov(Xt1,Xt)[Var(Xt1)Var(Xt)]1/2=ρ1\phi_{11} = Corr(X_{t−1}, X_t ) = \frac{Cov(X_{t−1}, X_t )} {[Var(X_{t−1})Var(X_t)]^{1/2}} = \rho_1

ϕkk=Corr(Z^tk,Z^t)=Cov(Z^tk,Z^t)[Var(Z^tk)Var(Z^t)]1/2, k2\phi_{kk} = Corr(\hat Z_{t−k},\hat Z_t) = \frac{Cov(\hat Z_{t−k},\hat Z_t)} {[Var(\hat Z_{t −k} )Var(\hat Z_t )]^{1/2}}, \ k ≥ 2

另一方面,以下定理为估计平稳时间序列的偏自相关函数(PACF)提供了途径,其证明可见于 Fan and Yao (2003)。

定理 1.{Xt}\{X_t \} 是一个平稳时间序列,且 E(Xt)=0E(X_t ) = 0,并且 {a1k,,akk}\{a_{1k},··· ,a_{kk}\} 满足

{a1k,,akk}=arg mina1,,akE(Xta1Xt1akXtk)2\{a_{1k},··· ,a_{kk}\}= \argmin_{a_1 ,··· ,a_k} E(X_t − a_1 X_{t−1}−···−a_k X_{t−k})^2

ϕkk=akk\phi_{kk} =a_{kk}k1k≥1 成立。

fig, axs = plt.subplots(nrows=1, ncols=2)

plot_acf(df["y"],  lags=30, ax=axs[0],color="fuchsia")
axs[0].set_title("Autocorrelation");

plot_pacf(df["y"],  lags=30, ax=axs[1],color="lime")
axs[1].set_title('Partial Autocorrelation')

plt.show();

时间序列分解

如何分解时间序列?为什么要分解?

在时间序列分析中,为了预测新值,了解过去的数据非常重要。更正式地说,了解数值随时间变化的模式非常重要。有很多原因可能导致我们的预测值方向错误。时间序列主要由四个组成部分构成。这些组成部分的变化导致时间序列模式的变化。这些组成部分是:

  • 水平(Level):这是随着时间推移平均变化的主要数值。
  • 趋势(Trend):趋势是导致时间序列出现增长或下降模式的数值。
  • 季节性(Seasonality):这是一种周期性事件,在时间序列中持续时间较短,并导致时间序列出现短期的增长或下降模式。
  • 残差/噪声(Residual/Noise):这是时间序列中的随机变化。

这些组成部分随时间组合形成时间序列。大多数时间序列包含水平和噪声/残差,而趋势或季节性是可选的。

如果季节性和趋势是时间序列的一部分,那么将对预测值产生影响。因为预测的时间序列的模式可能与之前的时间序列不同。

时间序列中组成部分的组合可以是两种类型: * 相加模型 (Additive) * 相乘模型 (Multiplicative)

相加时间序列

如果时间序列的组成部分相加以构成时间序列,则该时间序列称为相加时间序列。通过可视化,我们可以说,如果时间序列的增长或下降模式在整个序列中类似,则该时间序列是相加的。任何相加时间序列的数学函数可以表示为: y(t)=level+Trend+seasonality+noisey(t) = level + Trend + seasonality + noise

相乘时间序列

如果时间序列的组成部分相乘形成时间序列,则该时间序列称为相乘时间序列。从可视化来看,如果时间序列随时间呈指数级增长或下降,则可以将其视为相乘时间序列。相乘时间序列的数学函数可以表示为:

y(t)=LevelTrendseasonalityNoisey(t) = Level * Trend * seasonality * Noise

相加

from statsmodels.tsa.seasonal import seasonal_decompose 
a = seasonal_decompose(df["y"], model = "additive", period=12)
a.plot();

相乘

from statsmodels.tsa.seasonal import seasonal_decompose 
a = seasonal_decompose(df["y"], model = "Multiplicative", period=12)
a.plot();

将数据分割为训练集和测试集

我们将数据分为两部分:1. 用于训练我们的 Holt Model 的数据。2. 用于测试我们模型的数据。

对于测试数据,我们将使用最后 30 小时的数据来测试和评估模型的性能。

train = df[df.ds<='2017-09-20 17:00:00'] 
test = df[df.ds>'2017-09-20 17:00:00']
train.shape, test.shape
((186, 3), (30, 3))

现在绘制训练数据和测试数据。

sns.lineplot(train,x="ds", y="y", label="Train", linestyle="--")
sns.lineplot(test, x="ds", y="y", label="Test")
plt.title("Ads watched (hourly data)");
plt.show()

使用 StatsForecast 实现 Holt 方法

加载库

from statsforecast import StatsForecast
from statsforecast.models import Holt

实例化模型

导入并实例化模型。设置参数有时很棘手。大师 Rob Hyndmann 关于 季节性周期 的这篇文章对于设置 season_length 可能很有用。

season_length = 24 # Hourly data 
horizon = len(test) # number of predictions

models = [Holt(season_length=season_length, error_type="A", alias="Add"),
          Holt(season_length=season_length, error_type="M", alias="Multi")]

通过实例化一个新的 StatsForecast 对象并使用以下参数来拟合模型:

models: 模型列表。从 models 中选择您需要的模型并导入它们。

  • freq: 一个字符串,指示数据的频率。(参见 pandas 可用的频率别名)。

  • n_jobs: int,并行处理中使用的作业数,使用 -1 表示所有核心。

  • fallback_model: 如果某个模型失败时使用的备用模型。

任何设置都通过构造函数传入。然后调用其 fit 方法并传入历史数据帧。

sf = StatsForecast(models=models, freq='h')

拟合模型

sf.fit(df=train)
StatsForecast(models=[Add,Multi])

让我们看看我们的 Holt Model 的结果。我们可以通过以下指令观察:

result=sf.fitted_[0,0].model_
print(result.keys())
print(result['fit'])
dict_keys(['loglik', 'aic', 'bic', 'aicc', 'mse', 'amse', 'fit', 'residuals', 'components', 'm', 'nstate', 'fitted', 'states', 'par', 'sigma2', 'n_params', 'method', 'actual_residuals'])
results(x=array([9.99900000e-01, 1.00000000e-04, 7.97982888e+04, 3.33340440e+02]), fn=4456.295090550272, nit=74, simplex=None)

现在让我们可视化模型的拟合值。

正如我们所见,上面获得的结果是一个字典输出,为了从字典中提取每个元素,我们将使用 .get() 函数来提取元素,然后将其保存在一个 pd.DataFrame() 中。

residual=pd.DataFrame(result.get("residuals"), columns=["residual Model"])
residual
残差模型
0-16.629196
1-563.340440
29106.661223
......
183-268.370897
184-1313.391081
185-1428.364244
import scipy.stats as stats

fig, axs = plt.subplots(nrows=2, ncols=2)

residual.plot(ax=axs[0,0])
axs[0,0].set_title("Residuals");

sns.distplot(residual, ax=axs[0,1]);
axs[0,1].set_title("Density plot - Residual");

stats.probplot(residual["residual Model"], dist="norm", plot=axs[1,0])
axs[1,0].set_title('Plot Q-Q')

plot_acf(residual,  lags=35, ax=axs[1,1],color="fuchsia")
axs[1,1].set_title("Autocorrelation");

plt.show();

预测方法

如果您想在具有多个序列或模型的生产环境中提高速度,我们建议使用 StatsForecast.forecast 方法代替 .fit.predict

主要区别在于 .forecast 不存储拟合值,并且在分布式环境中具有高度可伸缩性。

forecast 方法接受两个参数:预测接下来的 h (horizon) 和 level

  • h (int): 表示未来 h 步的预测。在此示例中,提前 12 个月。

  • level (list of floats): 这个可选参数用于概率预测。设置预测区间(或置信百分位)的水平。例如,level=[90] 表示模型期望真实值有 90% 的时间落在该区间内。

这里的 forecast 对象是一个新的数据帧,其中包含一个带有模型名称和 y hat 值的列,以及不确定性区间的列。根据您的计算机,此步骤大约需要 1 分钟。

Y_hat = sf.forecast(df=train, h=horizon, fitted=True)
Y_hat
unique_idds相加相乘
012017-09-20 18:00:00139848.234375141089.625000
112017-09-20 19:00:00140181.328125142664.000000
212017-09-20 20:00:00140514.406250144238.359375
...............
2712017-09-21 21:00:00148841.671875183597.453125
2812017-09-21 22:00:00149174.750000185171.812500
2912017-09-21 23:00:00149507.843750186746.187500
values=sf.forecast_fitted_values()
values.head()
unique_iddsy相加相乘
012017-09-13 00:00:0080115.080131.63281279287.125000
112017-09-13 01:00:0079885.080448.34375081712.710938
212017-09-13 02:00:0089325.080218.33593881482.796875
312017-09-13 03:00:00101930.089658.28125090922.609375
412017-09-13 04:00:00121630.0102264.195312103528.398438
StatsForecast.plot(values)

使用 forecast 方法添加 95% 置信区间

sf.forecast(df=train, h=horizon, level=[95])
unique_idds相加相加-lo-95相加-hi-95相乘相乘-lo-95相乘-hi-95
012017-09-20 18:00:00139848.234375116559.250000163137.218750141089.625000113501.140625168678.125000
112017-09-20 19:00:00140181.328125107245.734375173116.906250142664.000000103333.265625181994.718750
212017-09-20 20:00:00140514.406250100175.375000180853.453125144238.35937595679.804688192796.921875
...........................
2712017-09-21 21:00:00148841.67187525453.445312272229.875000183597.4531254082.392090363112.531250
2812017-09-21 22:00:00149174.75000023596.246094274753.250000185171.8125001151.084961369192.562500
2912017-09-21 23:00:00149507.84375021776.173828277239.531250186746.187500-1776.010254375268.375000
sf.plot(train, Y_hat)

带有置信区间的 predict 方法

要生成预测,请使用 predict 方法。

predict 方法接受两个参数:预测接下来的 h (horizon) 和 level

  • h (int): 表示未来 h 步的预测。在此示例中,提前 12 个月。

  • level (list of floats): 这个可选参数用于概率预测。设置预测区间(或置信百分位)的水平。例如,level=[95] 表示模型期望真实值有 95% 的时间落在该区间内。

这里的 forecast 对象是一个新的数据帧,其中包含一个带有模型名称和 y hat 值的列,以及不确定性区间的列。

此步骤应该不到 1 秒。

sf.predict(h=horizon)
unique_idds相加相乘
012017-09-20 18:00:00139848.234375141089.625000
112017-09-20 19:00:00140181.328125142664.000000
212017-09-20 20:00:00140514.406250144238.359375
...............
2712017-09-21 21:00:00148841.671875183597.453125
2812017-09-21 22:00:00149174.750000185171.812500
2912017-09-21 23:00:00149507.843750186746.187500
forecast_df = sf.predict(h=horizon, level=[80,95]) 
forecast_df
unique_idds相加相加-lo-95相加-lo-80相加-hi-80相加-hi-95相乘相乘-lo-95相乘-lo-80相乘-hi-80相乘-hi-95
012017-09-20 18:00:00139848.234375116559.250000124620.390625155076.078125163137.218750141089.625000113501.140625123050.484375159128.781250168678.125000
112017-09-20 19:00:00140181.328125107245.734375118645.898438161716.750000173116.906250142664.000000103333.265625116947.015625168380.984375181994.718750
212017-09-20 20:00:00140514.406250100175.375000114138.132812166890.687500180853.453125144238.35937595679.804688112487.625000175989.093750192796.921875
.......................................
2712017-09-21 21:00:00148841.67187525453.44531268162.445312229520.890625272229.875000183597.4531254082.39209066218.867188300976.031250363112.531250
2812017-09-21 22:00:00149174.75000023596.24609467063.382812231286.125000274753.250000185171.8125001151.08496164847.128906305496.500000369192.562500
2912017-09-21 23:00:00149507.84375021776.17382865988.593750233027.093750277239.531250186746.187500-1776.01025463478.144531310014.218750375268.375000
sf.plot(train, forecast_df, level=[80, 95])

交叉验证

在前面的步骤中,我们使用了历史数据来预测未来。然而,为了评估其准确性,我们还希望了解模型在过去的表现。要评估模型在数据上的准确性和稳健性,请执行交叉验证。

对于时间序列数据,交叉验证是通过在历史数据上定义一个滑动窗口并预测其后的时期来完成的。这种形式的交叉验证使我们能够更好地估计模型在更广泛时间点上的预测能力,同时保持训练集中的数据是连续的,这是我们模型所要求的。

下图描述了这种交叉验证策略:

执行时间序列交叉验证

时间序列模型的交叉验证被认为是最佳实践,但大多数实现非常慢。statsforecast 库将交叉验证实现为分布式操作,从而减少了执行时间。如果您有大型数据集,您还可以使用 Ray、Dask 或 Spark 在分布式集群中执行交叉验证。

在此示例中,我们希望评估每个模型在过去 5 个月(n_windows=)中的性能,每隔 12 个月(step_size=12)进行一次预测。根据您的计算机,此步骤大约需要 1 分钟。

StatsForecast 类的 cross_validation 方法接受以下参数。

  • df: 训练数据帧。

  • h (int): 表示预测未来 h 步。在此示例中,提前 30 小时。

  • step_size (int): 每个窗口之间的步长。换句话说:您希望多久运行一次预测过程。

  • n_windows(int): 用于交叉验证的窗口数。换句话说:您希望评估过去多少个预测过程。

crossvalidation_df = sf.cross_validation(df=df,
                                         h=horizon,
                                         step_size=30,
                                         n_windows=3)

crossvaldation_df 对象是一个新的数据帧,其中包含以下列:

  • unique_id: 序列标识符。
  • ds: 日期戳或时间索引。
  • cutoff: n_windows 的最后一个日期戳或时间索引。
  • y: 真实值。
  • model: 包含模型名称和拟合值的列。
crossvalidation_df
unique_idds截止时间y相加相乘
012017-09-18 06:00:002017-09-18 05:00:0099440.0111573.328125112874.039062
112017-09-18 07:00:002017-09-18 05:00:0097655.0111820.390625114421.679688
212017-09-18 08:00:002017-09-18 05:00:0097655.0112067.453125115969.320312
.....................
8712017-09-21 21:00:002017-09-20 17:00:00103080.0148841.671875183597.453125
8812017-09-21 22:00:002017-09-20 17:00:0095155.0149174.750000185171.812500
8912017-09-21 23:00:002017-09-20 17:00:0080285.0149507.843750186746.187500

模型评估

现在我们将使用预测结果来评估我们的模型,我们将使用不同类型的指标 MAE、MAPE、MASE、RMSE、SMAPE 来评估准确性。

from functools import partial

import utilsforecast.losses as ufl
from utilsforecast.evaluation import evaluate
evaluate(
    test.merge(Y_hat),
    metrics=[ufl.mae, ufl.mape, partial(ufl.mase, seasonality=season_length), ufl.rmse, ufl.smape],
    train_df=train,
)
unique_id指标相加相乘
01MAE30905.75104248210.098958
11MAPE0.3362010.491980
21MASE3.8184645.956449
31RMSE38929.52248254653.132768
41SMAPE0.1297550.182024

参考文献

  1. Changquan Huang • Alla Petukhina. Springer series (2022). 应用时间序列分析与预测 Python 实现 (Applied Time Series Analysis and Forecasting with Python)。
  2. Ivan Svetunkov. 使用增强动态自适应模型(ADAM)进行预测和分析 (Forecasting and Analytics with the Augmented Dynamic Adaptive Model (ADAM))
  3. James D. Hamilton. 时间序列分析 (Time Series Analysis) Princeton University Press, Princeton, New Jersey, 1st Edition, 1994.
  4. Nixtla Parameters.
  5. Pandas 可用频率.
  6. Rob J. Hyndman and George Athanasopoulos (2018). “预测原则与实践 (第三版)” (“Forecasting Principles and Practice (3rd ed)”).
  7. 季节性周期 - Rob J Hyndman.