当前位置: 首页 > news >正文

【AI指导】Python实现prophet模型的业绩预测

以下是一个使用Facebook Prophet模型进行业绩预测的Python代码示例。Prophet适用于具有强季节性特征的时间序列数据预测,如销售业绩、用户增长等场景。

安装依赖

确保已安装prophetpandas库。未安装可通过以下命令安装:

(win+R键打开cmd)

pip install prophet pandas matplotlib
pip install plotly

完整代码

###——————————————————第一步,把数据整理成“两列”import pandas as pd
from prophet import Prophetdf = pd.read_excel('daily_sales.xlsx', parse_dates=['date'])# 只要两列核心,格式必须包含两列且列名为ds和y
df = df[['date', 'revenue']].rename(columns={'date': 'ds', 'revenue': 'y'})# 缺失值随手填,按日期排序后线性插值,然后默认打印前5行
df = df.sort_values('ds').interpolate()
print(df.head())###——————————————————第二步,把节假日 & 促销活动喂给模型# 1) 节假日表(可一次性写死,也可从原始 is_holiday=1 抽)
'''
各字段含义(官方文档关键词)
holiday:字符串,给这组节假日起个名字,同一名字可多年复用。
ds:日期列,必须是 pandas datetime64[ns] 类型。
lower_window:向前影响几天(负值表示“节前”)。
upper_window:向后影响几天(正值表示“节后”)。
** Prophet 会把 [ds + lower_window, ds + upper_window] 这段区间全部打上节假日指标 **。
'''
holiday = pd.read_excel('holidays.xlsx',parse_dates=['ds'])   # 确保 ds 是 datetime,这里是历史+未来的节假日表# assign 写法(一步完成,链式)
holiday = holiday.assign(lower_window=0, upper_window=0)   # 当天+节后0天
'''
assign 是 pandas 的“链式”加列语法糖,作用等价于 df['新列'] = 值,但返回一个新 DataFrame,原表不动,适合继续链式写下去。# 传统写法
holiday['lower_window'] = 0
holiday['upper_window'] = 1
'''# 2) 促销表(抽 is_promo=1 的日期)
promo = pd.read_excel('daily_sales.xlsx', parse_dates=['date'])
promo = promo[promo['is_promo'] == 1][['date']] 
'''
第一个中括号 按条件过滤行
第二个中括号 挑选列;写成 [['date']](列表套字符串)而不是 'date',是为了保持 DataFrame 结构——后者只会返回 Series
'''
promo['holiday'] = 'promo'
promo['lower_window'] = 0
promo['upper_window'] = 0
promo.rename(columns={'date': 'ds'}, inplace=True) 
'''
inplace=True 不返回新对象,直接改原 df
也就是把 promo 自己的 'date' 列当场改成 'ds',不再生成新表。
'''# 合并
holidays_all = pd.concat([holiday, promo])
'''
把两个 DataFrame 纵向拼在一起,形成一张总节假日表,让 Prophet 一次性识别「国家法定假 + 促销日」两种事件。
两表列名一定要对齐;若 promo 忘了加 lower/upper_window,先 assign 再 concat。
同一 ds 日期如果两边都出现,Prophet 会保留两行,节日效应会叠加(一般没问题)。
'''###——————————————————第三步,30 秒建立 Prophet 模型
model = Prophet(yearly_seasonality=True,weekly_seasonality=True,daily_seasonality=False,   # 日业绩不用日内季节holidays=holidays_all,seasonality_mode='multiplicative',  # 业绩随趋势放大changepoint_prior_scale=0.05,       # 拐点灵活度holidays_prior_scale=5)             # 节假日效应更强,新版本为holidays# 加入自定义促销回归量(可选)
df['promo_flag'] = pd.read_excel('daily_sales.xlsx')['is_promo']
model.add_regressor('promo_flag', mode='multiplicative')  # 默认 additive
'''
节假日表只能把「已知促销日」标成 1、未知日标 0,效应大小固定。
实际业务里促销强度、折扣力度、渠道差异很大,想让它「自己学系数」,就把促销列当外生回归器扔进去。
mode='additive' → 效应是 加减(默认)
mode='multiplicative' → 效应是 乘系数(销量随基数放大时选它)
'''
#拟合
model.fit(df)###——————————————————第四步,生成未来 90 天并预测
# 1. 未来时间框架
future = model.make_future_dataframe(periods=90,freq='D')
'''
把训练时用的日期列 ds 往后顺延 90 天,返回一张只有 ds 列的新 DataFrame,叫 future
freq='D' → 频率为日粒度(1 天 1 行)
如果你的训练集是按 周/月/小时,把 freq 对应改成 'W' / 'M' / 'H' 即可
此外,如果用了外生回归器(add_regressor('promo'))或节假日表,你要自己把对应列补进去
'''# 2. 把未来 promo 填进去(没有就补 0)
# 如果已知某几天要做促销,直接改 1:
# future.loc[future['ds']=='2024-06-18', 'promo'] = 1
promo_future = pd.read_excel('promo_future.xlsx', parse_dates=['ds'])
future['promo_flag'] = 0                               # 先全部填 0
future = future.merge(promo_future.assign(promo_flag=1),on='ds', how='left', suffixes=('', '_new'))
future['promo_flag'] = future['promo_flag_new'].fillna(future['promo_flag']).astype(int)
future = future.drop(columns='promo_flag_new')model.interval_width = 0.8   # 默认是 0.8(80%)forecast = model.predict(future)
'''
interval_width 就是 置信区间的“宽度”(Confidence Level),告诉 Prophet:
你预测时给我多大的概率区间?
默认 0.8 → 80% 置信区间(yhat_lower 到 yhat_upper 覆盖真实值 80% 的可能性)。
interval_width 越大,上下界越宽,模型越保守;越小,区间越窄,风险越高。
''''''
打印后预测结果的最后10天
print(forecast[['ds', 'yhat', 'promo']].tail(10))
'''
#文件保存结果,\表示“这行还没完,下一行是同一句话”。
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper', 'promo']] \.to_excel('完整预测结果.xlsx', index=False)###——————————————————第五步,画图验收
import matplotlib.pyplot as plt
from matplotlib import rcParams
# ① 让 matplotlib 用系统里自带的 SimHei(黑体)
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['SimHei']   # Windows 黑体
rcParams['axes.unicode_minus'] = False     # 解决负号显示成方块的问题model.plot(forecast, figsize=(12,6))
plt.title('90 天业绩预测')
plt.show()# 再看成分:趋势、周季节、年季节、节假日
model.plot_components(forecast)
plt.show()

部分代码解释

1.数据准备

Prophet 只认两列:

  • ds:日期(yyyy-mm-dd)

  • y:当日业绩(数值)

假设你的原始文件叫 daily_sales.xlsx,长这样:

daterevenueis_promois_holiday
2021-01-011200001
2021-01-02850000

2.模型参数

以下三个参数决定了 Prophet 怎样“拆”你的时间序列——季节效应是加还是乘、拐点可以多灵活、节假日/促销的权重放多大。下面逐个拆给你看:


  1. seasonality_mode='multiplicative'
    官方默认 'additive'(加法)。

    • 加法y = trend + seasonality + holiday

    • 乘法y = trend × (1 + seasonality) × (1 + holiday)

    什么时候用乘法?
    业务明显“旺季更旺、淡季更淡”——销售额绝对值随趋势增长而放大,比如 10 万/月基数时春节 +50% 得 15 万;100 万/月基数时同样 +50% 得 150 万。
    若用加法,春节永远固定 +5 万,就低估高峰、高估低谷
    ➜ 零售、电商、旅游、广告收入等量级随趋势上涨的场景,优先 multiplicative


  1. changepoint_prior_scale=0.05
    控制 趋势拐点(changepoint)的灵活度

    • 值越大 → 允许拐得越频繁,曲线贴近训练点,容易过拟合

    • 值越小 → 拐点少,趋势线更平滑,可能欠拟合

    默认 0.05。
    经验:

    • 业务历史突变少(传统线下零售)可再降到 0.01-0.03。

    • 互联网产品频繁活动、政策改来改去可提高到 0.1-0.3。
      调参时看 MAPE / MAE 是否改善,同时可视化 m.changepoints 确认拐点数量合理。


  1. holiday_prior_scale=10
    控制 节假日/促销系数估计的“方差”大小
    Prophet 对节假日效应使用 正态先验

    β_holiday ~ N(0, σ²) ,其中 σ = holiday_prior_scale
    • 值越大 → σ 越大 → 允许节假日峰值更高或更低(系数绝对值可以很大)。

    • 值越小 → 效应被压缩到接近 0,节日几乎不波动。

    默认 1。
    电商/零售大促常常当天销量翻几倍,就把 holiday_prior_scale 调到 5-20,让模型敢把系数放大;否则预测会被“拉扁”,显著低估大促峰值。
    反之,若节假日只比平日 +5%,用默认值甚至 0.1 即可。


调参口诀

场景seasonality_modechangepoint_prior_scaleholiday_prior_scale
稳定线下店additive0.01-0.050.5-2
日常电商multiplicative0.05-0.15-10
高频活动/爆品multiplicative0.1-0.310-20

步骤:先定 mode → 再 grid-search / 手动调两个 scale,看验证集 MAPE 最小即可。

3.merge解释:

future = future.merge(promo_future.assign(promo=1), on='ds', how='left', suffixes=('', '_new'))

merge 想成 “贴便利贴” 的动作:

  • on='ds'按日期对齐(两张表都有的同一天,才贴在一起)。

  • how='left'以左边表(future 日历)为准,右边没有的日期就空着(NaN)。

  • suffixes=('', '_new') → 如果两边出现同名列,左边保持原名,右边加 _new 后缀,避免重名冲突。

一张图秒懂:

future(左)promo_future.assign(promo=1)(右)贴完结果(how='left')
2025-11-102025-11-11 promo=12025-11-10 promo=0 promo_new=NaN
2025-11-112025-11-11 promo=0 promo_new=1.0 ← 贴到
2025-11-122025-11-12 promo=0 promo_new=NaN
  • 左边日历 一行没少(left 保证完整性)

  • 只有日期匹配的那一行被贴上了 promo=1,其余日期 promo_new 是 NaN,后面用 fillna 再补 0 即可

4.fillna解释:

future['promo'] = future['promo_new'].fillna(future['promo']).astype(int)

这行代码只有 3 个动作,拆开看就懂了:

  1. future['promo_new'].fillna(future['promo'])

    • promo_new 里的 NaN(没贴到促销的日期)用 同一行原来的 promo(0)填上。

    • 结果:促销日 → 1,其余日 → 0。

  2. .astype(int)

    • 把 0.0 / 1.0 这些小数转成 整型 0/1,Prophet 外生回归器要求数值类型。

  3. future['promo'] = ...

    • 把处理好的 0/1 写回 promo 列,覆盖原来的全 0 列,得到最终「未来每天是否促销」特征。

一句话:
“用贴过来的 1 覆盖促销日,其余日继续保留 0,并把小数变整数。”

5.forecast解释:

forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper', 'promo']]中的'yhat', 'yhat_lower', 'yhat_upper' 指什么?

Prophet 给每个预测点都配了三条数:

  1. yhat
    点预测值(模型最可能的结果),也就是你平时说的“预测销量/营收”。

  2. yhat_lower
    置信区间下限,默认 80% 区间(可改)。
    真实值有 80% 概率 ≥ 这个数。

  3. yhat_upper
    置信区间上限,同理,真实值有 80% 概率 ≤ 这个数。


直观例子(80% 区间):

dsyhatyhat_loweryhat_upper
2025-10-0110008501150

→ 模型认为 2025-10-01 的销量最可能是 1000,但 80% 的可能会落在 850~1150 之间。

关键参数说明

  • yearly_seasonality:是否启用年季节性(适合年度周期数据)。
  • weekly_seasonality:是否启用周季节性(适合周周期数据)。
  • changepoint_prior_scale:调整趋势灵活度(值越大模型对突变越敏感)。

输出说明

  • yhat:预测值。
  • yhat_lower/yhat_upper:预测值的置信区间下限/上限。
  • 可视化图表包含历史数据、预测结果及季节性分解组件。

注意事项

  1. 输入数据必须包含ds(日期列)和y(数值列),且为Pandas DataFrame格式。
  2. 默认使用加法季节性模型,若业绩变化幅度随时间增大,可设置seasonality_mode='multiplicative'
  3. 对于节假日效应,可通过add_country_holidays(country_name='CN')添加中国节假日。

输出结果

一眼就能回答老板 3 个问题:

  1. 整体趋势往上还是往下?

  2. 礼拜几是高峰?

  3. 节假日/促销到底多卖了多少?


快速调参口诀(以后用)

现象调哪个参数
曲线太平滑,没跟上拐点changepoint_prior_scale 调大(0.05→0.2)
节假日效应不明显holiday_prior_scale 调大(10→20)
季节幅度随业绩变大seasonality_mode='multiplicative'(已设)
长期预测越来越“飘”缩短预测跨度 or 加更多历史促销做回归量

下一步你可以

  1. 先把上面代码跑通,把图截给老板看 baseline;

  2. 把“促销计划”填到 future 表里,就能回答“如果 618 连做 3 天促销,预计会冲多少”;

  3. 想再准一点 → 把价格、流量、广告费当额外 add_regressor 扔进去。


文章转载自:

http://6A0d7NVe.ktskc.cn
http://wMjENrEz.ktskc.cn
http://UoLQwkHT.ktskc.cn
http://tZy8emNO.ktskc.cn
http://EiRKLomM.ktskc.cn
http://e6yPig1s.ktskc.cn
http://xNzGZ9XF.ktskc.cn
http://zTxv9kGi.ktskc.cn
http://osvkTETf.ktskc.cn
http://gh6NB0RN.ktskc.cn
http://8nk420cu.ktskc.cn
http://e7sv3aOy.ktskc.cn
http://6g89CK4q.ktskc.cn
http://VVWSaACh.ktskc.cn
http://DuVlM6BT.ktskc.cn
http://cgrTG5A6.ktskc.cn
http://Hpp3oeuZ.ktskc.cn
http://lA00svbH.ktskc.cn
http://sBji1Qx8.ktskc.cn
http://Gtortd6W.ktskc.cn
http://bxqRwvAV.ktskc.cn
http://vAplG4sP.ktskc.cn
http://Oam16VUU.ktskc.cn
http://FDdVTcch.ktskc.cn
http://PQLVujKa.ktskc.cn
http://ldNCDRfv.ktskc.cn
http://CxlJUOGf.ktskc.cn
http://lo78cMm7.ktskc.cn
http://a0umPqNX.ktskc.cn
http://8i4ex5iz.ktskc.cn
http://www.dtcms.com/a/377861.html

相关文章:

  • RPA-4.0.0.0_SAAS新版本已上线,Edge扩展自动安装,快速实现RPA流程自动化
  • Server 13 ,CentOS 上使用 Nginx 部署多个前端项目完整指南( 支持多端口与脚本自动化 )
  • Java后端测试
  • Skywork-OR1:昆仑万维开源的数学代码推理系列模型
  • 【Linux】基本指令 · 上
  • OBS插件详细教程:OBS美颜插件下载,OBS美颜插件怎么用?
  • 如何在 Spring Boot 中指定不同的配置文件?
  • spring boot 拦截器增加语言信息
  • leedcode 算法刷题第三十二天
  • CentOS 7 下iscsi存储服务配置验证
  • 求解指定泛函的驻点所满足的偏微分方程及边界条件
  • 股指期货保证金一手需要多少钱?
  • LVS与Keepalived详解(一)负载均衡集群介绍
  • 【Proteus仿真】按键控制系列仿真——LED灯表示按键状态/按键控制LED灯/4*4矩阵键盘控制LED
  • 【前沿技术拓展Trip one】 芯片自动化和具身智能
  • javaEE之线程初步认识
  • `struct iovec`详解
  • python超市购物 2025年6月电子学会python编程等级考试一级真题答案解析
  • 项目模块划分
  • leetcode18(无重复字符的最长子串)
  • HackathonCTF: 1
  • redis cluster(去中心化)
  • 量子机器学习入门:三种数据编码方法对比与应用
  • 【Mysql】数据库的内置函数
  • 【Unity基础】枚举AudioType各个枚举项对应的音频文件类型
  • 2025数字化转型时代必备证书有哪些?
  • 认知-学习-时间管理系统模型-md说明文档
  • 如何用Postman做接口自动化测试
  • huggingface模型中各文件详解
  • cJson系列——json数据结构分析