一、问题描述
时间序列预测是一种利用历史数据来预测未来数据值的方法,它在金融、气象、经济分析等多个领域都有广泛应用。时间序列预测的核心在于理解和提取时间序列中的关键组成部分,包括长期趋势、季节性、循环变动和不规则变动等模式,并建立数学模型进行预测。
常用时间序列预测方法
- 自回归模型(AR):假设时间序列中的每个值都与之前的 p 个值线性相关。
- 移动平均模型(MA):通过将历史预测误差加以平均来预测未来值。
- 自回归移动平均模型(ARMA):将AR和MA模型结合,利用历史值和历史误差共同预测。
- 自回归积分滑动平均模型(ARIMA):ARMA模型的扩展,用于非平稳时间序列数据的预测。
- 季节性自回归积分滑动平均模型(SARIMA):在ARIMA的基础上增加了季节性因素的分析。
- 指数平滑法(Exponential Smoothing):通过给予不同时间点数据不同权重的方式来预测未来值。
时间序列预测的评估指标
- 均方误差(MSE)
- 均方根误差(RMSE)
- 平均绝对误差(MAE)
- 平均绝对百分比误差(MAPE)
应用案例
- 股票价格预测:使用XGBoost模型进行股票价格时间序列预测。
- 销售预测:零售企业利用ARIMA模型预测商品需求量。
- 气象预测:分析历史气象数据,预测未来天气变化。
时间序列预测通过分析历史数据中的模式和趋势,能够帮助企业做出更准确的预测,从而优化决策过程。
二、数据集内容
洗发水销售数据集sales-of-shampoo.csv描述了在3年期间每月洗发水的销售数量。单位是销售计数,共有36个观测值。数据集发布时间为1998年。
数据结构
所有数据如下:
Month | Sales of shampoo over a three year period |
---|---|
1-Jan | 266 |
2-Jan | 145.9 |
3-Jan | 183.1 |
4-Jan | 119.3 |
5-Jan | 180.3 |
6-Jan | 168.5 |
7-Jan | 231.8 |
8-Jan | 224.5 |
9-Jan | 192.8 |
10-Jan | 122.9 |
11-Jan | 336.5 |
12-Jan | 185.9 |
1-Feb | 194.3 |
2-Feb | 149.5 |
3-Feb | 210.1 |
4-Feb | 273.3 |
5-Feb | 191.4 |
6-Feb | 287 |
7-Feb | 226 |
8-Feb | 303.6 |
9-Feb | 289.9 |
10-Feb | 421.6 |
11-Feb | 264.5 |
12-Feb | 342.3 |
1-Mar | 339.7 |
2-Mar | 440.4 |
3-Mar | 315.9 |
4-Mar | 439.3 |
5-Mar | 401.3 |
6-Mar | 437.4 |
7-Mar | 575.5 |
8-Mar | 407.6 |
9-Mar | 682 |
10-Mar | 475.3 |
11-Mar | 581.3 |
12-Mar | 646.9 |
致谢
The original dataset is credited to Makridakis, Wheelwright, and Hyndman (1998).
许可协议
Deed – CC0 1.0 Universal – Creative Commons
三、时间序列预测
安装
常用数据分析和传统机器学习开发包的安装方法如下:
conda create -n ml python=3.12
conda activate ml
conda install numpy pandas matplotlib seaborn statsmodels
conda install scikit-learn scipy
安装后的开发包版本信息:
python 3.12.7 h14ffc60_0 anaconda
numpy 1.26.4 py312hfd52020_0 anaconda
scipy 1.13.1 py312hbb039d4_0 anaconda
pandas 2.2.2 py312h0158946_0 anaconda
scikit-learn 1.5.1 py312h0158946_0 anaconda
matplotlib 3.9.2 py312haa95532_0 anaconda
seaborn 0.13.2 py312haa95532_0 anaconda
statsmodels 0.14.2 py312h4b0e54e_0 anaconda
导入开发包
import pandas as pd
# from pandas import datetime
from pandas import to_datetime
import statsmodels.api as sm
from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
import numpy as np
这段代码是从两个Python库中导入特定的模块或函数:
from statsmodels.tsa.arima_model import ARIMA
* `statsmodels` 是一个Python库,用于估计许多不同统计模型,以及进行统计测试和统计数据探索。
* `tsa` 是 `statsmodels` 中的一个子模块,代表“时间序列分析”(Time Series Analysis)。
* `arima_model` 是 `tsa` 子模块中的一个模块,提供了ARIMA模型的实现。
* `ARIMA` 是从 `arima_model` 模块中导入的一个类,用于构建和拟合ARIMA模型。
from sklearn.metrics import mean_squared_error
* `sklearn`(也称为 `scikit-learn`)是一个广泛使用的Python机器学习库。
* `metrics` 是 `sklearn` 中的一个子模块,提供了各种评估指标,用于衡量模型的性能。
* `mean_squared_error` 是从 `metrics` 子模块中导入的一个函数,用于计算预测值与真实值之间的均方误差。
简而言之,这段代码导入了用于构建和拟合ARIMA模型的 ARIMA
类,以及用于评估模型性能的 mean_squared_error
函数。这通常用于时间序列预测任务中。
预测代码解析
- 导入函数:
from statsmodels.tsa.stattools import acf, pacf
acf
和pacf
是statsmodels.tsa.stattools
模块中的两个函数,分别用于计算自相关函数和偏自相关函数。
- 计算自相关函数(ACF):
lag_acf = acf(train_log_diff.dropna(), nlags=10)
train_log_diff
是一个时间序列数据,通常是经过对数变换和差分处理后的数据,以使其平稳。dropna()
方法用于去除数据中的缺失值(NaN)。nlags=10
参数指定计算前10个滞后(lag)的自相关系数。
- 计算偏自相关函数(PACF):
lag_pacf = pacf(train_log_diff.dropna(), nlags=10, method='ols')
pacf
函数计算偏自相关系数,用于确定时间序列模型中的自回归(AR)阶数。method='ols'
参数指定使用普通最小二乘法(Ordinary Least Squares, OLS)来估计偏自相关系数。
用途和解释:
- 自相关函数(ACF):描述时间序列与其自身在不同滞后下的相关性。ACF图可以帮助识别时间序列中的季节性和趋势成分。
- 偏自相关函数(PACF):描述在控制其他滞后项的影响后,某一滞后项与当前值的相关性。PACF图有助于确定AR模型的阶数。
以下代码使用 statsmodels
库中的 ARIMA
类来拟合一个自回归(AR)模型,并将模型的拟合值与原始数据进行比较。
#AR model
from statsmodels.tsa.arima.model import ARIMA # 使用新版本的 ARIMA
model = ARIMA(Train_log, order=(2, 1, 0)) # here the q value is zero since it is just the AR model
# results_AR = model.fit(disp=-1)
results_AR = model.fit()
plt.plot(train_log_diff.dropna(), label='original')
plt.plot(results_AR.fittedvalues, color='red', label='predictions')
plt.legend(loc='best')
plt.show()
以下代码使用 statsmodels
库中的 ARIMA
类来拟合一个结合了自回归(AR)、差分(I)和移动平均(MA)的 ARIMA 模型,并将模型的拟合值与原始数据进行比较。
#Combined ARIMA model
model = ARIMA(Train_log, order=(2, 1, 1))
results_ARIMA = model.fit(disp=-1)
plt.plot(train_log_diff.dropna(), label='original')
plt.plot(results_ARIMA.fittedvalues, color='red', label='predicted')
plt.legend(loc='best')
plt.show()