ETA(Estimated Time of Arrival,「預計送達時間」),即用戶下單後,配送人員在多長時間內將外賣送達到用戶手中。送達時間預測的結果,將會以」預計送達時間」的形式,展示在用戶的客戶端頁面上,是配送系統中很是重要的參數,直接影響了用戶的下單意願、運力調度、騎手考覈,進而影響配送系統總體成本和用戶體驗。html
對於整個配送系統而言,ETA既是配送系統的入口和全局約束,又是系統的調節中樞。具體體如今:java
在這樣多維度的約束之下,外賣配送的ETA的建模和估計會變得更加複雜。與打車場景中的ETA作對比,外賣場景的ETA面臨以下的挑戰:c++
下圖是騎手履約全過程的時間軸,過程當中涉及各類時長參數,能夠看到有十幾個節點,其中關鍵時長達到七個。這些時長涉及多方,好比騎手(接-到-取-送)、商戶(出餐)、用戶(交付),要經歷室內室外的場景轉換,所以挑戰性很是高。對於ETA建模,不光是簡單一個時間的預估,更須要的是全鏈路的時間預估,同時更須要兼顧」單量-運力-用戶轉化率」轉化率之間的平衡。配送ETA的演變包括了數據、特徵層面的持續改進,也包括了模型層面一路從LR-XGB-FM-DeepFM-自定義結構的演變。算法
具體ETA在整個配送業務中的位置及配送業務的總體機器學習實踐,請參看《機器學習在美團配送系統的實踐:用技術還原真實世界》。服務器
與大部分CTR模型的迭代路徑類似,配送ETA模型的業務迭代經歷了LR->樹模型->Embedding->DeepFM->針對性結構修改的路徑。特徵層面也進行不斷迭代和豐富。網絡
目前版本模型在比較了Wide&Deep、DeepFM、AFM等經常使用模型後,考慮到計算性能及效果,最終選擇了DeepFM做爲初步的Base模型。整個DeepFM模型特徵Embedding化後,在FM(Factorization Machine)基礎上,進一步加入deep部分,分別針對稀疏及稠密特徵作針對性融合。FM部分經過隱變量內積方式考慮一階及二階的特徵融合,DNN部分經過Feed-Forward學習高階特徵融合。模型訓練過程當中採起了Learning Decay/Clip Gradient/求解器選擇/Dropout/激活函數選擇等,在此不作贅述。架構
在ETA預估場景下,準時率及置信度是比較重要的業務指標。初步嘗試將Square的損失函數換成Absolute的損失函數,從直觀上更爲切合MAE相比ME更爲嚴苛的約束。在適當Learning Decay下,結果收斂且穩定。框架
同時,在迭代中考慮到相同的ETA承諾時間下,在先後N分鐘限制下,早到1min優於晚到1min,損失函數的設計但願總體的預估結果可以儘可能前傾。對於提早部分,適當下降數值懲罰。對於遲到部分,適當增大數值懲罰。進行屢次調試設計後,最終肯定之前後N分鐘以及原點做爲3個分段點。在原先absolute函數優化的基礎上,在前段設計1.2倍斜率absolute函數,後段設計1.8倍斜率absolute函數,以便讓結果總體往中心收斂,且預估結果更傾向於提早送達,對於ETA各項指標均有較大幅度提高。機器學習
目前的業務架構是」模型+規則」,在模型預估一個ETA值以後,針對特定業務場景,會有特定業務規則時間疊加以知足特定場景需求,各項規則由業務指標屢次迭代產生。這裏產生了模型和規則總體優化的割裂,在模型時間和規則時間分開優化後,即模型訓練時並不能考慮到規則時間的影響,而規則時間在一年之中不一樣時間段,會產生不一樣的浮動,在通過一段時間重複迭代後,會加大割裂程度。異步
在嘗試了不一樣方案後,最終將總體規則寫入到了TF模型中,在TF模型內部調整總體規則參數。
經過調節不一樣的擬合部分及參數,將多個規則徹底在TF模型中實現。最終對業務指標具有很大提高效果,且經過對部分定值參數的更改,具有部分人工干涉模型能力。
在這裏,總體架構就簡化爲多目標預估的架構,這裏採用多任務架構中經常使用的Shared Parameters的結構,訓練時按比例採起不一樣的交替訓練策略。結構上從最下面的模型中間融合層出發,分別在TF內實現常規預測結構及多個規則時間結構,而其對應的Label則仍然從常規的歷史值和規則時間值中來,這樣考慮瞭如下幾點:
模型結構在進行預估目標調整嘗試中:
在模型處理中,特徵層面不可避免存在必定的缺失值,而對於缺失值的處理,徹底借鑑了《美團「猜你喜歡」深度學習排序模型實踐》文章中的方法。對於特徵x進入TF模型,進行判斷,若是是缺失值,則設置w1參數,若是不是缺失值則進入模型數值爲w2*x,這裏將w1和w2做爲可學習參數,同時放入網絡進行訓練。以此方法來代替均值/零值等做爲缺失值的方法。
基礎模型學習的是總體的統計分佈,但對於一些長尾情形的學習並不充分,體如今長尾情形下預估時間偏短(因爲ETA擁有考覈騎手的功能,預估偏短對騎手而言意味着很大的傷害)。故將長尾拆解成兩部分來分析:
在上述拆解下,採用補時規則來解決長尾預估偏短的問題:長尾規則補時爲 <業務長尾因子 , 模型長尾因子> 組合。其中業務長尾因子爲距離、價格等業務因素,模型長尾因子爲RF標準差。最終的ETA策略即爲模型預估結果+長尾規則補時。
總體訓練流程
對於線下訓練,採起以下訓練流程:
Spark原始數據整合 -> Spark生成TFRecord -> 數據並行訓練 -> TensorFlow Serving線下GPU評估 -> CPU Inference線上預測
整個例行訓練億級數據多輪Epoch下流程持續約4小時,其中TF訓練中,考慮到TF實際計算效率並非很高,有很大比例在數據IO部分,經過Spark生成TFRecord部分,在此可將速度加速約3.6倍。而在數據並行訓練部分,16卡內的並行度擴展基本接近線性,具有良好的擴展性。因爲PS上參數量並未達到單機沒法承受,暫時未對參數在PS上進行切分。Serving線下GPU評估部分,是整個流程中的非必需項,雖然在訓練過程當中Chief Worker設置Valid集合可有必定的指標,但對全量線下,經過Spark數據調用Serving GPU的評估具有短期內完成所有流程能力,且能夠指定大量複雜自定義指標。
數據並行訓練方式
整個模型的訓練在美團的AFO平臺上進行,前後嘗試分佈式方案及單機多卡方案。考慮到生產及結果穩定性,目前線上模型生產採用單機多卡方案進行例行訓練。
採用TF自帶的PS-Worker架構,異步數據並行方式,利用tf.train.MonitoredTrainingSession
協調整個訓練過程。整個模型參數存儲於PS,每一個Step上每一個Worker拉取數據進行數據並行計算,同時將梯度返回,完成一次更新。目前的模型單Worker吞吐1~2W/s,億級數據幾輪Epoch耗時在幾小時內完成。同時測試該模型在平臺上的加速比,大約在16塊內,計算能力隨着Worker數目線性增長,16卡後略微出現分離。在目前的業務實踐中,基本上4-6塊卡能夠短期內完成例行的訓練任務。
採用PS-Worker的方案在平臺上具有不錯的擴展性,可是也存在必定的弊端,使用RPC的通信很容易受到其餘任務的影響,整個的訓練過程受到最慢Worker的影響,同時異步更新方式對結果也存在必定的波動。對此,在線上生產中,最終選取單機多卡的方案,犧牲必定的擴展性,帶來總體訓練效果和訓練速度的穩定性。單機多卡方案採起多GPU手動指定OP的Device,同時在各個Device內完成變量共享,最後綜合Loss與梯度,將Grad更新到模型參數中。
TF模型集成預處理
模型訓練過程當中,ID類特徵低頻過濾須要用到Vocab詞表,連續型特徵都須要進行歸一化。這裏會產生大量的預處理文件,在線下處理流程中很容易在Spark中處理成Libsvm格式,而後載入到模型中進行訓練。可是在線上預測時,須要在工程開發端載入多個詞表及連續型特徵的歸一化預處理文件(avg/std值文件等),同時因爲模型是按天更新,存在不一樣日期版本的對齊問題。
爲了簡化工程開發中的難度,在模型訓練時,考慮將全部的預處理文件寫入TF計算圖之中,每次在線預測只要輸入最原始的特徵,不通過工程預處理,直接可獲得結果:
tf_look_up = tf.constant(list_arr, dtype=tf.int64) table = tf.contrib.lookup.HashTable(tf.contrib.lookup.KeyValueTensorInitializer(tf_look_up, idx_range), 0) ph_idx = table.lookup(ph_vals) + idx_bias
constant_avg = tf.constant(feat_avg, dtype=tf.float32, shape=[feat_dim], name="avg") constant_std = tf.constant(feat_std, dtype=tf.float32, shape=[feat_dim], name="std") ph_out = (ph_in - constant_avg) / constant_std
配送機器學習平臺內置了模型管理平臺,對算法訓練產出的模型進行統一管理和調度,管理線上模型所用的版本,並支持模型版本的切換和回退,同時也支持節點模型版本狀態的管理。
ETA使用的DeepFM模型用TensorFlow訓練,生成SavedModel格式的模型,須要模型管理平臺支持Tensorflow SavedModel格式。
實現方案 S 線上服務加載TensorFlow SavedModel模型有多種實現方案:
最終採用TensorFlow Java API加載SavedModel在CPU上作預測,測試batch=1時預測時間在1ms之內,選擇方案3做爲實現方案。
遠程計算模式
TensorFlow Java API的底層C++動態連接庫對libstdc++.so的版本有要求,須要GCC版本不低於4.8.3,而目前線上服務的CPU機器大部分系統爲CentOS 6, 默認自帶GCC版本爲4.4.7。若是每臺線上業務方服務器都支持TensorFlow SavedModel本地計算的話,須要把幾千臺服務器統一升級GCC版本,工做量比較大並且可能會產生其餘風險。
所以,咱們從新申請了幾十臺遠程計算服務器,業務方服務器只須要把Input數據序列化後傳給TensorFlow Remote集羣,Remote集羣計算完後再將Output序列化後返回給業務方。這樣只須要對幾十臺計算服務器升級就能夠了。
線上性能
模型上線後,支持了多個業務方的算法需求,遠程集羣計算時間的TP99基本上在5ms之內,能夠知足業務方的計算需求。
模型落地並上線後,對業務指標帶來較大的提高。後續將會進一步根據業務優化模型,進一步提高效果: