Prophet 是 Meta (Facebook) 于 2017 年开源的时序预测库,因其简单、稳定且对缺失值和异常值鲁棒,成为工业界的事实标准。核心概念包括自动处理多重季节性(年、周、日)和节假日效应,以及无需手动选择参数。读者将学会使用 Prophet 进行时序预测,包括如何处理缺失值和异常值、添加自定义节假日(如春节和双11)以提升预测精度,以及如何调参以优化模型性能。完成学习后,读者能够使用 Prophet 进行高效准确的时序预测,并了解其与 ARIMA、NeuralProphet、DeepAR 和 TFT 等模型的优缺点。
Prophet 实战
Prophet 是 Meta (Facebook) 2017 年开源的时序预测库,工业界的事实标准。比 ARIMA 简单,比深度学习稳定,对缺失值和异常值鲁棒。
为什么选 Prophet
对比 ARIMA:
- ✅ 不用手动选 p, d, q
- ✅ 自动处理缺失值、异常值
- ✅ 多重季节性 (年 + 周 + 日) 一起学
- ✅ 加节假日效应 (春节、双11)
- ❌ 不适合 < 1 年的数据 (学不到季节性)
- ❌ 不能外推"未见过的趋势"
5 行跑通 Prophet
import pandas as pd
from prophet import Prophet
# 1. 准备数据 (Prophet 要求列名是 ds, y)
df = pd.read_csv("sales.csv")
df = df.rename(columns={"date": "ds", "sales": "y"})
# 2. 训练
model = Prophet()
model.fit(df)
# 3. 预测未来 90 天
future = model.make_future_dataframe(periods=90, freq="D")
forecast = model.predict(future)
# 4. 看结果
print(forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail(10))
yhat 是预测值,yhat_lower / yhat_upper 是 95% 置信区间。
可视化
# 1. 预测 + 置信区间
fig1 = model.plot(forecast)
plt.title("Prophet 预测结果")
plt.show()
# 2. 分解: 趋势 / 季节性 / 节假日
fig2 = model.plot_components(forecast)
plot_components 会画出 4 个子图:
- Trend: 长期趋势 (线性 or 逻辑回归)
- Yearly: 年季节性 (哪个月份最高)
- Weekly: 周季节性 (周几最高)
- Holidays (如果有): 节假日效应
加入节假日:中文场景
中国节假日 (春节、双11) 对销量影响巨大。Prophet 内置了美国 + 部分国际节日,但中国节日需要自己加:
# 自定义节假日
holidays = pd.DataFrame({
"holiday": "chinese_new_year",
"ds": pd.to_datetime([
"2022-02-01", "2023-01-22", "2024-02-10", "2025-01-29",
"2026-02-17" # 预测范围内
]),
"lower_window": -7, # 前后 7 天都受春节影响
"upper_window": 7,
})
# 双11
double11 = pd.DataFrame({
"holiday": "double_11",
"ds": pd.to_datetime([f"{y}-11-11" for y in range(2022, 2027)]),
"lower_window": 0,
"upper_window": 3, # 前后 3 天
})
# 国庆
national_day = pd.DataFrame({
"holiday": "national_day",
"ds": pd.to_datetime([f"{y}-10-01" for y in range(2022, 2027)]),
"lower_window": 0,
"upper_window": 7,
})
all_holidays = pd.concat([holidays, double11, national_day])
model = Prophet(holidays=all_holidays)
model.fit(df)
处理多重季节性
默认 Prophet 学年 + 周季节性。如果数据有日内小时模式:
# 关闭默认 + 加自定义季节性
model = Prophet(weekly_seasonality=False, yearly_seasonality=True)
model.add_seasonality(name="daily", period=1, fourier_order=8)
model.add_seasonality(name="hourly", period=24, fourier_order=15)
调参:4 个最常用参数
model = Prophet(
growth="linear", # "linear" / "logistic" (有上限)
changepoints=25, # 自动检测趋势变化的点数
changepoint_prior_scale=0.05, # 趋势灵活度, 越大越"跟"数据
seasonality_prior_scale=10, # 季节性强弱, 越大越拟合
holidays_prior_scale=10,
seasonality_mode="additive" # "additive" / "multiplicative"
)
调参经验:
changepoint_prior_scale是关键, 太大过拟合, 太小欠拟合- 数据有明显上限 (用户量、库存) 用
growth="logistic"+cap - 季节性随趋势放大用
multiplicative
调上限的 logistic 增长
df["cap"] = 10000 # 上限
model = Prophet(growth="logistic")
model.fit(df)
future = model.make_future_dataframe(periods=90)
future["cap"] = 10000 # 预测时也要设
forecast = model.predict(future)
评估
from sklearn.metrics import mean_absolute_error, mean_absolute_percentage_error
# 留出最后 30 天评估
train = df[:-30]
test = df[-30:]
model = Prophet()
model.fit(train)
future = model.make_future_dataframe(periods=30)
forecast = model.predict(future)
y_pred = forecast["yhat"].tail(30).values
mae = mean_absolute_error(test["y"], y_pred)
mape = mean_absolute_percentage_error(test["y"], y_pred)
print(f"MAE: {mae:.2f}, MAPE: {mape:.2%}")
典型表现: 日销量数据 MAPE 在 5-15% 之间。
模型保存 + 加载
import pickle
# 保存
with open("prophet_model.pkl", "wb") as f:
pickle.dump(model, f)
# 加载
with open("prophet_model.pkl", "rb") as f:
loaded = pickle.load(f)
# 继续预测
future = loaded.make_future_dataframe(periods=30)
forecast = loaded.predict(future)
异常值处理
Prophet 对异常值默认鲁棒,但极端异常还是会影响。如果某天销量突然 10 倍:
# 方法 1: 直接删除异常点
df_clean = df[(df["y"] > df["y"].quantile(0.01)) & (df["y"] < df["y"].quantile(0.99))]
# 方法 2: 设 floor
df["floor"] = 0
model = Prophet(growth="logistic")
model.fit(df) # 需要 cap + floor 都设
三个替代方案
- NeuralProphet (2020): Prophet 的深度学习版, 加了滞后变量、自回归
- DeepAR (Amazon): 概率预测, 给出预测分布
- TFT (Temporal Fusion Transformer): Google 的注意力时序模型, 长序列效果好
小结
- Prophet: 工业界时序预测的事实标准, 简单稳定
- 公式: y(t) = trend + seasonality + holidays + error
- 必须列名
ds, y, 用make_future_dataframe生成预测时间 - 节假日是核心: 自定义春节/双11 能显著提升 MAPE
- 调参重点:
changepoint_prior_scale(灵活度) +seasonality_mode(加法/乘法)
练习思考
- 同一份销售数据, ARIMA 和 Prophet 的 MAPE 差距多少?哪种更好?
- 加了"双11"自定义节假日后, 11 月 11 号附近的预测值变化多大?
- 用
growth="logistic"拟合用户量数据,cap怎么设才合理?
章末小测验
检验你对《Prophet 实战》的掌握程度。
1
Prophet 公式 y(t) = ?
2
Prophet 处理中国春节影响最常用的方法是?
讨论区(0)
加载评论中...