智能搜索模型預估框架的建設與實踐

在過去十年,機器學習在學術界取得了衆多的突破,在工業界也有很多應用落地。美團很早就開始探索不同的機器學習模型在搜索場景下的應用,從最開始的線性模型、樹模型,再到近兩年的深度神經網絡、BERT、DQN 等,並在實踐中也取得了良好的效果與產出。

在美團搜索 AI 化的過程中,比較核心的兩個組件是模型訓練平臺 Poker 和在線預估框架 Augur。本文主要與大家探討 Augur 的設計思路、效果,以及它的優勢與不足,最後也簡單介紹了一下 Poker 平臺的價值。希望這些內容對大家有所幫助或者啓發。

1. 背景

搜索優化問題,是個典型的 AI 應用問題,而 AI 應用問題首先是個系統問題。經歷近 10 年的技術積累和沉澱,美團搜索系統架構從傳統檢索引擎升級轉變爲 AI 搜索引擎。當前,美團搜索整體架構主要由搜索數據平臺、在線檢索框架及雲搜平臺、在線 AI 服務及實驗平臺三大體系構成。

在 AI 服務及實驗平臺中,模型訓練平臺 Poker 和在線預估框架 Augur 是搜索 AI 化的核心組件,解決了模型從離線訓練到在線服務的一系列系統問題,極大地提升了整個搜索策略迭代效率、在線模型預估的性能以及排序穩定性,並助力商戶、外賣、內容等核心搜索場景業務指標的飛速提升。

首先,讓我們看看在美團 App 內的一次完整的搜索行爲主要涉及哪些技術模塊。如下圖所示,從點擊輸入框到最終的結果展示,從熱門推薦,到動態補全、最終的商戶列表展示、推薦理由的展示等,每一個模塊都要經過若干層的模型處理或者規則干預,纔會將最適合用戶(指標)的結果展示在大家的眼前。

爲了保證良好的用戶體驗,技術團隊對模型預估能力的要求變得越來越高,同時模型與特徵的類型、數量及複雜度也在與日俱增。算法團隊如何儘量少地開發和部署上線,如何快速進行模型特徵的迭代?如何確保良好的預估性能?在線預估框架 Augur 應運而生。

經過一段時間的實踐,Augur 也有效地滿足了算法側的需求,併成爲美團搜索與 NLP 部通用的解決方案。下面,我們將從解讀概念開始,然後再分享一下在實施過程中我們團隊的一些經驗和思考。

2. 抽象過程:什麼是模型預估?

其實,模型預估的邏輯相對簡單、清晰。但是如果要整個平臺做得好用且高效,這就需要框架系統和工具建設(一般是管理平臺)兩個層面的配合,需要兼顧需求、效率與性能。

那麼,什麼是模型預估呢?如果忽略掉各種算法的細節,我們可以認爲模型是一個函數,有一批輸入和輸出,我們提供將要預估文檔的相關信息輸入模型,並根據輸出的值(即模型預估的值)對原有的文檔進行排序或者其他處理。

純粹從一個工程人員視角來看:模型可以簡化爲一個公式( 舉例:f(x1,x2)= ax1 + bx2 +c ),訓練模型是找出最合適的參數 abc。所謂特徵,是其中的自變量 x1 與 x2,而模型預估,就是將給定的自變量 x1 與 x2 代入公式,求得一個解而已。(當然實際模型輸出的結果可能會更加複雜,包括輸出矩陣、向量等等,這裏只是簡單的舉例說明。)

所以在實際業務場景中,一個模型預估的過程可以分爲兩個簡單的步驟:第一步,特徵抽取(找出 x1 與 x2);第二步,模型預估(執行公式 ƒ,獲得最終的結果)。

