随着移動互聯網的發展,用戶使用習慣日趨碎片化,如何讓用戶在有限的訪問時間裡找到想要的産品,成為了搜索/推薦系統演進的重要職責。作為外賣領域的獨角獸, 餓了麼擁有百萬級的日活躍用戶,如何利用數據挖掘/機器學習的方法挖掘潛在用戶、增加用戶粘性,已成為迫切需要解決的問題。
個性化推薦系統通過研究用戶的興趣偏好,進行個性化計算,發現用戶的興趣點,從而引導用戶發現自己的信息需求。一個好的推薦系統不僅能為用戶提供個性化的服務,還能和用戶之間建立密切關系,讓用戶對推薦産生依賴。
本次分享介紹餓 了麼如何從0到1構建一個可快速叠代的推薦系統,從産品形态出發,包括推薦模型與特征工程、日志處理與效果評估,以及更深層次的場景選擇和意圖識别。
在攜程個性化推薦與人工智能meetup上,已經就以上幾部分做了整體上的說明,本文将就其中模型排序與特征計算的線上實現做具體說明,同時補充有關業務規則相關的洗牌邏輯說明,力圖從細節上還原和展示餓了麼美食推薦系統。
一、模型排序1.設計流程
這裡需要說明的是:任何一個模型Model都必須以打分器Scorer形式展示或者被調用。主要是基于以下幾點考慮:
2.排序邏輯
對于機器學習或者學習排序而言, 多種模型的組合(Bagging, Voting或Boosting等)往往能夠帶來穩定、有效的預測結果。所以, 針對當前美食推薦項目, 框架結合ABTest系統, 支持single、linear及multi三種組合模式, 具體說明如下:
具體說明如下:
單一模式:rankType=single
對于單一模式, 僅有一個Scorer, 且不存在混合情況, 所以隻要簡單對Scorer的打分進行排序即可, 故在此不做詳細展開。ABTest配置格式如下表:
線性加權模式:rankType=linear
對于線性加權模式, 在單一模式配置的基礎上,需要在ABTest配置每個Scorer的權重, 格式如下表所示:
當LinearRanker初始化時, 會校驗和初始化所有打分器Scorer。之後, 按照以下步驟對餐廳/食物列表進行排序, 詳見下圖(左):
多輪排序模式:rankType=multi
對于多輪排序模式, 每輪設定一個Scorer, 對前一輪top=Num個餐廳/食物進行排序, 故在ABTest中需要設定每個Scorer的輪次(round)和排序數(num), 格式如下表。
MultiRanker初始化與特征計算與LinearRanker類似, 具體步驟詳見上圖(右):
重複步驟3、4, 直到走完所有輪次。
在初始化階段, Ranker根據ABTest配置信息指定算法版本(algoVersion)、排序類型(rankType)、排序層級(rankLevel)及相關打分器(ScorerList)。
3.模型定義
對于線上任何Model,ModelManager 都會通過以下流程獲取相應實例和功能(如下圖所示):
對于Model的叠代和更新、以及之後的Online Learning等, 通過ModelManager對接相應服務來實現。
如上圖所示, 對于任何一個可被Scorer直接調用Model, 都需要實現以下接口:
1.設計流程
不同于離線模型訓練,線上特征計算要求低延遲、高複用、強擴展,具體如下:
根據以上系統設計要求, 下圖給出了特征計算的設計流程和特征基類說明。
具體說明如下:
a.特征管理:包括自定義特征、基礎特征、實時特征、複合特征等; b.特征導入:自定義特征靜态代碼注冊,其他特征數據庫導入; c.特征構建:CompsiteFeature類型特征構建。
a.從每個Scorer獲取Feature列表, 去重, 依賴計算, 最後初始化; b.層級、并行計算每個EntityInfo的特征值(之後會考慮接入ETL, 用于Online Learning)。
2.特征定義
上圖給出了特征基類說明, 以下是具體的字段和方法說明:
根據上兩小節設計流程和基類定義的說明, 我們能夠非常快速、簡便地實現一個自定義特征, 具體流程如下(score為例, 對應類名XXXFeature):
特征類實現:
特征注冊:
3.特征分類
(1) 基礎特征:
基礎特征為線上可以通過配置特征名直接從SHOP/USER獲取特征值的特征, 比如:shop_meta_、user_meta_、food_meta_等, 詳細說明如下表,其從本質上來講等同于特征操作符(複合特征)。
(2)實時特征:
實時特征來源于Kafka與Storm的日志實時計算,存于Redis,比如:用戶食物搜索與點擊信息,實例如下表。
(3) 自定義特征:
線上除CompositeFeature特征外, 所有XXXFeature均為自定義特征, 在此不再累述。
(4)複合特征(CompositeFeature):
用戶特征組合的複雜操作, 比如下表所示(部分)
三、洗牌邏輯
1.洗牌類型
很多時候, 基于算法模型的結果能夠給出數據層面的最佳結果, 但是不能保證推薦結果符合人的認知, 比如基于CTR預估的邏輯, 在結果推薦上會傾向于用戶已點過或已購買過的商戶/食物, 這樣就使得推薦缺少足夠的興趣面。所以, 為了保證推薦結果與用戶的相關性, 我們會保留算法模型的結果; 同時, 為了保證結果符合認知, 我們會人為地添加規則來對結果進行洗牌; 最後, 為了擴展用戶興趣點、引導用戶選擇, 将會人工地引入非相關商戶/食物, 該部分将是我們後續優化點之一。下面将詳細介紹“猜你喜歡”模塊線上生效的部分洗牌邏輯,其他洗牌規則類似。
餐廳類目洗牌:
考慮到餐廳排序時, 為避免同類目餐廳紮堆問題, 我們設定了餐廳類目洗牌, 基本規則如下:
針對 top = SHOP_CATE_TOPNUM 餐廳, 不允許同類目餐廳連續超過 MAX_SHOP_SHOPCNT。
餐廳推薦食物數洗牌:
在餐廳列表排序時, 總是希望排在前面的商戶具有更好的展示效果、更高的質量。針對 1*餐廳 3*食物 模式, 如果前排餐廳食物缺失(少于3個)時, 頁面的整體效果就會大打折扣, 所以我們制定了食物數洗牌, 具體規則如下:
所有1個食物的餐廳沉底; 針對top=SHOP_FOODCNT_TOPNUM餐廳, 食物數 < SHOP_FOODCNT_FOODCNT(3) 的餐廳降權
餐廳名稱洗牌:
正常時候, 推薦需要擴展和引導用戶的興趣點, 避免同類紮堆, 比如蓋澆飯類目餐廳等。同樣的, 我們也不希望相同或相似名稱的餐廳紮堆, 比如連鎖店、振鼎雞等。針對此問題, 考慮到餐廳名稱的不規則性, 我們通過分詞和統計, 把所有餐廳名稱做了結構化歸類(distinct_flag), 比如所有“XXX黃焖雞”都歸為“黃焖雞”、“星巴克 XX店”歸為“星巴克”等。之後類似于餐廳類目洗牌, 做重排, 具體規則如下:
對top=SHOP_FLAG_TOPNUM 餐廳進行标簽(flag)洗牌, 使得同一标簽的餐廳排序位置差不得小于 SHOP_FLAG_SPAN
2.線上邏輯從上一節中可知, 各個洗牌之間存在相互制約, 即洗牌不能并行、隻能串行, 誰前誰後就會導緻不同的排序結果, 所以, 這裡需要考慮各個洗牌對排序的影響度和優先級:
- 影響度:即對原列表的重排力度, 比如對于連鎖店少的區域, 名稱洗牌的影響度就會小, 反之, 比如公司周邊有25家振鼎雞, 影響度就會變大;
- 優先級:即洗牌的重要性, 比如前排餐廳如果食物少于規定數量, 其實質是浪費了頁面曝光機會, 所以食物數洗牌很有必要。
考慮到洗牌的串行邏輯, 越靠後的洗牌具有更高優先級。為了能夠靈活變更線上的洗牌規則, 系統結合Huskar System(線上配置修改系統), 能夠快速、便捷地更改洗牌邏輯,下面給出了一個配置實例。
四、總結對于一個處于業務快速增長期的互聯網企業,如何能夠在最短時間内構建一個可快速叠代的推薦系統,是擺在眼前的現實問題。此次分享從餓了麼自身業務出發,結合推薦系統的常見問題和解決方案,給出了從産品形态出發, 包括推薦模型與特征工程、日志處理與效果評估, 以及更深層次的場景選擇和意圖識别等在内多方面的線上實踐,力圖從整體及細節上還原和展示推薦系統的本質,以期能夠為大家今後的工作提供幫助。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!