[Kaggle] M5 Forecasting - Accuracy summary

Chapter

  1. Backgroud
  2. Feature engineering
  3. Data selection
  4. Loss function & weight
  5. Train Strategy
  6. Post process & shake up
  7. Top solution analysis

Backgroud

M5 Forecasting - Accuracy是关于沃尔玛的一场数据挖掘比赛。比赛提供了数据的层次结构信息(state, store, dept, item)和对应2011-01-29 到2016-06-19商品的销售情况。



目的是预测未来28天的不同商品的销售量(或者是需求量)。比赛的评分公式WRMSSE十分复杂。

WRMSSE评估公式

这里简要介绍一下公式。Y_t其实是历史上第t天的销售量,h=28也就是预测的时间间隔,那么在RMSSE的分子是MSE公式,而分母代表第t-1天与第t天销售之差的开方平均。WRMSSE分为了12个level,而这12个level总共有42840个系列。如下图所示:


M5 series table

权值商品的销售价格在当前系列的销售占比。


WRMSSE权值计算

比赛真评估公式真的复杂得不得了。

Feature engineering

整个比赛一开始我将自己的主要工作是挖特征。主要有效的特征还是做时序模型的特征:

  1. Shift sales (7/14/28/30/60/180 days)
  2. Rolling mean/std sales
  3. Category id and cross different category id (state_dept, store_cate, ...)
  4. Difference of day period (7/14/28 days)
  5. Groupby id price mix, max, mean, lag price, norm value
  6. Calendar event, snap

但后来发现特征挖得复杂也不一定能够提分。更重要是将按level进行划分训练集或许效果有不错的体现。

Data selection

做过简单的EDA你会发现,有部分数据真的无法使用。2011年这一段时间的销售数据几乎为0。另外比赛说明书已经说明了,有部分商品没有价钱就是没有销售。其实可以将其删除的。数据清洗可是适当做一下,降低样本噪声并且减少运算资源的需要。

这是其中一个item在不同的store的销售情况。有些参赛者也会使用不同数据数据筛选策略得到不错的效果。

Loss function & weight

比赛一开始都是用rmse作为目标函数,但仔细看过样本分布的分布就悄悄使用了possion loss,后来都转去用Tweedie loss。



分布显然不是高斯分布,但与possion分布比较相近。进一步,泊松分布其实是一种离散分布且有大量0值。而Tweedie 分布是一种混合分布混合了高斯分布,gamma分布和逆高斯分布,与待预测的目标值更加吻合。

Train Strategy

在比赛其中就有 两种训练方式 :

  1. 训练好每日预测的模型,然后循环预测28天的销售情况。也可以使用已预测的销量作为特征,如lag7, 14。
  2. 在预测当前第t+1天时,重新使用start 到t作为训练数据进行训练并预测。特征也可以使用lag 7, 14这些与待预测日期相近的平移特征。

这里大部分人都采用第一种方式,当然我也使用了这种方式去做。看似没什么问题,但是这种做法有可能使得模型往“坏”的方向发展,偏差越来越大。尽管你在public lb当中效果不错,但有谁能确保private lb可行呢?还有一点public lb与private lb两个数据分布显然是不同的。因为它不同其他比赛那样随机采样,而是跳过28天的测试集。当然这也不是这次比赛shake up最大的原因,等等后续会谈到。另外将数据分开store进行预测是对结果有帮助,其原因就要逐个level serise的wrmsse进行比较分析,也可以说分析一下bad case。假如你没有使用按store或者dept分开训练模型,其实state, store level的wrmsse是偏高的:


Top wrmsse score

这也解释了为了我会选择按照store或者dept划分数据集进行训练。

Post process & shake up

比赛private lb可以看到出现严重的shake up。其实大部分原因都是因为在每次预测当中都用了Multiplier,并且都是public lb表现最好的系数1.03,导致最后private lb翻车。有些人乘以一个适合的multiplier: 0.95后就冲到前排。以我作为例子:

上面是乘以0.95,下面是没有乘以任何magic multiplier

后来我将我的每个预测结果都乘上了0.95,使用每日迭代预测。结果就排到了前排。这真叫人不服。赛后不少参赛者都分析了原因。赛后应该更加关注一些并非通过这些magic number, multiplier factor参赛者分析。因此不要太在乎所谓的排名,更加关注背后的分析和原因。
另外一个原因就是使用迭代预测的方式,迭代预测的好处是可以将预测的特征假如到训练当中,但前提是确保模型学习的确实与实际趋势一致。否则误差一层一层传下去,导致最后一天的预估值完全变了样子。因此有些参赛者使用另外的模型对趋势做了纠正。所以日后仍然考虑这种策略的朋友们要多加留意预估值的趋势是否走样了。https://github.com/jakevdp/supersmoother

