,是對所有item特徵的處理。每條樣本中,需要分別代入item+和item-進行計算。細心的同學會發現,常見的召回模型中採用「user embedding與item embedding做點積或cosine」來計算匹配度,以方便利用FAISS進行快速近鄰檢索,擔心以上公式訓練出來的模型無法與FAISS兼容。不用擔心,接下來講線上服務的時候,我們會發現以上完整的FM公式也可以轉變成兩個向量點積的形式 ,同樣可以利用FAISS快速檢索。
如何定義"遠遠高於"一種是採用margin hinge loss,即user與正樣本item的匹配程度,要比,user與負樣本item的匹配程度,高出一定的閾值。寫成公式,就是
=
但是,這個公式裡面又多出一個超參margin需要調節,因此我主要使用如下的BPR Loss。
BPR Loss的思想是計算"給user召回時,將item+排在item-前面的概率",。因為一個三元組<user, item+, item->的ground-truth label永遠是1,所以將 餵入binary cross-entropy loss的公式,則有
=
線上服務 傳統u2i召回上文已經提到,訓練時,我們用完整的FM公式來描述User與Item之間的匹配度。但是,在線上服務時,我們必須將匹配度描述成點積或cosine的形式,才能利用FAISS完成在百萬、千萬級物料庫中的快速召回。這個"FM→點積"的公式轉化如下圖所示。
這時還可以做兩個簡化:
當為一個用戶召回時,這個用戶的一階權重和特徵隱向量都是固定的,因此從公式中省略"所有User特徵一階權重之和"和「所有User特徵隱向量兩兩點積之和」(圖中綠色公式)也不影響排序所有User特徵與所有Item特徵之間的兩兩點積之和(第一行紅色公式),等價於,將所有User特徵embedding相加得到user embedding,將所有Item特徵embedding相加得到item embedding,再拿user embedding與item embedding做點積(第二行紅色公式)
這時,有一種方案就是,忽略公式中的藍色部分,線上服務時只保留user embedding與item embedding的點積。這樣做,也不是不行,但是效果不是特別好。因為用戶喜歡的,未必一定是與自身最匹配的,也包括一些自身性質極佳的item(e.g.,熱門item) ,所以,非常有必要將"所有Item特徵一階權重之和"和「所有Item特徵隱向量兩兩點積之和」考慮進去 ,但是也還必須寫成點積的形式。
解決方法是將user/item embedding都增廣一維,如下圖公式所示。
Embedding的其他玩法除了以上最常用的u2i召回,在我們得到user embedding和item embedding之後,還有很多其他玩法
拿用戶最近一次點擊的item embedding,在item faiss庫中檢索相似item,推薦給用戶,實現「看了又看」、「猜你喜歡」等功能拿當前user embedding,在user faiss庫中檢索相似user,把這些相似user消費過的item推薦給當前user,類似User CF,效果也非常好可以拿item embedding,在user faiss庫中檢索可能對它感興趣的user,把item給這些用戶Push出去,達到提高用戶黏性、減少用戶流失的目的。冷啟動新用戶與新物料需要特別指出的是,很多召回,比如基於ALS的矩陣分解、Item CF等,都有冷啟動問題,儘管單路召回性能很好,但是由於能夠覆蓋的用戶、物料有限,對大盤指標的影響也很有限。而FM召回的優勢在於,它對新用戶、新物料都非常友好 。
對新用戶,哪怕他是一個純新用戶,沒有任何畫像與交互歷史,他至少有一個特徵叫「IsNewUser=1」,也就能夠生成user embedding,FM也能替他召回對新物料,任何物料都能拿到其畫像(e.g., 一二級 分類、標籤等),自然能夠得到item embedding。我們可以專門建立一個FAISS庫,裡面的item都是剛入庫的新item 。用戶請求到來時,除了在常規的、由已經有一些點擊量的item faiss庫裡召回之外,還在這個只由新item組成的faiss庫裡召回。這樣既能夠將新item分發出去,又保證分發是高度個性化的,提高流量的利用率。FM解釋模型 模型解釋性:全局 vs. 局部 如果說,如果要追求模型的表達能力,還要靠DNN這樣的大殺器,FM只能算「模型能力+工程複雜度」綜合考慮下一個不錯的折中方案。但是,如果論模型的可解釋性,DNN模型就難望FM的項背了。不僅如此,FM在解釋性上最大優點,是能夠提供針對一個或一群樣本上的「局部特徵重要性」 。
首先,先解釋一下「全局特徵重要性」與「局部特徵重要性」兩個概念。
GBDT能提供的特徵重要性,就是「全局特徵重要性」,它代表每個特徵對整個模型的影響力。但是,如果我們想知道,對某一個具體樣本的預測得分,哪些特徵的影響力比較大,「全局特徵重要性」是無能為力的。這時就需要「局部特徵重要性 」,能夠針對每一個樣本,分析出該樣本的每個特徵對該樣本預測得分的貢獻。比如SHAP算法能提供如下圖形化展示,模型給這條樣本的最終打分是24.41,從圖中我們可以看到是哪些特徵做了貢獻,又有哪些特徵拖了後腿。
為什麼「局部特徵重要性」更重要?因為數據分析的精髓就在於指標的拆解、下鑽 。
我們可以按性別、年齡篩選出不同用戶的消費樣本,「局部特徵重要性」能夠告訴我們,影響某一類用戶消費的正負向因素我們可以專門篩選出那些false positive/false negative的bad case,看看哪些特徵的表現不如預期,導致預測失敗 FM得分拆解 FM允許我們將最終預測得分,拆解到各feature和feature組合上,從而能夠提供「局部特徵重要性」。但是,推薦場景下,feature空間有上億維,而且高度稀疏,拆解到feature與feature組合級別,計算量太大,而且即便能夠拆解成功,拆解後的信息也太瑣碎,讓人無從分析。因此,更合理的解決方案是拆解到field級別 ,因為field最多幾百個,算上field組合也不過幾萬個,無論是計算規模,還是分析規模,還是可以接受的。(有些同學對field的概念不太熟悉,這裡做一下簡單說明。比如「一級分類」算是field,而「軍事」、「歷史」這樣的具體的分類值是這個field下的feature。)
拆解方法也很簡單:針對每一個樣本,將這個樣本的feature embedding按所屬field分組,同一field下所有feature embedding相加得到field embedding,然後兩兩field embedding做點積,這樣就將樣本得分拆解到了field和field pair的維度上。以上算法可以在Spark中分布式運行。
單獨看一個樣本上的拆解結果,可能有很多噪聲。我們可以選取一組樣本進行得分拆解,然後將這組樣本在各個field pair上的得分進行統計,比如繪製熱力圖,就能看出哪些field pair對這組樣本至關重要。