2021 年 2 月 5 日
在本文中,Data 科学家 Maxime Lutel 总结了他在 M5 销售预测竞赛中的学习成果,该竞赛的内容包括预测沃尔玛几家商店的未来销售额。他将向您介绍我们的解决方案,并讨论哪种机器学习模型最适合这项任务。.

利用机器学习解决零售商的业务难题
准确的销售预测对于零售公司在正确的时间生产所需的数量至关重要。但是,即使避免浪费和短缺是零售商最关心的问题之一,他们仍有很大的改进空间。至少,沃尔玛的员工是这么认为的,因为他们在 2020 年 3 月发起了一项开放式 data 科学挑战--"沃尔玛的销售预测"。 M5 比赛 - 以了解如何改进其预测模型。.
比赛的目的是根据 data 的历史数据,在产品层面预测未来的销售情况。由 5000 多名 data 爱好者和预测专家组成的团队就解决这一众所周知的机器学习问题的最佳方法、特征和模型进行了长达数月的讨论。这些讨论凸显了几乎所有预测项目中反复出现的一些问题。更重要的是,他们提出了各种各样的方法来解决这些问题。.
本文旨在总结一些 从挑战中得出的主要启示. .在 Artefact,我们相信在实践中学习,因此我们决定试一试,编写我们自己的解决方案来说明这一点。现在,让我们回顾一下整个预测流程,并在过程中停下来,了解哪些是成功的,哪些是失败的。.
问题陈述:分层时间序列预测
dataset 包含各种产品和商店从 2011 年到 2016 年的 5 年历史销售额。还提供了一些附加信息,如销售价格和日历事件。Data 按等级组织:商店分为 3 个状态,产品按类别和子类别分组。.

我们的任务是 预测每个商店所有产品在可用 dataset 后几天的销售额. .这意味着在预测范围内,每天必须进行 30 490 次预测。.
这种层次结构将指导我们的建模选择,因为产品类别或商店内部的互动包含了对预测非常有用的信息。事实上,同一商店和类别中的商品可能会有相似的销售变化,或者相反,它们可能会相互蚕食。因此,我们将通过捕捉这些互动的特征来描述每一个样本,并且 将基于机器学习的方法置于传统预测方法之上, 因此,在训练模型时应考虑这一信息。.
两大挑战:间歇性数值和较长的预测范围
在这个阶段,您可能会认为这是一个非常常见的预测问题。你说得没错,这也是它有趣的原因:它可以与其他各种项目相关联,即使每个行业都有自己的特点。然而,这一挑战有两个重要的特殊性,会使任务比预期的更加困难。.
首先,我们所使用的时间序列有很多间歇值,即长时间连续几天没有销售,如下图所示。这可能是由于缺货或商店货架面积有限造成的。无论如何,这都会使任务复杂化,因为如果在产品缺货的情况下按正常水平预测销售额,误差就会激增。.

