【推荐系统】深入理解推荐系统:无需人工特征工程的xDeepFM
【推薦系統】專欄歷史部分文章:
深入理解推薦系統:召回
深入理解推薦系統:排序
深入理解推薦系統:Fairness、Bias和Debias
深入理解推薦系統:推薦系統中的attention機制
深入理解推薦系統:特征交叉組合模型演化簡史
深入理解推薦系統:十大序列化推薦算法梳理
作為【推薦系統】系列文章的第十五篇,將以“xDeepFM”作為今天的主角,中科大、北大與微軟合作發表在 KDD’18 的文章:《xDeepFM: Combining Explicit and Implicit Feature Interactions for Recommender Systems》。本文主要對xDeepFM進行詳細描述,并進行代碼實現。
背景介紹
傳統交叉特征工程主要有三個缺點,以下部分來自paper:
獲取高質量特征代價高昂
大規模預測系統(比如:推薦系統),存在大量原始特征(raw features),很難人工抽取所有交叉特征
人工交叉特征不能泛化到在訓練數據中未見過的交叉上
FM會將每個特征i嵌入到一個隱因子向量 上,pairwise型特征交叉可以被建模成隱向量的內積:。在本paper中,使用術語bit來表示在隱向量中的一個元素(比如:)。經典的FM可以被擴展到專門的高階特征交叉上,但一個主要缺點是:會建模所有的特征交叉,包括有用組合和無用組合。無用組合會引入噪聲、以及效果的下降。最近幾年,DNNs越來越流行。利用DNNs可以學習復雜和可選擇的特征交叉。FNN用于學習高階特征交叉,它會使用對于field embedding的預訓練FM,然后應用于DNN。PNN則不依賴預訓練的FM,而是在embedding layer和DNN layer之間引入了一個product layer。FNN和PNN的主要缺點是,它們主要更多關注高階特征交叉,而非低階交叉。Wide&Deep模型和DeepFM模型通過引入混合結構克服了上面的缺點,它包含了一個shallow組件以及一個deep組件,可以學到memorization和generalization。因而可以聯合學習低階和高階特征交叉。
上面的所有模型都使用DNN來學習高階特征交叉。然而,DNN可以以一個隱式的方式建模高階特征交叉。由DNN學到的最終函數可以是任意形式,關于特征交叉的最大階數(maximum degree)沒有理論上的結論。另外,DNNs在bit-wise級別建模征交叉,這與FM框架不同(它會在vector-wise級別建模)。這樣,在推薦系統的領域,其中DNN是否是用于表示高階特征交叉的最有效模型,仍然是一個開放問題。在本paper中,我們提供了一個基于NN的模型,以顯式、vector-wise的方式來學習特征交叉。論文的方法基于DCN(Deep&Cross Network)之上,該方法能有效捕獲有限階數(bounded ?degree)的特征交叉,然而,DCN將帶來一種特殊形式的交叉。論文設計了一種新的壓縮交叉網絡CIN(compressed interaction network)來替換在DCN中的cross network。CIN可以顯式地學到特征交叉,交叉的階數會隨著網絡depth增長。根據Wide&Deep模型和DeepFM模型的精神,論文會結合顯式高階交叉模塊和隱式交叉模型,以及傳統的FM模塊,并將該聯合模型命名為“eXtreme Deep Factorization Machine (xDeepFM)”。這種新模型無需人工特征工程,可以讓數據科學家們從無聊的特征搜索中解放出來??偨Y一下,主要有三個貢獻:
提出了一種新模型xDeepFM,可以聯合訓練顯式和隱式高階特征交叉,無需人工特征工程
設計了CIN來顯式學習高階特征交叉,論文展示了特征交叉的階(degree)會在每一層增加,特征會在vector-wise級別進行交叉。
論文在三個數據集中進行了實驗,結果展示xDeepFM效果好于其它state-of-art模型
準備工作
Embedding Layer
在CV或NLP領域,輸入數據通常是圖片或文本信號,它們空間相關(spatially correlated)或時序相關(temporally correlated),因而DNN可以被直接應用到dense結構的原始特征上。然而,在推薦系統中,輸入特征是sparse、高維、沒有明顯地空間相關或時序相關。因此,multi-field類別形式被廣泛使用。例如,一個輸入實例為:?
[user_id=s02, gender=male, organization=msra, interests=comedy&rock]
通過field-aware one-hot進行編碼成高維稀疏特征:
在原始特征輸入上使用一個embedding layer,可以將它壓縮到一個低維、dense、real-value vector上。如果field是一階的(univalent),feature embedding被當成field embedding使用。以上述實例為例,特征(male)的embedding被當成field gender的embedding。如果field是多階的(multivalent),feature embedding的求和被用于field embedding。embedding layer如下圖所示。embedding layer的結果是一個wide concatenated vector:
其中,m表示fields的數目,
表示一個field的embedding。盡管實例的feature長度可以是多變的,它們的embedding具有相同的長度 m x D, 其中D是field embedding的維數。下圖中,field embedding layer。本例中embedding的維度是4隱式高階交叉
FNN, Deep&Cross,以及Wide&Deep的deep part會使用一個在field embedding vector e上的feed-forward神經網絡來學習高階特征交叉。forward process是:
其中,k是layer depth,是激活函數,是第k層的output??梢暬Y構與下圖展示的非常像,但不包括FM layer或Product layer。該結構會以bit-wise的方式建模交叉。也就是說,相同field embedding vector中的元素也會相互影響。
PNN和DeepFM在上述結構上做了小修改。除了在embedding vector e上應用了DNNs外,它們在網絡中添加了一個2-way interaction layer。因而,bit-wise和vector-wise的交叉都能在模型中包含。PNN和DeepFM中主要不同是,PNN會將product layer的輸出連接到DNNs中,而DeepFM會直接將FM layer連接給output unit。
顯式高階交叉
Cross Network(CrossNet)的結構如下圖所示:
它可以顯式建模高階特征交叉。不同于經典的fully-connected feed-forward network,它的hidden layers通過以下的cross操作進行計算:
其中,是第k層的weights,bias以及output。對于CrossNet能學到一個特殊類型的高階交叉這一點我們有爭論,其中,CrossNet中的每個hidden layer是一個關于的標量乘積。
theorem: 考慮到一個k層cross network,第i+1層的定義為:。接著,cross network的output 是一個關于的標量乘積。
證明如下:
k=1時,根據矩陣乘法的結合律和分配律,我們具有:
其中,標量實際上是關于的線性回歸。其中,是關于的一個標量乘。假設標量乘適用于k=i。對于k=i+1, 我們可以有:
其中,是一個標量。其中,仍是一個關于的標量乘。通過引入hypothesis,cross network的output 是一個關于的標量乘。
注意,標量乘并不意味著是與是線性關系的。系數是與敏感的。CrossNet可以非常有效地學到特征交叉(復雜度與一個DNN模型對比是微不足道的),然而,缺點是:
CrossNet的輸出受限于一個特定的形式,每個hidden layer是關于的一個標量乘
交叉是以bit-wise的方式進行
CIN模型
CIN
論文設計了一個新的cross network,命名為CIN(Compressed Interaction Network),具有如下注意事項:
交叉是在vector-wise級別上進行,而非bit-wise級別
高階特征的交叉顯式衡量
網絡的復雜度不會隨著交叉階數進行指數增長
由于一個embedding vector被看成是一個關于vector-wise 交叉的unit,后續會將field embedding公式化為一個矩陣:,其中,假設,表示在第k層的(embedding)feature vectors的數量。對于每一層,通過以下方式計算:
其中,是第h個feature vector的參數矩陣,表示Hadamard product,例如:。注意,通過在和間的交叉產生,其中,特征交叉會被顯式衡量,交叉的階數會隨著layer depth增長。CIN的結構與RNN非常相似,其中下一個hidden layer的outputs取決于最近一個(the last)的hidden layer和一個額外的input。論文在所有layers上都持有embedding vectors的結構,這樣,即可在vector-wise級別上使用交叉。
有意思的是,等式與CNN具有很強的關聯。如上圖 a 所示,引入了一個內部張量(intermediate tensor) ,其中,它是hidden layer和原始特征矩陣的外積(outer products:沿著每個embedding維度)。被看成是一個特殊類型的圖片,看成是一個filter。如上圖 b 所示跨沿著該embedding dimension(D)滑動該filter,獲得一個hidden vector ,這在CV中通常被稱為一個feature map。在CIN命名中所使用的術語"compressed"表示了第k個hidden layer會將 向量的隱空間壓縮到向量中。
上圖中,提供了CIN的一個總覽。假設T表示網絡的深度。每個hidden layer 具有一個與output units的連接。首先在hidden layer的每個feature map上使用sum pooling:
其中,。這樣,就可以得到一個pooling vector:,對于第k個hidden layer相應的長度為。hidden layers的所有polling vectors在連接到output units之前會被concatenated:。如果直接使用CIN進行分類,output unit是在上的一個sigmoid節點:
其中,是回歸參數。
CIN詳解
論文對CIN進行分析,研究了模型復雜度以及潛在的效果。
空間復雜度
在第k層的第h個feature map,包含了個參數,它與具有相同的size。因而,在第k層上具有個參數??紤]到對于output unit的當前最近(the last)的regression layer,它具有個參數,CIN的參數總數是 。注意,CIN與embedding dimension D相互獨立。相反的,一個普通的T-layers DNN包含了個參數,參數的數目會隨著embedding dimension D而增長。
通常,m和不會非常大,因而,的規模是可接受的。當有必要時,我們可以利用一個L階的分解,使用兩個小的矩陣以及來替換:
其中以及。出于簡潔性,論文假設每個hidden layer都具有相同數目(為H)的feature maps。盡管L階分解,CIN的空間復雜度從下降到。相反的,普通DNN的空間復雜度是,它對于field embedding的維度D是敏感的。
時間復雜度
計算tensor 的開銷是O(mHD)。由于在第一個hidden layer上具有H個feature maps,計算一個T-layers CIN會花費時間。相反的,一個T-layer plain DNN,會花費時間。因此,CIN的主要缺點是在時間復雜度上。
多項式近似(Polynomial Approximation)
接下來,作者檢查了CIN的高階交叉屬性。出于簡潔性,論文假設,在hidden layers上的feature maps數目,等于fields m的數目。假設[m]表示小于或等于m的正整數集。在第1層上的第h個feature map,表示為,通過下式計算:
因此,在第1層的每個feature map會使用個系數來建模pair-wise特征交叉。相似的,在第2層的第h個feature map為:
注意,l和k相關的所有計算在前一個hidden layer已經完成。在等式 擴展的因子是為了清晰。可以觀察到,在第二層的每個feature map會使用新參數來建模3-way交叉。
一個經典的k階多項式具有系數。展示了CIN會逼近這類型多項式,根據一個feature maps鏈,只需要個參數。通過引入hypothesis,我們可以證明,在第k層的第h個feature map為:
為了更好地演示,假設表示一個multi-index,其中。會從中忽略原始的上標,使用來表示它,因為對于最終展開的表達式,只關心來自第0層(等同于field embedding)的feature maps?,F在,使用一個上標來表示向量操作,比如。假設表示一個multi-vector 多項式的階數k:
在該類中的每個向量多項式都具有個系數。接著,我們的CIN接似系數:
其中, 是一個multi-index,是索引()的所有排列。
與隱式網絡的組合
我們知道plain DNNs可以學到隱式高階特征交叉。由于CIN和plain DNNs可以互補,一個直觀的做法是,將這兩種結構進行組合使模型更強。產生的模型與Wide&Deep和DeepFM非常像。結構如下圖所示,新模型命名為eXtreme Deep Factorization Machine(xDeepFM),一方面,它同時包含了低階和高階特征交叉;另一方面,它包含了隱式特征交叉和顯式特征交叉。它產生的output unit如下:
其中,a是原始特征。分別是是plain DNN和CIN的outputs。和b是可學習的參數。對于二分類,loss函數為log loss:
其中,N是訓練實例的總數。Optimization過程是最小化下面的目標函數:
其中表示正則項,表示參數集,包含linear part,CIN part,DNN part。
與FM和DeepFM的關系
假設所有field是一階的(univalent)。如上圖所示(xDeepFM的結構),當depth和CIN part的feature maps同時設為1時,xDeepFM就是DeepFM的一個泛化,通過為FM layer學習線性回歸權重實現(注意,在DeepFM中,FM layer的units直接與output unit相連,沒有任何系數)。當我們進一步移去DNN part,并同時為該feature map使用一個constant sum filter(它簡單采用輸入求和,無需任何參數學習),接著xDeepFM就變成了傳統的FM模型。
CIN 源碼淺析
詳細注釋寫在了代碼中, 其中不太直觀的地方有兩處, 這里寫了很簡單的測試用例, 可以用于后續的參考:dot_result_m = tf.matmul(split_tensor0, split_tensor, transpose_b=True)
import?tensorflow?as?tfB?=?2 D?=?3 m?=?2 H?=?2?##?理解為?H_{k-1} a?=?tf.reshape(tf.range(B?*?D?*?m,?dtype=tf.float32),(B,?m,?D)) b?=?tf.split(a,?D?*?[1],?2) c?=?tf.matmul(b,?b,?transpose_b=True)with?tf.Session()?as?sess:print(sess.run(tf.shape(c)))?##?shape?為?[D,?B,?m,?H_{k-1}]curr_out = tf.nn.conv1d(dot_result, filters=self.filters[idx], stride=1, padding='VALID')
import?tensorflow?as?tfB?=?2 D?=?3 E?=?4??##?代表?m?*?H_{k-1} F?=?5??##?代表?H_{k} a?=?tf.reshape(tf.range(B?*?D?*?E,?dtype=tf.float32),(B,?D,?E)) b?=?tf.reshape(tf.range(1?*?E?*?F,?dtype=tf.float32),(1,?E,?F)) curr_out?=?tf.nn.conv1d(a,?filters=b,?stride=1,?padding='VALID')with?tf.Session()?as?sess:print(sess.run(tf.shape(curr_out)))?##?結果為?[B,?D,?H_{k}]CIN 模塊的代碼如下:
class?CIN(Layer):"""Compressed?Interaction?Network?used?in?xDeepFM.This?implemention?isadapted?from?code?that?the?author?of?the?paper?published?on?https://github.com/Leavingseason/xDeepFM.Input?shape-?3D?tensor?with?shape:?``(batch_size,field_size,embedding_size)``.Output?shape-?2D?tensor?with?shape:?``(batch_size,?featuremap_num)``?``featuremap_num?=??sum(self.layer_size[:-1])?//?2?+?self.layer_size[-1]``?if?``split_half=True``,else??``sum(layer_size)``?.Arguments-?**layer_size**?:?list?of?int.Feature?maps?in?each?layer.-?**activation**?:?activation?function?used?on?feature?maps.-?**split_half**?:?bool.if?set?to?False,?half?of?the?feature?maps?in?each?hidden?will?connect?to?output?unit.-?**seed**?:?A?Python?integer?to?use?as?random?seed.References-?[Lian?J,?Zhou?X,?Zhang?F,?et?al.?xDeepFM:?Combining?Explicit?and?Implicit?Feature?Interactions?for?Recommender?Systems[J].?arXiv?preprint?arXiv:1803.05170,?2018.]?(https://arxiv.org/pdf/1803.05170.pdf)"""def?__init__(self,?layer_size=(128,?128),?activation='relu',?split_half=True,?l2_reg=1e-5,?seed=1024,?**kwargs):if?len(layer_size)?==?0:raise?ValueError("layer_size?must?be?a?list(tuple)?of?length?greater?than?1")self.layer_size?=?layer_sizeself.split_half?=?split_halfself.activation?=?activationself.l2_reg?=?l2_regself.seed?=?seedsuper(CIN,?self).__init__(**kwargs)def?build(self,?input_shape):if?len(input_shape)?!=?3:raise?ValueError("Unexpected?inputs?dimensions?%d,?expect?to?be?3?dimensions"?%?(len(input_shape)))self.field_nums?=?[int(input_shape[1])]self.filters?=?[]self.bias?=?[]for?i,?size?in?enumerate(self.layer_size):##?layer_size?對應著論文中的?H_{k},?表示?CIN?每層中?feature?map?的個數##?self.filters[i]?的?shape?為?[1,?m?*?H_{k-1},?H_{k}]self.filters.append(self.add_weight(name='filter'?+?str(i),shape=[1,?self.field_nums[-1]?*?self.field_nums[0],?size],dtype=tf.float32,?initializer=glorot_uniform(seed=self.seed?+?i),regularizer=l2(self.l2_reg)))##?self.bias[i]?的?shape?為?[H_{k}]self.bias.append(self.add_weight(name='bias'?+?str(i),?shape=[size],?dtype=tf.float32,initializer=tf.keras.initializers.Zeros()))if?self.split_half:if?i?!=?len(self.layer_size)?-?1?and?size?%?2?>?0:raise?ValueError("layer_size?must?be?even?number?except?for?the?last?layer?when?split_half=True")self.field_nums.append(size?//?2)else:self.field_nums.append(size)self.activation_layers?=?[activation_layer(self.activation)?for?_?in?self.layer_size]super(CIN,?self).build(input_shape)??#?Be?sure?to?call?this?somewhere!def?call(self,?inputs,?**kwargs):##?inputs?的?shape?為?[B,?m,?D],?其中?m?為?Field?的數量,##?D?為?embedding?size,?我注釋的符號盡量和論文中的一樣if?K.ndim(inputs)?!=?3:raise?ValueError("Unexpected?inputs?dimensions?%d,?expect?to?be?3?dimensions"?%?(K.ndim(inputs)))dim?=?int(inputs.get_shape()[-1])?#?Dhidden_nn_layers?=?[inputs]final_result?=?[]##?split_tensor0?表示?list:?[x1,?x2,?...,?xD],?其中?xi?的?shape?為?[B,?m,?1]split_tensor0?=?tf.split(hidden_nn_layers[0],?dim?*?[1],?2)for?idx,?layer_size?in?enumerate(self.layer_size):##?split_tensor?表示?list:?[t1,?t2,?...,?tH_{k-1}],?即有?H_{k-1}?個向量;##?其中?ti?的?shape?為?[B,?H_{k-1},?1]split_tensor?=?tf.split(hidden_nn_layers[-1],?dim?*?[1],?2)##?dot_result_m?為一個?tensor,?其?shape?為?[D,?B,?m,?H_{k-1}]dot_result_m?=?tf.matmul(split_tensor0,?split_tensor,?transpose_b=True)##?dot_result_o?的?shape?為?[D,?B,?m?*?H_{k-1}]dot_result_o?=?tf.reshape(dot_result_m,?shape=[dim,?-1,?self.field_nums[0]?*?self.field_nums[idx]])##?dot_result?的?shape?為?[B,?D,?m?*?H_{k-1}]dot_result?=?tf.transpose(dot_result_o,?perm=[1,?0,?2])##?牛掰啊,?還可以這樣寫,?精彩!##?self.filters[idx]?的?shape?為?[1,?m?*?H_{k-1},?H_{k}]##?因此?curr_out?的?shape?為?[B,?D,?H_{k}]curr_out?=?tf.nn.conv1d(dot_result,?filters=self.filters[idx],?stride=1,?padding='VALID')##?self.bias[idx]?的?shape?為?[H_{k}]##?因此?curr_out?的?shape?為?[B,?D,?H_{k}]curr_out?=?tf.nn.bias_add(curr_out,?self.bias[idx])##?curr_out?的?shape?為?[B,?D,?H_{k}]curr_out?=?self.activation_layers[idx](curr_out)##?curr_out?的?shape?為?[B,?H_{k},?D]curr_out?=?tf.transpose(curr_out,?perm=[0,?2,?1])if?self.split_half:if?idx?!=?len(self.layer_size)?-?1:next_hidden,?direct_connect?=?tf.split(curr_out,?2?*?[layer_size?//?2],?1)else:direct_connect?=?curr_outnext_hidden?=?0else:direct_connect?=?curr_outnext_hidden?=?curr_outfinal_result.append(direct_connect)hidden_nn_layers.append(next_hidden)##?先假設不走?self.split_half?的邏輯,?此時?result?的##?shape?為?[B,?sum(H_{k}),?D]?(k=1?->?T,?T?為?CIN?的總層數)result?=?tf.concat(final_result,?axis=1)##?result?最終的?shape?為?[B,?sum(H_{k})]result?=?reduce_sum(result,?-1,?keep_dims=False)return?result往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯溫州大學《機器學習課程》視頻 本站qq群851320808,加入微信群請掃碼:總結
以上是生活随笔為你收集整理的【推荐系统】深入理解推荐系统:无需人工特征工程的xDeepFM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爱奇艺如何设置最小化显示在托盘
- 下一篇: 360浏览器鼠标手势怎么关 取消360浏