0

我正在运行一个预言机模型来预测呼入电话量。我花了很多时间清理数据、运行对数刻度和超参数调整——这产生了“好的”MAPE(平均百分比误差)。

在这一点上我的问题是模型一直欠拟合。尤其是在本月的前 12 天 - 在本月的前 6 天更是如此。由于运营原因,这些天的通话量总是要高得多。随着交易量进入下个月的开始,它们也开始在月底附近开始建造。

实际是蓝点,预测是灰线。这只是一个月,但它代表了所有其他月份的每月季节性:

这

为简单起见,我将仅包含模型详细信息,并将所有数据清理过程排除在外。如果有帮助,我可以提供更多信息,但到目前为止我得到的反馈是,额外的细节只会让事情变得混乱。真正唯一重要的是,对构建模型的数据运行 boxcox 转换后的结果,以及对来自模型的数据进行反向 boxcox 后的结果:

# Create Model
M = Prophet(
    changepoint_prior_scale = 15,
    changepoint_range = .8,
    growth='linear',
    seasonality_mode= 'multiplicative',
    daily_seasonality=False,
    weekly_seasonality=False,
    yearly_seasonality=False,
    holidays=Holidays
    ).add_seasonality(
        name='monthly',
        period=30.5,
        fourier_order = 20,
        prior_scale = 45
    ).add_seasonality(
        name='daily',
        period=1,
        fourier_order=75,
        prior_scale=20
    ).add_seasonality(
        name='weekly',
        period=7,
        fourier_order=75,
        prior_scale=30
    ).add_seasonality(
        name='yearly',
        period = 365.25,
        fourier_order = 30, 
        prior_scale = 15)

总的来说,我想全面改善欠拟合的情况——尤其是在月初和月底。我尝试增加 changepoint_range 以放松模型,但结果并不明显。我也尝试增加“每月”季节性的prior_scale,但没有比上面的截图更好的结果。

我有点不知所措。有没有可以与 FaceBook Prophet 模型一起使用的建模技术来解决这个问题?有没有办法添加一个回归量,将特定的季节性分配给前 12 天和最后 7 天?我做了一些研究,不确定你是否可以和/或如何工作。

任何帮助将不胜感激。

作为更新,我尝试提升 change_point 范围和更改点先验比例,但没有任何影响。打算尝试减少训练数据量(目前使用 4 年)。

4

1 回答 1

1

我想我找到了一个可行的解决方案,将其记录为答案,以防其他人在路上遇到类似的问题。

由于我知道这种行为是周期性的,并且我知道它为什么存在(月初有 2 个不同的月度计费周期,而月末的交易量反复增加,这是不合适的),我使用 Prophet 文档来创建这些特定时期的额外季节性回归量。

我首先定义了季节的函数(根据 Prophet 文档,示例适用于 NFL 赛季和 NFL 休赛期):

def is_1st_billing_season(ds):
    date = pd.to_datetime(ds)
    return (date.day >= 1 and date.day <= 6)


def is_2nd_billing_season(ds):
    date = pd.to_datetime(ds)
    return (date.day >= 7 and date.day <= 12)


def EOM (ds):
    date = pd.to_datetime(ds)
    return (date.day >= 25 and date.day <= 31)

然后我将这些函数应用于我的数据框:

#Create Additional Seasonal Categories
Box_Cox_Data['1st_season'] = Call_Data['ds'].apply(is_1st_billing_season)
Box_Cox_Data['2nd_season'] = Call_Data['ds'].apply(is_2nd_billing_season)
Box_Cox_Data['EOM'] = Call_Data['ds'].apply(EOM)

然后我更新了我的模型以包含额外的季节性回归变量:

# Create Model
M = Prophet(
    changepoint_prior_scale = 15,
    changepoint_range = .8,
    growth='linear',
    seasonality_mode= 'multiplicative',
    daily_seasonality=False,
    weekly_seasonality=False,
    yearly_seasonality=False,
    holidays=Holidays
    ).add_seasonality(
        name='monthly',
        period=30.5,
        fourier_order = 20,
        prior_scale = 45
    ).add_seasonality(
        name='daily_1st_season',
        period=1,
         fourier_order=75,
        prior_scale=20,
        condition_name='1st_season'
    ).add_seasonality(
        name='daily_2nd_season',
        period=1,
        fourier_order=75,
        prior_scale=20,
        condition_name='2nd_season'
    ).add_seasonality(
        name='daily_EOM_season',
        period=1,
        fourier_order=75,
        prior_scale=20,
        condition_name='EOM'
    ).add_seasonality(
        name='weekly',
        period=7,
        fourier_order=75,
        prior_scale=30
    ).add_seasonality(
        name='yearly',
        period = 365.25,
        fourier_order = 30, #CHECK THIS
        prior_scale = 15)
        
#Fit Model
M.fit(Box_Cox_Data)

# Create Future Dataframe (in Hours)
future = M.make_future_dataframe(freq='H', periods = Hours_Needed)
future['1st_season'] = future['ds'].apply(is_1st_billing_season)
future['2nd_season'] = future['ds'].apply(is_2nd_billing_season)
future['EOM'] = future['ds'].apply(EOM)

# Predict Future Values
forecast = M.predict(future)

最终结果看起来好多了:

在此处输入图像描述

为了完全透明,此屏幕截图的时间与原始屏幕截图略有不同。对于这个项目,我的起点并不是特别重要(对未来时期的预测是主要关注点),我不小心对不同的时间范围进行了交叉验证,但最终结果是在所有时间范围内更合适的季节预测我到目前为止已经看到了。

于 2021-11-20T04:51:12.357 回答