模型預估很簡單,從業務工程的視角來看,無論多複雜,它只是一個計算分數的過程。對於整個運算的優化,無論是矩陣運算,還是底層的 GPU 卡的加速,業界和美團內部都有比較好的實踐。美團也提供了高性能的 TF-Serving 服務(參見《基於 TensorFlow Serving 的深度學習在線預估》一文)以及自研的 MLX 模型打分服務,都可以進行高性能的 Batch 打分。基於此,我們針對不同的模型,採取不同的策略:

這一套邏輯很簡單,構建起來也不復雜,所以在建設初期,我們快速在主搜的核心業務邏輯中快速實現了這一架構,如下圖所示。這樣的一個架構使得我們可以在主搜的核心排序邏輯中,能夠使用各類線性模型的預估,同時也可以藉助公司的技術能力,進行深度模型的預估。關於特徵抽取的部分,我們也簡單實現了一套規則,方便算法同學可以自行實現一些簡單的邏輯。

3. 預估框架思路的改變

3.1 老框架的侷限

舊架構中模型預估與業務邏輯耦合的方式,在預估文檔數和特徵數量不大的時候可以提供較好的支持。

但是,從 2018 年開始,搜索業務瓶頸開始到來,點評事業部開始對整個搜索系統進行升級改造,並打造基於知識圖譜的分層排序架構(詳情可以參見點評搜索智能中心在 2019 年初推出的實踐文章《大衆點評搜索基於知識圖譜的深度學習排序實踐》)。這也意味着:更多需要模型預估的文檔,更多的特徵,更深層次的模型,更多的模型處理層級,以及更多的業務。

在這樣的需求背景下,老框架開始出現了一些侷限性,主要包括以下三個層面:

3.2 新框架的邊界

跟所有新系統的誕生故事一樣,老系統一定會出現問題。原有架構在少特徵以及小模型下雖有優勢,但業務耦合,無法橫向擴展,也難以複用。針對需求和老框架的種種問題,我們開始構建了新的高性能分佈式模型預估框架 Augur,該框架指導思路是:

架構上的改變,讓 Augur 具備了複用的基礎能力,同時也擁有了分佈式預估的能力。可惜,系統架構設計中沒有 “銀彈”:雖然系統具有了良好的彈性,但爲此我們也付出了一些代價,我們會在文末進行解釋。

4. 預估平臺的構建過程

框架思路只能解決 “能用” 的問題,平臺則是爲了 “通用” 與“好用”。一個優秀的預估平臺需要保證高性能,具備較爲通用且接口豐富的核心預估框架,以及產品級別的業務管理系統。爲了能夠真正地提升預估能力和業務迭代的效率,平臺需要回答以下幾個問題:

下面,我們將逐一給出答案。

4.1 構建預估內核:高效的特徵和模型迭代

4.1.1 Operator 和 Transformer

在搜索場景下,特徵抽取較爲難做的原因主要包括以下幾點:

針對特徵的處理邏輯,我們抽象出兩個概念:

Operator:通用特徵處理邏輯,根據功能的不同又可以分爲兩類:

通過 IO、計算分離,特徵抽取執行階段就可以進行 IO 異步、自動聚合 RPC、並行計算的編排優化,從而達到提升性能的目的。

Transformer:用於處理與模型相關的特徵邏輯,如分桶、低頻過濾等等。一個特徵可以配置一個或者多個 Transformer。Transformer 也提供接口,業務方可以根據自己的需求定製邏輯。

基於這兩個概念,Augur 中特徵的處理流程如下所示:首先,我們會進行特徵抽取 ,抽取完後,會對特徵做一些通用的處理邏輯;而後,我們會根據模型的需求進行二次變換,並將最終值輸入到模型預估服務中。如下圖所示:

4.1.2 特徵計算 DSL

有了 Operator 的概念,爲了方便業務方進行高效的特徵迭代,Augur 設計了一套弱類型、易讀的特徵表達式語言,將特徵看成一系列 OP 與其他特徵的組合,並基於 Bison&JFlex 構建了高性能語法和詞法解析引擎。我們在解釋執行階段還做了一系列優化,包括並行計算、中間特徵共享、異步 IO,以及自動 RPC 聚合等等。

