写点什么

Spark 技术在京东智能供应链预测的应用

  • 2017-08-10
  • 本文字数:10538 字

    阅读完需:约 35 分钟

大家晚上好,做一个简单的介绍:我叫郭景瞻,来自京东,著有《图解 Spark:核心技术与案例实战》一书,还有我的同事杨冬越,他在京东 Y 事业部,主要从事供应链销量预测、单量预测等系统的设计与实现工作。

今天非常感谢 InfoQ 提供这样的机会给大家做一次分享,我们分享的主题是《Spark 技术在智能供应链的应用》。在该分享中,首先介绍京东智能供应链并介绍预测在供应链中的作用,接着介绍预测系统的业务和技术架构,再接着介绍系统核心系统并介绍 Spark 在核心系统中的使用,最后结合本人所著书《图解 Spark:核心技术与案例实战》部分章节介绍在预测系统中的应用与优化。(戳“阅读原文”查看京东链接)。

1. 背景

前段时间京东公开了面向第二个十二年的战略规划,表示京东将全面走向技术化,大力发展人工智能和机器人自动化技术,将过去传统方式构筑的优势全面升级。京东 Y 事业部顺势成立,该事业部将以服务泛零售为核心,着重智能供应能力的打造,核心使命是利用人工智能技术来驱动零售革新。

1.1 京东的供应链

京东一直致力于通过互联网电商建立需求侧与供给侧的精准、高效匹配,供应链管理是零售联调中的核心能力,是零售平台能力的关键体现,也是供应商与京东紧密合作的纽带,更是未来京东智能化商业体布局中的核心环节。

目前京东在全国范围内的运营 256 个大型仓库,按功能可划分为 RDC、FDC、大件中心仓、大件卫星仓、图书仓和城市仓等等。RDC(Regional Distribution Center)即区域分发中心,可理解为一级仓库,向供货商采购的商品会优先送往这里,一般设置在中心城市,覆盖范围大。FDC(Forward Distribution Center)即区域运转中心,可理解为二级仓库,覆盖一些中、小型城市及边远地区,通常会根据需求将商品从 RDC 调配过来。

结合人工智能、大数据等技术,京东首先从供货商那里合理采购定量的商品到 RDC,再根据实际需求调配到 FDC,然后运往离客户最近的配送站,最后快递员将商品带到客户手中。这只是京东供应链体系中一个普通的场景,但正因为有这样的体系,使得京东对用户的响应速度大大提高,用户体验大大提升。

1.2 京东供应链优化

用户体验提升的同时也伴随着大量资金的投入和成本的提高,成本必须得到控制,整个体系才能发挥出最大的价值,于是对供应链的优化就显得至关重要了。

京东自打建立供应连体系的那一天起,就不断地进行改进和优化,并且努力深入到供应链的每一个环节。优化其实是一门运筹学问题,需考虑在各种决策目标之间如何平衡以达到最大收益,在这个过程中需要考虑很多问题,把这些考虑清楚,问题就容易解决了。举几个简单的例子:

  • 商品补货:考虑在什么时间,给哪个 RDC 采购什么商品,采购量是多少?
  • 商品调拨:考虑在什么时间,给哪个 FDC 调配什么商品,调配量是多少?
  • 仓储运营:在大促来临之际,仓库和配送站要增配多少人手、多少辆货车?

虽然看上去这些问题都很容易回答,但仔细想想却又很难给出答案,原因就在于想要做到精确不是那么容易的事情,就拿补货来说,补的太多会增加库存成本,补的太少会增加缺货成本,只有合理的补货量才能做到成本最低。

1.3 预测技术在京东供应链的作用

借助机器学习、大数据等相关技术,京东在很多供应链优化问题上都已经实现系统化,由系统自动给出优化建议,并与生产系统相连接,实现全流程自动化。在这里有一项技术起着至关重要的低层支撑作用–预测技术。据粗略估算,1% 的预测准确度的提升可以节约数倍的运营成本。

怎样理解预测在供应链优化中的作用呢? 拿商品补货举例,一家公司为了保证库房不缺货,可能会频繁的从供货商那里补充大量商品,这样做虽然不会缺货,但可能会造成更多卖不出去的商品积压在仓库中,从而使商品的周转率降低,库存成本增加。反之,这家公司有可能为了追求零库存而补很少的商品,但这就可能出现严重的缺货问题,从而使现货率降低,严重影响用户体验,缺货成本增加。于是问题就来了,要补多少商品才合适,什么时间补货,这就需要权衡考虑了,最终目的是要使库存成本和缺货成本达到一个平衡。

考虑一下极端情况,等库存降到零时再去补货,这时供货商接到补货通知后将货物运往仓库。但是这么做有个问题,因为运送过程需要时间,这段时间库房就缺货了。那怎么办呢? 就是利用预测技术。利用预测我们可以计算出未来商品在途的这段时间里销量大概是多少,然后我们让仓库保证这个量,低于这个量就给供货商下达补货通知,于是问题得以解决。总而言之,预测技术在这里发挥了重要的作用,成为关键的一个环。

2. 京东预测系统

2.1 预测系统介绍

预测系统在整个供应链体系中处在最底层并且起到一个支撑的作用,支持上层的多个决策优化系统,而这些决策优化系统利用精准的预测数据结合运筹学技术得出最优的决策,并将结果提供给更上层的业务执行系统或是业务方直接使用。

目前,预测系统主要支持三大业务:销量预测、单量预测和 GMV 预测。其中销量预测主要支持商品补货、商品调拨;单量预测主要支持仓库、站点的运营管理;GMV 预测主要支持销售部门计划的定制。

销量预测按照不同维度又可以分为 RDC 采购预测、FDC 调拨预测、城市仓调拨预测、大建仓补货预测、全球购销量预测和图书促销预测等;单量预测又可分为库房单量预测、配送中心单量预测和配送站单量预测等(在这里“单量”并非指用户所下订单的量,而是将订单拆单后流转到仓库中的单量。例如一个用户的订单中包括 3 件物品,其中两个大件品和一个小件品,在京东的供应链环节中可能会将其中两个大件品组成一个单投放到大件仓中,而将那个小件单独一个单投放到小件仓中,单量指的是拆单后的量);GMV 预测支持到商品粒度。

2.2 预测系统架构

整体架构从上至下依次是:数据源输入层、基础数据加工层、核心业务层、数据输出层和下游系统。首先从外部数据源获取我们所需的业务数据,然后对基础数据进行加工清洗,再通过时间序列、机器学习等人工智能技术对数据进行处理分析,最后计算出预测结果并通过多种途径推送给下游系统使用。

  • 数据源输入层:京东数据仓库中存储着我们需要的大部分业务数据,例如订单信息、商品信息、库存信息等等。而对于促销计划数据则大部分来自于采销人员通过 Web 系统录入的信息。除此之外还有一小部分数据通过文本形式直接上传到 HDFS 中。

  • 基础数据加工层:在这一层主要通过 Hive 对基础数据进行一些加工清洗,去掉不需要的字段,过滤不需要的维度并清洗有问题的数据。

  • 核心业务层:这层是系统的的核心部分,横向看又可分为三层:特征构建、预测算法和预测结果加工。纵向看是由多条业务线组成,彼此之间不发生任何交集。

    • 特征构建:将之前清洗过的基础数据通过近一步的处理转化成标准格式的特征数据,提供给后续算法模型使用。
    • 核心算法:利用时间序列分析、机器学习等人工智能技术进行销量、单量的预测,是预测系统中最为核心的部分。
    • 预测结果加工:预测结果可能在格式和一些特殊性要求上不能满足下游系统,所以还需要根据实际情况对其进行加工处理,比如增加标准差、促销标识等额外信息。
  • 预测结果输出层:将最终预测结果同步回京东数据仓库、MySql、HBase 或制作成 JSF 接口供其他系统远程调用。

  • 下游系统:包括下游任务流程、下游 Web 系统和其他系统。

3. 预测系统核心介绍

3.1 预测系统核心层技术选型

预测系统核心层技术主要分为四层:基础层、框架层、工具层和算法层

基础层:

HDFS 用来做数据存储,Yarn 用来做资源调度,BDP(Big Data Platform)是京东自己研发的大数据平台,我们主要用它来做任务调度。

框架层:

以 Spark RDD、Spark SQL、Hive 为主, MapReduce 程序占一小部分,是原先遗留下来的,目前正逐步替换成 Spark RDD。 选择 Spark 除了对性能的考虑外,还考虑了 Spark 程序开发的高效率、多语言特性以及对机器学习算法的支持。在 Spark 开发语言上我们选择了 Python,原因有以下三点:

  • Python 有很多不错的机器学习算法包可以使用,比起 Spark 的 MLlib,算法的准确度更高。我们用 GBDT 做过对比,发现 xgboost 比 MLlib 里面提供的提升树模型预测准确度高出大概 5%~10%。虽然直接使用 Spark 自带的机器学习框架会节省我们的开发成本,但预测准确度对于我们来说至关重要,每提升 1% 的准确度,就可能会带来成本的成倍降低。
  • 我们的团队中包括开发工程师和算法工程师,对于算法工程师而言他们更擅长使用 Python 进行数据分析,使用 Java 或 Scala 会有不小的学习成本。
  • 对比其他语言,我们发现使用 Python 的开发效率是最高的,并且对于一个新人,学习 Python 比学习其他语言更加容易。

工具层:

一方面我们会结合自身业务有针对性的开发一些算法,另一方面我们会直接使用业界比较成熟的算法和模型,这些算法都封装在第三方 Python 包中。我们比较常用的包有 xgboost、numpy、pandas、sklearn、scipy 和 hyperopt 等。

Xgboost:它是 Gradient Boosting Machine 的一个 C++ 实现,xgboost 最大的特点在于,它能够自动利用 CPU 的多线程进行并行,同时在算法上加以改进提高了精度。

numpy:是 Python 的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比 Python 自身的嵌套列表结构要高效的多(该结构也可以用来表示矩阵)。

pandas:是基于 NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。

sklearn:是 Python 重要的机器学习库,支持包括分类、回归、降维和聚类四大机器学习算法。还包含了特征提取、数据处理和模型评估三大模块。

scipy:是在 NumPy 库的基础上增加了众多的数学、科学以及工程计算中常用的库函数。例如线性代数、常微分方程数值求解、信号处理、图像处理和稀疏矩阵等等。

算法层:

我们用到的算法模型非常多,原因是京东的商品品类齐全、业务复杂,需要根据不同的情况采用不同的算法模型。我们有一个独立的系统来为算法模型与商品之间建立匹配关系,有些比较复杂的预测业务还需要使用多个模型。我们使用的算法总体上可以分为三类:时间序列、机器学习和结合业务开发的一些独有的算法。

1. 机器学习算法主要包括 GBDT、LASSO 和 RNN :

GBDT:是一种迭代的决策树算法,该算法由多棵决策树组成,所有树的结论累加起来做最终答案。我们用它来预测高销量,但历史规律不明显的商品。

RNN:这种网络的内部状态可以展示动态时序行为。不同于前馈神经网络的是,RNN 可以利用它内部的记忆来处理任意时序的输入序列,这让它可以更容易处理如时序预测、语音识别等。

LASSO:该方法是一种压缩估计。它通过构造一个罚函数得到一个较为精炼的模型,使得它压缩一些系数,同时设定一些系数为零。因此保留了子集收缩的优点,是一种处理具有复共线性数据的有偏估计。用来预测低销量,历史数据平稳的商品效果较好。

2. 时间序列主要包括 ARIMA 和 Holt winters :

ARIMA:全称为自回归积分滑动平均模型,于 70 年代初提出的一个著名时间序列预测方法,我们用它来主要预测类似库房单量这种平稳的序列。

Holt winters:又称三次指数平滑算法,也是一个经典的时间序列算法,我们用它来预测季节性和趋势都很明显的商品。

3. 结合业务开发的独有算法包括 WMAStockDT、SimilarityModel 和 NewProduct 等:

WMAStockDT:库存决策树模型,用来预测受库存状态影响较大的商品。

SimilarityModel:相似品模型,使用指定的同类品数据来预测某商品未来销量。

NewProduct:新品模型,顾名思义就是用来预测新品的销量。

3.2 预测系统核心流程

预测核心流程主要包括两类:以机器学习算法为主的流程和以时间序列分析为主的流程。

1. 以机器学习算法为主的流程如下:

特征构建:通过数据分析、模型试验确定主要特征,通过一系列任务生成标准格式的特征数据。

模型选择:不同的商品有不同的特性,所以首先会根据商品的销量高低、新品旧品、假节日敏感性等因素分配不同的算法模型。

特征选择:对一批特征进行筛选过滤不需要的特征,不同类型的商品特征不同。

样本分区:对训练数据进行分组,分成多组样本,真正训练时针对每组样本生成一个模型文件。一般是同类型商品被分成一组,比如按品类维度分组,这样做是考虑并行化以及模型的准确性。

模型参数:选择最优的模型参数,合适的参数将提高模型的准确度,因为需要对不同的参数组合分别进行模型训练和预测,所以这一步是非常耗费资源。

模型训练:待特征、模型、样本都确定好后就可以进行模型训练,训练往往会耗费很长时间,训练后会生成模型文件,存储在 HDFS 中。

模型预测:读取模型文件进行预测执行。

多模型择优:为了提高预测准确度,我们可能会使用多个算法模型,当每个模型的预测结果输出后系统会通过一些规则来选择一个最优的预测结果。

预测值异常拦截:我们发现越是复杂且不易解释的算法越容易出现极个别预测值异常偏高的情况,这种预测偏高无法结合历史数据进行解释,因此我们会通过一些规则将这些异常值拦截下来,并且用一个更加保守的数值代替。

模型评价:计算预测准确度,我们通常用使用 mapd 来作为评价指标。

误差分析:通过分析预测准确度得出一个误差在不同维度上的分布,以便给算法优化提供参考依据。

2. 以时间序列分析为主的预测流程如下:

生成历史时序:将历史销量、价格、库存等数据按照规定格式生成时序数据。

节假日因子:计算节假日与销量之间的关系,用来平滑节假日对销量影响。

周日因子:计算周一到周日这 7 天与销量的关系,用来平滑周日对销量的影响。

促销因子:计算促销与销量之间的关系,用来平滑促销对销量的影响。

因子平滑:历史销量是不稳定的,会受到节假日、促销等影响,在这种情况下进行预测有很大难度,所以需要利用之前计算的各类因子对历史数据进行平滑处理。

时序预测:在一个相对平稳的销量数据上通过算法进行预测。

因子叠加:结合未来节假日、促销计划等因素对预测结果进行调整。

3.3 Spark 在预测核心层的应用

我们使用 Spark SQL 和 Spark RDD 相结合的方式来编写程序,对于一般的数据处理,我们使用 Spark 的方式与其他无异,但是对于模型训练、预测这些需要调用算法接口的逻辑就需要考虑一下并行化的问题了。我们平均一个训练任务在一天处理的数据量大约在 500G 左右,虽然数据规模不是特别的庞大,但是 Python 算法包提供的算法都是单进程执行。我们计算过,如果使用一台机器训练全部品类数据需要一个星期的时间,这是无法接收的,所以我们需要借助 Spark 这种分布式并行计算框架来将计算分摊到多个节点上实现并行化处理。

我们实现的方法很简单,首先需要在集群的每个节点上安装所需的全部 Python 包,然后在编写 Spark 程序时考虑通过某种规则将数据分区,比如按品类维度,通过 groupByKey 操作将数据重新分区,每一个分区是一个样本集合并进行独立的训练,以此达到并行化。流程如下图所示:

伪码如下:

repartitionBy 方法即设置一个重分区的逻辑返回 (K,V) 结构 RDD,train 方法是训练数据,在 train 方法里面会调用 Python 算法包接口。saveAsPickleFile 是 Spark Python 独有的一个 Action 操作,支持将 RDD 保存成序列化后的 sequnceFile 格式的文件,在序列化过程中会以 10 个一批的方式进行处理,保存模型文件非常适合。

虽然原理简单,但存在着一个难点,即以什么样的规则进行分区,key 应该如何设置。为了解决这个问题我们需要考虑几个方面,第一就是哪些数据应该被聚合到一起进行训练,第二就是如何避免数据倾斜。

针对第一个问题我们做了如下几点考虑:

  • 被分在一个分区的数据要有一定的相似性,这样训练的效果才会更好,比如按品类分区就是个典型例子。
  • 分析商品的特性,根据特性的不同选择不同的模型,例如高销商品和低销商品的预测模型是不一样的,即使是同一模型使用的特征也可能不同,比如对促销敏感的商品就需要更多与促销相关特征,相同模型相同特征的商品应倾向于分在一个分区中。

针对第二个问题我们采用了如下的方式解决:

  • 对于数据量过大的分区进行随机抽样选取。
  • 对于数据量过大的分区还可以做二次拆分,比如图书小说这个品类数据量明显大于其他品类,于是就可以分析小说品类下的子品类数据量分布情况,并将子品类合并成新的几个分区。
  • 对于数据量过小这种情况则需要考虑进行几个分区数据的合并处理。

总之对于后两种处理方式可以单独通过一个 Spark 任务定期运行,并将这种分区规则保存。

4. 结合图解 Spark 书进行应用与优化

《图解 Spark:核心技术与案例实战》一书以 Spark2.0 版本为基础进行编写,系统介绍了 Spark 核心及其生态圈组件技术。其内容包括 Spark 生态圈、实战环境搭建和编程模型等,重点介绍了作业调度、容错执行、监控管理、存储管理以及运行架构,同时还介绍了 Spark 生态圈相关组件,包括了 Spark SQL 的即席查询、Spark Streaming 的实时流处理、MLlib 的机器学习、GraphX 的图处理和 Alluxio 的分布式内存文件系统等。下面介绍京东预测系统如何进行资源调度,并描述如何使用 Spark 存储相关知识进行系统优化。

4.1 结合系统中的应用

在图解 Spark 书的第六章描述了 Spark 运行架构,介绍了 Spark 集群资源调度一般分为粗粒度调度和细粒度调度两种模式。粗粒度包括了独立运行模式和 Mesos 粗粒度运行模式,在这种情况下以整个机器作为分配单元执行作业,该模式优点是由于资源长期持有减少了资源调度的时间开销,缺点是该模式中无法感知资源使用的变化,易造成系统资源的闲置,从而造成了资源浪费。而细粒度包括了 Yarn 运行模式和 Mesos 细粒度运行模式, 该模式的优点是系统资源能够得到充分利用,缺点是该模式中每个任务都需要从管理器获取资源,调度延迟较大、开销较大。

由于京东 Spark 集群属于基础平台,在公司内部共享这些资源,所以集群采用的是 Yarn 运行模式,在这种模式下可以根据不同系统所需要的资源进行灵活的管理。在 YARN-Cluster 模式中,当用户向 YARN 集群中提交一个应用程序后,YARN 集群将分两个阶段运行该应用程序:第一个阶段是把 Spark 的 SparkContext 作为 Application Master 在 YARN 集群中先启动;第二个阶段是由 Application Master 创建应用程序,然后为它向 Resource Manager 申请资源,并启动 Executor 来运行任务集,同时监控它的整个运行过程,直到运行完成。下图为 Yarn-Cluster 运行模式执行过程:

4.2 结合系统的优化

我们都知道大数据处理的瓶颈在 IO。我们借助 Spark 可以把迭代过程中的数据放在内存中,相比 MapReduce 写到磁盘速度提高近两个数量级;另外对于数据处理过程尽可能避免 Shuffle,如果不能避免则 Shuffle 前尽可能过滤数据,减少 Shuffle 数据量;最后,就是使用高效的序列化和压缩算法。在京东预测系统主要就是围绕这些环节展开优化,相关 Spark 存储原理知识可以参见图解 Spark 书第五章的详细描述。

