LESSON

Facebook Prophet

「ARIMAは強力だが、ビジネスの実務で使うにはやや敷居が高い。Prophetはその課題を解決するために作られた。」

田中VPoEがProphetの論文を開く。

「トレンドの変化点を自動検出し、祝日効果をそのまま組み込める。しかもパラメータチューニングがほぼ不要。Store Salesの祝日データを活かすなら、Prophetは有力な選択肢だ。」

Prophetとは

Facebook(Meta)が開発した時系列予測ライブラリ。加法的モデルで以下を組み合わせる。

y(t) = g(t) + s(t) + h(t) + ε(t)

g(t): トレンド成分(区分線形 or ロジスティック成長)
s(t): 季節成分(フーリエ級数で表現)
h(t): 祝日・イベント効果
ε(t): 誤差項

Prophetの強み

強み説明
トレンド変化点自動で成長率の変化を検出
祝日効果祝日リストを渡すだけで効果を推定
欠損値対応欠損があってもそのまま学習可能
解釈性各成分の寄与を可視化できる
使いやすさパラメータチューニングがほぼ不要

基本的な使い方

from prophet import Prophet
import pandas as pd

# データの準備(Prophet形式: ds, y)
grocery = train[train['family'] == 'GROCERY I'].groupby('date')['sales'].sum()
prophet_df = grocery.reset_index()
prophet_df.columns = ['ds', 'y']

# モデルの構築
model = Prophet(
    yearly_seasonality=True,
    weekly_seasonality=True,
    daily_seasonality=False,
    changepoint_prior_scale=0.05,   # トレンド変化の柔軟性
    seasonality_prior_scale=10,     # 季節性の柔軟性
)

# 学習
model.fit(prophet_df[prophet_df['ds'] < '2017-08-01'])

# 未来の日付を生成して予測
future = model.make_future_dataframe(periods=15)
forecast = model.predict(future)

# 予測結果の確認
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(15))

祝日効果の組み込み

Store Salesの複雑な祝日データをProphetに組み込む。

# 祝日データの変換
holidays_raw = pd.read_csv('holidays_events.csv', parse_dates=['date'])

# 国定祝日のみ抽出してProphet形式に変換
national_holidays = holidays_raw[
    (holidays_raw['locale'] == 'National') &
    (holidays_raw['type'].isin(['Holiday', 'Additional']))
].copy()

prophet_holidays = pd.DataFrame({
    'holiday': national_holidays['description'],
    'ds': national_holidays['date'],
    'lower_window': -1,   # 祝日の1日前から効果開始
    'upper_window': 0,    # 祝日当日まで
})

# 地震をイベントとして追加
earthquake = pd.DataFrame({
    'holiday': ['Earthquake'],
    'ds': [pd.Timestamp('2016-04-16')],
    'lower_window': [0],
    'upper_window': [14],  # 2週間の影響
})
prophet_holidays = pd.concat([prophet_holidays, earthquake])

# 祝日付きモデル
model_with_holidays = Prophet(
    yearly_seasonality=True,
    weekly_seasonality=True,
    holidays=prophet_holidays,
    changepoint_prior_scale=0.05,
)
model_with_holidays.fit(prophet_df[prophet_df['ds'] < '2017-08-01'])

トレンド変化点の分析

# トレンド変化点の可視化
from prophet.plot import add_changepoints_to_plot

fig = model.plot(forecast)
add_changepoints_to_plot(fig.gca(), model, forecast)
plt.title('トレンド変化点の検出')
plt.show()

# 検出された変化点の確認
print("検出された変化点:")
for cp in model.changepoints:
    print(f"  {cp.strftime('%Y-%m-%d')}")

# changepoint_prior_scaleの調整
# 大きい値: 変化点を多く検出(オーバーフィットのリスク)
# 小さい値: 変化点を少なく検出(アンダーフィットのリスク)

成分の可視化

# 各成分のプロット
fig = model_with_holidays.plot_components(forecast)
plt.tight_layout()
plt.show()

# 表示される成分:
# 1. trend: 長期的な成長・衰退
# 2. weekly: 曜日別の効果(日曜高い、等)
# 3. yearly: 月別の効果(12月高い、等)
# 4. holidays: 各祝日の効果

パラメータチューニング

from prophet.diagnostics import cross_validation, performance_metrics

# クロスバリデーション
cv_results = cross_validation(
    model_with_holidays,
    initial='730 days',   # 最初の学習期間
    period='30 days',     # 毎30日ごとに評価
    horizon='15 days',    # 15日先を予測
)

# 性能指標の算出
metrics = performance_metrics(cv_results)
print(metrics[['horizon', 'mae', 'rmse', 'mape']].tail())

# パラメータグリッドサーチ
param_grid = {
    'changepoint_prior_scale': [0.01, 0.05, 0.1, 0.5],
    'seasonality_prior_scale': [1, 5, 10, 15],
}

best_mape = float('inf')
best_params = {}

for cps in param_grid['changepoint_prior_scale']:
    for sps in param_grid['seasonality_prior_scale']:
        m = Prophet(
            changepoint_prior_scale=cps,
            seasonality_prior_scale=sps,
            holidays=prophet_holidays,
        )
        m.fit(prophet_df[prophet_df['ds'] < '2017-08-01'])
        cv = cross_validation(m, initial='730 days', period='60 days', horizon='15 days')
        metrics = performance_metrics(cv)
        avg_mape = metrics['mape'].mean()
        if avg_mape < best_mape:
            best_mape = avg_mape
            best_params = {'cps': cps, 'sps': sps}

print(f"最適パラメータ: {best_params}")
print(f"最良MAPE: {best_mape:.4f}")

Prophetの限界

限界説明
外部回帰変数add_regressorで追加可能だが、未来の値が必要
多変量単一系列のみ。系列間の関係を考慮しない
短期予測日次の細かいパターンは苦手
大量系列1,782系列を個別に学習するのは時間がかかる

まとめ

項目ポイント
Prophetトレンド + 季節性 + 祝日の加法モデル
祝日効果lower/upper_windowで影響範囲を指定
変化点changepoint_prior_scaleで柔軟性を制御
評価cross_validationで信頼性の高い評価

チェックリスト

  • Prophetの3成分(トレンド、季節性、祝日)を説明できる
  • 祝日データをProphet形式に変換できる
  • トレンド変化点の可視化と解釈ができる
  • クロスバリデーションで性能評価ができる

次のステップへ

Prophetで季節性と祝日効果をモデル化できた。次はLightGBMを使い、特徴量エンジニアリングで予測精度をさらに向上させよう。

推定読了時間: 30分