轉(zhuǎn)帖|實(shí)施案例|編輯:龔雪|2017-03-28 11:07:25.000|閱讀 786 次
概述:京東的物流速度為什么這么快?原來大數(shù)據(jù)分析和人工智能等前沿技術(shù)功不可沒
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
預(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ā)的高效率、多語言特性以及對(duì)機(jī)器學(xué)習(xí)算法的支持。在Spark開發(fā)語言上我們選擇了Python,原因有以下三點(diǎn):
工具層: 一方面我們會(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ú)有的算法。
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è)、語音識(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)的商品效果較好。
ARIMA:全稱為自回歸積分滑動(dòng)平均模型,于70年代初提出的一個(gè)著名時(shí)間序列預(yù)測(cè)方法,我們用它來主要預(yù)測(cè)類似庫(kù)房單量這種平穩(wěn)的序列。
Holt winters:又稱三次指數(shù)平滑算法,也是一個(gè)經(jīng)典的時(shí)間序列算法,我們用它來預(yù)測(cè)季節(jié)性和趨勢(shì)都很明顯的商品。
WMAStockDT:庫(kù)存決策樹模型,用來預(yù)測(cè)受庫(kù)存狀態(tài)影響較大的商品。
SimilarityModel:相似品模型,使用指定的同類品數(shù)據(jù)來預(yù)測(cè)某商品未來銷量。
NewProduct:新品模型,顧名思義就是用來預(yù)測(cè)新品的銷量。
預(yù)測(cè)核心流程主要包括兩類:以機(jī)器學(xué)習(xí)算法為主的流程和以時(shí)間序列分析為主的流程。
特征構(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ù)。
我們使用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á)到并行化。流程如下圖所示:
偽碼如下:
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)考慮:
針對(duì)第二個(gè)問題我們采用了如下的方式解決:
總之對(duì)于后兩種處理方式可以單獨(dú)通過一個(gè)Spark任務(wù)定期運(yùn)行,并將這種分區(qū)規(guī)則保存。
未完待續(xù)......
更多行業(yè)資訊,更新鮮的技術(shù)動(dòng)態(tài),盡在。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn