美團點評旅遊搜尋召回策略的演進

背景

美團點評作為最大的生活服務平臺,有豐富的品類可供使用者選擇,因此搜尋這個入口對各業務的重要性不言而喻,除了平臺搜尋外,業務搜尋系統的質量和效果對使用者體驗、商家曝光、平臺交易也有著關鍵作用。

相對美團點評平臺的O2O檢索,旅遊搜尋系統主要面臨以下幾點挑戰:

  • 本異地差異大。在本地生活場景中使用者的搜尋需求往往集中在本城市內,而在旅遊場景特別是行前場景使用者會先搜尋異地的POI(門店),比如常駐城市為北京的使用者在去上海之前可能會先搜尋“東方明珠”、“迪士尼”瞭解相關資訊。

  • 搜尋意圖多樣,不同意圖的展現形式可能不同。搜“故宮”、“故宮成人票”是景點門票意圖,搜“北京”、“雲南”是行政區意圖,搜“水上樂園”、“滑雪場”是品類意圖,搜“上海到南京”、“一日遊”是線路遊意圖。

  • 底層髒資料多。旅遊早期由於上單稽核不嚴等原因,會出現“真人CS”Deal(團購單)下掛在“故宮博物館”POI的情況,按照平臺的檢索策略,搜“真人CS”時會展現“故宮”的POI,導致大量誤召回。

針對上述問題,我們建設了一套相對完整的搜尋系統,包括檢索召回、查詢分析、智慧排序和業務應用幾部分,本文將重點介紹搜尋召回(檢索召回、查詢分析)的策略演進過程。

評價指標

我們在2015年Q2啟動了旅遊搜尋系統的建設,此時旅遊業務有獨立的周邊遊頻道,其中的搜尋策略由平臺統一負責,不能很好的解決旅遊場景中的諸多問題。為了解決這些問題,我們首先需要確定搜尋的評價指標:

  • 訪購率:支付使用者數/搜尋訪問UV,這個是評估搜尋效果的主指標。美團點評是一家電商公司,營業收入是核心指標,以搜尋為例,使用者行為鏈條包括搜尋Query->點選搜尋結果列表頁中的POI/Deal等->下單支付->消費,最後計算消費收入。如果只看點選率,關注的鏈條太短,沒有反映交易屬性;如果看最終的收入結果,部分因素(消費受產品的購買限制、退款條件等影響,收入又跟商戶拓展人員談單的毛利等相關)非搜尋可控。因此以訪購率作為搜尋的核心指標跟美團點評的業務特點最為匹配。

  • 點選率:點選PV/搜尋PV(Page View)。部分景點由於商戶拓展人員沒有談單或者是免費景點等原因導致沒有門票或線路遊Deal可售時,訪購率為零,但使用者可能需要了解景點相關資訊,這時點選率是重要的輔助評價指標。一個相關的指標是有點行為比,以搜尋請求量為統計口徑。

  • 無結果率:無結果請求數/搜尋請求數,衡量搜尋召回質量的重要指標。

  • 使用者滿意度:由產品經理定期人工評測,比如取搜尋結果的前20條,如果是單景點意圖,對應的POI能排在首位,排序合理,無重複POI則為1分;搜尋結果滿足部分使用者需求,存在誤召回、排序不合理的情況則為0.5分;完全不能滿足使用者旅遊需求,搜尋結果沒有有效資訊則為0分。

除了可以用指標評估的問題外,還有一些指標外的問題,比如廣告運營、直籤門票加權等,這些問題可能跟指標負相關或不好量化評估。指標內的問題又分為兩類:一類是演算法問題,比如查詢意圖理解、召回檢索策略、個性化排序;另一類是產品和業務問題,比如頁面改版、源資料清洗,部分產品問題也需要策略協同解決。

策略迭代方法

明確評價指標後需要找到策略優化的方向和思路,不同於推薦(可以參考作者之前的文章《旅遊推薦系統的演進》),搜尋的bad
case往往非常明確,因此我們確立了以case驅動為主的策略迭代方法。

  1. 質量評估:定義滿意度標準和評估體系,定期(月/季度)評估搜尋滿意度,確定評估樣本,瞭解Query需求分佈、意圖識別準召率、召回及排序情況。

  2. 問題分析:對問題進行梳理分類,比如無供給問題、誤召回問題、意圖識別問題、POI排序問題、展示問題等,找出主要問題並明確優化方向。

  3. 專案開發:評估專案實施的可行性,制定相應的技術方案,配合產品、客戶端等其他技術團隊聯調、測試。

  4. 實驗迭代:上線A/B Testing驗證優化效果,根據指標評估專案收益,效果正向則擴量,負向則分析調整或下線,並繼續迭代優化。

召回策略迭代


全國召回

2015年Q2啟動了第一次周邊遊頻道內的搜尋質量評估,其中Query搜尋無結果影響面非常大,除無供給問題外最重要的一個原因是不支援異地搜尋。比如在德州搜尋“北京故宮”無結果,進一步分析發現在旅遊場景中超過30%的訂單來自於異地請求,即常駐城市為A的使用者購買了城市B的旅遊訂單。因此在周邊遊頻道內先放開了上單城市的召回限制,當使用者搜尋Query時根據POI和Deal欄位匹配召回全國範圍內的結果,比如在北京搜“武侯祠”能召回多個城市的結果,全國召回策略上線後無結果率大幅下降。


模組化展示

除全國召回外,周邊遊頻道搜尋當時仍沿用了美團點評平臺的展示及召回機制:

  • POI下掛Deal形式展示。

  • 通過POI及POI下掛的Deal資訊進行召回。

這些機制主要有兩個問題:

  • 以POI為主的展現形式不能很好滿足使用者的線路遊需求,比如使用者搜“北京一日遊”,返回的是故宮、長城等POI結果,使用者不能方便找到線路遊Deal。

  • 旅遊不同於其他品類,Deal與POI不是一一對應關係,尤其是線路遊、年票等Deal往往關聯多個景點,按照平臺現有召回策略,會導致大量POI被誤召回,比如搜“長城”返回“故宮”POI結果;同時由於上單稽核不嚴等原因,會出現“真人CS”Deal下掛在“故宮”POI的髒資料,也會被誤召回。

針對這些問題,在2015年Q3啟動了旅遊搜尋結果分模組展示的開發,即對使用者Query進行意圖分類,每類意圖定製召回策略和展現樣式,Query意圖分類如下:

以意圖佔比為56%的景點POI為例,當使用者搜尋“長城”時會展現“長城相關景點”和“長城相關度假產品”兩個類聚,景點類聚只在POI欄位域搜尋“長城”,比如POI所在城市、名稱,這些欄位中不包含“故宮”Term,因此不會返回“故宮”POI。度假產品類聚只限定在非門票Deal集合內檢索Deal標題、品類、商圈等欄位,返回的都是跟團遊、酒景套餐自由行等線路遊資訊,方便使用者決策。

當使用者在北京搜“上海”時是行政區意圖,會展示“上海目的地”、“上海熱門景點”、“北京-上海度假產品”、“上海當地度假產品”4個類聚,其中“目的地”是為城市專門定製的落地頁,“北京-上海度假產品”是根據出發地為北京、目的地為上海這兩個線路遊欄位來進行檢索。

當使用者搜尋“溫泉”時是品類意圖,檢索策略跟POI景點搜尋類似,但會增加品類檢索欄位。

分模組展示上線後一方面改善了使用者體驗,另一方面打壓了旅遊POI和Deal關聯的髒資料,訪購率和點選率也大幅提升。

同時為了降低無結果率,在一次召回無結果的基礎上增加了二次、三次召回,比如增加POI商圈欄位。如果二次召回也沒有結果,會增加門票Deal欄位進行三次召回,返回門票結果。

綜上可知使用者Query主要包含景點、行政區、品類、線路遊4類意圖,每類意圖又可能展現多個類聚,每個類聚的召回檢索策略不同。而早期的技術架構在單次請求下只支援單策略檢索,同時在多次召回時只能序列執行,因此需要對檢索架構進行升級:

  • 由單任務執行變成多工並行執行,比如搜尋“故宮”時需要併發執行POI和線路遊兩個檢索策略。

  • 由序列執行變成基於狀態機的排程執行,比如POI策略下一次召回無結果,會增加商圈欄位二次召回,再無結果時會基於門票Deal欄位進行三次召回。


無結果優化

為了進一步降低無結果率,在2015年Q4對線上Query做了一次無結果分析,其中32%原因是POI不線上(無供給,POI沒有可售Deal),27%是POI品類錯誤(即POI品類標籤不是旅遊),這兩類問題策略不好解決,剩下30%是由於Query表達方式多樣導致搜尋無結果,這些case細分原因如下:

  • 15%是Query包含冗餘詞,比如搜“東莞的隱賢山莊”無結果,去掉“的”有結果。

  • 7%是Query含有錯別字或同義詞,比如在北京搜“雁西湖”無結果,使用者實際需求是“雁棲湖”。

  • 5%是Query包含多個資訊,比如搜“北京動物園海洋館門票”無結果,分別搜“北京動物園”和“北京海洋館”有結果。

  • 3%是Query詞與商家實際資訊不符,比如在北京搜“798藝術3D體驗館”,搜“活的3D博物館”有結果。


丟詞&查詢改寫

針對上述問題分別定製了以下幾類策略:

  • 丟詞策略:通過挖掘Query日誌,統計其中的高頻停用詞,比如的、一張、價格、團購、去哪等,對使用者輸入Query直接丟棄其中的停用詞,再進行檢索召回。

  • Query糾錯&同義詞改寫:統計同一Session(比如一個小時內)內使用者的查詢對,選擇詞頻共現比較高的查詢對作為候選,再人工稽核加入到同義詞詞典。使用者查詢,同時用原詞和同義詞去檢索,最後對兩者返回的結果取並集。

  • 二次召回:在上文中已有提及,即一次召回無結果時擴大檢索欄位和檢索範圍。

  • 無結果推薦:推薦本身並不能降低無結果率,但在無結果時給使用者提供了另外的選擇。


無合作POI召回

上述策略上線後搜尋無結果率又有了大幅下降,但仍有一定的優化空間,2016年Q2啟動了新一輪的無結果分析,無結果case大致可以分為3類:

  • 無法追回專案:比如免費景區或全網無售(商戶拓展人員無法談單),這類case早期由於評價指標是訪購率,搜尋並不能召回,但其實對使用者體驗傷害較大,容易導致使用者流失。因此放開一次召回無結果時二次召回無合作POI,比如搜尋“潭柘寺”會返回結果,雖然暫無可售的Deal,但使用者可以瀏覽POI詳情頁的景區簡介、預訂須知等。

  • 待追回專案:即目前無供給,但可以反饋給商戶拓展人員談單,針對這類case建立了搜尋反饋商戶拓展人員上單的流程,自動生成任務工單並分派商戶拓展人員處理,形成無結果反饋的整體閉環。

  • 線上已有供給:搜尋召回策略問題導致的無結果,分析發現通過丟詞可以解決大部分case。之前的丟詞是詞表丟詞,丟詞的範圍有限,需要在一次詞表丟詞的基礎上增加基於模型的二次丟詞,主要方法是對Query做Chunk分析,為每個Term打上Chunk標籤,人工定義哪些Chunk可以丟棄。

上述策略上線後搜尋無結果率橫向對比美團點評平臺和其他業務基本達到了合理正常的水平。


分類意圖識別

模組化展示中用到了Query意圖分類,早期的意圖分類使用詞表精確匹配的方法,比如搜“大理”和“雲南大理”都是行政區意圖,其中“雲南大理”被切分成“雲南”和“大理”,然後分別和省份、城市詞表匹配。詞表精確匹配的準確率較高,但召回率不高,比如“大理旅遊”、“去大理”跟“大理”都是同一個意圖,但無法通過詞表精確匹配。如果採用寬泛匹配準確率又不會太高,比如“北海公園”、“中山公園”中都包含行政區,但其實是景點意圖。基於此,2015年Q4啟動了分類意圖識別的優化,首先根據Query分佈定義了8類意圖:

  • POI:景點、遊樂場、度假村等。

  • 行政區:國家、省、市、縣、區、鎮。

  • 品類:POI品類體系中的品類詞,以及公園、體驗館等指代詞。

  • 線路遊:一日遊、跟團遊等。

  • 旅遊關鍵詞:旅遊同義詞如旅行、遊玩等。

  • 旅行社。

  • 門票詞:門票、套票、成人票等。

  • 非旅遊:美食、住宿等外品類詞,雜質詞(的、一張等)。

可以通過識別Query中Term的意圖來判定整個Query的意圖,但上述意圖分類對Term而言粒度較粗,比如“珠海長隆海洋王國門票”會被切分成“珠海 長隆 海洋 王國 門票”,“珠海”是行政區,“門票”是門票詞,“長隆 海洋 王國”整體是POI,但每個Term無法對應到上述分類體系,因此需要設計一套更精細的tag體系。

其中將行政區細化到國家、省、市、區縣、鄉鎮和地標商圈等tag,POI細化為POI核心詞、品類詞、品類修飾詞tag。在上例中“長隆”是POI核心詞,“海洋 王國”兩個Term合併是POI品類詞,“海洋王國”即是一個Chunk,Chunk可以認為是一個語義單元,粒度要大於等於Term分詞粒度。


基於模型的Chunk分析

對於Query分詞後的Term,問題轉化為識別Chunk的邊界以及為Chunk打上何種tag,即序列標註問題。Chunk邊界可以採用BMES(Begin、Middle、End、Single)標記方式,比如“海洋 王國”Chunk中“海洋”標記是B,“王國”標記是E。“珠海”是一個單獨的Chunk,所以整體標記為S-城市,同理“長隆”整體標記為S-POI核心詞,“海洋”標記為B-品類詞。

Chunk分析轉化為序列標註問題後跟其他機器學習問題類似,需要考慮三方面因素:1)演算法模型;2)標記語料;3)特徵選取。演算法模型方面採用CRF(條件隨機場)模型,其結合了最大熵模型和隱馬爾可夫模型的特點,近年來在分詞、詞性標註和命名實體識別等序列標註任務中取得了很好的效果。

標記語料方面採用一段時間內的搜尋日誌,分詞後對每個Term進行標註,但全部採用人工標註費時費力,因此採用詞表規則標註然後人工校驗,其中重點是收集各tag的詞表,其中行政區、Deal、旅行社等詞表比較好收集,POI核心詞、品類詞、修飾詞可以通過挖掘和模板匹配來實現,這裡以POI名稱為候選詞集合,分詞後從後向前匹配,定義模板規則,迭代挖掘品類詞、修飾詞和核心詞。

特徵選取方面主要包括三類:

  • 邊界特徵:即可以用於確定Chunk邊界的特徵,包括左右熵、互資訊等。

  • tag特徵:即可以用於確定Chunk tag類別的特徵,包括詞長度、Term的tag類別等。

  • 組合特徵:左右熵組合,詞的組合等。

模型訓練時採用CRF ,需要將標註語料轉成CRF 的訓練格式,以Query“珠海 長隆 海洋 王國 門票”為例,訓練語料格式如下:

最後通過離線訓練生成模型供線上使用,對使用者輸入的Query,模型會輸出分詞後每個Term的tag。Chunk分析是一項非常基礎的工作,基於分析的結果可以應用於丟詞、Term重要度、意圖識別、Query改寫等。


從Chunk分析到意圖識別

得到Chunk的tag後可以制定規則輸出整個Query的意圖,意圖之間有優先順序順序:線路遊>POI>品類>門票,比如“北京故宮一日遊”是線路遊意圖,“北京故宮”是POI意圖,“北京動物園”是POI意圖,“動物園”是品類意圖。

分類意圖識別對搜尋整個流程都意義重大,召回層面可以分意圖定製檢索欄位、相關性計算等檢索策略,Rerank層面可以分意圖優化特徵,展示層面可以控制不同的展現樣式。

粗排序改進

除了Query分析、檢索策略外,粗排序是搜尋召回的另一個核心功能。當搜尋結果較多時,如果粗排序不合理,會導致部分優質POI或Deal無法召回,並且這些case不好人工干預。因此我們在2016年Q3啟動了粗排序的改進工作,主要包括:

  • 距離分分段:計算客戶端選擇城市中心和POI的距離,若距離>=300KM,則距離分為0,300KM以內距離越近,得分越高。另外當搜尋品類意圖時,加大距離分的權重,比如東莞使用者更希望去東莞附近的溫泉(東莞本地溫泉較少),而不是北京的。

  • 綜合評價數和評分:早期評價數和評分是線性加權,會出現部分冷門POI評價人數較少但評分較高的情況,因此考慮評分的置信度,評價數越多,置信度越高,總體評分越高。

  • 新單銷量平滑:新單或新POI由於上線時間較短銷量一般不高,因此對據當前日期一段時間內上線的產品會賦予預設銷量,並考慮時間衰減。

  • 各因子相乘:文字相關性、距離、評價、銷量這些因子維度差異較大,線性加權的權重不好設定,改成相乘,會使各因子的影響更為顯著。


文字相關性改進

除了數值類因子優化外,我們對文字相關性也進行了一些改進,早期的文字相關性計算基於TF-IDF,公式可以簡化如下:

RQ,D=∑t∈Q(∑f∈Htft,flf∗wf)∗idftRQ,D=∑t∈Q(∑f∈Htft,flf∗wf)∗idft

RQ,DRQ,D是搜尋詞和文件的相關性,t是QQ分詞後的Term,HH是t在文件中命中的文字域集合,tft,ftft,f是t在某個命中文字域f中的出現次數,lflf是文字域f的長度,wfwf是f的權重,比如POI名稱域的權重一般會高於Deal標題域,idftidft是Term
t的倒排文件頻率。上述公式主要存在如下問題:

  • 文字域長度影響過大,比如搜“廬山”,官方POI是“廬山風景名勝區”,分詞後包含“廬山”、“風景”、“名勝區”3個Term,而“廬山植物園”只包含“廬山”、“植物園”2個Term,權重是官方POI的1.5倍。

  • 多個域計算結果求和,對部分文字域缺失的POI不公平,比如搜“歡樂谷”,“天津歡樂谷”POI的品牌名(Brand Name)欄位是“歡樂谷”,“北京歡樂谷”POI的品牌名欄位為空,導致“北京歡樂谷”的權重不如“天津歡樂谷”。

  • 沒有考慮欄位域的動態權重,比如搜“動物園”,細粒度分詞會分成“動物”、“園”,“蘇州文化園”POI(包含“動物園、文化園一日遊”的Deal)命中了Term“園”,“萬鳥林”POI的品類欄位是“動物園”,由於POI名稱域的權重高於品類域,導致“蘇州文化園”的權重更高。

  • IDF只體現了Term自身的重要程度,不能體現Term在Query中的重要程度。

基於上述問題對文字相關性計算公式做了如下改進:

其中和b是調節因子,這部分參考了BM25的相關性計算,可以降低文字域長度的影響;另外對多個域的計算結果求max,減小部分欄位缺失的影響;是命中域的動態權重,可以根據命中Term在Query中的比例或權重來設定;使用的是Term在Query中的動態權重。


Term重要度

如何計算Term在Query中的動態權重呢?實現時採用模型打分方法,以搜尋Query為原始語料,人工進行標註,重要度共分4級:

  • Super important:主要包括POI核心詞,比如方特、歡樂谷。

  • Required:包括行政區詞、品類詞等,比如“北京 溫泉”中“北京”和“溫泉”都很重要。

  • Important:包括品類詞、門票等,比如“順景 溫泉”中“溫泉”相對沒有那麼重要,使用者搜“順景”大部分都是溫泉的需求。

  • Unimportant:包括線路遊、泛需求詞、停用詞等。

上例中可見“溫泉”在不同的Query中重要度是不同的,在特徵選取方面有4類:

  • 文字特徵:包括Query長度、Term長度,Term在Query中的偏移量等。

  • 統計特徵:包括PMI、IDF等。

  • 語言模型特徵:整個query的語言模型概率/去掉該Term後的Query的語言模型概率。

  • Chunk tag特徵。

模型方面採用XGBoost進行訓練,離線生成模型後供線上使用。


全欄位召回

隨著粗排序和Rerank的改進優化上線,我們放開了POI類聚檢索欄位的限制,改為使用所有欄位做文字匹配,包括POI城市、名稱、品類、商圈,簡化了二次召回的邏輯。


召回策略流程示例

經過一年多的迭代,整個搜尋召回的流程大致如下,以搜尋“北京著名的溫泉”為例:

  1. 對輸入的查詢進行預處理,比如特殊字元處理、全半形轉換。

  2. 查詢分詞和詞性標註,“北京”是地名、“著名”是形容詞、“的”是助詞、“溫泉”是名詞。

  3. 基於詞表的一次丟詞,“的”作為停用詞被丟棄。

  4. 同義詞改寫,對分詞的Term匹配同義詞,如“溫泉”和“熱泉”是同義詞。

  5. 在同義詞改寫的同時分析chunk tag,“北京”是城市、“著名”是品類修飾詞、“溫泉”是品類詞。

  6. 基於Chunk分析的結果識別Query整體為品類意圖。

  7. 同時計算Term在Query中的重要度,“北京”為0.48、“著名”為0.39、“溫泉”為0.55。

  8. 基於品類意圖確定檢索欄位和相關性計算的邏輯,比如距離加權。

  9. 由於所有POI的文字欄位中都不包含“著名”,一次召回無結果,因此擴大POI範圍,在無合作POI集合中進行二次檢索。

  10. 由於無合作POI的文字欄位也不包含“著名”,二次召回也無結果,因此基於Chunk丟棄品類修飾詞“著名”,然後進行三次檢索。

  11. 最終返回搜尋結果列表,“順景溫泉”、“九華山莊”等北京著名溫泉。


總結

在旅遊搜尋召回策略的迭代過程中我們並沒有採用大開大合的做法,而是參照策略迭代的四步方法論,定期評估搜尋質量,對問題分類分析,集中解決主要核心問題,上線實驗驗證效果,在避免“誤召回”和“無召回”之間保持平衡,逐步迭代,為實現更全更準的搜尋目標不斷改進。