由于资源限制,分配给预测系统的 Spark 集群规模并不是很大, 在有限的资源下运行 Spark 应用程序确实是一个考验,因为在这种情况下经常会出现诸如程序计算时间太长、找不到 Executor 等错误。我们通过调整参数、修改设计和修改程序逻辑三个方面进行优化:

4.2.1 参数调整

  • 减少 num-executors,调大 executor-memory,这样的目的是希望 Executor 有足够的内存可以使用。
  • 查看日志发现没有足够的空间存储广播变量,分析是由于 Cache 到内存里的数据太多耗尽了内存,于是我们将 Cache 的级别适当调成 MEMORY_ONLY_SER 和 DISK_ONLY。
  • 针对某些任务关闭了推测机制,因为有些任务会出现暂时无法解决的数据倾斜问题,并非节点出现问题。
  • 调整内存分配,对于一个 Shuffle 很多的任务,我们就把 Cache 的内存分配比例调低,同时调高 Shuffle 的内存比例。

4.2.2 修改设计

参数的调整虽然容易做,但往往效果不好,这时候需要考虑从设计的角度去优化:

  • 原先在训练数据之前会先读取历史的几个月甚至几年的数据,对这些数据进行合并、转换等一系列复杂的处理,最终生成特征数据。由于数据量庞大,任务有时会报错。经过调整后当天只处理当天数据,并将结果保存到当日分区下,训练时按天数需要读取多个分区的数据做 union 操作即可。
  • 将“模型训练”从每天执行调整到每周执行,将“模型参数选取”从每周执行调整到每月执行。因为这两个任务都十分消耗资源,并且属于不需要频繁运行,这么做虽然准确度会略微降低,但都在可接受范围内。
  • 通过拆分任务也可以很好的解决资源不够用的问题。可以横向拆分,比如原先是将 100 个品类数据放在一个任务中进行训练,调整后改成每 10 个品类提交一次 Spark 作业进行训练。这样虽然整体执行时间变长,但是避免了程序异常退出,保证任务可以执行成功。除了横向还可以纵向拆分,即将一个包含 10 个 Stage 的 Spark 任务拆分成两个任务,每个任务包含 5 个 Stage,中间数据保存到 HDFS 中。

4.2.3 修改程序逻辑

为了进一步提高程序的运行效率,通过修改程序的逻辑来提高性能,主要是在如下方面进行了改进:避免过多的 Shuffle、减少 Shuffle 时需要传输的数据和处理数据倾斜问题等。

1. 避免过多的 Shuffle

Spark 提供了丰富的转换操作,可以使我们完成各类复杂的数据处理工作,但是也正因为如此我们在写 Spark 程序的时候可能会遇到一个陷阱,那就是为了使代码变的简洁过分依赖 RDD 的转换操作,使本来仅需一次 Shuffle 的过程变为了执行多次。我们就曾经犯过这样一个错误, 本来可以通过一次 groupByKey 完成的操作却使用了两回。业务逻辑是这样的:我们有三张表分别是销量(s)、价格(p)、库存(v),每张表有 3 个字段:商品 id(sku_id)、品类 id(category)和历史时序数据(data),现在需要按 sku_id 将 s、p、v 数据合并,然后再按 category 再合并一次,最终的数据格式是:[category,[[sku_id, s , p, v], [sku_id, s , p, v], […],[…]]]。一开始我们先按照 sku_id + category 作为 key 进行一次 groupByKey,将数据格式转换成 [sku_id, category , [s,p, v]],然后按 category 作为 key 再 groupByKey 一次。后来我们修改为按照 category 作为 key 只进行一次 groupByKey,因为一个 sku_id 只会属于一个 category,所以后续的 map 转换里面只需要写一些代码将相同 sku_id 的 s、p、v 数据 group 到一起就可以了。两次 groupByKey 的情况:

修改后变为一次 groupByKey 的情况:

** 多表 join 时,如果 key 值相同,则可以使用 union + groupByKey + flatMapValues 形式进行。** 比如:需要将销量、库存、价格、促销计划和商品信息通过商品编码连接到一起,一开始使用的是 join 转换操作,将几个 RDD 彼此 join 在一起。后来发现这样做运行速度非常慢,于是换成 union+groypByKey+flatMapValue 形式,这样做只需进行一次 Shuffle,这样修改后运行速度比以前快多了。实例代码如下:

如果两个 RDD 需要在 groupByKey 后进行 join 操作,可以使用 cogroup 转换操作代替。比如, 将历史销量数据按品类进行合并,然后再与模型文件进行 join 操作,流程如下:

使用 cogroup 后,经过一次 Shuffle 就可完成了两步操作,性能大幅提升。

2. 减少 Shuffle 时传输的数据量

  • 在 Shuffle 操作前尽量将不需要的数据过滤掉。
  • 使用 comebineyeByKey 可以高效率的实现任何复杂的聚合逻辑。

comebineyeByKey 属于聚合类操作,由于它支持 map 端的聚合所以比 groupByKey 性能好,又由于它的 map 端与 reduce 端可以设置成不一样的逻辑,所以它支持的场景比 reduceByKey 多,它的定义如下:

reduceByKey 和 groupByKey 内部实际是调用了 comebineyeByKey,

我们之前有很多复杂的无法用 reduceByKey 来实现的聚合逻辑都通过 groupByKey 来完成的,后来全部替换为 comebineyeByKey 后性能提升了不少。

3. 处理数据倾斜

有些时候经过一系列转换操作之后数据变得十分倾斜,在这样情况下后续的 RDD 计算效率会非常的糟糕,严重时程序报错。遇到这种情况通常会使用 repartition 这个转换操作对 RDD 进行重新分区,重新分区后数据会均匀分布在不同的分区中,避免了数据倾斜。如果是减少分区使用 coalesce 也可以达到效果,但比起 repartition 不足的是分配不是那么均匀。

5. 小结

虽然京东的预测系统已经稳定运行了很长一段时间,但是我们也看到系统本身还存在着很多待改进的地方,接下来我们会在预测准确度的提高、系统性能的优化、多业务支持的便捷性上进行改进。未来,随着大数据、人工智能技术在京东供应链管理中的使用越来越多,预测系统也将发挥出更大作用,对于京东预测系统的研发工作也将是充满着挑战与乐趣。

答疑环节

Q1:用 hive 清洗完以后的数据还存在 hive 中吗?那原始数据还保留吗?或者说保留多久?谢谢老师!

杨冬越:清洗后数据还会存回 hive,原始数据不会删,但在清洗转换过程中可能会执行多个 hive 脚本,会产生很多中间数据,这些中间数据只会保留一段时间,然后自动删除(是按时间进行分区的)。

Q2:几种细化的场景,如 promotion,fast sale,商品 sku 的画像是否有?

杨冬越:对于促销这种情况会引入历史促销销量作为特征,预测时也会结合促销计划,促销计划都是提前录入到系统中的,除此还需要分析价格、PV 在商品上的敏感成的。对于快消品需要结合商品的生命周期去做。

Q3:按架构看,那种交互探索性的请求,类似于以前 sql 请求去仓库捞一下数据看看的情况,是用 sparksql 来支撑吗?一般响应时间大概如何?

郭景瞻:对,离线数据是通过 SparkSQL 进行查询,响应时间依赖于集群的规模、查询的数据量及 SQL 的复杂程度, 在预测系统使用的数据大概 500GB,少的 2 分钟左右,最多不超过 20 分钟。

Q4:请问如何选择模型? 是不同品类有不同模型吗?

杨冬越:不完全是根据品类分模型,还要考虑是否高销量品、是否长尾品、是否新品、是否是季节性比较明显的商品等。

Q5:节假日因子怎么量化?

杨冬越:首先要进行平滑,尽量把其他干扰因素去掉,再计算节假日期间与前后一段时间均值对比,要注意考虑阳历和农历,还有如果新品还会根据同品类或同品牌进行替代。

作者介绍

