DeepFM原理及tensorflow代码实战
目錄
1、背景
2、引入
FM挑戰
DNN的局限
3、組件介紹
FM
Deep
4、代碼解析
?
1、背景
之前說了wide&deepGoogle于?2016 年在DLRS上發表了一篇文章:2016-Wide & Deep Learning for Recommender Systems,模型的核心思想是結合線性模型的記憶能力(memorization)和 DNN 模型的泛化能力(generalization),在訓練過程中同時優化 2 個模型的參數,從而達到整體模型的預測能力最優。
但是由于Wide & Deep的wide部分是一個LR模型,因此仍然需要大量的人工特征工程工作。但是Wide & Deep模型給整個學術界和工業界提供了一種框架思想。基于這種思想,華為諾葉方舟團隊結合FM的特征交叉功能,將Wide & Deep的LR部分替換成FM來避免人工工程,提出了Deep FM模型。
整體的結構如圖
?
2、引入
?
特征組合的挑戰
對于一個基于CTR預估的推薦系統,最重要的是學習到用戶點擊行為背后隱含的特征組合。在不同的推薦場景中,低階組合特征或者高階組合特征可能都會對最終的CTR產生影響。
之前介紹的因子分解機(Factorization Machines, FM)通過對于每一維特征的隱變量內積來提取特征組合。最終的結果也非常好。但是,雖然理論上來講FM可以對高階特征組合進行建模,但實際上因為計算復雜度的原因一般都只用到了二階特征組合。
那么對于高階的特征組合來說,我們很自然的想法,通過多層的神經網絡即DNN去解決。
?
DNN的局限
下面的圖片來自于張俊林教授在AI大會上所使用的PPT。
對于離散特征的處理,我們使用的是將特征轉換成為one-hot的形式,但是將One-hot類型的特征輸入到DNN中,會導致網絡參數太多:
如何解決這個問題呢,類似于FFM中的思想,將特征分為不同的field:
再加兩層的全鏈接層,讓Dense Vector進行組合,那么高階特征的組合就出來了
但是低階和高階特征組合隱含地體現在隱藏層中,如果我們希望把低階特征組合單獨建模,然后融合高階特征組合。
即將DNN與FM進行一個合理的融合:
二者的融合總的來說有兩種形式,一是串行結構,二是并行結構
DeepFM,就是并行結構中的一種典型代表。
如下:
?
3、組件介紹
DeepFM包含兩部分:神經網絡部分與因子分解機部分,分別負責低階特征的提取和高階特征的提取。這兩部分共享同樣的輸入。DeepFM的預測結果可以寫為:
FM
FM部分是一個因子分解機。關于因子分解機可以參閱文章[Rendle, 2010] Steffen Rendle. Factorization machines. In ICDM, 2010.。因為引入了隱變量的原因,對于幾乎不出現或者很少出現的隱變量,FM也可以很好的學習。
FM的輸出公式為:
Deep
深度部分是一個前饋神經網絡。與圖像或者語音這類輸入不同,圖像語音的輸入一般是連續而且密集的,然而用于CTR的輸入一般是及其稀疏的。因此需要重新設計網絡結構。具體實現中為,在第一層隱含層之前,引入一個嵌入層來完成將輸入向量壓縮到低維稠密向量。
嵌入層(embedding layer)的結構如上圖所示。當前網絡結構有兩個有趣的特性,1)盡管不同field的輸入長度不同,但是embedding之后向量的長度均為K。2)在FM里得到的隱變量Vik現在作為了嵌入層網絡的權重。
這里的第二點如何理解呢,假設我們的k=5,首先,對于輸入的一條記錄,同一個field 只有一個位置是1,那么在由輸入得到dense vector的過程中,輸入層只有一個神經元起作用,得到的dense vector其實就是輸入層到embedding層該神經元相連的五條線的權重,即vi1,vi2,vi3,vi4,vi5。這五個值組合起來就是我們在FM中所提到的Vi。在FM部分和DNN部分,這一塊是共享權重的,對同一個特征來說,得到的Vi是相同的。
?
4、代碼解析
?
整個模型是由FM + Deep組成,所以代碼也是按照這個邏輯來做的
FM包括兩個部分,一個是線性部分,另一個是Embedding
可以根據公示進行得到
Y_liner = tf.matmul(x, W) + bembeddings = tf.multiply(v, Input_x) # None * V * X summed_features_emb = tf.reduce_sum(embeddings, 1) # sum(v*x) summed_features_emb_square = tf.square(summed_features_emb) # (sum(v*x))^2# square_sum part squared_features_emb = tf.square(embeddings) # (v*x)^2 squared_sum_features_emb = tf.reduce_sum(squared_features_emb, 1) # sum((v*x)^2)Y_pair = 0.5 * tf.subtract(summed_features_emb_square, squared_sum_features_emb) # 0.5*((sum(v*x))^2 - sum((v*x)^2))deep部分,就是將Embedding part的輸出再經過兩層全鏈接
input_size = n_features*fv output_size = dnn_layer[0] deep_inputs = tf.reshape(embeddings, shape=[-1, input_size]) # None * (F*K) print("%s: %s" % ("lay1, deep_inputs", deep_inputs))# 全連接計算 deep_outputs = udf_full_connect(deep_inputs, input_size, output_size, dnn_active_fuc[0])for i in range(len(dnn_layer) - 1):with tf.variable_scope("deep_layer%d"%(i+2), reuse=tf.AUTO_REUSE):print("lay%s, input_size: %s, output_size: %s, active_fuc: %s" % (i+2, dnn_layer[i], dnn_layer[i+1], dnn_active_fuc[i+1]))# 全連接計算deep_outputs = udf_full_connect(deep_outputs, dnn_layer[i], dnn_layer[i+1], dnn_active_fuc[i+1])print("lay%s, deep_outputs: %s" % (i+2, deep_outputs))# 輸出層計算 print("lay_last, input_size: %s, output_size: %s, active_fuc: %s" % (dnn_layer[-1], 2, dnn_active_fuc[-1])) with tf.variable_scope("deep_layer%d"%(len(dnn_layer)+1), reuse=tf.AUTO_REUSE):deep_outputs = udf_full_connect(deep_outputs, dnn_layer[-1],2, dnn_active_fuc[-1])最后把兩部分輸入進行結合
concat_input = tf.concat([Y_liner, Y_pair, Y_deep], axis=1) Y_sum = tf.reduce_sum(concat_input, 1) print("Y_sum",Y_sum) score=tf.nn.sigmoid(Y_sum,name='score') After 900 steps, loss_value is: 0.522057 After 900 trainging steps ,validation accuarcy is 77.1932% Testing Accuracyis 77.4728%?
完整代碼可以到GitHub進行查看
https://github.com/Andyszl/Recommendation_algorithm/tree/tensorflow
總結
以上是生活随笔為你收集整理的DeepFM原理及tensorflow代码实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2023王道数据结构考研习题汇总
- 下一篇: 深度学习100题(1)