Day57打卡 @浙大疏锦行
知识点回顾
- 序列数据的处理:
- 处理非平稳性:n阶差分
- 处理季节性:季节性差分
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller# 1. 生成一段有季节性的数据
# 假设是4年的月度数据,周期为12
time_index = pd.date_range(start='2020-01-01', periods=48, freq='M')
# 季节性成分(用sin函数模拟)
seasonal_component = np.sin(np.arange(48) * (2 * np.pi / 12)) * 10 # 振幅为10,周期为12个月,sin函数模拟季节性波动
# 趋势成分
trend_component = np.linspace(0, 20, 48) # linspace函数为生成0到20的线性趋势,包含48个点
# 随机噪声
noise = np.random.randn(48) * 2# 合成数据
seasonal_data = pd.Series(seasonal_component + trend_component + noise, index=time_index)# 2. 观察原始数据
plt.figure(figsize=(12, 6))
plt.subplot(211)
plt.plot(seasonal_data)
plt.title('原始季节性数据')# 3. 进行季节性差分(周期s=12)
seasonal_data_diff = seasonal_data.diff(periods=12).dropna()plt.subplot(212)
plt.plot(seasonal_data_diff)
plt.title('季节性差分后 (s=12) 的数据')
plt.tight_layout()
plt.show()# 4. 检查差分后的平稳性
# 注意:原始数据因为有趋势,肯定不平稳。季节性差分通常也能消除一部分趋势。
adf_result_original = adfuller(seasonal_data)
print(f'原始季节性数据的p-value: {adf_result_original[1]}')adf_result_seasonal_diff = adfuller(seasonal_data_diff)
print(f'季节性差分后数据的p-value: {adf_result_seasonal_diff[1]}')
-
- 自回归性无需处理
- 模型的选择
- AR(p) 自回归模型:当前值受到过去p个值的影响
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.arima_process import ArmaProcess
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.arima.model import ARIMA# 设置中文字体,防止matplotlib显示乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# --- AR(2) 案例:湖水温度 ---
print("--- 案例一:AR(2)模型 - 湖水温度 ---")# 1.1 生成AR(2)时间序列数据
# AR(2)模型结构:X_t = 0.7*X_{t-1} + 0.2*X_{t-2} + ε_t
# 其中ε_t是白噪声,系数0.7和0.2控制了前两期对当前值的影响程度
ar_params = np.array([0.7, 0.2]) # AR系数:φ₁=0.7, φ₂=0.2
ma_params = np.array([]) # MA部分为空(纯AR模型)# 转换为statsmodels要求的格式:
# AR系数需添加首项1并取负,即 [1, -φ₁, -φ₂]
ar_coeffs = np.r_[1, -ar_params] # 生成 [1, -0.7, -0.2]
# MA系数需添加首项1,即 [1, θ₁, θ₂, ...]
ma_coeffs = np.r_[1, ma_params] # 生成 [1.]# 创建AR(2)过程实例
ar_process = ArmaProcess(ar=ar_coeffs, ma=ma_coeffs)# 生成500个样本点,模拟500天的湖水温度数据
# 设置随机种子确保结果可复现
np.random.seed(100)
ar_data = ar_process.generate_sample(nsample=500)# 1.2 时间序列分析的"侦探工作":通过可视化初步诊断模型阶数
fig, axes = plt.subplots(3, 1, figsize=(10, 9))# 1.2.1 绘制原始时间序列图
axes[0].plot(ar_data)
axes[0].set_title('模拟的湖水温度数据 (AR(2)过程)')
axes[0].set_ylabel('温度值')
# 关键点:观察数据是否具有平稳性特征(均值和方差是否随时间变化)# 1.2.2 绘制自相关函数(ACF)图 - 衡量序列与其滞后值的相关性
plot_acf(ar_data, ax=axes[1], lags=20, title='自相关函数 (ACF)')
# 关键点:AR(p)模型的ACF会呈现指数衰减或周期性衰减
# 这里我们应该看到ACF在滞后2阶后显著下降# 1.2.3 绘制偏自相关函数(PACF)图 - 控制了中间滞后项后的相关性
plot_pacf(ar_data, ax=axes[2], lags=20, title='偏自相关函数 (PACF)')
# 关键点:AR(p)模型的PACF会在p阶后截断(变为不显著)
# 这里我们应该看到PACF在滞后2阶后截断,辅助确认p=2plt.tight_layout()
plt.show()
-
- MA(q) 移动平均模型:当前值收到短期冲击的影响,且冲击影响随时间衰减
# --- MA(2) 案例:生产线意外 ---
print("\n" + "---"*15)
print("--- 案例二:MA(2)模型 - 生产线意外 ---")"""
=====================
2.1 生成MA(2)时间序列
=====================
MA(2)模型数学表达式:y_t = ε_t + θ₁ε_{t-1} + θ₂ε_{t-2}
- 当前值由当前及前两期的随机冲击(ε)线性组合而成
- 适用于捕捉短期冲击对序列的影响(如生产线故障、原料短缺)
"""
# AR部分参数:因无自回归项
ar_params = np.array([])
# MA部分参数:0.8和0.4分别是前两期冲击的权重
ma_params = np.array([0.8, 0.4]) # 生成MA(2)过程:直接传入AR和MA系数数组(注意无参数名)
ma_process = ArmaProcess.from_coeffs(ar_params, ma_params)# 设置随机种子保证结果可复现,生成500个样本点
np.random.seed(200)
ma_data = ma_process.generate_sample(nsample=500)"""
============================
2.2 可视化分析时间序列特征
============================
通过观察ACF和PACF图判断模型阶数:
- MA(q)模型的ACF应在q阶后截尾(本例q=2)
- PACF应呈现拖尾特征(与AR模型区分)
"""
# 创建3个子图:时间序列图、ACF图、PACF图
fig, axes = plt.subplots(3, 1, figsize=(10, 9))# 绘制时间序列图:展示生产线产量波动
axes[0].plot(ma_data)
axes[0].set_title('模拟的生产线产量波动 (MA(2)过程)')
axes[0].set_xlabel('时间点')
axes[0].set_ylabel('产量波动值')# 绘制自相关函数(ACF)图:观察序列相关性衰减模式
plot_acf(ma_data, ax=axes[1], lags=20, title='自相关函数 (ACF)')
# 理论预期:MA(2)的ACF应在2阶后截尾(相关性骤降为0)# 绘制偏自相关函数(PACF)图:剔除中间变量影响的直接相关性
plot_pacf(ma_data, ax=axes[2], lags=20, title='偏自相关函数 (PACF)')
# 理论预期:MA(2)的PACF应呈现拖尾(指数或振荡衰减)# 优化子图布局,避免重叠
plt.tight_layout()
plt.show()
-
- ARMA(p,q) 自回归滑动平均模型:同时存在自回归和冲击影响
# --- ARMA(1,1) 案例:公司月度销售 ---
print("\n" + "---"*15)
print("--- 案例三:ARMA(1,1)模型 - 公司月度销售 ---")# 3.1 我们来“创造”一个ARMA(1,1)过程
# 修复:直接传入系数数组,并确保包含常数项
ar_params = np.array([1, -0.8]) # AR部分: [1, -φ1]
ma_params = np.array([1, 0.5]) # MA部分: [1, θ1]# 正确调用方式:直接传入系数数组,不使用参数名
arma_process = ArmaProcess.from_coeffs(ar_params, ma_params)np.random.seed(300)
arma_data = arma_process.generate_sample(nsample=500)# 3.2 作为“侦探”,我们观察数据和ACF/PACF图
fig, axes = plt.subplots(3, 1, figsize=(10, 9))
axes[0].plot(arma_data)
axes[0].set_title('模拟的公司月度销售 (ARMA(1,1)过程)')
plot_acf(arma_data, ax=axes[1], lags=20, title='自相关函数 (ACF)')
plot_pacf(arma_data, ax=axes[2], lags=20, title='偏自相关函数 (PACF)')
plt.tight_layout()
plt.show()
@浙大疏锦行