Top solution analysis

这里是一些我对赛后各种结局方案的简要分析。有些我还是没有理解好,所以先空着。假如有些兴趣的朋友可以补充一下。

  • 1st:


    Recursive和non-recursive其实就是刚刚提及到两种训练方式。并且将数据分割为:1. store_id,2. store_id - cat_id, 3. store_id - dept_id三种方式训练模型。所以一共输出6个submission结果最后平均求和。关键是考虑Recursive和non-recursive两种方式融合,避免模型在day-by-day的趋势上将误差传播下去。

  • 2nd

  • 3rd :仅仅使用nn而没有用lgbm。算是这次比赛的一个非主流做法

  1. Network: nn模型使用DeepAR(https://arxiv.org/abs/1704.04110),模型是基于lstm进行拓展。
  2. Loss: Tweedie Loss
  3. Train: Scheme以28天为一个序列时间段,那么有num_item * day / 28条时序序列,随机采样其中的某一时间段序列预测下一个时间段,即num_item。
  4. Batch_size: 64, epoch: 300
  5. Cv: 使用14个时间段(28 days)去做检验(1914, 1886, 1858,… 1550),取其WRMSSE平均值作为validation score并选择最小的前三个epoch模型。一共训练八个模型,每个模型的random initialization都不一样,最后将3 * 8个结果进行融合
  • 4th: 与参赛者一样,使用多个validation去做校验。分别训练四个模型预测4周sales结果,每个模型的特征都不一样,每个模型都没有依赖上一个模型的预测输出,也就是non-recursive预测。

  • 5th: 这里对每一个store和department联合key比较分析校验集sales和预测的sales, 去找magic multiplier。这样避免magic multiplier的过拟合

  • 7th

  • 14th 数据集使用了14年的数据,模型方面使用lgbm, 一共训练了70个模型[store_id & dept_id],迭代预测并将预测结果用在下次预测的特征当中。

  • 21th 该参赛者使用了三个模型:分store训练lgbm,全部样本一起训练lgbm,keras nn训练。结合每个模型每天预测折线图。进行融合。

  • 34th 作者仅仅使用了2013年开始的数据进行训练。为了避免占用过多的资源。他并没有day-by-day进行预测或者训练。而是使用week-by-week进行训练。除了使用回归模型还使用二分类模型,判断模型是否有销量,假如输出的大于0.18,那么使用归回预测的结果代替。这个0.18是通过56 days校验集。

  • 36th 本次比赛其中一个新模型Time series Boost。正如其名,它是一个用于时间序列预测的boost模型

  • 59th 特征和训练模型方式大同小异。我认为其选择数据也算挺特别,该参赛者选择使用11年到15年的3,4,5,6月,2016年所有数据。这是因为预测的时间段集中于上年,而且下半年有不少假期和奇奇怪怪的数据,如圣诞节前后的数据都十分异常,对预测有一些影响。当然啦,该参赛者主要是因为运算资源的不足所以才减少数据。这里也是使用了分类算法做缺货判断,但没有很明显提高。

  • 63th: 作者使用了280个模型去做预测(10 * 28 LGBM ([10 store_id] * [28 day-by-day]))对每个store使用不同的训练参数,round只有300。算是大力出奇迹的一种办法。

  • 68th其使用了4个validation:去年同一时间段,去年同一时间段的28天前,同年28天前,同年56天前。Lgbm将item_id设置为categorical的话使得测试大部分的分割节点都使用item_id,其他特征是使用就少了很多。那么将item_id设置为默认的encoding(即参数categorical_feature)可以提高其他特征的使用频率,提高模型的鲁棒性。另外一个亮点就是趋势修正,使用训练数据以及28天的预测数据训练出趋势模型或者单单使用训练数据去训练。

  • 178th 回归模型和缺货判断分类算法结合。Preds_ = regression preds * classification preds并将在classification preds 低于5%的预测值设置为0。

  • 219th


Conclusion

这次比赛并没有取得好成绩,但其实也有一些小收获去记录一下。

  • 时序题目的validation最好是n holdout。可以是同期,上一期或其他与带预测的数据分布相近的时期
  • 在没有太多思路的情况下,根据validation的bad case进行分析。
  • 不要太迷恋magic number。不然比赛就变成赌博了。
  • 多留意notebook和discussion。大牛都会将一些私活分享给大家。这也是与国内比赛最大的区别。

你可能感兴趣的:([Kaggle] M5 Forecasting - Accuracy summary)