大數(shù)據(jù)|Spark技術(shù)在京東智能供應(yīng)鏈預(yù)測(cè)的應(yīng)用案例深度剖析(二)

慧都學(xué)院
佚名
          3. 預(yù)測(cè)系統(tǒng)核心介紹 3.1 預(yù)測(cè)系統(tǒng)核心層技術(shù)選型            &...

         

3. 預(yù)測(cè)系統(tǒng)核心介紹

3.1 預(yù)測(cè)系統(tǒng)核心層技術(shù)選型


              大數(shù)據(jù)|Spark技術(shù)在京東智能供應(yīng)鏈預(yù)測(cè)的應(yīng)用案例深度剖析(二)

預(yù)測(cè)系統(tǒng)核心層技術(shù)主要分為四層:基礎(chǔ)層、框架層、工具層和算法層

基礎(chǔ)層: HDFS用來做數(shù)據(jù)存儲(chǔ),Yarn用來做資源調(diào)度,BDP(Big Data Platform)是京東自己研發(fā)的大數(shù)據(jù)平臺(tái),我們主要用它來做任務(wù)調(diào)度。

框架層: 以Spark RDD、Spark SQL、Hive為主, MapReduce程序占一小部分,是原先遺留下來的,目前正逐步替換成Spark RDD。 選擇Spark除了對(duì)性能的考慮外,還考慮了Spark程序開發(fā)的高效率、多語(yǔ)言特性以及對(duì)機(jī)器學(xué)習(xí)算法的支持。在Spark開發(fā)語(yǔ)言上我們選擇了Python,原因有以下三點(diǎn):

Python有很多不錯(cuò)的機(jī)器學(xué)習(xí)算法包可以使用,比起Spark的MLlib,算法的準(zhǔn)確度更高。我們用GBDT做過對(duì)比,發(fā)現(xiàn)xgboost比MLlib里面提供的提升樹模型預(yù)測(cè)準(zhǔn)確度高出大概5%~10%。雖然直接使用Spark自帶的機(jī)器學(xué)習(xí)框架會(huì)節(jié)省我們的開發(fā)成本,但預(yù)測(cè)準(zhǔn)確度對(duì)于我們來說至關(guān)重要,每提升1%的準(zhǔn)確度,就可能會(huì)帶來成本的成倍降低。

我們的團(tuán)隊(duì)中包括開發(fā)工程師和算法工程師,對(duì)于算法工程師而言他們更擅長(zhǎng)使用Python進(jìn)行數(shù)據(jù)分析,使用Java或Scala會(huì)有不小的學(xué)習(xí)成本。

對(duì)比其他語(yǔ)言,我們發(fā)現(xiàn)使用Python的開發(fā)效率是最高的,并且對(duì)于一個(gè)新人,學(xué)習(xí)Python比學(xué)習(xí)其他語(yǔ)言更加容易。

工具層: 一方面我們會(huì)結(jié)合自身業(yè)務(wù)有針對(duì)性的開發(fā)一些算法,另一方面我們會(huì)直接使用業(yè)界比較成熟的算法和模型,這些算法都封裝在第三方Python包中。我們比較常用的包有xgboost、numpy、pandas、sklearn、scipy和hyperopt等。

Xgboost:它是Gradient Boosting Machine的一個(gè)C++實(shí)現(xiàn),xgboost最大的特點(diǎn)在于,它能夠自動(dòng)利用CPU的多線程進(jìn)行并行,同時(shí)在算法上加以改進(jìn)提高了精度。

numpy:是Python的一種開源的數(shù)值計(jì)算擴(kuò)展。這種工具可用來存儲(chǔ)和處理大型矩陣,比Python自身的嵌套列表結(jié)構(gòu)要高效的多(該結(jié)構(gòu)也可以用來表示矩陣)。

pandas:是基于NumPy 的一種工具,該工具是為了解決數(shù)據(jù)分析任務(wù)而創(chuàng)建的。Pandas 納入了大量庫(kù)和一些標(biāo)準(zhǔn)的數(shù)據(jù)模型,提供了高效地操作大型數(shù)據(jù)集所需的工具。