杨冬越,就职于京东 Y 事业部,主要从事供应链销量预测、单量预测等模型、算法的研究与实现工作

郭景瞻,就职于京东服饰家居事业部,主要负责 POP 商家订单及数据挖掘等工作,著有《图解 Spark:核心技术与案例实战》一书


感谢杜小芳对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-08-10 17:356527

评论

发布
暂无评论
发现更多内容

如何设计一组会出现死锁(Deadlock)的 ABAP 程序

汪子熙

Java 死锁 SAP abap 6 月 优质更文活动

MobPush 查看推送数据

MobTech袤博科技

官宣!XTransfer与全球社交网络服务巨头Meta达成战略合作

XTransfer技术

首个锚定BTC Mining算力的HAG证券通证,或成传统投资者的另一选择

股市老人

红杉中国独立,艰难时期“美元基金”投资路径浮出水面

B Impact

2023-06-07:Redis 持久化方式有哪些?以及有什么区别?

福大大架构师每日一题

redis 福大大

开放源代码平台Flynn的架构与实现原理

穿过生命散发芬芳

Flynn 6 月 优质更文活动

程序员如何成长

光毅

成长 程序员‘

聊聊那些奇葩的代码规范 —— 滥用 lombok

HoneyMoose

什么是智慧公共厕所?光明源智慧厕所

光明源智慧厕所

CoinList打新以太坊虚拟机Neon

币离海

以太坊虚拟机 neon Coinlist Solana

1v1视频交友APP的详细搭建部署步骤和视频交友APP核心功能介绍

山东布谷科技胡月

一对一直播源码 一对一直播系统 1v1语音系统搭建 视频社交APP开发 1v1交友app开发

搞定大模型,AI 大底座系列云智公开课 6 月 20 日开始上线

Baidu AICLOUD

大模型 AI 大底座

开源“上天入地”的本领都在这!2023开放原子全球开源峰会「开源展览」一文拿捏!

开放原子开源基金会

开源 开放原子全球开源峰会 开源展览

ChatGPT赋能产品管理

俞凡

人工智能 产品管理 ChatGPT

文心一言 VS 讯飞星火 VS chatgpt (34)-- 算法导论5.3 1题

福大大架构师每日一题

福大大 ChatGPT

C语言编程—预处理器

芯动大师

C语言 预处理器 6 月 优质更文活动

Unlimiformer:用搜索的思路来处理注意力机制长度限制

Zilliz

Transformer

Java 8升级Java 17过程记录

程序员架构进阶

jdk8 升级 java17 6月月更 6 月 优质更文活动

Flink实例:Flink流处理程序编程模型

TiAmo

scala 数据流 Flink 平台 6 月 优质更文活动

JMeter笔记10 | JMeter检查点

测试 Jmeter 性能测试 自动化测试 接口测试

什么是双机热备技术?华为和思科如何实现双机热备?

wljslmz

6 月 优质更文活动

能力,责任心和危机感(67/100)

hackstoic

管理

【Python金融-002】快速计算收益,批量做T必备!

程序员晚枫

Python 数据分析 金融 股票 做T

RocketMQ 学习社区重磅上线!AI 互动,一秒了解 RocketMQ 功能源码

阿里巴巴云原生

阿里云 AI RocketMQ 云原生

十大理由,说清企业为何需要 CI/CD

极狐GitLab

DevOps 自动化 CI/CD 降本增效 效能提升

GOTC全球开源技术峰会|Sermant首次亮相,推进云原生微服务治理技术的演进

华为云开源

#云原生

【Netty】「NIO」(四)消息边界与可写事件

sidiot

Java 后端 Netty 6 月 优质更文活动

探访官招募 | InfoQ 写作社区 邀您探访 2023 亚马逊云科技中国峰会

InfoQ写作社区官方

热门活动

GitOps 最佳实践(上)| 基于 Amazon EKS 构建 CI/CD 流水线

亚马逊云科技 (Amazon Web Services)

微服务

Spark技术在京东智能供应链预测的应用_语言 & 开发_杨冬越_InfoQ精选文章