← M08 大數據分析 M08 大數據分析

M08.07|時間序列分析與預測

讀懂時間的語言 — 從趨勢到季節性,讓資料預見未來

L1-AI基礎知識-統計分析 L2-AI技術應用-預測分析
時間序列 趨勢分析 季節性 ARIMA Prophet 預測模型 移動平均 時間序列分解
📋

本講學習重點

時間序列和普通資料的本質差異是什麼?
趨勢、季節性和殘差如何分解?
ARIMA 的三個參數 p、d、q 代表什麼?
Prophet 為何適合業務預測場景?
時間序列的評估指標有哪些?

時間序列 = 按時間順序排列的資料點,相鄰資料點之間存在時間依賴性(autocorrelation),不能直接用普通回歸處理

時間序列分解:趨勢(長期方向)+ 季節性(固定週期波動)+ 殘差(隨機波動),加法模型 vs 乘法模型

平穩性(Stationarity):均值和方差不隨時間改變,是 ARIMA 的前提;差分(Differencing)可讓非平穩序列變平穩

ARIMA(p,d,q):p=自回歸階數(用過去幾個值預測),d=差分次數,q=移動平均階數(過去預測誤差的影響)

Prophet:加法模型,自動處理趨勢轉折點、多重季節性和假期效應,適合業務場景,不需要平穩性假設

時間序列交叉驗證:必須保持時間順序(Walk-Forward Validation),不能隨機打亂分訓練/測試集

評估指標:MAE(平均絕對誤差)、MAPE(平均絕對百分比誤差)、RMSE(均方根誤差)、SMAPE(對稱 MAPE)

📌 時間序列分析的核心是理解資料中的時間結構:趨勢(長期方向)、季節性(週期波動)和殘差(隨機性)。ARIMA 是統計學的經典框架,要求序列平穩;Prophet 是 Facebook 開發的實用工具,自動處理業務場景中的複雜季節性和假期效應,適合非技術人員使用。無論哪種模型,時間序列評估的最大陷阱是資料洩漏:必須用 Walk-Forward Validation,確保訓練集的時間始終在測試集之前。
時間序列分析與預測

🎙️ Podcast(中文)

0:00 / 0:00

一句話搞懂

時間序列分析是專門處理「按時間順序排列的資料」的方法——它的核心假設是「今天的數值和昨天、上周、去年同期的數值是有關聯的」,因此必須用特殊的方法來分析和預測;從氣象預報、股價分析、電商的銷售預測,到工廠設備的故障預警,任何「隨時間變化且我們想預測未來走勢」的問題,都屬於時間序列的範疇,而 ARIMA 和 Prophet 是其中最廣泛使用的預測框架。


白話解說

時間序列:資料裡藏著時間的記憶

普通的資料分析(如用年齡預測收入)假設樣本之間是獨立的——張三的收入和李四的收入互不影響。但時間序列資料根本上是不同的:今天的氣溫受到昨天氣溫的影響;本月的銷售量受到上個月、去年同期銷售量的影響。這種「過去影響現在」的特性稱為自相關(Autocorrelation),是時間序列分析的核心。

如果你把時間序列資料用散點圖畫出,通常可以直觀地看到幾個組成成分:

趨勢(Trend):資料的長期方向,可以是上升(如全球電商市場規模逐年增長)、下降(如實體書店銷售量逐年減少),或先漲後跌的非線性趨勢。趨勢反映了驅動該指標長期變化的根本因素。

季節性(Seasonality):在固定週期內重複出現的波動模式。例如:零售業的日季節性(午飯時間和下班後的流量高峰)、週季節性(周末的消費行為和工作日不同)、年季節性(雙 11、聖誕節、農曆新年的銷售高峰)。季節性是可預測的、有規律的波動。

週期性(Cyclicality):與季節性不同,週期性的波動週期不固定,通常與宏觀經濟週期(繁榮、衰退)相關,可能長達幾年甚至幾十年。

殘差(Residual/Noise):去除趨勢和季節性後剩下的隨機波動,代表無法被解釋的隨機因素。

時間序列分解(Decomposition)是把這些成分分離出來的技術,有兩種主要形式:

  • 加法模型:時間序列 = 趨勢 + 季節性 + 殘差。適用於季節性波動的幅度不隨趨勢水準改變的情況(如每年銷售高峰固定增加 1000 件)。
  • 乘法模型:時間序列 = 趨勢 × 季節性 × 殘差。適用於季節性波動的幅度隨趨勢水準等比例放大的情況(如銷售量越大,雙 11 的絕對增量也越大)。電商、旅遊等業務常符合乘法模型。

平穩性:ARIMA 的前提條件

ARIMA 等經典統計模型要求時間序列具備平穩性(Stationarity)——粗略地說,就是序列的統計特性(均值、方差)不隨時間改變,不存在系統性的趨勢或季節性。

大多數真實世界的時間序列是非平穩的(想想股票價格,整體是往上走的,均值不是固定的)。把非平穩序列轉換為平穩序列最常用的方法是差分(Differencing)

一階差分:計算相鄰兩個時間點的差值,ΔYₜ = Yₜ - Yₜ₋₁。如果原始序列有線性趨勢(價格持續上漲),一階差分後得到的「漲跌幅」序列通常是平穩的。如果一階差分後仍不平穩,可以做二階差分(對差分後的序列再做一次差分)。

判斷序列是否平穩的正式方法是統計檢定,常用的有:

  • ADF 檢定(Augmented Dickey-Fuller Test):如果 p 值 < 0.05,可以拒絕「有單位根(非平穩)」的零假設,認為序列是平穩的。
  • KPSS 檢定:零假設是「序列是平穩的」,和 ADF 相反,兩者搭配使用可以更確定地判斷。

ARIMA:統計學的經典預測框架

ARIMA(AutoRegressive Integrated Moving Average,自回歸整合移動平均)是時間序列預測中最著名的經典方法,由三個部分組成:

AR(AutoRegressive,自回歸):用過去 p 個時間點的值來預測當前值。直觀上,「今天的氣溫是昨天、前天氣溫的加權組合」就是一個 AR(2) 模型(使用過去 2 個時間點)。

I(Integrated,整合):指對序列做 d 次差分,讓序列變平穩。d=1 代表一階差分,d=0 代表原始序列已經是平穩的。

MA(Moving Average,移動平均):用過去 q 個時間點的預測誤差(而非觀測值本身)來修正預測。直觀上,如果模型昨天、前天都高估了,MA 部分會自動修正「今天也不要預測太高」。

ARIMA(p, d, q) 的參數選擇通常借助以下工具:

  • ACF(自相關函數圖):觀察各時間滯後(Lag)的自相關係數,幫助確定 MA 的 q 參數。
  • PACF(偏自相關函數圖):控制中間滯後項影響後的自相關係數,幫助確定 AR 的 p 參數。
  • auto_arimapmdarima 套件):自動搜索最優的 (p, d, q) 組合(根據 AIC/BIC 資訊準則)。

ARIMA 的變體 SARIMA(Seasonal ARIMA) 在 ARIMA 的基礎上增加了季節性成分參數 (P, D, Q, m),其中 m 是季節週期長度(如月度資料的季節週期是 m=12)。

Prophet:為業務人員設計的預測工具

雖然 ARIMA 在統計上嚴謹,但對於非統計背景的業務人員來說,選擇合適的 p、d、q 參數、診斷模型等步驟門檻很高。Facebook(現 Meta)的資料科學家於 2017 年開發並開源了 Prophet,專門針對業務場景中的時間序列預測。

Prophet 的核心設計哲學是「把業務知識直接融入模型」:

自動趨勢轉折點偵測(Changepoint Detection):Prophet 會自動找到趨勢發生突變的時間點(如某次重大產品更新、政策改變導致用戶增長曲線出現拐點),而不是假設趨勢永遠是線性的。

多重季節性(Multiple Seasonalities):可以同時處理日、週、月、年等多個週期的季節性,不需要像 SARIMA 一樣只能指定單一季節週期。

假期效應(Holiday Effects):允許直接指定業務相關的假期和特殊事件(雙 11、春節等),模型會自動估計這些事件對時間序列的影響,這對電商、旅遊等業務非常實用。

自動處理缺失值和異常值:Prophet 對資料中的缺失值和異常值有較強的魯棒性,不需要像 ARIMA 那樣對資料進行嚴格的前處理。

from prophet import Prophet
import pandas as pd

# Prophet 要求資料格式:ds(日期)和 y(目標值)
df = pd.DataFrame({'ds': dates, 'y': sales_values})

# 加入自定義假期
holidays = pd.DataFrame({
    'holiday': ['double_11', 'double_11'],
    'ds': ['2024-11-11', '2023-11-11'],
    'lower_window': -2,   # 節日前 2 天有效果
    'upper_window': 2,    # 節日後 2 天有效果
})

model = Prophet(holidays=holidays, yearly_seasonality=True, weekly_seasonality=True)
model.fit(df)

# 未來 90 天的預測
future = model.make_future_dataframe(periods=90)
forecast = model.predict(future)
model.plot(forecast)

時間序列評估:Walk-Forward Validation

時間序列的模型評估不能隨機分訓練集和測試集(因為隨機打亂會把未來的資料放進訓練集,導致資料洩漏)。正確的方法是 Walk-Forward Validation(前向滾動驗證)

  1. 用時間上最早的 N 個觀測值訓練模型,預測第 N+1 個觀測值。
  2. 加入第 N+1 個觀測值的真實值,重新訓練,預測第 N+2 個。
  3. 重複滾動,直到測試完所有保留的測試期資料。

常用的評估指標:

  • MAE(Mean Absolute Error,平均絕對誤差):容易解讀,對大誤差不特別敏感。
  • MAPE(Mean Absolute Percentage Error,平均絕對百分比誤差):以百分比表示,便於跨不同量級的序列比較;但當真實值接近 0 時會爆炸(除以 0 的問題)。
  • RMSE(Root Mean Square Error,均方根誤差):對大誤差更敏感,當你特別不希望出現大誤差時(如供應鏈庫存預測)適合使用。

應用場景

場景 預測目標 適用方法 特殊考量
零售銷售預測 每日/每週銷售量 Prophet(處理多重季節性和假期) 促銷活動需要作為外生變數加入模型
電力負載預測 未來 24 小時的用電量 SARIMA、LSTM 日週期和年週期都很強,天氣是重要外生變數
股價/匯率分析 明天的價格走勢 ARIMA 分析結構,但預測精度有限 金融時間序列接近隨機遊走,可預測性本就有限
伺服器流量預測 未來 1 小時的請求量 SARIMA(週期性明顯)、Prophet 用於自動擴縮容(Auto-scaling)決策
設備故障預警 未來 N 天內是否發生故障 時間序列異常偵測 + 分類模型 需要對感測器讀數的異常模式特別敏感
疫情預測 未來病例趨勢 SEIR 傳染病模型、Prophet 干預措施(封城)是重要的趨勢轉折點
財務預測 下季度的收入/支出 指數平滑、Prophet 業務判斷(計畫中的新產品上線)應作為外部知識輸入

常見誤區

誤區 1:「預測的資料越多、模型越複雜,預測就越準確」

這是時間序列預測中最普遍的誤解,實際情況恰恰相反。對於時間序列預測,增加訓練資料的效益是遞減的,而更複雜的模型往往在長期預測上表現更差

