學習心得
(1)首先學習了經典推薦算法協同過濾的深度學習進化版本 NerualCF。相比于矩陣分解算法,NeuralCF 用一個多層的神經網絡,替代了矩陣分解算法中簡單的點積操作,讓使用者和物品隐向量之間進行充分的交叉。通過改進物品隐向量和使用者隐向量互操作層的方法,增強模型的拟合能力。
(2)利用 NerualCF 的思想,改進出雙塔模型。其特點優勢:
1)它通過豐富物品側和使用者側的特征,讓模型能夠融入除了使用者 ID 和物品 ID 外更豐富的資訊,ex:YouTube就使用召回層的雙塔模型,融入除了使用者id和物品id,還有如:
使用者正在觀看的視訊 ID、頻道 ID(圖中的 seed features)、該視訊的觀看數、被喜歡的次數,以及使用者曆史觀看過的視訊 ID 等等。物品側的特征包括了候選視訊的 ID、頻道 ID、被觀看次數、被喜歡次數等等。
2)模型服務的便捷性,由于最終的互操作層是簡單的内積操作或淺層神經網絡。是以,我們可以把物品塔的輸出當作物品 Embedding,使用者塔的輸出當作使用者 Embedding 存入特征資料庫(即不用将整個模型都部署線上),線上上服務隻要實作簡單的互操作過程就可以了。
文章目錄
- 學習心得
- 一、NeuralCF 模型的結構
- 二、NeuralCF拓展—雙塔模型
- 2.1 YouTube召回層的雙塔模型
- 2.2 雙塔模型的優勢
- 三、NeuralCF 的 TensorFlow 實作
- 3.1 NeuralCF模型
- 3.2 Neural雙塔模型
- 四、作業
- 五、課後答疑
- Reference
一、NeuralCF 模型的結構
協同過濾:利用使用者和物品之間的互動行為曆史,建構出一個像圖 1 左一樣的共現矩陣。在共現矩陣的基礎上,利用每一行的使用者向量相似性,找到相似使用者,再利用相似使用者喜歡的物品進行推薦。
矩陣分解:進一步加強了協同過濾的泛化能力,它把協同過濾中的共現矩陣分解成了使用者矩陣和物品矩陣,從使用者矩陣中提取出使用者隐向量,從物品矩陣中提取出物品隐向量,再利用它們之間的内積相似性進行推薦排序。結構圖如下。
圖2 矩陣分解的神經網絡化示意圖
圖 2 中的輸入層是由使用者 ID 和物品 ID 生成的 One-hot 向量,Embedding 層是把 One-hot 向量轉化成稠密的 Embedding 向量表達,這部分就是矩陣分解中的使用者隐向量和物品隐向量。輸出層使用了使用者隐向量和物品隐向量的内積作為最終預測得分,之後通過跟目标得分對比,進行反向梯度傳播,更新整個網絡。
把矩陣分解神經網絡化之後,把它跟 Embedding+MLP 以及 Wide&Deep 模型做對比,我們可以看出網絡中的薄弱環節:矩陣分解在 Embedding 層之上的操作是直接利用内積,得出最終結果。這會導緻特征之間還沒有充分交叉就直接輸出結果,模型會有欠拟合的風險。NeuralCF 基于這點對矩陣分解進行了改進,結構圖如下。
圖3 NeuralCF的模型結構圖 (出自論文Neural Collaborative Filtering)
差別就是 NeuralCF 用一個多層的神經網絡替代掉了原來簡單的點積操作。這樣就可以讓使用者和物品隐向量之間進行充分的交叉,提高模型整體的拟合能力。
二、NeuralCF拓展—雙塔模型
NeuralCF 的模型結構的思想:可以把模型分成使用者側模型和物品側模型兩部分,然後用互操作層把這兩部分聯合起來,産生最後的預測得分。
這裡的使用者側模型結構和物品側模型結構,可以是簡單的 Embedding 層,也可以是複雜的神經網絡結構,最後的互操作層可以是簡單的點積操作,也可以是 MLP 結構。這種物品側模型 + 使用者側模型 + 互操作層的模型結構,統稱為“雙塔模型”結構。
圖4 雙塔模型結構 (出自論文 Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations)
2.1 YouTube召回層的雙塔模型
對于 NerualCF 來說,它隻利用了使用者 ID 作為“使用者塔”的輸入特征,用物品 ID 作為“物品塔”的輸入特征。其實也可以把其他使用者和物品相關的特征也分别放入使用者塔和物品塔,讓模型能夠學到的資訊更全面。比如說,YouTube 在建構用于召回層的雙塔模型時,就分别在使用者側和物品側輸入了多種不同的特征。
圖5 YouTube雙塔召回模型的架構
(出自論文 Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations)
YouTube 召回雙塔模型:
使用者側特征包括了使用者正在觀看的視訊 ID、頻道 ID(圖中的 seed features)、該視訊的觀看數、被喜歡的次數,以及使用者曆史觀看過的視訊 ID 等等。
物品側的特征包括了候選視訊的 ID、頻道 ID、被觀看次數、被喜歡次數等等。
在經過了多層 ReLU 神經網絡的學習之後,雙塔模型最終通過
softmax
輸出層連接配接兩部分,輸出最終預測分數。
2.2 雙塔模型的優勢
這個雙塔模型相比我們之前學過的 Embedding MLP 和 Wide&Deep 有什麼優勢呢?
在實際工作中,雙塔模型最重要的優勢:易上線、易服務。
具體說:物品塔和使用者塔分别生成各自的embedding(這裡說是u(x)和v(y)表示),可以将這兩個embedding存入特征資料庫(即不用将整個模型都部署線上),然後再線上服務時,隻需要将它們取出來做【互操作層】得到最後的模型預估結果。
三、NeuralCF 的 TensorFlow 實作
3.1 NeuralCF模型
# neural cf model arch two. only embedding in each tower, then MLP as the interaction layers
def neural_cf_model_1(feature_inputs, item_feature_columns, user_feature_columns, hidden_units):
# 物品側特征層
item_tower = tf.keras.layers.DenseFeatures(item_feature_columns)(feature_inputs)
# 使用者側特征層
user_tower = tf.keras.layers.DenseFeatures(user_feature_columns)(feature_inputs)
# 連接配接層及後續多層神經網絡
interact_layer = tf.keras.layers.concatenate([item_tower, user_tower])
for num_nodes in hidden_units:
interact_layer = tf.keras.layers.Dense(num_nodes, activation='relu')(interact_layer)
# sigmoid單神經元輸出層
output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(interact_layer)
# 定義keras模型
neural_cf_model = tf.keras.Model(feature_inputs, output_layer)
return
代碼中定義的生成 NeuralCF 模型的函數,它接收了四個輸入變量:
feature_inputs
代表着所有的模型輸入;
item_feature_columns
和
user_feature_columns
分别包含了物品側和使用者側的特征。
在訓練時,如果我們隻在
item_feature_columns
中放入
movie_id
,在
user_feature_columns
放入
user_id
, 就是 NeuralCF 的經典實作了。
通過 DenseFeatures 層建立好使用者側和物品側輸入層之後,我們會再利用
concatenate
層将二者連接配接起來,然後輸入多層神經網絡進行訓練。如果想要定義多層神經網絡的層數和神經元數量,我們可以通過設定
hidden_units
數組來實作。
3.2 Neural雙塔模型
基于雙塔模型的原理實作了一個 NeuralCF 的雙塔版本。與上面的經典 NerualCF 實作不同,把多層神經網絡操作放到了物品塔和使用者塔内部,讓塔内的特征進行充分交叉,最後使用内積層作為物品塔和使用者塔的互動層。
# neural cf model arch one. embedding+MLP in each tower,
# then dot product layer as the output
def neural_cf_model_2(feature_inputs, item_feature_columns, user_feature_columns, hidden_units):
# 物品側輸入特征層
item_tower = tf.keras.layers.DenseFeatures(item_feature_columns)(feature_inputs)
# 物品塔結構
for num_nodes in hidden_units:
item_tower = tf.keras.layers.Dense(num_nodes, activation='relu')(item_tower)
# 使用者側輸入特征層
user_tower = tf.keras.layers.DenseFeatures(user_feature_columns)(feature_inputs)
# 使用者塔結構
for num_nodes in hidden_units:
user_tower = tf.keras.layers.Dense(num_nodes, activation='relu')(user_tower)
# 使用内積操作互動物品塔和使用者塔,産生最後輸出
output = tf.keras.layers.Dot(axes=1)([item_tower, user_tower])
# 定義keras模型
neural_cf_model = tf.keras.Model(feature_inputs, output)
return
四、作業
雙塔模型把物品側的 Embedding 和使用者側的 Embedding 存起來,就可以進行線上服務了。但如果我們把一些場景特征,比如目前時間、目前地點加到使用者側或者物品側,那我們還能用這種方式進行模型服務嗎?為什麼?
(1)如果從model serving的角度考慮,如果在物品側或者使用者側加入場景特征的話,就沒法做到預存embedding的serving方式了。因為場景特征是線上上不斷變化的。
(2)栗子:一些地點和時間波動這種波動較大的特征就不能通過預存embedding來表示目前的使用者或者目前的物品,如新聞推薦和外賣推薦,比如在公司和家時的embedding都是應該是不一樣的,或者新聞網站早晨和晚上的embedding也不一樣。
五、課後答疑
(1)embedding之後,如果使用點積,那麼這兩個embedding是在同一個向量空間;如果使用的MLP則不在同一個向量空間。因為點積不影響向量空間,線性變換矩陣會影響。
(2)把context特征放進user塔或者item塔,那麼離線生成user embedding或者item embedding的數量就要翻好多倍,能否考慮把context特征單獨作為context塔呢?
【答】離線有組合爆炸的風險。
一般不會有context塔,如果希望引入context特征,最好就不用雙塔模型,因為雙塔模型易線上serving的優勢就不存在了。
(3)雙塔模型對于新聞場景是不是也不太好?新聞時效性很強,在一些公司的資料裡,大部分新聞曝光在2個小時内,雙塔的訓練資料有足夠的曝光時,新聞的價值也失去了很多了。
【答】新聞的場景确實是很有意思的場景,因為時效性很強。這時候新聞id類的特征就不太管用了,因為如果不重新訓練,id類特征對應的embedding沒辦法引入。
是以對于這類時效性很強的場景,還是推薦基于一些與id無關的feature來構模組化型,比如新聞的類型、人物、地點、關鍵詞等等。
(4)為什麼不能加入context的特征。在訓練DSSM的時候除了user和item的特征外,在user塔加入context的特征,比如使用者的地理位置、手機型号等等,訓練完後,将user和item的embedding存入redis後。線上請求時,将user的靜态特征和實時context特征再過一遍DSSM,得到新的user embedding後,與存入redis的item emebdding取topN即可,為什麼不妥呢?
【答】因為将user的靜态特征和實時context特征再過一遍DSSM是一個非常重的操作,需要把深度模型部署上線,做實時推斷。這樣當然是可以的。但跟離線生成user 和 item emb預存起來,線上隻做簡單dot product這樣的部署方式,顯然複雜了許多。業界往往追求的實用性的效率,這就是加不加入context特征的差別所在。