sklearn:是Python重要的機(jī)器學(xué)習(xí)庫(kù),支持包括分類、回歸、降維和聚類四大機(jī)器學(xué)習(xí)算法。還包含了特征提取、數(shù)據(jù)處理和模型評(píng)估三大模塊。

scipy:是在NumPy庫(kù)的基礎(chǔ)上增加了眾多的數(shù)學(xué)、科學(xué)以及工程計(jì)算中常用的庫(kù)函數(shù)。例如線性代數(shù)、常微分方程數(shù)值求解、信號(hào)處理、圖像處理和稀疏矩陣等等。

算法層: 我們用到的算法模型非常多,原因是京東的商品品類齊全、業(yè)務(wù)復(fù)雜,需要根據(jù)不同的情況采用不同的算法模型。我們有一個(gè)獨(dú)立的系統(tǒng)來為算法模型與商品之間建立匹配關(guān)系,有些比較復(fù)雜的預(yù)測(cè)業(yè)務(wù)還需要使用多個(gè)模型。我們使用的算法總體上可以分為三類:時(shí)間序列、機(jī)器學(xué)習(xí)和結(jié)合業(yè)務(wù)開發(fā)的一些獨(dú)有的算法。

1. 機(jī)器學(xué)習(xí)算法主要包括GBDT、LASSO和RNN :

GBDT:是一種迭代的決策樹算法,該算法由多棵決策樹組成,所有樹的結(jié)論累加起來做最終答案。我們用它來預(yù)測(cè)高銷量,但歷史規(guī)律不明顯的商品。

RNN:這種網(wǎng)絡(luò)的內(nèi)部狀態(tài)可以展示動(dòng)態(tài)時(shí)序行為。不同于前饋神經(jīng)網(wǎng)絡(luò)的是,RNN可以利用它內(nèi)部的記憶來處理任意時(shí)序的輸入序列,這讓它可以更容易處理如時(shí)序預(yù)測(cè)、語(yǔ)音識(shí)別等。

LASSO:該方法是一種壓縮估計(jì)。它通過構(gòu)造一個(gè)罰函數(shù)得到一個(gè)較為精煉的模型,使得它壓縮一些系數(shù),同時(shí)設(shè)定一些系數(shù)為零。因此保留了子集收縮的優(yōu)點(diǎn),是一種處理具有復(fù)共線性數(shù)據(jù)的有偏估計(jì)。用來預(yù)測(cè)低銷量,歷史數(shù)據(jù)平穩(wěn)的商品效果較好。

2. 時(shí)間序列主要包括ARIMA和Holt winters :

ARIMA:全稱為自回歸積分滑動(dòng)平均模型,于70年代初提出的一個(gè)著名時(shí)間序列預(yù)測(cè)方法,我們用它來主要預(yù)測(cè)類似庫(kù)房單量這種平穩(wěn)的序列。

Holt winters:又稱三次指數(shù)平滑算法,也是一個(gè)經(jīng)典的時(shí)間序列算法,我們用它來預(yù)測(cè)季節(jié)性和趨勢(shì)都很明顯的商品。

3. 結(jié)合業(yè)務(wù)開發(fā)的獨(dú)有算法包括WMAStockDT、SimilarityModel和NewProduct等:

WMAStockDT:庫(kù)存決策樹模型,用來預(yù)測(cè)受庫(kù)存狀態(tài)影響較大的商品。

SimilarityModel:相似品模型,使用指定的同類品數(shù)據(jù)來預(yù)測(cè)某商品未來銷量。

NewProduct:新品模型,顧名思義就是用來預(yù)測(cè)新品的銷量。

3.2 預(yù)測(cè)系統(tǒng)核心流程

預(yù)測(cè)核心流程主要包括兩類:以機(jī)器學(xué)習(xí)算法為主的流程和以時(shí)間序列分析為主的流程。