原因一:時間序列的預測不確定性隨預測期增長而急劇擴大。預測「明天的氣溫」和預測「一個月後的氣溫」的難度是完全不同量級的,因為每往前預測一步,誤差就會累積。即使是世界最先進的氣象模型,超過 10 天的預測也幾乎沒有實際參考價值。理解你的預測問題在「哪個時間跨度內是可預測的」比追求模型複雜度更重要。

原因二:使用太久遠的歷史資料可能反而降低準確性,因為 3-5 年前的模式和現在的業務環境可能已經完全不同(例如,疫情前的旅遊消費模式不能直接用來預測疫情後的趨勢)。實務中,許多業務預測問題使用最近 1-2 年的資料反而比使用 5 年資料得到更好的近期預測效果。

原因三:LSTM 等深度學習方法在看似「更強大」的宣傳下,在許多標準時間序列基準測試中(如 M4 Competition、M5 Competition)的表現並不比 ARIMA、指數平滑等傳統統計方法更好,甚至更差。M4 和 M5 競賽的結論都指出,傳統統計方法配合合理的特徵工程(加入外部資訊),仍然是大多數業務預測場景的可靠選擇。

誤區 2:「時間序列可以直接用普通的 K-Fold 交叉驗證評估」

這是一個會讓你的模型評估完全失去意義的操作失誤。在普通的機器學習中,K-Fold 交叉驗證隨機把資料分成 K 個等份,輪流把其中一份作為測試集,其餘作為訓練集。這個方法的前提是樣本之間相互獨立

但在時間序列中,樣本之間是時間相依的——2024 年 12 月的資料「知道」2024 年 11 月發生了什麼,因為兩者相鄰在時間上。如果你隨機打亂資料後做 K-Fold,訓練集中可能包含 2024 年 12 月的數據,而測試集是 2024 年 10 月的數據——這等於「用未來的資料預測過去」,是典型的資料洩漏,評估結果會顯示出不切實際的高準確率,部署到真實環境後效果遠不如評估結果。

正確做法是Walk-Forward Validation(也稱為時間序列 Cross-Validation):把最早的資料作為初始訓練集,每次往後滾動一個時間窗口,始終確保測試集的時間點在訓練集之後。這樣才能真正模擬「用過去的資料預測未來」的場景,得到有意義的泛化性能評估。

另一種簡化的做法是時間分割(Time-Based Split):把資料按時間切割為前 80% 作為訓練集、後 20% 作為測試集,一次性評估。雖然不如 Walk-Forward Validation 全面,但至少避免了資料洩漏。

誤區 3:「Prophet 是萬能的,任何時間序列預測直接用 Prophet 就好」

Prophet 是一個優秀的工具,特別適合非技術背景的業務分析師使用,但它並非萬能,有幾類場景下的表現反而不佳:

高頻短週期序列:Prophet 設計上最適合每日或更低頻率(每週、每月)的資料,並且通常需要至少幾個月到幾年的歷史資料才能有效地估計季節性。如果你要預測每分鐘或每小時的機器感測器讀數,SARIMA 或基於深度學習的方法(如 N-BEATS、Temporal Fusion Transformer)可能更合適。

多變數時間序列:Prophet 本質上是單變量的(只考慮一個時間序列的歷史值),雖然支援加入外生變數(Regressor),但外生變數的未來值也需要事先知道,這在許多場景下是不現實的。如果你的預測問題有多個相互關聯的時間序列(如多個商品的銷售量互相影響),VAR(向量自回歸)或 LightGBM/XGBoost 配合時間特徵可能更合適。

突然性結構斷裂(Structural Break):如果時間序列在某個時間點因為外部衝擊(如新冠疫情、重大政策改變)而完全改變了行為模式,Prophet 的趨勢轉折點機制雖然能偵測到漸進性的趨勢改變,但對「今天和昨天完全不同」的突然性斷裂的適應能力有限。這類情況需要人工介入:明確地告訴模型「以這個日期為界,前後是兩個不同的世界」,或者直接只使用斷裂後的資料訓練。


