返回列表

35th Place Solution - GRU+XGB

559. GoDaddy - Microbusiness Density Forecasting | godaddy-microbusiness-density-forecasting

开始: 2022-12-16 结束: 2023-06-16 销量与需求预测 数据算法赛

第35名解决方案 - GRU+XGB

作者: therealmathisk (MASTER)
发布时间: 2023-06-21

本次竞赛的目标是预测美国所有县每月的小型企业域名注册数量除以活跃人口的结果。与其他时间序列竞赛最大的不同在于:公开排行榜仅评估1个月后的预测分数(1月份),而最终评分将基于3-5个月后的数据(3月、4月、5月)。我原本预期需要处理各种宏观经济解释变量,甚至可能包含资本市场数据,但事实证明情况并非如此😄。

未能奏效的方法

  • 我在statsamerica网站(www.statsamerica.org/downloads)的文件中花费了大量时间寻找可能对数据增强有帮助的信息,但遗憾未能找到在此场景下有效的证据。不过他们确实有很多有趣的内容(https://www.statsamerica.org/innovation)。
  • 资本市场指标也几乎无效。一个令人惊讶的发现是:注册域名的决策似乎不受VIX恐慌指数或美联储点阵图的影响(或者更准确地说,这些指标对县级预测没有帮助)。

数据质量与预处理

因此,异常值检测成了关键。我虽然没有探测排行榜,但仍花费大量时间对比小县的数据及其不规则的时间序列。此外,我们还需处理2021年1月数据的结构性变化以及人口数据的变动

为此,我使用最新人口普查数据调整了目标变量,并移除了所有县在超过±7%阈值时的可疑突增:

for o in tqdm(raw.cfips.unique()):
        indices = (raw['cfips']==o)
        tmp = raw.loc[indices].copy().reset_index(drop=True)
        var = tmp.microbusiness_density.values.copy()
        var_pct = tmp.microbusiness_density.pct_change().clip(-0.07,0.07)
        for j in range(40, 0, -1):
            if j==18 and (var_pct[j]== -0.07 or var_pct[j]== 0.07):
                var[j-1] = var[j]
            else:
                var[j-1] = var[j]/(1+var_pct[j])
        raw.loc[indices, 'microbusiness_density'] = var

随后使用时间序列自编码器进一步去噪:

def create_autoencoder(noise=0.05):
    i = tf.keras.Input(shape=(24,))
    encoded = tf.keras.layers.BatchNormalization()(i)
    encoded = tf.keras.layers.GaussianNoise(noise)(encoded)
    encoded = tf.keras.layers.Dense(64,activation='relu')(encoded)
    decoded = tf.keras.layers.Dropout(0.2)(encoded)
    decoded = tf.keras.layers.Dense(24)(decoded)
    x = tf.keras.layers.Dense(32,activation='relu')(decoded)
    x = tf.keras.layers.BatchNormalization()(x)
    x = tf.keras.layers.Dropout(0.2)(x)
    x = tf.keras.layers.Dense(24,activation='linear')(x)
    
    encoder = tf.keras.Model(inputs=i,outputs=x)
    loss = tf.keras.losses.MeanSquaredError()
    encoder.compile(optimizer=Adam(0.001),loss=loss)
    return encoder

我不确定这是否会造成数据泄露,因为它在交叉验证的fold结构之前/外部应用。但它稳定了我的CV分数,对公开排行榜分数没有负面影响。因此我仅在GRU模型中使用它,XGB模型仍使用"原始"数据训练。

模型与目标设计

仅考虑拥有超过150家微型企业的县作为模型输入,低于此阈值的县直接使用最后观测值。

基于Chris的提案,我使用GRU模型,输入24个月的np.log1p(微型企业密度)序列,采用3折GroupKFold(按日期分组),预测1、3、4、5个月后的值。

第二个模型使用XGB,参考GIBA分享的方法,将1、3、4、5个月的增长率差值作为目标。虽然加入了多数县级特征,但它们解释力有限。后处理时,我将XGB预测的百分比变化按预处理后的10%和90%分位数进行截断。两个模型在最终提交中各占50%权重。

备用提交方案

这是一个受21行代码方案启发的简单线性模型。它计算2021年1月结构性变化后21个月内各县的平均月增长率,均值限制在-0.5%至+1%之间,对活跃域名少于150的县将增长率乘以0.3(这些参数基于粗略统计:平均增长率及5%、25%、75%、95%分位数的人工判断)。对于11月和12月增长停滞的县,则永久沿用最后观测值。该方案得分4.0731,可排175名(付出10%的努力仍可获得银牌)🙀

同比赛其他方案