1. 以機(jī)器學(xué)習(xí)算法為主的流程如下:


               大數(shù)據(jù)|Spark技術(shù)在京東智能供應(yīng)鏈預(yù)測(cè)的應(yīng)用案例深度剖析(二)

特征構(gòu)建:通過數(shù)據(jù)分析、模型試驗(yàn)確定主要特征,通過一系列任務(wù)生成標(biāo)準(zhǔn)格式的特征數(shù)據(jù)。

模型選擇:不同的商品有不同的特性,所以首先會(huì)根據(jù)商品的銷量高低、新品舊品、假節(jié)日敏感性等因素分配不同的算法模型。

特征選擇:對(duì)一批特征進(jìn)行篩選過濾不需要的特征,不同類型的商品特征不同。

樣本分區(qū):對(duì)訓(xùn)練數(shù)據(jù)進(jìn)行分組,分成多組樣本,真正訓(xùn)練時(shí)針對(duì)每組樣本生成一個(gè)模型文件。一般是同類型商品被分成一組,比如按品類維度分組,這樣做是考慮并行化以及模型的準(zhǔn)確性。

模型參數(shù):選擇最優(yōu)的模型參數(shù),合適的參數(shù)將提高模型的準(zhǔn)確度,因?yàn)樾枰獙?duì)不同的參數(shù)組合分別進(jìn)行模型訓(xùn)練和預(yù)測(cè),所以這一步是非常耗費(fèi)資源。

模型訓(xùn)練:待特征、模型、樣本都確定好后就可以進(jìn)行模型訓(xùn)練,訓(xùn)練往往會(huì)耗費(fèi)很長(zhǎng)時(shí)間,訓(xùn)練后會(huì)生成模型文件,存儲(chǔ)在HDFS中。

模型預(yù)測(cè):讀取模型文件進(jìn)行預(yù)測(cè)執(zhí)行。

多模型擇優(yōu):為了提高預(yù)測(cè)準(zhǔn)確度,我們可能會(huì)使用多個(gè)算法模型,當(dāng)每個(gè)模型的預(yù)測(cè)結(jié)果輸出后系統(tǒng)會(huì)通過一些規(guī)則來選擇一個(gè)最優(yōu)的預(yù)測(cè)結(jié)果。

預(yù)測(cè)值異常攔截:我們發(fā)現(xiàn)越是復(fù)雜且不易解釋的算法越容易出現(xiàn)極個(gè)別預(yù)測(cè)值異常偏高的情況,這種預(yù)測(cè)偏高無法結(jié)合歷史數(shù)據(jù)進(jìn)行解釋,因此我們會(huì)通過一些規(guī)則將這些異常值攔截下來,并且用一個(gè)更加保守的數(shù)值代替。

模型評(píng)價(jià):計(jì)算預(yù)測(cè)準(zhǔn)確度,我們通常用使用mapd來作為評(píng)價(jià)指標(biāo)。

誤差分析:通過分析預(yù)測(cè)準(zhǔn)確度得出一個(gè)誤差在不同維度上的分布,以便給算法優(yōu)化提供參考依據(jù)。

2. 以時(shí)間序列分析為主的預(yù)測(cè)流程如下:


               大數(shù)據(jù)|Spark技術(shù)在京東智能供應(yīng)鏈預(yù)測(cè)的應(yīng)用案例深度剖析(二)

3.3 Spark在預(yù)測(cè)核心層的應(yīng)用

我們使用Spark SQL和Spark RDD相結(jié)合的方式來編寫程序,對(duì)于一般的數(shù)據(jù)處理,我們使用Spark的方式與其他無異,但是對(duì)于模型訓(xùn)練、預(yù)測(cè)這些需要調(diào)用算法接口的邏輯就需要考慮一下并行化的問題了。我們平均一個(gè)訓(xùn)練任務(wù)在一天處理的數(shù)據(jù)量大約在500G左右,雖然數(shù)據(jù)規(guī)模不是特別的龐大,但是Python算法包提供的算法都是單進(jìn)程執(zhí)行。我們計(jì)算過,如果使用一臺(tái)機(jī)器訓(xùn)練全部品類數(shù)據(jù)需要一個(gè)星期的時(shí)間,這是無法接收的,所以我們需要借助Spark這種分布式并行計(jì)算框架來將計(jì)算分?jǐn)偟蕉鄠€(gè)節(jié)點(diǎn)上實(shí)現(xiàn)并行化處理。