第二个问题来自任务本身,更确切地说,来自 预测范围的大小. .竞争对手不仅要生成下周的天气预报,还要生成四周的天气预报。你是愿意依赖第二天的天气预报,还是一个月后的天气预报?销售预测也是如此:随着时间的推移,不确定性的增加,预测范围的延长会使问题变得更加复杂。.
功能工程 - 销售驱动因素建模
既然我们已经了解了当前的任务,就可以开始计算可能影响销售变化的所有现象的模型特征。这样做的目的是用一组指标来描述每个三元组 "日 x 产品 x 商店",这些指标可以捕捉季节性、趋势或定价等因素的影响。.
季节性
与其直接使用销售日期作为预测指标,不如将其分解为几个特征来描述季节性:年、月、周数、, 星期......后者尤其具有洞察力,因为这个问题具有很强的周周期性:周末的销售量更大,因为人们在超市花费的时间更多。.
日历活动 如节假日或 NBA 总决赛也会产生强烈的季节性影响。我们为每个事件创建了一个特征,其值如下:
我们的想法是,不仅要模拟圣诞节当天的季节性影响,还要模拟圣诞节前后的季节性影响。例如,一种产品如果作为圣诞礼物大量发售,其销售额就会在圣诞节前几天达到高峰,而在圣诞节后马上下降。.
发展趋势
最近的趋势也为未来的销售提供了有用的信息,其模型得益于 滞后特性. .滞后值是指目标变量的值偏移了一段时间。对于特定商店的任何特定商品,1 周的滞后值就是该特定商品和商店一周前的销售额。可以考虑不同的移动值,也可以计算多个滞后期的平均值,以获得更可靠的预测结果。滞后值也可以根据综合销售额来计算,以捕捉更全面的趋势,例如商店或产品类别层面的趋势。.
定价
一个产品的价格可能在不同商店之间发生变化,甚至在同一商店内不同星期之间也会发生变化。这些变化对销售影响很大,因此应该用一些特征来描述。而不是绝对价格、, 相关产品之间的相对价格差异更有可能解释销售变化. .这就是计算以下预测因子的原因:
分类变量编码
州、商店、产品名称或其类别等分类变量也具有很强的预测能力。这些信息必须编码成特征,以帮助模型利用 dataset 层次结构。由于其中一些分类变量的卡入度非常高(3049 个不同的产品),因此这里不能使用单热编码。相反,我们使用了 有序目标编码, ,这意味着每个观测值都是由具有相同分类值的过去观测值的平均销售额编码的。在这项任务中,data 集按时间排序,以避免 data 泄露。.
所有分类变量及其部分组合都采用这种方法进行编码。这就产生了信息量非常大的特征,其中最好的特征是产品和商店组合的编码。如果您想尝试其他编码器,您可以找到多种方法 这里.
处理间歇值的特威迪损耗
处理间歇性价值问题可以采用不同的策略。一些参与者决定创建两个独立的模型:一个用于预测产品在某一天是否有货,另一个用于预测销售情况。与其他许多人一样,我们也选择了另一种方法,那就是依赖于一个与问题相适应的目标函数:"......"。 weedie损失.
在不涉及数学细节的情况下,让我们通过比较训练 data 和 tweedie 分布中的销售分布,来理解为什么这个损失函数适合我们的问题:

它们看起来非常相似,数值都集中在 0 左右。 最大化该分布的可能性 从而预测出适当数量的 0。此外,这个损失函数还带有一个参数,其值从 1 到 2 不等,可以根据当前问题的分布情况进行调整:

根据我们的 dataset 分布,我们可以预期最佳值介于 1 和 1.5 之间,但为了更加精确,我们稍后将通过交叉验证来调整该参数。这个目标函数也适用于其他梯度提升模型,如 XGBoost 或 CatBoost,因此如果你需要处理间歇性数值,绝对值得一试。.
如何提前 28 天预报?充分利用滞后特征
如上所述,滞后特征是指销售额在一定时期内的变化。因此,它们的值取决于你在预测范围内所处的位置。如果您提前一天进行预测,特定日期 D 的销售额可视为 1 天滞后,如果您提前 28 天进行预测,则可视为 28 天滞后。下图说明了这一点:

这一概念对于了解将有哪些功能非常重要。 预测时可用. .在这里,我们处于第 D 天,希望预测未来 28 天的销售情况。这意味着,如果我们使用 1 天滞后特征来训练模型,那么在预测 D+2、D+3......和 D+28 时,也必须填写该变量,因为它指的是未来的日期。.
不过,滞后可能是 预测能力最强的特征, 因此,找到充分利用这些信息的方法非常重要。我们考虑了 3 个方案来解决这个问题,让我们看看它们的表现如何。.
方案 1:所有星期都使用一种模式

第一个方案是最明显的方案。它包括使用同一模型对预测范围内的所有周进行预测。正如我们刚才所解释的,它有一个很大的限制:只能使用 D+28 时的预测特征。因此,我们必须 剔除 27 个最新滞后期提供的所有信息. .这是一个遗憾,因为最近的滞后也是信息量最大的滞后,所以我们考虑了另一种方案。.
方案 2:每周模式

这种方法是为每周训练一个不同的 LightGBM 模型。在上图中,每个模型都是根据其预测范围所施加的限制,从最近可能的滞后期进行学习。按照与前一种方案相同的逻辑,这意味着每个模型都可以利用所有滞后期进行预测,但比最远预测日新的滞后期除外。.
更准确地说
通过这种方法,我们可以 更好地利用前 3 周的滞后信息,从而提高我们解决方案的预测准确性. .因为这是一场 Kaggle 竞赛,所以值得。 对于工业化项目来说,还应该考虑复杂性、维护和可解释性等问题.
事实上,这一方案的计算成本可能很高,如果我们的目标是在全国范围内推广,则需要维护数百个实时模型。在这种情况下,有必要评估性能增量是否大到足以证明这种更复杂的实施是合理的。.
方案 3:递归建模

最后一个选项也使用周模型,但这次是递归方式。. 递归建模 的意思是,为某一周生成的预测结果将被用作接下来几周的滞后特征。这种情况 先后方案 1:我们首先使用除 6 个最新滞后期之外的所有滞后期对第一周进行预测。然后,我们用之前的预测作为 1 周的滞后期来预测第 2 周,而不是像方案 2 那样排除更多的滞后期。通过重复同样的过程,我们总能得到最近的滞后期,甚至是第 3 周和第 4 周的滞后期,这样我们就可以利用这些信息来训练模型。.
这种方法值得一试,但请记住,它相当 不稳定,因为误差在周与周之间蔓延. .如果第一周的模型出现重要错误,这些错误就会被下一周的模型当作真理,而下一周的模型就不可避免地会表现不佳,以此类推。这就是为什么我们决定 坚持选择 2, 这似乎更可靠。.
通过适当的交叉验证确保模型的稳健性:为什么交叉验证对时间序列至关重要
在任何机器学习项目中,采用适当的交叉验证策略对于正确模拟样本外精度、全面选择超参数和避免过度拟合都至关重要。说到预测,这一点必须小心谨慎,因为必须保留观察结果之间的时间依赖性。换句话说, 在训练模型时,我们要防止模型展望未来.
在处理时间序列时,对模型进行测试的验证期也非常重要。模型的性能和最佳超参数集可能会因模型的训练和测试期不同而有很大差异。. 因此,我们的目标是找到哪些参数最有可能最大限度地提高性能,而不是在一个随机的时期内,而是在我们想要预测的时期内, 即未来 4 周。.
根据当前问题调整验证过程
为实现这一目标,我们选择了 5 个验证集,它们是 与预测期有关. .下图显示了它们随时间的分布情况。对于每个交叉验证褶皱,模型在训练集上使用不同的参数组合进行训练,并在验证集上使用均方根误差进行评估。.

折线 1、折线 2 和折线 3 的目的是找出在最近一段时期(基本上是过去 3 个月)能使业绩最大化的参数。问题在于,这 3 个月的具体情况可能与我们希望预测的未来一段时间不同。例如,假设商店在过去几个月里推出了一个大型促销季,但今天刚刚停止。.
这些促销活动可能会对模型的行为产生影响,但仅靠最近这段时间来调整模型是有风险的,因为这并不代表接下来会发生什么。.
为了降低这种风险,我们还加入了折线 4 和折线 5,这两个折线分别对应于预测期推移 1 年和 2 年。这些周期很可能相似,因为问题具有很强的年度季节性,这在零售业中经常发生。如果有不同的周期,我们可以选择任何更具商业意义的交叉验证策略。最后,我们选择了在 5 次折叠中误差最小的超参数组合来训练最终模型。.
成果
通过上述不同的技术,我们得出了以下结论 0.59 加权 RMSSE - 这相当于 82.8% 的加权预测准确率。下图总结了每个步骤产生的性能增量:

这些数字仅供参考:精度的递增还取决于每个步骤的实施顺序。.
主要收获
我们从这次挑战中学到了很多,这要归功于参与者分享的见解,我们希望这次挑战也能给你们带来启发。以下是我们的主要收获:
感谢您阅读到现在,如果您对此有任何意见,请随时联系我们!

博客





