hga038客户端最新版 hga038客户端最新版 hga038客户端最新版

单变量时间序列平滑方法简介

时间序列是由按时间排序的观察单元组成的数据。可能是天气数据、股市数据。,也就是说,它是由按时间排序的观察组成的数据。

序列标注模型 实体识别_正弦函数序列预测问题_长期时间序列预测模型

本文介绍并解释了时间序列的平滑方法,另一篇文章解释了时间序列的统计方法。本文将解释以下4个结构概念:

1. 固定式

稳态是系统状态不再随时间变化的状态。换句话说,如果时间序列的均值、方差和协方差随时间保持不变,则称该时间序列是平稳的。

为什么稳态很重要?:有一种理论解释是,在一定的平稳性下,即在一定的模式下,时间序列的结构更容易预测。也就是说,如果它是静止的,那么运动的下一步动作也是可预测的。所以通常有一个期望:时间序列是平稳的吗?如果它是静止的,我们可以更容易地做出预测。为了捕捉到这一点,人们可以通过查看时间序列图像而不是统计测试来了解这一点。

正弦函数序列预测问题_长期时间序列预测模型_序列标注模型 实体识别

2. 趋势

它是一个时间序列的长期增减结构。如果有趋势,则序列不太可能是平稳的,因为期间的统计量(均值、标准差等)会以增加或减少的趋势变化。

3. 季节性

季节性是时间序列以特定间隔重复特定行为的时间。

4. 循环

它包含类似于季节性的重复模式,但这两个问题可能会相互混淆。季节性可以映射到特定的时间段。它与天、周、年、季度等时间段重叠。例如,市场在周末有更多的生意,或者一个产品在冬天得到更多的关注等。

周期性发生在更长、更不确定的结构上,其方式与天、周等结构不重叠。它主要是由于结构原因而发生的,并且具有周期性变化。例如,虽然有些促销活动不是完全季节性的,它们是在一定时期内发生的,但具体时期会根据不同的营销策略来确定。

理解时间序列模型的本质:上面我们已经看到了时间序列的基本结构。时间序列的假设是时间序列在时间段t的值受上一个时间段(t-1)的值影响最大。例如,今天是星期日,它前面的值最能说明星期日时间序列的值。有了这些基础知识,我们就可以开始介绍平滑方法了

单变量平滑法

1. 简单指数平滑 (SES)

它仅在平稳时间序列中表现良好,因为它要求序列中不应存在趋势和季节性。它可以建模Level(Level可以被认为是系列的平均值)。过去的影响是在“未来与最近的过去更相关”的假设上加权的。SES适用于没有趋势和季节性的单变量时间序列,在平稳序列中最成功。

2. 双指数平滑(Double Exponential Smoothing - DES)

在SES的基础上增加趋势判断。所以它适用于有和没有季节性的单变量时间序列。

3. 三重指数平滑 (TES - Holt-Winters):

它是目前最先进的平滑方法。该方法通过动态评估水平、趋势和季节性的影响来进行预测。它可用于具有趋势和/或季节性的单变量序列。

序列标注模型 实体识别_正弦函数序列预测问题_长期时间序列预测模型

平滑方法使用示例

我们将在这里使用来自 sm 模块的数据集。它根据时间显示夏威夷大气中的二氧化碳。记录时间:1958年3月-2001年12月

import itertools
import warnings
import matplotlib.pyplot as plt
import numpy as np

长期时间序列预测模型_序列标注模型 实体识别_正弦函数序列预测问题

import pandas as pd import statsmodels.api as sm from sklearn.metrics import mean_absolute_error from statsmodels.tsa.holtwinters import ExponentialSmoothing from statsmodels.tsa.holtwinters import SimpleExpSmoothing from statsmodels.tsa.seasonal import seasonal_decompose # to split the time series into components import statsmodels.tsa.api as smt warnings.filterwarnings('ignore')data = sm.datasets.co2.load_pandas() # A dataset from the sm module y = data.data # target varible y

正弦函数序列预测问题_长期时间序列预测模型_序列标注模型 实体识别

索引是日期长期时间序列预测模型,通过查看日期,可以确定这个数据集是每周一次!如果您想查看每月数据,则需要进行转换。

y = y['co2'].resample('MS').mean()
y.isnull().sum()