我們實(shí)現(xiàn)的方法很簡(jiǎn)單,首先需要在集群的每個(gè)節(jié)點(diǎn)上安裝所需的全部Python包,然后在編寫Spark程序時(shí)考慮通過某種規(guī)則將數(shù)據(jù)分區(qū),比如按品類維度,通過groupByKey操作將數(shù)據(jù)重新分區(qū),每一個(gè)分區(qū)是一個(gè)樣本集合并進(jìn)行獨(dú)立的訓(xùn)練,以此達(dá)到并行化。流程如下圖所示:


              大數(shù)據(jù)|Spark技術(shù)在京東智能供應(yīng)鏈預(yù)測(cè)的應(yīng)用案例深度剖析(二)

偽碼如下:


               大數(shù)據(jù)|Spark技術(shù)在京東智能供應(yīng)鏈預(yù)測(cè)的應(yīng)用案例深度剖析(二)

repartitionBy方法即設(shè)置一個(gè)重分區(qū)的邏輯返回(K,V)結(jié)構(gòu)RDD,train方法是訓(xùn)練數(shù)據(jù),在train方法里面會(huì)調(diào)用Python算法包接口。saveAsPickleFile是Spark Python獨(dú)有的一個(gè)Action操作,支持將RDD保存成序列化后的sequnceFile格式的文件,在序列化過程中會(huì)以10個(gè)一批的方式進(jìn)行處理,保存模型文件非常適合。

雖然原理簡(jiǎn)單,但存在著一個(gè)難點(diǎn),即以什么樣的規(guī)則進(jìn)行分區(qū),key應(yīng)該如何設(shè)置。為了解決這個(gè)問題我們需要考慮幾個(gè)方面,第一就是哪些數(shù)據(jù)應(yīng)該被聚合到一起進(jìn)行訓(xùn)練,第二就是如何避免數(shù)據(jù)傾斜。

針對(duì)第一個(gè)問題我們做了如下幾點(diǎn)考慮:

被分在一個(gè)分區(qū)的數(shù)據(jù)要有一定的相似性,這樣訓(xùn)練的效果才會(huì)更好,比如按品類分區(qū)就是個(gè)典型例子。

分析商品的特性,根據(jù)特性的不同選擇不同的模型,例如高銷商品和低銷商品的預(yù)測(cè)模型是不一樣的,即使是同一模型使用的特征也可能不同,比如對(duì)促銷敏感的商品就需要更多與促銷相關(guān)特征,相同模型相同特征的商品應(yīng)傾向于分在一個(gè)分區(qū)中。

針對(duì)第二個(gè)問題我們采用了如下的方式解決:

對(duì)于數(shù)據(jù)量過大的分區(qū)進(jìn)行隨機(jī)抽樣選取。

對(duì)于數(shù)據(jù)量過大的分區(qū)還可以做二次拆分,比如圖書小說這個(gè)品類數(shù)據(jù)量明顯大于其他品類,于是就可以分析小說品類下的子品類數(shù)據(jù)量分布情況,并將子品類合并成新的幾個(gè)分區(qū)。

對(duì)于數(shù)據(jù)量過小這種情況則需要考慮進(jìn)行幾個(gè)分區(qū)數(shù)據(jù)的合并處理。

總之對(duì)于后兩種處理方式可以單獨(dú)通過一個(gè)Spark任務(wù)定期運(yùn)行,并將這種分區(qū)規(guī)則保存。

未完待續(xù)......

THEEND