時間序列預測:用 Prophet 預測未來

到目前為止,我們學的都是「靜態預測」——用當下的特徵來預測當下的結果。但現實中還有一類非常重要的預測問題:時間序列預測 (Time Series Forecasting)

  • 下個月的營業額是多少?
  • 明年這個時候的網站流量會是多少?
  • 未來 7 天的氣溫變化?

這些問題的共同點是:資料有時間順序,而且未來的值依賴過去的值。

時間序列的核心概念

時間序列資料有三個重要的組成要素:

1. 趨勢 (Trend)

長期來看,資料是上升、下降還是持平?

  • 一個成長型公司的營收:長期趨勢是 上升
  • 一台二手車的價值:長期趨勢是 下降
  • 每日平均氣溫:長期趨勢是 持平(但會有季節波動)

2. 季節性 (Seasonality)

資料是否呈現固定的週期性波動?

  • 年週期:聖誕節購物季、暑假旅遊潮
  • 週週期:週末購物人次比平日多
  • 日週期:辦公室附近的餐飲店,中午業績最好

3. 殘差 (Residual / Noise)

去除趨勢與季節性後剩下的隨機波動——通常是無法預測的雜訊。

Prophet:Facebook 開源的時間序列神器

Prophet 是由 Facebook 核心資料科學團隊開發並開源的時間序列預測工具。它的設計哲學是:讓非專家也能做出專業等級的預測。

Prophet 的優勢

  • 自動處理缺失值:不需要填補空值
  • 自動偵測趨勢變化:能夠捕捉到趨勢的轉折點
  • 強大的季節性建模:支援年、週、日等多層次季節性
  • 自動處理假日效應:可以加入特定日期(如雙十一、聖誕節)的影響
  • 不確定性區間:預測同時給出信心區間
  • 對異常值強健:不會因為少數異常值而崩潰

安裝 Prophet

pip install prophet

實戰:預測未來 30 天的網站流量

準備資料

Prophet 要求資料必須是特定的格式:

  • ds (datestamp):日期欄位
  • y:要預測的數值
import pandas as pd
import numpy as np
from prophet import Prophet
import matplotlib.pyplot as plt

# 產生模擬的每日網站流量資料(365 天)
np.random.seed(42)
dates = pd.date_range(start='2025-01-01', periods=365, freq='D')

# 模擬流量:基線 + 成長趨勢 + 季節性 + 週末效應 + 雜訊
trend = np.linspace(1000, 2000, 365)  # 長期成長
seasonal = 200 * np.sin(2 * np.pi * np.arange(365) / 365)  # 年週期
weekly = np.where(np.arange(365) % 7 >= 5, 300, 0)  # 週末流量較高
noise = np.random.normal(0, 100, 365)

df = pd.DataFrame({
    'ds': dates,
    'y': trend + seasonal + weekly + noise
})

df.head()

訓練 Prophet 模型

# 建立模型
model = Prophet(
    yearly_seasonality=True,
    weekly_seasonality=True,
    daily_seasonality=False,
    changepoint_prior_scale=0.05,  # 趨勢變化靈敏度
    seasonality_prior_scale=10.0,   # 季節性強度
    interval_width=0.95            # 95% 信心區間
)

# 加入假日效應(台灣的春節、雙十一等)
holidays = pd.DataFrame({
    'holiday': 'chinese_new_year',
    'ds': pd.to_datetime(['2025-01-29', '2025-01-30', '2025-01-31']),
    'lower_window': -3,
    'upper_window': 3,
})
model.add_country_holidays(country_name='TW')

# 訓練模型
model.fit(df)

預測未來

# 建立未來 30 天的日期框架
future = model.make_future_dataframe(periods=30)

# 預測
forecast = model.predict(future)

# 顯示預測結果
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(10))
  • yhat:預測值
  • yhat_lower:預測下限(95% 信心區間)
  • yhat_upper:預測上限

視覺化預測結果

# Prophet 內建視覺化
fig1 = model.plot(forecast)
plt.title('網站流量預測(未來 30 天)')
plt.xlabel('日期')
plt.ylabel('每日流量 (人次)')
plt.show()

# 趨勢與季節性分解
fig2 = model.plot_components(forecast)
plt.show()

plot_components() 會畫出三個子圖:

  1. 趨勢 (Trend):長期成長或下降的趨勢
  2. 年週期 (Yearly Seasonality):一年中的旺季與淡季
  3. 週週期 (Weekly Seasonality):一週中各天的流量差異

評估預測準確度

要評估時間序列預測的準確度,不能使用傳統的 train/test split(因為時間序列不能亂序分割)。正確的做法是使用時間序列交叉驗證

from prophet.diagnostics import cross_validation, performance_metrics

# 時間序列交叉驗證
df_cv = cross_validation(
    model,
    initial='730 days',   # 初始訓練長度
    period='180 days',    # 每次預測的間隔
    horizon='30 days',    # 預測長度
)

# 計算評估指標
df_p = performance_metrics(df_cv)
print(df_p[['horizon', 'mse', 'rmse', 'mae', 'mape']].head())

mape (Mean Absolute Percentage Error) 是最直觀的指標:

  • MAPE = 10% 代表平均預測誤差為 10%
  • MAPE < 20% 通常是可接受的

將 Prophet 整合到 ML API

from fastapi import FastAPI
from pydantic import BaseModel
import joblib
import pandas as pd
from prophet import Prophet

app = FastAPI(title="流量預測 API")

# 載入已訓練的 Prophet 模型
model = joblib.load('traffic_forecast_model.pkl')

class ForecastRequest(BaseModel):
    periods: int = 30  # 預測天數

class ForecastPoint(BaseModel):
    date: str
    predicted: float
    lower_bound: float
    upper_bound: float

@app.post("/forecast", response_model=list[ForecastPoint])
def predict_forecast(req: ForecastRequest):
    future = model.make_future_dataframe(periods=req.periods)
    forecast = model.predict(future)
    
    # 只回傳未來的預測(不含歷史資料的擬合值)
    future_forecast = forecast.tail(req.periods)
    
    results = []
    for _, row in future_forecast.iterrows():
        results.append(ForecastPoint(
            date=str(row['ds'].date()),
            predicted=round(row['yhat'], 2),
            lower_bound=round(row['yhat_lower'], 2),
            upper_bound=round(row['yhat_upper'], 2)
        ))
    
    return results

使用 Vibe Coding 進行時間序列預測

🔥 【時間序列預測詠唱範例】 「我有一個 daily_sales.csv,包含 date 與 sales 兩個欄位,請幫我: 1. 使用 Prophet 訓練時間序列模型,設定年週期與週週期。 2. 預測未來 90 天的銷售額。 3. 畫出預測圖與趨勢/季節性分解圖。 4. 輸出未來 90 天的預測結果表格(含信心區間)。 5. 使用時間序列交叉驗證計算 MAPE。 6. 判斷下個月的銷售高峰大概在哪幾天。」

本日總結

在本章中,你學到了:

  1. 時間序列基礎:趨勢、季節性、殘差
  2. Prophet:Facebook 開源的時間序列預測神器
  3. 預測實戰:從歷史資料預測未來 30 天的網站流量
  4. 趨勢分解:了解資料的長期趨勢與季節性模式
  5. 評估方法:時間序列交叉驗證與 MAPE
  6. API 整合:將 Prophet 預測模型包裝成 API

恭喜你完成了整個 機器學習基礎 課程!你現在已經具備了從資料清洗、模型訓練、評估優化到部署整合的完整機器學習能力。

這些技能無論是用來接案(客戶流失預測系統報價 15-20 萬)、優化自己的產品(流量預測與庫存管理)、或是求職資料科學相關職位,都能讓你擁有巨大的競爭優勢!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!