小練習

練習 1:識別時間序列的組成成分

以下是四個不同業務場景的描述,請為每個場景識別出最主要的時間序列成分(趨勢、季節性、週期性、隨機性),並解釋你的判斷理由:

  1. 一家台灣的傳統百貨公司在過去 10 年的月銷售額資料,整體呈現緩慢下滑,每年 12 月和農曆新年前後銷售明顯高於其他月份。
  2. 過去 2 年的台股加權指數日收盤價,夾雜著各種震盪,但大方向隨著全球景氣緩慢上升。
  3. 一個 SaaS 軟體平台過去 18 個月的每日活躍用戶(DAU),因為是企業用戶,周末的 DAU 明顯低於工作日,但整體 DAU 因產品持續成長而上升。
  4. 一家精品咖啡館的每日來客數,整體水準穩定,但有時因附近辦大型展覽而突然暴增。

練習 2:設計電商銷售預測方案

一家台灣電商平台希望預測「未來 30 天每天的訂單量」,用來優化倉儲備貨和物流排班。已知:

  • 歷史資料:過去 3 年的每日訂單量
  • 每年有雙 11(11/11)、雙 12(12/12)、母親節(5 月第二個周日)等重要促銷活動,活動日的訂單量是平日的 3-10 倍
  • 周末的訂單量平均比工作日高 25%
  • 近半年平台整體訂單量有上升趨勢,每月大約增長 2%

請設計一個使用 Prophet 的預測方案:(1)說明你會加入哪些設定讓 Prophet 更準確;(2)如何評估這個模型的預測準確性;(3)模型建好後,倉儲團隊應如何使用預測結果做決策?

查看答案 **練習 1:識別時間序列的組成成分** 1. **百貨公司月銷售額**: - 主要成分:**季節性**(每年 12 月和農曆新年前後的週期性高峰)+ **趨勢**(整體 10 年緩慢下滑) - 判斷:農曆新年和聖誕/元旦購物是台灣零售業年年重複的固定模式,這是典型的年度季節性。整體下滑趨勢反映了實體百貨業在電商衝擊下的長期結構性挑戰。這個序列適合用**乘法分解**(因為銷售量越高的月份,節日效應的絕對金額也越大)。 2. **台股加權指數日收盤價**: - 主要成分:**趨勢**(隨景氣緩慢上升)+ **隨機性**(每日震盪)+ **週期性**(受宏觀經濟週期影響,但週期不固定) - 判斷:股價有很強的隨機遊走(Random Walk)特性,每日的短期波動主要是隨機的,難以預測。長期看,全球景氣擴張期台股整體上升,這是不固定週期的宏觀週期性,而非固定週期的季節性。預測股價的短期走勢(明天漲跌)準確率很難超過 55-60%,即使是複雜的深度學習模型也難以顯著超越基準。 3. **SaaS 平台 DAU**: - 主要成分:**季節性**(周末低、工作日高的週週期)+ **趨勢**(整體上升) - 判斷:企業 SaaS 的使用模式強烈受工作時間影響,周末的 DAU 可能只有工作日的 40-60%,這是非常規律的 7 日週期季節性。同時,DAU 隨產品成長在整體上升。適合使用 Prophet 的每週季節性設定,或 SARIMA(p,d,q)(P,D,Q,7) 來捕捉這個模式。 4. **精品咖啡館日來客數**: - 主要成分:**隨機性**(突發大型展覽等不可預期事件)+ 穩定的低幅度**季節性**(如假日稍多) - 判斷:整體水準穩定、無明顯趨勢,但有因外部突發事件(展覽)導致的不規律爆發。這類事件是不可預測的(除非你事前知道展覽日期),是時間序列中的「異常值」或「外生衝擊」。如果展覽日期是已知的,可以把它們作為虛擬變數加入模型;否則這些高峰就是純粹的隨機噪音。 --- **練習 2:電商銷售預測方案** **(1)Prophet 設定建議** **加入促銷假期(Holiday Effects)**:這是最重要的設定。雙 11、雙 12、母親節等促銷活動日的訂單量是平日的 3-10 倍,如果不告訴模型這些日期,Prophet 會把它們當成異常值處理,導致節日前後的預測嚴重失準。 ```python promotions = pd.DataFrame({ 'holiday': ['double_11', 'double_12', 'mothers_day', ...], 'ds': ['2024-11-11', '2024-12-12', '2024-05-12', ...], 'lower_window': -3, # 節日前 3 天預熱期也有效果 'upper_window': 1, # 節日後 1 天補單效果 }) model = Prophet(holidays=promotions, yearly_seasonality=True, weekly_seasonality=True) ``` **考慮乘法季節性**:如果節日效應的絕對訂單數量隨整體趨勢增長而增大(今年雙 11 比去年多賣更多,比例接近),應該設定 `seasonality_mode='multiplicative'`,而非預設的加法。 **加入目標變數的對數轉換**:訂單量通常有重尾分佈(大部分時候是正常水準,少數節日暴增),對 `y` 做對數轉換可以讓模型更穩定地處理這種不對稱性:`df['y'] = np.log1p(df['y'])`,預測完再做反轉換 `np.expm1(forecast['yhat'])`。 **(2)模型評估方式** 使用 **Walk-Forward Validation(時間序列交叉驗證)**,Prophet 內建了這個功能: ```python from prophet.diagnostics import cross_validation, performance_metrics df_cv = cross_validation( model, initial='730 days', # 用前 2 年訓練 period='30 days', # 每 30 天往前滾動一次 horizon='30 days' # 評估未來 30 天的預測準確性 ) metrics = performance_metrics(df_cv) ``` 主要評估指標: - **MAPE**:以百分比表示的誤差,直觀易懂。例如,MAPE=15% 代表預測平均偏差約 15%。 - **需要特別關注節日前後的誤差**:分別計算促銷日和普通日的 MAPE,確認模型對高峰期的預測是否準確。 **(3)倉儲團隊的決策框架** Prophet 的輸出包含 `yhat`(點預測)、`yhat_lower`(預測下界)和 `yhat_upper`(預測上界,對應 80% 信賴區間)。倉儲決策應考慮: **分層使用預測區間**:對於倉儲備貨,使用 `yhat_upper`(預測上界)而非點預測——因為備貨不足(缺貨)的代價(失去銷售機會、客戶不滿)通常遠大於備貨過多(占用倉儲成本)的代價。一個務實的規則:備貨量 = `yhat_upper * 安全係數`(如 1.1,視商品類別的缺貨敏感度調整)。 **節日和平日分開計劃**:節日的預測不確定性遠高於平日(預測區間更寬),倉儲應提前 2-3 周就完成節日備貨決策,避免臨時缺貨。 **建立預測 vs 實際的滾動追蹤**:每天把前一天的實際訂單量和 30 天前的預測值進行對比,追蹤誤差趨勢。如果連續 2-3 週的實際值都系統性地高於預測值,可能預示著業務加速成長,需要觸發模型重訓。

關鍵字自我檢核

✅ 時間序列 ✅ Time Series ✅ 趨勢 ✅ Trend ✅ 季節性 ✅ Seasonality ✅ 自相關 ✅ Autocorrelation ✅ ARIMA ✅ AutoRegressive Integrated Moving Average ✅ Prophet ✅ Facebook Prophet ✅ 移動平均 ✅ Moving Average ✅ 指數平滑 ✅ Exponential Smoothing ✅ 時間序列分解 ✅ Decomposition ✅ 平穩性 ✅ Stationarity ✅ 差分 ✅ Differencing ✅ 週期性 ✅ Cyclicality ✅ LSTM ✅ 長短期記憶網路 ✅ 交叉驗證 ✅ Time Series Cross-Validation