舉個例子:

1// IO Feature: binaryBusinessTime;  ReadKV 是一個 IO 類型的 OP
2ReadKV('mtptpoionlinefeatureexp','_id',_id,'ba_search.platform_poi_business_hour_new.binarybusinesstime','STRING')
3// FeatureA : CtxDateInfo;   ParseJSON 是一個 Calc 類型的 OP
4ParseJSON(_ctx['dateInfo']);
5// FeatureB : isTodayWeekend 需要看 Json 這種的日期是否是週末, 便可以複用  CtxDateInfo  這個特徵; IsWeekend 也是是一個 Calc 類型的 OP
6IsWeekend(CtxDateInfo['date'])
7

在上面的例子中,ParseJSON 與 IsWeekend 都是 OP, CtxDateInfo 與 isTodayWeekend 都是由其他特徵以及 OP 組合而成的特徵。通過這種方式,業務方根據自己的需求編寫 OP , 可以快速複用已有的 OP 和特徵,創造自己需要的新特徵。而在真實的場景中,IO OP 的數量相對固定。所以經過一段時間的累計,OP 的數量會趨於穩定,新特徵只需基於已有的 OP 和特徵組合即可實現,非常的高效。

4.1.3 配置化的模型表達

特徵可以用利用 OP、使用表達式的方式去表現,但特徵還可能需要經過 Transformer 的變換。爲此,我們同樣爲模型構建一套可解釋的 JSON 表達模板,模型中每一個特徵可以通過一個 JSON 對象進行配置,以一個輸入到 TF 模型裏的特徵結構爲例:

 1// 一個的特徵的 JSON 配置
 2{
 3    "tf_input_config": {"otherconfig"},
 4    "tf_input_name": "modulestyle",
 5    "name": "moduleStyle",
 6    "transforms": [                      // Transfomers:模型相關的處理邏輯,可以有多個,Augur 會按照順序執行
 7      {
 8        "name": "BUCKETIZE",             // Transfomer 的名稱:這裏是分桶
 9        "params": {
10          "bins": [0,1,2,3,4]           // Transfomer 的參數
11        }
12      }
13    ],
14    "default_value": -1
15}
16

通過以上配置,一個模型可以通過特徵名和 Transformer 的組合清晰地表達。因此,模型與特徵都只是一段純文本配置,可以保存在外部,Augur 在需要的時候可以動態的加載,進而實現模型和特徵的上線配置化,無需編寫代碼進行上線,安全且高效。

其中,我們將輸入模型的特徵名(tf_input_name)和原始特徵名(name)做了區分。這樣的話,就可以只在外部編寫一次表達式,註冊一個公用特徵,卻能通過在模型的結構體中配置不同 Transfomer 創造出多個不同的模型預估特徵。這種做法相對節約資源,因爲公用特徵只需抽取計算一次即可。

此外,這一套配置文件也是離線樣本生產時使用的特徵配置文件,結合統一的 OP&Transformer 代碼邏輯,進一步保證了離線 / 在線處理的一致性,也簡化了上線的過程。因爲只需要在離線狀態下配置一次樣本生成文件,即可在離線樣本生產、在線模型預估兩個場景通用。

4.2 完善預估系統:性能、接口與周邊設施

4.2.1 高效的模型預估過程

OP 和 Transformer 構建了框架處理特徵的基本能力。實際開發中,爲了實現高性能的預估能力,我們採用了分片純異步的線程結構,層層 Call Back,最大程度將線程資源留給實際計算。因此,預估服務對機器的要求並不高。

爲了描述清楚整個過程,這裏需要明確特徵的兩種類型:

  1. ContextLevel Feature:全局維度特徵,一次模型預估請求中,此類特徵是通用的。比如時間、地理位置、距離、用戶信息等等。這些信息只需計算一次。

  2. DocLevel Feature:文檔維度特徵,一次模型預估請求中每個文檔的特徵不同,需要分別計算。

