推荐算法DeepFM原理介绍及tensorflow代码实现
DeepFM
- 目標:
- 產生背景:
- 模型介紹:
- 善于處理特征交叉的機器學習模型 FM
- 如何優化FM的計算效率
- 深度學習模型和 FM 模型的結合 DeepFM
- 特征交叉新方法:元素積操作
- 技巧:
- 代碼部分:
目標:
掌握DeepFM原理,以及發展歷程。和具體的代碼實現。
華為在 IJCAI’2017 提出的模型DeepFM
產生背景:
產生DeepFM模型的原因:前面學習的Embedding MLP、Wide&Deep、NerualCF 等幾種不同的模型結構,都沒有用到交叉特征。特征都是一個一個獨立的送進模型訓練,對于挖掘特征交叉或者特征組合的信息,比較低效。
1、 Embedding MLP是把各個特征,進行了embeding后送進MLP無交叉。直接把獨立的特征扔進神經網絡,讓它們在網絡里面進行自由組合。
2、 NerualCF也是僅僅把物品和用戶分別進行特征的embeding后,送進MLP。NeuralCF 也只在最后才把物品側和用戶側的特征交叉起來。
3、 Wide&Deep中Wide部分,有開始意識到需要進行特征交叉,但是僅僅用到了特征組合的multi-hot編碼,理論上也不算是特征交叉,叫特征組合吧。
4、 所以,可不可以對Wide&Deep再進行一次改進,讓Wide部分學習到更多的特征交叉特性?于是就誕生了DeepFM。模型對于特征組合和特征交叉的學習能力,決定了模型對于未知特征組合樣本的預測能力,而這對于復雜的推薦問題來說,是決定其推薦效果的關鍵點之一。
模型介紹:
善于處理特征交叉的機器學習模型 FM
解決特征交叉問題的傳統機器學習模型,曾經紅極一時的機器學習模型因子分解機模型(Factorization Machine)了,簡稱 FM。
- 它的輸入是由類別型特征轉換成的 One-hot 向量,往上就是深度學習的常規操作,也就是把 One-hot 特征通過 Embedding 層轉換成稠密 Embedding 向量。
- 再往上。FM 會使用一個獨特的層 FM Layer 來專門處理特征之間的交叉問題。
- FM 層中有多個內積操作單元對不同特征向量進行兩兩組合,這些操作單元會把不同特征的內積操作的結果輸入最后的輸出神經元,以此來完成最后的預測。這樣一來,如果我們有兩個特征是用戶喜愛的風格和電影本身的風格,通過 FM 層的兩兩特征的內積操作,這兩個特征就可以完成充分的組合,不至于像 Embedding MLP 模型一樣,還要 MLP 內部像黑盒子一樣進行低效的交叉。
可以看到FM部分對一維的特征和二維的特征進行了建模。一維特征是線性加權,二維特征通過隱向量來求出交叉特征的權重。公式如下所示
FM的泛化能力強,可以理解為
如何優化FM的計算效率
FM如今被廣泛采用并成功替代LR模型的一個關鍵所在是:它可以通過數學公式改寫,把表面貌似是
的復雜度降低到
,其中n是特征數量,k是特征的embedding size,這樣就將FM模型改成了和LR類似和特征數量n成線性規模的時間復雜度了,這點非常好。
詳細的變化過程見鏈接:https://zhuanlan.zhihu.com/p/58160982?utm_source=ZHShareTargetIDMore&utm_medium=social&utm_oi=40535670652928
我們在真正計算的時候,會采用改造后的公式計算。
深度學習模型和 FM 模型的結合 DeepFM
FM 是一個善于進行特征交叉的模型,深度學習模型的擬合能力強,那二者之間能結合嗎?
學習過 Wide&Deep 結構之后,可以快速給出答案,可以把 FM 跟其他深度學習模型組合起來,生成一個全新的既有強特征組合能力,又有強擬合能力的模型。基于這樣的思想,DeepFM 模型就誕生了。DeepFM 是由哈工大和華為公司聯合提出的深度學習模型,架構示意圖如下:
類別WideDeep,模型,可以這樣理解
DeepFM 利用了 Wide&Deep 組合模型的思想,用 FM 替換了 Wide&Deep 左邊的 Wide 部分,加強了淺層網絡部分特征組合的能力,而右邊的部分跟 Wide&Deep 的 Deep 部分一樣,主要利用多層神經網絡進行所有特征的深層處理,最后的輸出層是把 FM 部分的輸出和 Deep 部分的輸出綜合起來,產生最后的預估結果。這就是 DeepFM 的結構。
- DNN部分則是一個簡單的多層的全連接神經網絡。每一層的輸出公式如下所示:
特征交叉新方法:元素積操作
FM 和 DeepFM 中進行特征交叉的方式,都是進行 Embedding 向量的點積操作,那是不是說特征交叉就只能用點積操作了?答案當然是否定的。事實上還有很多向量間的運算方式可以進行特征的交叉,比如模型 NFM(Neural Factorization Machines,神經網絡因子分解機),它就使用了新的特征交叉方法。下面,我們一起來看一下。圖 4 就是 NFM 的模型架構圖,相信已經看了這么多模型架構圖的你,一眼就能看出它跟其他模型的區別,也就是 Bi-Interaction Pooling 層。那這個夾在 Embedding 層和 MLP 之間的層到底做了什么呢?
Bi-Interaction Pooling Layer 翻譯成中文就是“兩兩特征交叉池化層”。假設 Vx 是所有特征域的 Embedding 集合,那么特征交叉池化層的具體操作如下所示。
其中 ⊙ 運算代表兩個向量的元素積(Element-wise Product)操作,即兩個長度相同的向量對應維相乘得到元素積向量。其中,第 k 維的操作如下所示。
其中的xi 和 xj,可以理解為特征Vi和Vj的權重,也是模型需要學習的參數,表示特征在進行交叉的時候,重要程度并不是都一樣,需要進行權重分配。
在進行兩兩特征 Embedding 向量的元素積操作后,再求取所有交叉特征向量之和(SUM),我們就得到了池化層的輸出向量。接著,我們再把該向量輸入上層的多層全連接神經網絡,就能得出最后的預測得分。
總的來說,NFM 并沒有使用內積操作來進行特征 Embedding 向量的交叉,而是使用元素積的操作。在得到交叉特征向量之后,也沒有使用 concatenate 操作把它們連接起來,而是采用了求和的池化操作,把它們疊加起來。
元素積操作和點積操作到底哪個更好呢?真實的效果怎么樣,要去在具體的業務場景的實踐中驗證。
技巧:
剛開始學習的時候,遇到一個問題,就是特征的權重,如何讓模型自己去訓練,這因為是個線性問題y=wx+b,如何確定這個w。看了代碼后才明白:
1、 單個神經元,如果我們不指定激活函數,他就是個線性模型,如圖:
所以,我們把特征輸入一個沒有激活函數的神經元,然后再把神經元輸出的y再和其他特征進行交叉,進行模型訓練,神經網絡便可以自己訓練W的權重值,這點有點超乎想象。
2、如果能進行embeding,盡量讓embeding維度統一,這樣兩兩就可以計算點積或者元素積,但是當要和數值特征,沒有embeding向量,而是一個一維數值,怎么辦呢?
后來學到一招。就是讓embeding后的特征,還有數值特征等等,輸入給多個神經元,比如50個,并不指定激活函數,這樣每個特征都會得到一個50維度的線性權重向量,然后再和其他特征的50維向量進行點積或者元素積,這樣,就不論特征embeding維度是多少,有沒有embeding,都可以進行特征交叉。如下圖
最終的Y就可以和其他特征進行交叉。
代碼部分:
完整代碼GitHub地址:https://github.com/jiluojiluo/recommenderSystemForFlowerShop
一階線性部分:
first_order_cat_feature = tf.keras.layers.DenseFeatures(cat_columns)(inputs) first_order_cat_feature = tf.keras.layers.Dense(1, activation=None)(first_order_cat_feature) first_order_deep_feature = tf.keras.layers.DenseFeatures(deep_columns)(inputs) first_order_deep_feature = tf.keras.layers.Dense(1, activation=None)(first_order_deep_feature) ## first order featurefirst_order_feature = tf.keras.layers.Add()([first_order_cat_feature, first_order_deep_feature])二階交叉特征代碼:
second_order_sum_feature = ReduceLayer(1)(second_order_fm_feature) second_order_sum_square_feature = tf.keras.layers.multiply([second_order_sum_feature, second_order_sum_feature]) second_order_square_feature = tf.keras.layers.multiply([second_order_fm_feature, second_order_fm_feature]) second_order_square_sum_feature = ReduceLayer(1)(second_order_square_feature) ## second_order_fm_feature second_order_fm_feature = tf.keras.layers.subtract([second_order_sum_square_feature, second_order_square_sum_feature])Deep部分代碼:
deep_feature = tf.keras.layers.Flatten()(second_order_fm_feature) deep_feature = tf.keras.layers.Dense(32, activation='relu')(deep_feature) deep_feature = tf.keras.layers.Dense(16, activation='relu')(deep_feature)最終拼接3個模塊,組成一個大向量,送入到最后的sigmoid函數,進行預測
concatenated_outputs = tf.keras.layers.Concatenate(axis=1)([first_order_feature, second_order_fm_feature, deep_feature]) output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(concatenated_outputs)運行結果:
1064/1064 [==============================] - 31s 24ms/step - loss: 0.7667 - accuracy: 0.7406 - auc: 0.8041 - auc_1: 0.7558 Epoch 2/5 1064/1064 [==============================] - 25s 23ms/step - loss: 0.4634 - accuracy: 0.8022 - auc: 0.8765 - auc_1: 0.8534 Epoch 3/5 1064/1064 [==============================] - 25s 23ms/step - loss: 0.4243 - accuracy: 0.8220 - auc: 0.8953 - auc_1: 0.8754 Epoch 4/5 1064/1064 [==============================] - 25s 23ms/step - loss: 0.3970 - accuracy: 0.8341 - auc: 0.9070 - auc_1: 0.8905 Epoch 5/5 1064/1064 [==============================] - 25s 23ms/step - loss: 0.3832 - accuracy: 0.8391 - auc: 0.9126 - auc_1: 0.8984 264/264 [==============================] - 6s 16ms/step - loss: 0.3950 - accuracy: 0.8380 - auc: 0.9114 - auc_1: 0.8904Test Loss 0.39503785967826843, Test Accuracy 0.8380219340324402, Test ROC AUC 0.9113883376121521, Test PR AUC 0.8903669118881226可以看到運行結果,同一份數據,相比之前的的Wide@Deep,NutralCF等,模型的準確度提升太多了。也說明順著模型的升級,效果越來越顯著,挖掘到的交叉特征確實能提升模型的準確度。
總結
以上是生活随笔為你收集整理的推荐算法DeepFM原理介绍及tensorflow代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 经典Wide Deep模型介绍及ten
- 下一篇: 推荐系统XDeepFM模型--DeepF