数据中有缺失值。但是时间序列中的缺失值不能用均值、中位数来填充。所以这里我们用它之前或之后的值来填充,也可以通过对它之前和之后的值取平均值来填充。

y = y.fillna(y.bfill())
y.isnull().sum() # output => 0
y.plot(figsize=(10, 7))
plt.show()

正弦函数序列预测问题_序列标注模型 实体识别_长期时间序列预测模型

可以看出这个系列是有趋势的,其中也包含了明显的季节性。

我们在这里使用保持方法,因为模型在训练模型时往往会过度拟合,无论是时间序列还是深度学习方法。因此,我们应该使用一些方法来防止这种情况并更准确地评估错误并验证模型。这就是我们将数据集拆分为训练测试的原因。

train = y[:'1997-12-01']
print("Lenght of train", len(train)) # 478 months

正弦函数序列预测问题_序列标注模型 实体识别_长期时间序列预测模型

test = y['1998-01-01':] print("Lenght of test", len(test)) # 48 months

1. SES

SES = 水平(如果趋势和季节性不成功)。

这里有一个“smoothing_level”参数。如果没有输入smoothing_level,该方法不会报错。这是因为后面会有更多的参数,所以这里我们临时设置一个值

ses_model = SimpleExpSmoothing(train).fit(smoothing_level=0.5)
y_pred = ses_model.forecast(48)

可视化功能

def plot_co2(train, test, y_pred, title):
mae = mean_absolute_error(test, y_pred)
train["1985":].plot(legend=True, label="TRAIN", title=f"{title}, MAE: {round(mae,2)}")
test.plot(legend=True, label="TEST", figsize=(6, 4))
y_pred.plot(legend=True, label="PREDICTION")
plt.show()
plot_co2(train, test, y_pred, "Single Exponential Smoothing")

长期时间序列预测模型_正弦函数序列预测问题_序列标注模型 实体识别

可以看出SES预测不好,这是因为我们的系列包含了季节相关的信息,我们会做个微调

def ses_optimizer(train, alphas, step=48): # step for length of test set
best_alpha, best_mae = None, float("inf")
for alpha in alphas:
ses_model = SimpleExpSmoothing(train).fit(smoothing_level=alpha)
y_pred = ses_model.forecast(step)
mae = mean_absolute_error(test, y_pred)
if mae < best_mae:
best_alpha, best_mae = alpha, mae
print("alpha:", round(alpha, 2), "mae:", round(mae, 4))
print("best_alpha:", round(best_alpha, 2), "best_mae:", round(best_mae, 4))

正弦函数序列预测问题_长期时间序列预测模型_序列标注模型 实体识别

return best_alpha, best_mae alphas = np.arange(0.8, 1, 0.01)

从 0.8 到 1 以 0.01 的步长生成 alpha。如果你愿意,你可以以 0.1 的增量从 0.1 写到 1,但是 SES 已经是一个弱模型,更接近历史基础事实会产生更好的结果,所以我们从 0.8 开始.

best_alpha, best_mae = ses_optimizer(train, alphas) 
# best_alpha: 0.99 best_mae: 4.5451

最终模型参数如下所示:

ses_model = SimpleExpSmoothing(train).fit(smoothing_level=best_alpha)
y_pred = ses_model.forecast(48)
plot_co2(train, test, y_pred, "Single Exponential Smoothing")

序列标注模型 实体识别_长期时间序列预测模型_正弦函数序列预测问题

MAE有所下降,但仍然不是那么好,对吧?

2.DES

DES:水平(SES)+趋势

这些系列可以是乘法或加法,例如

在乘法运算中,结构的变化更加依赖。如果季节性和残差独立于趋势,则该系列是相加的。如果季节性和残差是根据趋势形成的,它们是相乘的。

季节性和残差在0附近随机分布。因此可以确定趋势不会影响残差,因此我们确定该序列是可加的。

通常我们应该建立两个模型并决定使用误差较小的一个。但这里证实残差和季节性与趋势无关。所以直接使用“add”参数。

des_model = ExponentialSmoothing(train, trend="add").fit(smoothing_level=0.5, smoothing_trend=0.5)
y_pred = des_model.forecast(48)
plot_co2(train, test, y_pred, "Double Exponential Smoothing")

正弦函数序列预测问题_序列标注模型 实体识别_长期时间序列预测模型

虽然结果看起来不错并且趋势已被捕捉到,但由于缺乏季节性,这个估计并不是那么好,我们继续完善