一個典型的模型預估請求,如下圖所示:

Augur 啓動時會加載所有特徵的表達式和模型,一個模型預估請求 ModelScoreRequest 會帶來對應的模型名、要打分的文檔 id(docid)以及一些必要的全局信息 Context。Augur 在請求命中模型之後,將模型所用特徵構建成一顆樹,並區分 ContextLevel 特徵和 DocLevel 特徵。由於 DocLevel 特徵會依賴 ContextLevel 特徵,故先將 ContextLevel 特徵計算完畢。

對於 Doc 維度,由於對每一個 Doc 都要加載和計算對應的特徵,所以在 Doc 加載階段會對 Doc 列表進行分片,併發完成特徵的加載,並且各分片在完成特徵加載之後就進行打分階段。也就是說,打分階段本身也是分片併發進行的,各分片在最後打分完成後彙總數據,返回給調用方。期間還會通過異步接口將特徵日誌上報,方便算法同學進一步迭代。

在這個過程中,爲了使整個流程異步非阻塞,我們要求引用的服務提供異步接口。若部分服務未提供異步接口,可以將其包裝成僞異步。這一套異步流程使得單機(16c16g)的服務容量提升超過 100%,提高了資源的利用率。

4.2.2 預估的性能及表達式的開銷

框架的優勢:得益於分佈式,純異步流程,以及在特徵 OP 內部做的各類優化(公用特徵 、RPC 聚合等),從老框架遷移到 Augur 後,上千份文檔的深度模型預估性能提升了一倍。

至於大家關心的表達式解析對對於性能的影響其實可以忽略。因爲這個模型預估的耗時瓶頸主要在於原始特徵的抽取性能(也就是特徵存儲的性能)以及預估服務的性能(也就是 Serving 的性能)。而 Augur 提供了表達式解析的 Benchmark 測試用例,可以進行解析性能的驗證。

1_I(_I('xxx'))
2Benchmark              Mode  Cnt  Score   Error  Units
3AbsBenchmarkTest.test  avgt   25  1.644 ± 0.009  ms/op
4
5

一個兩層嵌套的表達式解析 10W 次的性能是 1.6ms 左右。相比於整個預估的時間,以及語言化表達式對於特徵迭代效率的提升,這一耗時在當前業務場景下,基本可以忽略不計。

4.2.3 系統的其他組成部分

一個完善可靠的預估系統,除了 “看得見” 的高性能預估能力,還需要做好以下幾個常被忽略的點:

Augur 在完成了以上多種能力的建設之後,就可以當做一個功能相對完善且易擴展的在線預估系統。由於我們在構建 Augur 的時候,設立了明確的邊界,故以上能力是獨立於業務的,可以方便地進行復用。當然,Augur 的功能管理,更多的業務接入,都需要管理平臺的承載。於是,我們就構建了 Poker 平臺,其中的在線預估管理模塊是服務於 Augur,可以進行模型特徵以及業務配置的高效管理。我們將在下一小節進行介紹。

4.3 建設預估平臺:快速複用與高效管理

4.3.1 能力的快速複用

Augur 在設計之初,就將所有業務邏輯通過 OP 和 Transformer 承載,所以跟業務無關。考慮到美團搜索與 NLP 部模型預估場景需求的多樣性,我們還爲 Augur 賦予多種業務調用的方式。

其中服務化是被應用最多的方式,爲了方便業務方的使用,除了完善的文檔外,我們還構建了標準的服務模板,任何一個業務方基本上都可以在 30 分鐘內構建出自己的 Augur 服務。服務模板內置了 60 多個常用邏輯和計算 OP , 並提供了最佳實踐文檔與配置邏輯,使得業務方在沒有指導的情況下可以自行解決 95% 以上的問題。整個流程如下圖所示:

當然,無論使用哪一種方式去構建預估服務,都可以在美團內部的 Poker 平臺上進行服務、模型與特徵的管理。

4.3.2 Augur 管理平臺 Poker 的構建

實現一個框架價值的最大化,需要一個完整的體系去支撐。而一個合格的在線預估平臺,需要一個產品級別的管理平臺輔助。於是我們構建了 Poker(搜索實驗平臺),其中的在線預估服務管理模塊,也是 Augur 的最佳拍檔。Augur 是一個可用性較高的在線預估框架,而 Poker+Augur 則構成了一個好用的在線預估平臺。下圖是在線預估服務管理平臺的功能架構:

首先是預估核心特徵的管理,上面說到我們構建了語言化的特徵表達式,這其實是個較爲常見的思路。Poker 利用 Augur 提供的豐富接口,結合算法的使用習慣,構建了一套較爲流暢的特徵管理工具。可以在平臺上完成新增、測試、上線、卸載、歷史回滾等一系列操作。同時,還可以查詢特徵被服務中的哪些模型直接或者間接引用,在修改和操作時還有風險提示,兼顧了便捷性與安全性。

模型管理也是一樣,我們在平臺上實現了模型的配置化上線、卸載、上線前的驗證、灰度、獨立的打分測試、Debug 信息的返回等等。同時支持在平臺上直接修改模型配置文件,平臺可以實現模型多版本控制,一鍵回滾等。配置皆爲實時生效,避免了手動上線遇到問題後因處理時間過長而導致損失的情況。

4.3.3 Poker + Augur 的應用與效果

隨着 Augur 和 Poker 的成熟,美團搜索與 NLP 部門內部已經有超過 30 個業務方已經全面接入了預估平臺,整體的概況如下圖所示:

預估框架使用遷移 Augur 後,性能和模型預估穩定性上均獲得了較大幅度的提升。更加重要的是,Poker 平臺的在線預估服務管理和 Augur 預估框架,還將算法同學從繁複且危險的上線操作中解放出來,更加專注於算法迭代,從而取得更好的效果。以點評搜索爲例,在 Poker+Augur 穩定上線之後,經過短短半年的時間,點評搜索核心 KPI 在高位基礎上仍然實現了大幅提升,是過去一年半漲幅的六倍之多,提前半年完成全年的目標。

4.4 進階預估操作:模型也是特徵

4.4.1 Model as a Feature,同構 or 異構?

在算法的迭代中,有時會將一個模型的預估的結果當做另外一個模型輸入特徵,進而取得更好的效果。如美團搜索與 NLP 中心的算法同學使用 BERT 來解決長尾請求商戶的展示順序問題,此時需要 BERT as a Feature。一般的做法是離線進行 BERT 批量計算,灌入特徵存儲供線上使用。但這種方式存在時效性較低(T+1)、覆蓋度差等缺點。最好的方式自然是可以在線實時去做 BERT 模型預估,並將預估輸出值作爲特徵,用於最終的模型打分。這就需要 Augur 提供 Model as a Feature 的能力。

得益於 Augur 抽象的流程框架,我們很快超額完成了任務。Model as a feature,雖然要對一個 Model 做預估操作,但從更上層的模型角度看,它就是一個特徵。既然是特徵,模型預估也就是一個計算 OP 而已。所以我們只需要在內部實現一個特殊的 OP,ModelFeatureOpreator 就可以乾淨地解決這些問題了。

我們在充分調研後,發現 Model as a Feature 有兩個維度的需求:同構的特徵和異構的特徵。同構指的是這個模型特徵與模型的其他特徵一樣,是與要預估的文檔統一維度的特徵,那這個模型就可以配置在同一個服務下,也就是本機可以加載這個 Stacking 模型;而異構指的是 Model Feature 與當前預估的文檔不是統一維度的,比如商戶下掛的商品,商戶打分需要用到商品打分的結果,這兩個模型非統一維度,屬於兩個業務。正常邏輯下需要串行處理,但是 Augur 可以做得更高效。爲此我們設計了兩個 OP 來解決問題:

美團搜索內部,已經通過 LocalModelFeature 的方式,實現了 BERT as a Feature。在幾乎沒有新的使用學習成本的前提下,同時在線上取得了明顯的指標提升。

4.4.2 Online Model Ensemble

Augur 支持有單獨抽取特徵的接口,結合 Model as a Feature,若需要同時爲一個文檔進行兩個或者多個模型的打分,再將分數做加權後使用,非常方便地實現離線 Ensemble 出來模型的實時在線預估。我們可以配置一個簡單的 LR、Empty 類型模型(僅用於特徵抽取),或者其他任何 Augur 支持的模型,再通過 LocalModelFeature 配置若干的 Model Feature,就可以通過特徵抽取接口得到一個文檔多個模型的線性加權分數了。而這一切都被包含在一個統一的抽象邏輯中,使用戶的體驗是連續統一的,幾乎沒有增加學習成本。

除了上面的操作外,Augur 還提供了打分的同時帶回部分特徵的接口,供後續的業務規則處理使用。

5. 更多思考

當然,肯定沒有完美的框架和平臺。Augur 和 Poker 還有很大的進步空間,也有一些不可迴避的問題。主要包括以下幾個方面。

被迫 “消失” 的 Listwise 特徵

前面說到,系統架構設計中沒有 “銀彈”。在採用了無狀態分佈式的設計後,請求會分片。所以 ListWise 類型的特徵就必須在打分前算好,再通過接口傳遞給 Augur 使用。在權衡性能和效果之後,算法同學放棄了這一類型的特徵。

當然,不是說 Augur 不能實現,只是成本有些高,所以暫時 Hold 。我們也有設計過方案,在可量化的收益高於成本的時候,我們會在 Augur 中開放協作的接口。

單機多層打分的缺失

Augur 一次可以進行多個模型的打分,模型相互依賴(下一層模型用到上一層模型的結果)也可以通過 Stacking 技術來解決。但如果模型相互依賴又逐層減少預估文檔(比如,第一輪預估 1000 個,第二輪預估 500),則只能通過多次 RPC 的方式去解決問題,這是一個現實問題的權衡。分片打分的性能提升,能否 Cover 多次 RPC 的開銷?在實際開發中,爲了保持框架的清晰簡單,我們選擇了放棄多層打分的特性。

離線能力缺失?

Poker 是搜索實驗平臺的名字。我們設計它的初衷,是解決搜索模型實驗中,從離線到在線所有繁複的手工操作,使搜索擁有一鍵訓練、一鍵 Fork、一鍵上線的能力。與公司其他的訓練平臺不同,我們通過完善的在線預估框架倒推離線訓練的需求,進而構建了與在線無縫結合的搜索實驗平臺,極大地提升了算法同學的工作效。

未來,我們也會向大家介紹產品級別的一站式搜索實驗平臺,敬請期待。

6. 未來展望

在統一了搜索的在線預估框架後,我們會進一步對 Augur 的性能 & 能力進行擴展。未來,我們將會在檢索粗排以及性能要求更高的預估場景中去發揮它的能力與價值。同時 ,我們正在將在線預估框架進一步融合到我們的搜索實驗平臺 Poker 中,與離線訓練和 AB 實驗平臺做了深度的打通,爲業務構建高效完整的模型實驗基礎設施。

如果你想近距離感受一下 Augur 的魅力,歡迎關注文末的招聘信息,加入美團技術團隊!

7. 作者簡介

朱敏,紫順,樂欽,洪晨,喬宇,武進,孝峯,俊浩等,均來自美團搜索與 NLP 部。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/4H5-DNkiBSbeOq_3WpajBw