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

Python中Prophet时间序列模型全参数寻优需求咨询

Prophet时间序列预测调参优化方案

核心需求

使用Prophet模型进行时间序列预测,通过训练集-测试集验证方法最小化MAPE误差,需优化以下参数:

  • changepoint_range
  • changepoint_prior_scale
  • seasonality_prior_scale
  • holiday_prior_scale
  • holiday_mode
    完成调参后执行未来预测。

自定义MAPE计算函数

def mape(y_true, y_pred):
    return round(np.mean(np.abs(((y_true-y_pred)/y_true)*100)),2)

当前调参局限

目前使用Optuna和Tuner库调参,但仅能设置有限尝试次数(50次试验、10次迭代50个样本),无法充分覆盖参数空间,需优化调参逻辑提升参数覆盖度。

Optuna调参代码

def objective(trial):
    params={'changepoint_range': trial.suggest_loguniform('changepoint_range', 0.1, 1),
            'changepoint_prior_scale' : trial.suggest_loguniform('changepoint_prior_scale', 0.01, 0.5),
            'seasonality_prior_scale': trial.suggest_loguniform('seasonality_prior_scale', 0.01, 10),
            'holidays_prior_scale': trial.suggest_loguniform('holidays_prior_scale', 0.01, 10),
            'holidays_mode': trial.suggest_categorical('holidays_mode', ['additive', 'multiplicative'])
    }
    model = Prophet()
    model.fit(Train)
    future= model.make_future_dataframe(periods= tst)
    forecast= model.predict(future)
    prediction= forecast.tail(tst)
    return mape(Test['y'], prediction['yhat'])
study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=50)

Tuner库调参代码

def objective_function(args_list):
    global Train, Test

    params_evaluated= []
    results= []

    for params in args_list:
        try:
            model = Prophet()
            model.fit(Train)
            future= model.make_future_dataframe(periods= tst)
            forecast= model.predict(future)
            prediction= forecast.tail(tst)
            error= mape(Test['y'], prediction['yhat'])

            params_evaluated.append(params)
            results.append(error)
        except Exception as e:
            print(f"Error for params {params}: {e}")
            params_evaluated.append(params)
            results.append(25)

    return params_evaluated, results

from scipy.stats import uniform
params_space= dict(changepoint_range= uniform(0.5,0.5),
                   changepoint_prior_scale= uniform(0.001,0.5),
                   seasonality_prior_scale= uniform(0.01,10),
                   holidays_prior_scale= uniform(0.01, 10),
                   holidays_mode= ['additive', 'multiplicative']
                   )

conf_dict= dict()
conf_dict['initial_random']= 10
conf_dict['num_iteration']= 50
tuner= Tuner(params_space, objective_function, conf_dict)
results= tuner.minimize()

优化方案:最大化参数空间覆盖

由于部分参数为连续型变量,无法实现绝对意义上的全参数组合遍历,可通过「网格采样+随机采样结合」的方式最大化覆盖合理参数区间:

混合调参实现代码

import itertools
import numpy as np
from prophet import Prophet

# 1. 定义参数采样范围:离散参数全枚举,连续参数按合理逻辑采样
holiday_modes = ['additive', 'multiplicative']
# 连续参数取对数/线性尺度的密集采样点,覆盖Prophet官方建议的合理区间
changepoint_ranges = np.linspace(0.7, 0.95, 6)  # 0.7-0.95是changepoint_range常用区间
changepoint_priors = np.logspace(-2, -0.3, 5)   # 对数尺度采样0.01-0.5
seasonality_priors = np.logspace(-2, 1, 6)      # 对数尺度采样0.01-10
holiday_priors = np.logspace(-2, 1, 6)          # 对数尺度采样0.01-10

# 2. 生成所有离散参数+连续网格的组合
param_grid = list(itertools.product(
    changepoint_ranges,
    changepoint_priors,
    seasonality_priors,
    holiday_priors,
    holiday_modes
))

# 3. 补充随机采样点,覆盖网格未涉及的边缘区间
random_sample_count = 200
random_params = []
for _ in range(random_sample_count):
    random_params.append([
        np.random.uniform(0.1, 1),
        np.random.uniform(0.01, 0.5),
        np.random.uniform(0.01, 10),
        np.random.uniform(0.01, 10),
        np.random.choice(holiday_modes)
    ])

# 4. 合并网格与随机参数,遍历计算MAPE寻找最优解
all_params = param_grid + random_params
best_mape = float('inf')
best_params = None

for params in all_params:
    cp_range, cp_prior, seas_prior, hol_prior, hol_mode = params
    try:
        model = Prophet(
            changepoint_range=cp_range,
            changepoint_prior_scale=cp_prior,
            seasonality_prior_scale=seas_prior,
            holidays_prior_scale=hol_prior,
            holidays_mode=hol_mode
        )
        model.fit(Train)
        future = model.make_future_dataframe(periods=tst)
        forecast = model.predict(future)
        prediction = forecast.tail(tst)
        current_mape = mape(Test['y'], prediction['yhat'])
        
        if current_mape < best_mape:
            best_mape = current_mape
            best_params = params
            print(f"新最优MAPE: {best_mape}, 参数组合: {best_params}")
    except Exception as e:
        print(f"参数组合{params}执行失败: {e}")
        continue

# 5. 输出最优结果并训练最终模型
print(f"\n最终最优参数: {best_params}, 最优MAPE: {best_mape}")
final_model = Prophet(**dict(zip(
    ['changepoint_range', 'changepoint_prior_scale', 'seasonality_prior_scale', 'holidays_prior_scale', 'holidays_mode'],
    best_params
)))
final_model.fit(Train)
# 替换为实际需要的未来预测期数
future_final = final_model.make_future_dataframe(periods=30)
forecast_final = final_model.predict(future_final)

内容的提问来源于stack exchange,提问作者Arun Raaj Rajendhiran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:07:02