机器学习方法已开始渗透到各地业务的各个领域,从而优化,改进甚至创建新的业务流程,这已不是什么秘密。 重要的领域之一是确定商品价格的问题,在这里,有了足够的数据,MO可以完成以前难以实现的任务-从数据中恢复多要素需求曲线。 由于恢复了需求曲线,因此可以构建动态定价系统,该系统可以根据定价目的优化价格-增加收入或利润。 本文是我论文的汇编,其中动态定价模型LSTM-ANN针对家用零售商的一种商品开发并在实际中测试了4周。
我想立即指出,在这篇文章中,我不会透露进行研究的公司的名称(不过,这是该场所中的公司之一),而我只是将其命名为“零售商”。
背景知识
Leroy Merlin是家庭用品零售市场的价格领导者。 该网络的销售量使他们能够为整个产品系列维持最低价格策略,从而给其他市场参与者带来价格压力。
截至2017年12月31日,圣彼得堡主要零售商的收入和利润

在这方面,零售商使用不同的定价方法:
- 价格定在最低的竞争对手;
- 以下价格的限制:购买价格+最低溢价,反映出每单位商品的近似成本。
这种方法是昂贵的定价方法和竞争对手定价的组合。 但是,它并不完美-它没有直接考虑消费者需求。
由于动态定价模型考虑了许多因素(需求,季节性,促销,竞争对手的价格),并且还允许您对建议的价格施加限制(例如,从下至上覆盖成本),因此该系统可能会摆脱所有的单方面性和其他定价方法的缺点。
资料
对于该研究,该公司提供了2015年1月至2017年7月的数据(920天/ 131周)。 这些数据包括:
- 470种产品(16个产品组)的白天销售,包括周末;
- 店内促销天数;
- 提供商品折扣的天数;
- 470个产品中每个产品的价格;
- 关于圣彼得堡整个网络中支票数量的每日数据;
- 470种产品中大多数的主要竞争对手价格(数据是每周拍摄一次)。
除了这些数据之外,我还添加了日历虚拟变量:
- 一年中的季节(秋季/冬季/夏季/春季);
- 月份
- 季度;
- 星期几;
- 假期;
另外,天气变量:
通过直接分析商品的日常销售,我发现:
始终只有大约30%的商品一直被出售,所有其他商品要么在2015年晚些时候投入销售,要么在2017年之前退出销售,这对研究和价格实验的商品选择造成了严重限制。 这也使我们得出这样一个事实,由于商店生产线中商品的不断变化,很难创建一个集成的商品定价系统,但是,有一些方法可以解决此问题,这将在后面讨论。
定价系统
为了基于预测需求的模型为下一个时期的商品建立价格建议系统,我提出了以下方案:

由于在对数据进行了模型训练之后,我们得到了一个模型,该模型可以通过向输入提供各种商品价格来恢复多要素需求曲线,因此我们将根据此价格获得估计的销售额。 因此,我们可以进行价格优化以达到期望的结果-最大化预期收入或预期利润。 剩下的只是训练可以很好预测销售的模型。
什么没有解决
选择其中一种要研究的产品后,在直接移至LSTM模型之前,我使用了XGBoost。
我这样做是希望XGBoost可以帮助我丢弃许多不必要的因素(这种情况会自动发生),而其余因素应用于LSTM模型。 我有意识地使用了这种方法,因为为了避免在论文答辩中出现不必要的问题,我一方面希望获得强有力的,同时简单的模型选择因素的正当理由,另一方面又要简化开发过程。 另外,我收到了现成的,粗糙的模型,可以在该模型上快速测试研究中的各种想法。 然后,在最终了解了什么有效和什么无效之后,制作了最终的LSTM模型。
为了了解预测问题,我将为所选的第一个产品提供每日销售时间表:

图表上的整个销售时间序列均被划分为该时期的平均销售量,以便不显示真实价值,而是保持外观。
通常,会有很多噪音,但会有明显的突发事件-这是在网络级别进行的促销活动。
因为对我来说,这是构建机器学习模型的第一次经验,所以我不得不花大量时间在各种文章和文档上,以便最终对我有所帮助。
初步可能影响销售的因素清单:
- 该组其他商品的日销售数据,该组的总销售件数以及圣彼得堡所有商店滞后1、2、3、7、14、21、28的支票数量;
- 该集团其他商品的价格数据;
- 被调查产品的价格与该组其他商品的价格之比;
- 所有竞争者中最低的价格(数据是每周一次,我假设这样的价格将在下一周有效);
- 竞争对手价格最低的被调查产品的价格比率;
- 销售滞后(按组);
- 简单平均和RSI基于组的商品销售滞后,组中的总销售和支票数量。
共有380个因素。 (每个因素2.42个观察值)。 因此,消除无关紧要的因素的问题确实很高,但是,XGBoost帮助解决了这个问题,将因子的数量大大减少到23(每个因子40个观察值)。
使用贪婪搜索可以达到的最佳结果如下:

在测试样品上R ^ 2-adj = 0.4
数据被分为训练样本和测试样本,没有混合(因为这是一个时间序列)。 作为指标,我使用了自觉调整的指标R ^ 2,因为必须在委托之前保存工作的最终结果,包括。 因此,它由业务代表组成,是最著名,最容易理解的。
最终结果削弱了我对成功的信念,因为R ^ 2-adj 0.4的结果仅意味着预测系统将无法很好地预测第二天的需求,并且对价格的建议与“空中手指”系统相差无几。
另外,我决定检查XGBoost的使用在预测一组商品的日销售量(开玩笑)以及预测整个网络上的支票数量方面有多有效。
按产品组销售:

R ^ 2-adj = 0.71
检查:

R ^ 2-adj = 0.86
我认为无法从提供的图表中清楚地预测到特定产品的销售数据的原因-噪音。 事实证明,个人商品销售太容易受到机会的影响,因此构造回归的方法无效。 同时,通过汇总数据,我们消除了随机性的影响并获得了良好的预测能力。
为了最终确保提前一天预测需求是没有意义的练习,我将SARIMAX模型(适用于python的statsmodels软件包)用于每日销售:


实际上,结果与使用XGBoost获得的结果没有任何不同,这表明在这种情况下使用复杂模型是不合理的。
同时,我还想指出,XGBoost和SARIMAX天气因素都不重要。
建立最终模型
解决预测质量问题的方法是每周汇总数据。 这使得减少随机因素的影响成为可能,但是,显着减少了观察到的数据量:如果每天有920个数据,则只有131个每周;由于因子数量几乎保持不变(排除了一周中的虚拟对象),但情况有所恶化,但是目标变量的观察数量大大减少。
另外,由于当时公司决定更改将使用该模型进行实验的产品,因此我的任务变得很复杂,因此我不得不从头开始开发模型。
商品变化发生在具有明显季节性的商品上:

由于转向每周销售,出现了一个逻辑上的问题:仅使用如此少量的数据来使用LSTM模型是否足够? 我决定在实践中进行发现,首先,要减少因素的数量(即使这可能会减少大量信息)。 我提出了所有基于销售滞后(平均,RSI),天气因素(在每日数据中,天气无关紧要,并且转为每周水平的情况,甚至失去了某种意义)计算出的所有因素。 在那之后,我通常使用XGBoost来消除其他无关紧要的因素。 后来,我还基于LSTM模型另外划分了几个因素,简单地逐个排除这些因素,再次训练模型并比较结果。
最终因素列表如下:
- 每公斤被调查产品和底漆CERESIT ST 17 10 l的价格比。
- 被调查产品与该产品和底漆CERESIT ST 17的价格之比10 l;
- 被调查产品与底漆EURO PRIMER 3 l的价格比;
- 被调查产品的价格与竞争对手的最低价格之比;
- 网络级别的三个促销活动的虚拟变量;
- 春季,夏季,秋季的假变量;
- 记录被调查产品的1-5周销售量。
只有15个因素(每个因素9个观察值)。
最终的LSTM模型是使用Keras编写的,包括2个隐藏层(分别为25和20个神经元),并且激活器为S型。
使用Keras的最终LSTM模型的代码:
model = Sequential() model.add(LSTM(25, return_sequences=True, input_shape=(1, trainX.shape[2]))) model.add(LSTM(20)) model.add(Dense(1, activation='sigmoid')) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(trainX, trainY, epochs=40, batch_size=1, verbose=2) model.save('LSTM_W.h5')
结果:


通过该指标,测试样本的预测质量看起来非常令人信服,但是,我认为,它仍未达到理想水平,因为尽管对平均销售水平的确定非常准确,但个别周的销售量可能会与“平均”销售水平,这使销售预测在各天中与实际情况有很大出入(最高50%)。 不过,我直接将此模型用于实际实验。
有趣的是,从价格方面看恢复的需求曲线是什么样的。 为此,我在价格范围内运行了模型,并根据预测的销售量建立了需求曲线:

实验
每周,该网络都会提供圣彼得堡前一周的销售数据以及竞争对手的价格。 根据这些数据,我进行了价格优化,以最大限度地提高预期利润,并说网络应该在下周设定价格。 这持续了四个星期(该期限已与零售商商定)。
利润最大化是有限制的:最低价格是购买价格+固定价格。 附加费,最高价格受同一制造商的底漆价格的限制,仅在10升包装中。
实验结果显示在下表中(所有数字均除以某个值,以免显示出绝对值):
销售预测:

利润预测:

为了评估新定价系统对销售的影响,我比较了前几年同期的销售情况。
4周总结结果:

结果,我们得到了双重印象:对销售的完全不现实的预测,但与此同时,对经济指标(无论是利润还是收入)的纯正结果。
我认为,这种解释是,在这种情况下,该模型错误地预测了销售额,但却抓住了正确的想法-该产品的价格弹性低于1,这意味着可以提高价格,不用担心我们看到的销售下降(单位销售与上一年和前一年大致保持相同水平)。
但是请不要忘记4周是短期的,该实验仅针对一种产品进行。 从长远来看,商店中的商品定价过高通常会导致整个商店的销售下降。 为了证实我对此的直觉,我决定使用XGBoost来检查消费者是否对上一时期的价格有“记忆”(如果过去“整体”的价格比竞争对手贵,那么消费者会选择竞争者)。 即 是否将按产品组提供销售组最近1、3和6个月的平均价格水平。

的确,这一推测得到了证实:以前各时期的平均价格水平以某种方式影响了当前时期的销售。 这意味着仅在当前期间对单个产品进行价格优化是不够的-从长期来看,还必须考虑总体价格水平。 通常,这会导致战术(现在最大化利润)与战略(竞争中生存)背道而驰。 但是,这已经更好地留给了营销人员。
在我看来,鉴于结果和经验,最理想的情况是,基于销售预测的定价系统如下所示:
- 要从产品命名法上移半个步骤,是进行聚类分析并通过相似性和预测销售来对条件螺丝刀进行分组,并为该子组设置价格而不是单个螺丝刀,而是为这个子组设置价格,因此我们将避免不断删除和添加产品命名法的问题。
- 在综合大楼中进行价格优化-不仅针对单个商品分组,还考虑到长期影响。 为此,您可以使用模型来预测整个网络的整体销售情况,幸运的是,即使每天的销售量,它也具有惊人的准确性。
总结完成工作的结果,我想说,对于我而言,作为一个一般的开发人员,尤其是MO方法的开发人员,我很难,但是一切都变得可行。 自己检查一下这些方法在现实中的适用性也很有趣。 以前看过很多文章,我的眼神是我会自己做所有事情,并且期待获得出色的结果。 事实证明,这种做法是严厉的-少数商品具有悠久的销售历史,嘈杂的每日数据,在预测销量方面存在误区,使用复杂模型并不总是合理的。 但是,我获得了一次难忘的经历,并且了解了将分析付诸实践的意义。
→根据完成的工作,我在
存储库中准备了一个项目
在存储库中,您将找到一个基于从真实数据中获取的依存关系而生成的数据集,以及一个python脚本,该脚本可让您对这些生成的数据进行虚拟实验,从而为您提供运气并根据您的利润超越模型,从而设定商品价格。 您需要下载并运行脚本。
我希望我的经验可以帮助您确定MO方法的使用范围,并表明即使您不是任何领域的专业人员,耐心和毅力也可以取得成果。