def des_optimizer(train, alphas, betas, step=48):
best_alpha, best_beta, best_mae = None, None, float("inf")
for alpha in alphas:
for beta in betas:
des_model = ExponentialSmoothing(train, trend="add").fit(smoothing_level=alpha, smoothing_slope=beta)

序列标注模型 实体识别_正弦函数序列预测问题_长期时间序列预测模型

y_pred = des_model.forecast(step) mae = mean_absolute_error(test, y_pred) if mae < best_mae: best_alpha, best_beta, best_mae = alpha, beta, mae print("alpha:", round(alpha, 2), "beta:", round(beta, 2), "mae:", round(mae, 4)) print("best_alpha:", round(best_alpha, 2), "best_beta:", round(best_beta, 2), "best_mae:", round(best_mae, 4)) return best_alpha, best_beta, best_maealphas = np.arange(0.01, 1, 0.10) betas = np.arange(0.01, 1, 0.10) best_alpha, best_beta, best_mae = des_optimizer(train, alphas, betas)

最终模型参数:

final_des_model = ExponentialSmoothing(train, trend="add").fit(smoothing_level=best_alpha, smoothing_slope=best_beta)
y_pred = final_des_model.forecast(48)
plot_co2(train, test, y_pred, "Double Exponential Smoothing")

长期时间序列预测模型_正弦函数序列预测问题_序列标注模型 实体识别

MAE 小得多,趋势平坦,但没有季节性

3.TES

TES = SES + DES + 季节性

当我们输入趋势和季节性作为参数时,使用 TES。

tes_model = ExponentialSmoothing(train,
trend="add",
seasonal="add",
seasonal_periods=12)
.fit(smoothing_level=0.5,smoothing_slope=0.5,smoothing_seasonal=0.5)

我们将季节性周期设置为 12,因为数据集中的年份由月份决定。也就是说,我们确定季节性周期为12个月(1年)

y_pred = tes_model.forecast(48)
plot_co2(train, test, y_pred, "Triple Exponential Smoothing")

长期时间序列预测模型_正弦函数序列预测问题_序列标注模型 实体识别

序列标注模型 实体识别_长期时间序列预测模型_正弦函数序列预测问题

如您所见,有趋势和季节性长期时间序列预测模型,我们继续优化

alphas = betas = gammas = np.arange(0.20, 1, 0.10)

这里包含 3 个超参数:

abg = list(itertools.product(alphas, betas, gammas))
def tes_optimizer(train, abg, step=48):
best_alpha, best_beta, best_gamma, best_mae = None, None, None, float("inf")
for comb in abg:
tes_model = ExponentialSmoothing(train, trend="add", seasonal="add", seasonal_periods=12).\
fit(smoothing_level=comb[0], smoothing_slope=comb[1], smoothing_seasonal=comb[2])
# her satırın 0., 1., 2. elemanlarını seç ve model kur
y_pred = tes_model.forecast(step)
mae = mean_absolute_error(test, y_pred)
if mae < best_mae:
best_alpha, best_beta, best_gamma, best_mae = comb[0], comb[1], comb[2], mae
# print([round(comb[0], 2), round(comb[1], 2), round(comb[2], 2), round(mae, 2)])
print("best_alpha:", round(best_alpha, 2), "best_beta:", round(best_beta, 2), "best_gamma:", round(best_gamma, 2),
"best_mae:", round(best_mae, 4))
return best_alpha, best_beta, best_gamma, best_mae
best_alpha, best_beta, best_gamma, best_mae = tes_optimizer(train, abg)
# best_alpha: 0.8 best_beta: 0.5 best_gamma: 0.7 best_mae: 0.606

上面给出的参数smoothing_slope 与smoothing_trend 相同。这里使用 Smoothing_trend 来说明它们是一样的,看结果:

final_tes_model = ExponentialSmoothing(train, trend="add", seasonal="add", seasonal_periods=12).\
fit(smoothing_level=best_alpha, smoothing_trend=best_beta, smoothing_seasonal=best_gamma)
y_pred = final_tes_model.forecast(48)
plot_co2(train, test, y_pred, "Triple Exponential Smoothing")

正弦函数序列预测问题_序列标注模型 实体识别_长期时间序列预测模型

MAE 和可视化结果都很好,对吧?

总结