DAY 57 經典時序模型1
知識點回顧
- 序列數據的處理:
- 處理非平穩性:n階差分
- 處理季節性:季節性差分
- 自回歸性無需處理
- 模型的選擇
- AR(p) 自回歸模型:當前值受到過去p個值的影響
- MA(q) 移動平均模型:當前值收到短期沖擊的影響,且沖擊影響隨時間衰減
- ARMA(p,q) 自回歸滑動平均模型:同時存在自回歸和沖擊影響
作業:檢索下經典的時序單變量數據集有哪些,選擇一個嘗試觀察其性質。
數據集選擇的是經典的國際航空公司乘客數據集
數據集地址:國際航空公司乘客 --- International airline passengers
1.原數組展示
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.statespace.sarimax import SARIMAX
# 讀取數據
data = pd.read_csv('international-airline-passengers.csv')# 設置中文字體
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 設置圖片清晰度
plt.rcParams['figure.dpi'] = 300def parse_date(s):month_part, year_part = s.split('-')# 判斷年份簡寫,這里假設49代表1949,60代表1960等(根據數據集實際情況,若有20xx 可再細化邏輯)if int(year_part) <= 99: year = 1900 + int(year_part)else:year = int(year_part)return f'{year}-{month_part}'# 轉換日期列
data['Month'] = pd.to_datetime(data['Month'].apply(parse_date))# 創建圖表
plt.figure(figsize=(12, 6))
plt.plot(data['Month'], data['passengers'], marker='o', linestyle='-', color='#00A1FF')# 添加標題和軸標簽
plt.title('國際航空乘客數量趨勢圖', fontsize=14, fontweight='bold')
plt.xlabel('日期', fontsize=12)
plt.ylabel('乘客數量(千)', fontsize=12)# 設置X軸為日期格式,并自定義刻度間隔(每6個月顯示一次標簽)
ax = plt.gca()
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=6)) # 每6個月一個刻度
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b-%y')) # 格式化為"月-年"# 旋轉x軸標簽并右對齊,提升可讀性
plt.xticks(rotation=45, ha='right')# 移除左、右、上三邊的邊框,使圖表更簡潔
plt.gca().spines['left'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)# 添加網格橫線,增強數據可讀性
plt.grid(axis='y', linestyle='--', alpha=0.7)# 調整布局,防止標簽被截斷
plt.tight_layout()# 顯示圖形
plt.show()
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?有著顯著的季節性和趨勢?
ADF檢驗一下
# ADF檢驗
adf_result_original = adfuller(data['passengers'].values)
print(f'原始數據的ADF檢驗結果:')
print(f' ADF Statistic: {adf_result_original[0]}')
print(f' p-value: {adf_result_original[1]}') # p-value會非常大,說明是非平穩的
原始數據的ADF檢驗結果:
ADF Statistic: 0.8153688792060463
p-value: 0.991880243437641
P值這么高,顯然數據不穩定
2.季節性差分
# ======================== 季節性差分(周期 S=12) ========================
data.set_index('Month', inplace=True)
# 對原始數據做季節性差分(周期12,即一年的季節周期)
data_seasonal_diff = data['passengers'].diff(periods=12).dropna() # 可視化季節性差分結果
plt.figure(figsize=(12, 4))
plt.plot(data_seasonal_diff, color='#4CAF50', label='季節性差分(S=12)')
plt.title('季節性差分后的數據(周期 S=12)', fontsize=14)
plt.xlabel('日期', fontsize=12)
plt.ylabel('乘客數量差分', fontsize=12)
plt.xticks(rotation=45, ha='right')
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.show()# ======================== ADF 檢驗(驗證平穩性) ========================
adf_result_seasonal = adfuller(data_seasonal_diff)
print(f'季節性差分后數據的 ADF 檢驗結果:')
print(f' ADF Statistic: {adf_result_seasonal[0]}')
print(f' p-value: {adf_result_seasonal[1]}')
?季節性差分后數據的 ADF 檢驗結果:
? ADF Statistic: -3.383020726492481
? p-value: 0.011551493085514954
3.再對季節性差分結果做一階差分(處理趨勢)
# ======================== 2. 一階差分(在季節性差分基礎上) ========================
# 再對季節性差分結果做一階差分(處理趨勢性)
data_seasonal_first_diff = data_seasonal_diff.diff().dropna()# 可視化最終差分結果
plt.figure(figsize=(12, 4))
plt.plot(data_seasonal_first_diff, color='#FF5722', label='季節性差分 + 一階差分')
plt.title('先季節性差分(S=12)、再一階差分后的數據', fontsize=14)
plt.xlabel('日期', fontsize=12)
plt.ylabel('最終差分結果', fontsize=12)
plt.xticks(rotation=45, ha='right')
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.show()
ADF檢驗
# ======================== 3. ADF 檢驗(驗證最終差分后的數據是否平穩) ========================
adf_result = adfuller(data_seasonal_first_diff)
print(f'最終差分后數據的 ADF 檢驗結果:')
print(f' ADF Statistic: {adf_result[0]}')
print(f' p-value: {adf_result[1]}')
print(f' Critical Values:')
for key, value in adf_result[4].items():print(f' {key}: {value:.2f}')
?最終差分后數據的 ADF 檢驗結果:
ADF Statistic: -15.595618083746338
p-value: 1.856511600123444e-28
Critical Values: 1%: -3.48 5%: -2.88 10%: -2.58
4.繪制ACF、PACF圖查看數據適合什么模型
plt.figure(figsize=(12, 8))# 3.1 繪制差分后數據的時間序列圖
plt.subplot(311)
plt.plot(data_seasonal_first_diff)
plt.title('差分后國際航空乘客數量')
plt.xlabel('日期')
plt.ylabel('乘客數量差分')# 3.2 繪制自相關函數(ACF)圖
plt.subplot(312)
plot_acf(data_seasonal_first_diff, lags=40, ax=plt.gca())
plt.title('自相關函數(ACF)')# 3.3 繪制偏自相關函數(PACF)圖
plt.subplot(313)
plot_pacf(data_seasonal_first_diff, lags=40, ax=plt.gca())
plt.title('偏自相關函數(PACF)')plt.tight_layout()
plt.show()
?根據AI分析選擇AR模型
從圖中可以觀察到:
- PACF(偏自相關函數):在滯后 1 階后快速截斷(值落入置信區間,趨近于 0),但后續滯后階數(如滯后 2 階、3 階等)仍有小幅度波動(不過整體趨勢是快速衰減 )。
- ACF(自相關函數):呈現拖尾特征(緩慢衰減,沒有明顯的截斷點 )。
模型推薦
根據上述特征:
- PACF 呈現 “1 階左右截斷 + 拖尾”,但更接近?AR 模型?的特征(PACF 截斷,ACF 拖尾 )。
- 由于 PACF 并非 “嚴格在 1 階后完全截斷”(可能受數據噪聲或季節性影響 ),但整體趨勢符合?AR 模型?的判斷邏輯。
5 .AR模型
# 1.3 根據ACF/PACF圖的診斷,建立ARIMA(1,0,0)模型
model_ar = ARIMA(data_seasonal_first_diff, order=(1, 0, 0)).fit()
print("\nAR(2)模型診斷報告:")
print(model_ar.summary())
效果也就一般般
@浙大疏錦行?