You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用fbprophet结合多回归因子实现未来小时温度预测?

如何使用fbprophet结合多回归因子实现未来小时温度预测?

兄弟,我太懂你这个坑了!用Prophet加了一堆自定义回归器训练,在训练测试集上表现贼好,结果要预测未来时直接炸锅,提示回归器缺失——核心原因就是你生成的future数据框里只有ds列,而你加的那些像hourlyLag、movMean这类特征,要么依赖历史温度,要么是基于历史温度计算的统计量,Prophet根本不知道怎么给未来的这些列填值!

我给你拆解下问题,再一步步说怎么解决:

先搞懂为啥报错

model.make_future_dataframe()只会生成一个带ds(时间戳)的空架子,你之前加的13个回归器里,分三类:

  1. 能直接从ds算出来的:比如hour、month、dayOfYear——这些未来时间是已知的,好处理
  2. 依赖历史温度的:比如hourlyLag(前1小时温度)、dailyLag(前24小时)、movMean(滚动均值)——这些是核心难点,因为未来温度是我们要预测的,没法直接拿到这些值
  3. 逻辑上有问题的:比如devFromMean(movMean - Temperature)——这是用目标变量本身算出来的,训练时用真实温度没问题,但预测时温度未知,根本没法算,这类特征直接删了吧!

一步步解决问题

第一步:处理可直接计算的时间类回归器

像hour、month这些,你完全可以在生成future数据框后直接补上,因为未来的时间是确定的:

# 生成未来数据框
future = model.make_future_dataframe(periods=24*365*3, freq='h')

# 给未来数据框加时间特征
future['hour'] = future['ds'].dt.hour
future['month'] = future['ds'].dt.month
future['dayOfYear'] = future['ds'].dt.day  # 按你原代码的逻辑,注意dt.day是当月第几天,dt.dayofyear是当年第几天,按需选

这些列补完,时间类的回归器就没问题了。

第二步:处理依赖历史温度的回归器(核心难点)

像hourlyLag、dailyLag、movMean这些,因为未来温度未知,没法直接算,这里给你两个实用思路:

思路1:递归预测(最适合Prophet的方案)

简单说就是走一步看一步:每预测出一个小时的温度,就用这个预测值当“历史数据”,计算下一个小时需要的滞后项,再预测下一个小时。代码大概是这样:

# 1. 先准备好历史最后一段数据(要覆盖最大的滞后窗口,比如weeklyLag需要24*7=168小时)
last_history = temp.tail(24*7).copy()
# 把历史数据和未来数据框拼起来
full_df = pd.concat([last_history, future], ignore_index=True)
# 给full_df加个yhat列存预测值,初始历史部分用真实y
full_df['yhat'] = full_df['y']

# 2. 循环遍历每个未来时间点,一步步预测
for i in range(len(last_history), len(full_df)):
    # 计算当前时间点需要的滞后项
    # 前1小时的温度:历史用真实y,已预测的用yhat
    full_df.loc[i, 'hourlyLag'] = full_df.loc[i-1, 'y'] if i-1 < len(last_history) else full_df.loc[i-1, 'yhat']
    # 前24小时的温度
    full_df.loc[i, 'dailyLag'] = full_df.loc[i-24, 'y'] if i-24 < len(last_history) else full_df.loc[i-24, 'yhat']
    # 前7天的温度
    full_df.loc[i, 'weeklyLag'] = full_df.loc[i-24*7, 'y'] if i-24*7 < len(last_history) else full_df.loc[i-24*7, 'yhat']
    
    # 计算滚动均值和标准差:用历史+已预测的温度
    window_start = max(0, i-24)
    past_temps = full_df.loc[window_start:i-1, 'y'].fillna(full_df.loc[window_start:i-1, 'yhat'])
    full_df.loc[i, 'movMean'] = past_temps.mean()
    full_df.loc[i, 'mStd'] = past_temps.std()
    # 上下边界跟着算
    full_df.loc[i, 'ub'] = full_df.loc[i, 'movMean'] + 1.6 * full_df.loc[i, 'mStd']
    full_df.loc[i, 'lb'] = full_df.loc[i, 'movMean'] - 1.6 * full_df.loc[i, 'mStd']
    
    # 现在所有回归器都齐了,预测当前时间点
    current_row = full_df.loc[[i]]
    pred = model.predict(current_row)
    # 把预测值存到yhat里,供下一个时间点用
    full_df.loc[i, 'yhat'] = pred['yhat'].values[0]

# 最后提取未来的预测结果
future_predictions = full_df.loc[len(last_history):, ['ds', 'yhat', 'yhat_lower', 'yhat_upper']]

这个方法虽然麻烦,但能解决滞后项的问题,缺点是如果预测周期很长(比如3年),循环会有点慢,但小时级3年也才26k多步,电脑能扛住。

思路2:砍掉依赖历史的回归器,用Prophet内置季节性

其实Prophet本身已经内置了小时、日、周、年的季节性特征,你手动加的dailyLag、weeklyLag这些,Prophet自己能通过季节性捕捉到。不如把这些依赖历史的回归器删掉,让Prophet自己处理季节性:

# 重新定义模型,用内置季节性
model = Prophet(
    daily_seasonality=True,  # 捕捉小时级季节性
    weekly_seasonality=True,
    yearly_seasonality=True,
    seasonality_mode='additive'
)
# 只加能直接计算的时间回归器(甚至这些都可以不加,Prophet自己会处理)
model.add_regressor('hour')
model.add_regressor('month')

# 训练和预测就简单了
model.fit(train)
future = model.make_future_dataframe(periods=24*365*3, freq='h')
# 补时间特征
future['hour'] = future['ds'].dt.hour
future['month'] = future['ds'].dt.month
# 直接预测,不会报错!
predictions = model.predict(future)

这个方法最省心,而且Prophet的季节性拟合能力很强,效果不一定比你手动加滞后项差。

第三步:删掉逻辑无效的回归器

像devFromMean、devFromUB、devFromLB这些,都是用“真实温度”减出来的,而真实温度是我们要预测的目标,预测时根本拿不到,这些特征完全没用,直接从模型里删掉!

最后给你个快速试错的修改版

先把依赖历史的回归器从模型里去掉,只留时间类的,验证下预测流程能跑通:

# 重新准备特征(删掉无效的)
temp = df[["Temperature"]].apply(kelvinToDegC).copy()
# 只留能直接从时间算的特征
temp["hour"] = temp.index.hour
temp["dayOfYear"] = temp.index.day
temp["month"] = temp.index.month
temp = temp.reset_index()
temp.rename(columns={"Date": "ds", "Temperature": "y"}, inplace=True)

# 重新定义模型
model = Prophet(daily_seasonality=True, weekly_seasonality=True, yearly_seasonality=True)
model.add_regressor("hour")
model.add_regressor("dayOfYear")
model.add_regressor("month")

model.fit(train)

# 生成未来数据框+补特征
future = model.make_future_dataframe(periods=24*365*3, freq='h')
future['hour'] = future['ds'].dt.hour
future['dayOfYear'] = future['ds'].dt.day
future['month'] = future['ds'].dt.month

# 预测,这次不会报错了!
predictions = model.predict(future)

这样先跑通流程,再根据需要加递归预测的滞后项就行。

备注:内容来源于stack exchange,提问作者Imtiaz Nabi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 11:13:04