💡一句話定義
為什麼要獨立成一個主題?因為一般機器學習假設每筆資料獨立(今天這筆和昨天那筆沒關係),時間序列正好相反:相鄰的值高度相關(自相關)。把它當普通表格處理——隨機打亂、隨機切訓練測試——會讓模型偷看未來,分數漂亮、上線就崩。
🧬時序資料的三個特性與四個成分
三個特性:有順序、有自相關、不能隨機打亂
第 t 筆一定在第 t−1 筆之後。索引是時間(
DatetimeIndex),不是任意編號。yt 和 yt−1、yt−12 相關。這是「可預測」的來源,也是「不獨立」的原因。
打亂就等於讓模型用「未來」學「過去」。切分、交叉驗證都要按時間先後。
四個成分:趨勢、季節、循環、殘差
| 成分 | 長什麼樣 | 生活例子 | 怎麼抓 |
|---|---|---|---|
| 趨勢 Trend(T) | 長期往上或往下的方向 | 公司營收逐年成長、人口老化 | 移動平均、線性回歸對時間 |
| 季節 Seasonal(S) | 固定週期重複的起伏(週期已知) | 每年 12 月零售暴增、每天晚上 8 點用電高峰、每週一客服量多 | 按週期位置取平均(每月/每小時) |
| 循環 Cyclical(C) | 長期、週期不固定的起伏 | 景氣循環(3–10 年不等) | 難,常與趨勢合併處理 |
| 殘差 Residual/Noise(R) | 拿掉以上三者後剩下的隨機波動 | 突發新聞、天氣、量測誤差 | 分解後剩下的部分;理想上應像白噪音 |
分解(decomposition)就是把 y 拆回這幾條線,例如 statsmodels.tsa.seasonal.seasonal_decompose(y, model="additive", period=12)。看懂分解圖是中級科目二的常見判讀題:趨勢線往上、季節線週期 12、殘差應該沒有明顯樣式。
🎮互動一:時序合成與分解實驗
自己「造」一條 48 個月的序列:拉滑桿控制趨勢斜率、季節振幅、雜訊大小,右邊即時畫出合成後的序列並拆成三條子圖。再看下面兩個面板:一階差分怎麼把趨勢拿掉、ACF 怎麼透露季節週期。
📈 合成序列 y = 100 + 趨勢 + 季節 + 雜訊
↗ 趨勢 T
🌊 季節 S(週期 12)
🎲 殘差 R
Δ 一階差分 yt − yt−1
🔗 自相關函數 ACF(lag 1–24)lag 12、24 有尖峰=季節週期 12
📉平穩性、差分、ACF 與 ARIMA 三個字母
平穩性(stationarity):統計性質不隨時間變
平穩序列的平均數、變異數不隨時間改變,自相關只跟 lag 有關、不跟「現在是哪一年」有關。傳統模型(AR、MA、ARMA)都假設序列平穩,因為「過去的樣式延續到未來」只有在性質不變時才說得通。有趨勢的序列平均數一直在跑,就是非平穩。檢定用 ADF 檢定(Augmented Dickey–Fuller):p 值小 → 拒絕「有單位根」→ 平穩。
差分(differencing):把趨勢減掉
一階差分 Δyt = yt − yt−1:「這個月比上個月多多少」。線性趨勢差分一次就變成常數,所以差分是讓序列平穩最常用的招。季節差分 yt − yt−12:「跟去年同月比」,拿掉季節。差分太多次會把訊號也差掉、變異數反而變大,通常 d ≤ 2。
ACF:序列跟「自己的過去」有多像
自相關函數(ACF, autocorrelation function)在 lag k 的值=yt 與 yt−k 的相關係數。讀圖直覺:
- ACF 緩慢衰減、長期偏高 → 有趨勢、非平穩 → 先差分。
- ACF 在 lag 12、24 有尖峰 → 季節週期 12。
- ACF 幾乎全在 0 附近 → 白噪音,沒東西可預測。
- ACF 在 lag q 之後突然截斷 → 像 MA(q);PACF(偏自相關)在 lag p 之後截斷 → 像 AR(p)。
ARIMA(p, d, q):三個字母各管一件事
| 字母 | 全名 | 意思 | 白話 |
|---|---|---|---|
| AR(p) | AutoRegressive 自我回歸 | 用過去 p 期的值做回歸預測現在 | 「今天 ≈ a×昨天 + b×前天」。p 看 PACF 在哪截斷 |
| I(d) | Integrated 整合(差分) | 先差分 d 次讓序列平穩,預測完再加回去 | d=0 本來就平穩、d=1 一階差分(最常見)、d=2 很少 |
| MA(q) | Moving Average 移動平均 | 用過去 q 期的預測誤差修正現在 | 「昨天估太高,今天往下修一點」。q 看 ACF 在哪截斷 |
🎮互動二:移動平均視窗與指數平滑
用上面合成的同一條序列,拉視窗 w 看移動平均怎麼把雜訊磨平——w 越大越平滑、但也越落後(lag);w=12 剛好吃掉一整個季節週期。再調指數平滑的 α:α 大=相信最新值、反應快;α 小=平滑但遲鈍。
📈 原序列 vs 平滑後
# Pandas 寫法(trailing:只用「過去與現在」,不偷看未來)
df["ma3"] = df["y"].rolling(window=3).mean() # 前 2 筆是 NaN
df["ma12"] = df["y"].rolling(window=12).mean() # 吃掉季節,看趨勢
df["ema"] = df["y"].ewm(alpha=0.3).mean() # 指數加權:越近權重越大
# 簡單指數平滑的遞迴式:
# s_t = α·y_t + (1−α)·s_{t−1}
# Holt 加趨勢項、Holt-Winters 再加季節項(三參數)
🤖機器學習與深度學習做時序
用 ML 做時序=把「時間」變成特徵
樹模型、線性模型不懂順序,所以要手動把過去塞進欄位:
- lag 特徵:
df["y_lag1"] = df["y"].shift(1)(昨天的值)、shift(7)(上週同日)、shift(12)(去年同月)。 - rolling 特徵:
df["y"].shift(1).rolling(7).mean()(過去 7 天平均)、.std()(波動度)。 - 時間特徵:月份、星期幾、是否假日、距活動天數。
shift(-1) 是「明天的值」、rolling(7, center=True) 用到未來 3 天、對整段資料先做 fit_transform 再切分——都讓訓練時偷看到測試期。原則:任何特徵在時間 t 只能用 t 以前(含 t)的資訊。逐行解剖:rolling 移動平均與 shift 落後特徵——shift 正看過去、負偷未來;通論看 資料洩漏互動動畫。
驗證要用 Walk-forward(滾動前進)
不能用普通 K-fold(會隨機打亂)。Walk-forward/TimeSeriesSplit:訓練集永遠在前、驗證集永遠在後,一折一折往前推——第 1 折用 1–12 月訓練、13–15 月驗證;第 2 折用 1–15 月訓練、16–18 月驗證……模擬真實上線「用過去預測未來」。細看 時間序列切分 與 TimeSeriesSplit 讓驗證永遠晚於訓練。
深度學習:RNN/LSTM 天生吃序列
RNN(循環神經網路)一步一步讀序列、把「記憶」傳到下一步;LSTM 用閘門解決長序列的梯度消失,能記住更久以前的樣式。輸入形狀是 (樣本數, 時間步, 特徵數)——例如 (32, 24, 5)=32 段、每段 24 個時間點、每點 5 個特徵。概念看 RNN/LSTM 序列模型、RNN vs LSTM 記憶機制圖解;形狀怎麼讀看 LSTM 的輸入 shape。近年 Transformer 類模型(Temporal Fusion Transformer、PatchTST)也用於長序列預測。
🤔方法怎麼選:五種做法比較
| 方法 | 核心想法 | 適合 | 弱點 |
|---|---|---|---|
| 移動平均/指數平滑 | 用最近值的(加權)平均當預測 | 基準線、短期、資料少、要可解釋 | 抓不到複雜樣式;移動平均會落後 |
| Holt-Winters | 指數平滑 + 趨勢 + 季節三項 | 有明顯季節的單變量序列 | 只用自己的歷史,無法吃外部變數 |
| ARIMA/SARIMA | 差分平穩後用過去值與過去誤差回歸 | 單變量、平穩或可差分、要統計推論 | 要人工定 p d q、對非線性無力 |
| ML(XGBoost 等)+ lag 特徵 | 把時間攤成特徵欄,當一般回歸 | 多變量、有外部特徵(促銷、天氣)、多條序列 | 特徵工程重、容易洩漏、外推趨勢弱 |
| RNN/LSTM/Transformer | 模型自己從序列學樣式 | 長序列、大量資料、非線性 | 資料需求大、訓練慢、不易解釋 |
⚠️常見誤區
測試集裡混著訓練集前後的時間點,模型靠「插值」拿高分。要
shuffle=False 或 TimeSeriesSplit。特徵用到未來的值,上線時根本拿不到。
scaler 看到測試期的平均與標準差。scaler 只能 fit 訓練期。
MA(q) 是過去誤差的加權模型;rolling mean 是平滑技巧。
有趨勢的序列直接 AR 會得到假相關;先差分或檢定。
RMSE 看起來小,但「明天=今天」可能更小。基準線永遠先算。
✅自我檢測
Q1. 零售業每年 12 月營收固定飆高、1 月回落,這屬於時間序列的哪個成分?
Q2. ARIMA(2, 1, 0) 中間的「1」代表什麼?
Q3. 下列哪個特徵會造成資料洩漏?
Q4. 月資料的 ACF 圖在 lag 12 與 24 有明顯尖峰,最可能表示?
Q5. 要評估一個月營收預測模型,最合適的驗證方式是?
🎯重點整理
- 本質:時間序列有順序、有自相關、不能打亂;分析目標是「看懂」與「預測」。
- 分解:y = 趨勢 + 季節 +(循環)+ 殘差;季節週期固定、循環不固定;殘差應像白噪音。
- 平穩與差分:傳統模型要平穩;有趨勢就一階差分、有季節就季節差分;ACF 慢衰減=非平穩、lag 12 尖峰=季節。
- 模型:移動平均/指數平滑(基準)→ ARIMA(p,d,q)(AR 看過去值、I 差分、MA 看過去誤差)→ ML+lag 特徵 → LSTM/Transformer。
- 紀律:特徵只能用 t 以前的資訊(shift 正、不 center);scaler 只 fit 訓練期;驗證用 walk-forward;永遠跟 naive 比。