推薦系統遇上深度學習(三)--DeepFM模型理論和實踐

2021-03-02 LeadAI OpenLab

全文共3676字,18張圖,預計閱讀時間23分鐘。

對於一個基於CTR預估的推薦系統,最重要的是學習到用戶點擊行為背後隱含的特徵組合。在不同的推薦場景中,低階組合特徵或者高階組合特徵可能都會對最終的CTR產生影響。

之前介紹的因子分解機(Factorization Machines, FM)通過對於每一維特徵的隱變量內積來提取特徵組合。最終的結果也非常好。但是,雖然理論上來講FM可以對高階特徵組合進行建模,但實際上因為計算複雜度的原因一般都只用到了二階特徵組合。

那麼對於高階的特徵組合來說,我們很自然的想法,通過多層的神經網絡即DNN去解決。

下面的圖片來自於張俊林教授在AI大會上所使用的PPT。

我們之前也介紹過了,對於離散特徵的處理,我們使用的是將特徵轉換成為one-hot的形式,但是將One-hot類型的特徵輸入到DNN中,會導致網絡參數太多:

如何解決這個問題呢,類似於FFM中的思想,將特徵分為不同的field:

再加兩層的全連結層,讓Dense Vector進行組合,那麼高階特徵的組合就出來了

但是低階和高階特徵組合隱含地體現在隱藏層中,如果我們希望把低階特徵組合單獨建模,然後融合高階特徵組合。

即將DNN與FM進行一個合理的融合:

二者的融合總的來說有兩種形式,一是串行結構,二是並行結構

而我們今天要講到的DeepFM,就是並行結構中的一種典型代表。

我們先來看一下DeepFM的模型結構:

DeepFM包含兩部分:神經網絡部分與因子分解機部分,分別負責低階特徵的提取和高階特徵的提取。這兩部分共享同樣的輸入。DeepFM的預測結果可以寫為:

FM部分的詳細結構如下:

FM部分是一個因子分解機。關於因子分解機可以參閱文章[Rendle, 2010] Steffen Rendle. Factorization machines. In ICDM, 2010.。因為引入了隱變量的原因,對於幾乎不出現或者很少出現的隱變量,FM也可以很好的學習。

FM的輸出公式為:

深度部分是一個前饋神經網絡。與圖像或者語音這類輸入不同,圖像語音的輸入一般是連續而且密集的,然而用於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是相同的。

有關模型具體如何操作,我們可以通過代碼來進一步加深認識。

我們先來講兩個代碼中會用到的相關知識吧,代碼是參考的github上星數最多的DeepFM實現代碼。

Gini Normalization

代碼中將CTR預估問題設定為一個二分類問題,繪製了Gini Normalization來評價不同模型的效果。這個是什麼東西,不太懂,百度了很多,發現了一個比較通俗易懂的介紹。

假設我們有下面兩組結果,分別表示預測值和實際值:

predictions = [0.9, 0.3, 0.8, 0.75, 0.65, 0.6, 0.78, 0.7, 0.05, 0.4, 0.4, 0.05, 0.5, 0.1, 0.1]
actual = [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

然後我們將預測值按照從小到大排列,並根據索引序對實際值進行排序:

Sorted Actual Values [0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1]

然後,我們可以畫出如下的圖片:

接下來我們將數據Normalization到0,1之間。並畫出45度線。

橙色區域的面積,就是我們得到的Normalization的Gini係數。

這裡,由於我們是將預測概率從小到大排的,所以我們希望實際值中的0儘可能出現在前面,因此Normalization的Gini係數越大,分類效果越好。

embedding_lookup

在tensorflow中有個embedding_lookup函數,我們可以直接根據一個序號來得到一個詞或者一個特徵的embedding值,那麼他內部其實是包含一個網絡結構的,如下圖所示:

假設我們想要找到2的embedding值,這個值其實是輸入層第二個神經元與embedding層連線的權重值。

之前有大佬跟我探討word2vec輸入的問題,現在也算是有個比較明確的答案,輸入其實就是one-hot Embedding,而word2vec要學習的是new Embedding。

好,一貫的風格,先來介紹幾個地址:
原代碼地址:https://github.com/ChenglongChen/tensorflow-DeepFM

本文代碼地址:https://github.com/princewen/tensorflow_practice/tree/master/Basic-DeepFM-model


數據下載地址:https://www.kaggle.com/c/porto-seguro-safe-driver-prediction

好了,話不多說,我們來看看代碼目錄吧,接下來,我們將主要對網絡的構建進行介紹,而對數據的處理,流程的控制部分,相信大家根據代碼就可以看懂。

項目結構如下:

其實還應該有一個存放data的路徑。config.py保存了我們模型的一些配置。DataReader對數據進行處理,得到模型可以使用的輸入。DeepFM是我們構建的模型。main是項目的入口。metrics是計算normalized gini係數的代碼。

模型的輸入主要有下面幾個部分:

self.feat_index = tf.placeholder(tf.int32,
                         shape=[None,None],
                         name='feat_index')
self.feat_value = tf.placeholder(tf.float32,
                       shape=[None,None],
                       name='feat_value')

self.label = tf.placeholder(tf.float32,shape=[None,1],name='label')
self.dropout_keep_fm = tf.placeholder(tf.float32,shape=[None],name='dropout_keep_fm')
self.dropout_keep_deep = tf.placeholder(tf.float32,shape=[None],name='dropout_deep_deep')

feat_index是特徵的一個序號,主要用於通過embedding_lookup選擇我們的embedding。feat_value是對應的特徵值,如果是離散特徵的話,就是1,如果不是離散特徵的話,就保留原來的特徵值。label是實際值。還定義了兩個dropout來防止過擬合。

權重的設定主要有兩部分,第一部分是從輸入到embedding中的權重,其實也就是我們的dense vector。另一部分就是深度神經網絡每一層的權重。第二部分很好理解,我們主要來看看第一部分:


weights['feature_embeddings'] = tf.Variable(
tf.random_normal([self.feature_size,self.embedding_size],0.0,0.01),
name='feature_embeddings')
weights['feature_bias'] = tf.Variable(tf.random_normal([self.feature_size,1],0.0,1.0),name='feature_bias')

weights['feature_embeddings'] 存放的每一個值其實就是FM中的vik,所以它是N * F * K的。其中N代表數據量的大小,F代表feture的大小(將離散特徵轉換成one-hot之後的特徵總量),K代表dense vector的大小。

weights['feature_bias']是FM中的一次項的權重。

這個部分很簡單啦,是根據feat_index選擇對應的weights['feature_embeddings']中的embedding值,然後再與對應的feat_value相乘就可以了:

 
 self.embeddings = tf.nn.embedding_lookup(self.weights['feature_embeddings'],self.feat_index) 
feat_value = tf.reshape(self.feat_value,shape=[-1,self.field_size,1])
self.embeddings = tf.multiply(self.embeddings,feat_value)

首先來回顧一下我們之前對FM的化簡公式,之前去今日頭條面試還問到過公式的推導。

所以我們的二次項可以根據化簡公式輕鬆的得到,再加上我們的一次項,FM的part就算完了。同時更為方便的是,由於權重共享,我們這裡可以直接用Embedding part計算出的embeddings來得到我們的二次項:


self.y_first_order = tf.nn.embedding_lookup(self.weights['feature_bias'],self.feat_index)
self.y_first_order = tf.reduce_sum(tf.multiply(self.y_first_order,feat_value),2)
self.y_first_order = tf.nn.dropout(self.y_first_order,self.dropout_keep_fm[0])



self.summed_features_emb = tf.reduce_sum(self.embeddings,1) 
self.summed_features_emb_square = tf.square(self.summed_features_emb) 


self.squared_features_emb = tf.square(self.embeddings)
self.squared_sum_features_emb = tf.reduce_sum(self.squared_features_emb, 1)  


self.y_second_order = 0.5 * tf.subtract(self.summed_features_emb_square,self.squared_sum_features_emb)
self.y_second_order = tf.nn.dropout(self.y_second_order,self.dropout_keep_fm[1])

DNNpart的話,就是將Embedding part的輸出再經過幾層全連結層:

# Deep component
self.y_deep = tf.reshape(self.embeddings,shape=[-1,self.field_size * self.embedding_size])
self.y_deep = tf.nn.dropout(self.y_deep,self.dropout_keep_deep[0])

for i in range(0,len(self.deep_layers)):
self.y_deep = tf.add(tf.matmul(self.y_deep,self.weights["layer_%d" %i]), self.weights["bias_%d"%I])
self.y_deep = self.deep_layers_activation(self.y_deep)
self.y_deep = tf.nn.dropout(self.y_deep,self.dropout_keep_deep[i+1])

最後,我們要將DNN和FM兩部分的輸出進行結合:

concat_input = tf.concat([self.y_first_order, self.y_second_order, self.y_deep], axis=1)

我們可以使用logloss(如果定義為分類問題),或者mse(如果定義為預測問題),以及多種的優化器去進行嘗試,這些根據不同的參數設定得到:

# loss
if self.loss_type == "logloss":
self.out = tf.nn.sigmoid(self.out)
self.loss = tf.losses.log_loss(self.label, self.out)
elif self.loss_type == "mse":
self.loss = tf.nn.l2_loss(tf.subtract(self.label, self.out))
# l2 regularization on weights
if self.l2_reg > 0:
self.loss += tf.contrib.layers.l2_regularizer(
self.l2_reg)(self.weights["concat_projection"])
if self.use_deep:
for i in range(len(self.deep_layers)):
    self.loss += tf.contrib.layers.l2_regularizer(
        self.l2_reg)(self.weights["layer_%d" % I])


 if self.optimizer_type == "adam":
 self.optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate, beta1=0.9, beta2=0.999,
                                    epsilon=1e-8).minimize(self.loss)
elif self.optimizer_type == "adagrad":
self.optimizer = tf.train.AdagradOptimizer(learning_rate=self.learning_rate,
                                       initial_accumulator_value=1e-8).minimize(self.loss)
elif self.optimizer_type == "gd":
self.optimizer = tf.train.GradientDescentOptimizer(learning_rate=self.learning_rate).minimize(self.loss)
elif self.optimizer_type == "momentum":
self.optimizer = tf.train.MomentumOptimizer(learning_rate=self.learning_rate, momentum=0.95).minimize(
self.loss)

前面提到了,我們用logloss作為損失函數去進行模型的參數更新,但是代碼中輸出了模型的 Normalization 的 Gini值來進行模型評價,我們可以對比一下(記住,Gini值越大越好呦):

好啦,本文只是提供一個引子,有關DeepFM更多的知識大家可以更多的進行學習呦。


參考資料

1、http://www.360doc.com/content/17/0315/10/10408243_637001469.shtml


2、https://blog.csdn.net/u010665216/article/details/78528261

原文連結:https://mp.weixin.qq.com/s/4bw9GxQ10iyC08H0zYbSmw


查閱更為簡潔方便的分類文章以及最新的課程、產品信息,請移步至全新呈現的「LeadAI學院官網」:

www.leadai.org


請關注人工智慧LeadAI公眾號,查看更多專業文章

大家都在看

相關焦點

  • 推薦系統遇上深度學習(八)--AFM模型理論和實踐
    推薦系統遇上深度學習系列:推薦系統遇上深度學習(一)--FM模型理論和實踐推薦系統遇上深度學習(二)--FFM
  • 推薦系統遇上深度學習(六)--PNN模型理論和實踐
    作者:石曉文   中國人民大學信息學院在讀研究生個人公眾號:小小挖掘機(ID:wAIsjwj)
  • 【推薦算法】DeepFM模型原理與實踐
    1 算法背景對於一個基於CTR預估的推薦系統,學習用戶點擊行為背後複雜、有效的特徵表示非常重要。那麼,如何學習出有效的特徵表示呢?理論上來講FM可以對高階特徵組合進行建模,但實際上因為計算複雜度的原因一般都只用到了二階特徵組合。那麼對於高階的特徵組合來說,我們很自然的想法,通過多層的神經網絡即DNN去解決。DNN將FM模型的隱向量作為全連接層的輸入,學習到embedding vector之間更為複雜的關係。也就是說Deep部分的embedding層和FM共享參數。
  • 推薦系統遇上深度學習(二)--FFM模型理論和實踐
    作者:石曉文   中國人民大學信息學院在讀研究生個人公眾號:小小挖掘機(ID:wAIsjwj)
  • 推薦系統遇上深度學習(十二)--推薦系統中的EE問題及基本Bandit算法
    3、基礎知識3.1 累積遺憾Bandit算法需要量化一個核心問題:錯誤的選擇到底有多大的遺憾?能不能遺憾少一些?所以我們便有了衡量Bandit算法的一個指標:累積遺憾:,只需要一行代碼就能在選擇合適的老虎機。
  • 推薦系統遇上深度學習(十七)--探秘阿里之MLR算法淺析及實現
    (learning_rate).minimize(cost)隨後,我們就可以進行試驗了。可以看到,lr的效果是最好的,隨著m的增加,模型的效果越來越差。當然,這並不能說明mlr效果不如lr好,只是我們的數據實在是太少了,哈哈。
  • 推薦系統遇上深度學習(二十二)--DeepFM升級版XDeepFM模型強勢來襲!
    例如,在新聞推薦場景中,一個三階交叉特徵為AND(user_organization=msra,item_category=deeplearning,time=monday_morning),它表示當前用戶的工作單位為微軟亞洲研究院,當前文章的類別是與深度學習相關的,並且推送時間是周一上午。
  • 推薦系統遇上深度學習(三十三)--Neural Attentive Item Similarity Model
    模型的框架圖如下:好了,模型介紹就到這裡了,關於模型中的一些細節,大家可以閱讀原論文。3、NASI代碼實現作者給出了Python2版本的代碼:https://github.com/AaronHeee/Neural-Attentive-Item-Similarity-Model這個代碼在Python3中是無法運行的,主要是Python3中range函數得到的不是list,需要使用list()函數進行轉換,Python3版本的代碼地址:https://github.com
  • 推薦系統遇上深度學習(一)--FM模型理論和實踐
    www.jianshu.com/u/c5df9e229a67)     天善社區:https://www.hellobi.com/u/58654/articles     騰訊云:https://cloud.tencent.com/developer/user/16221401、FM背景在計算廣告和推薦系統中
  • Tensroflow練習,包括強化學習、推薦系統、nlp等
    4、推薦系統推薦系統遇上深度學習(一)--FM模型理論和實踐推薦系統遇上深度學習(二)--FFM模型理論和實踐推薦系統遇上深度學習(三)--DeepFM模型理論和實踐推薦系統遇上深度學習(四)--多值離散特徵的embedding解決方案推薦系統遇上深度學習(五)--Deep&Cross Network模型理論和實踐推薦系統遇上深度學習
  • 深度學習推薦模型DeepFM技術剖析:助力華為應用市場APP推薦
    今年8月下旬,在澳大利亞墨爾本召開的IJCAI2017會議上,來自華為伏羲推薦團隊的專家發表了他們在深度學習推薦算法方面的最新成果。伏羲推薦引擎是華為應用市場聯合華為諾亞方舟實驗室開發的一款推薦系統。針對華為應用市場的業務特點和數據特徵,伏羲推薦算法團隊提出的端到端的深度學習推薦模型DeepFM,助力華為應用市場更加精準、個性化的推薦體驗。
  • 推薦系統遇上深度學習(二十)--貝葉斯個性化排序(BPR)算法原理及實戰
    它在學習和預測過程中都將排序列表作為一個樣本。排序的組結構被保持。而模型的最終目標是尋找合適的矩陣W和H,讓X-(公式打不出來,這裡代表的是X上面有一個橫線,即W和H矩陣相乘後的結果)和X(實際的評分矩陣)最相似。看到這裡,也許你會說,BPR和矩陣分解沒有什區別呀?
  • 【推薦實踐】深度學習在阿里B2B電商推薦系統中的實踐
    推薦導購場景在電商中是重要的滿足用戶"逛"和"買"的場景,本次分享我們聚焦深度學習在阿里B2B電商 ( 1688 ) 推薦系統中的應用,其中包括商品推薦中召回 ( 多興趣Deep Match ),排序 ( 自研DMR ) 的相關工作,以及在新興的互動內容場景 ( 直播、短視頻 ) 中通過異構網絡來解決異構信息的精準匹配問題。
  • 【推薦】基於MATLAB編程、機器學習、深度學習在圖像處理中的實踐技術應用
    >Matlab科研經驗分享與科研工具推薦深度學習在遙感地物分類、目標識別和圖像分割技巧總結尤其是在計算機視覺和圖像處理領域,各種顛覆性的成果應運而生。因此,為了幫助廣大科研人員更加系統地學習圖像處理、機器學習和深度學習的基礎理論知識及對應的代碼實現方法,Ai尚研修特舉辦「MATLAB圖像處理與機器學習技術應用培訓班」 培訓班,旨在幫助學員掌握圖像處理的基礎知識,以及經典機器學習算法和最新的深度神經網絡、遷移學習、對抗生成網絡等算法的基本原理及其MATLAB編程實現方法。
  • 深度學習在推薦系統上的應用
    確實深度學習很火,近期深度學習的戰火燒到推薦系統,其強大的表徵能力和低準入門檻,已經成為各大高校和中國人改網絡發paper的紅利時代。可是我還沒能發上那麼幾篇,之前面試大廠的AI labs被總監虐,感覺工作之後被壓榨太多,快幹了。推薦系統為什麼引入深度學習?
  • 深度學習模型及應用詳解!50本包郵贈送福利
    書籍介紹本書內容定位本書側重在實際應用中讓讀者快速掌握基於深度學習模型的系統開發,內容覆蓋以下幾個部分。第1 部分(第1、2 章)講解深度學習的現狀、概念和實現工具。推薦語 本書深入淺出地介紹了深度學習中常用的多種算法和模型,並結合實際的搜索廣告系統,介紹了很多深度神經網絡在實際系統中的應用。本書兼顧了理論介紹和實際應用,尤其適合於想要將深度學習技術應用於工程實踐的讀者閱讀。
  • 新書推薦:TensorFlow深度學習及實踐
    自從深度學習在語音識別和圖像識別任務中取得突破性成果後,使用深度學習的應用數量開始呈爆炸式增加。深度學習方法被大量應用在身份識別、無人駕駛、癌症檢測、遊戲AI等方面,甚至在許多領域,深度神經網絡的準確度已經超過人類自身的操作。深度學習的數學原理並不複雜,但它的一些設計思想很巧妙。入門深度學習,在數學方面只要知道如何對函數求導以及知道與矩陣相乘相關的知識即可。
  • 推薦系統從零單排系列(五)—Word2Vec理論與實踐(下)
    - 2019年已經過去132天-【導讀】上一篇推薦系統從零單排系列(四)—Word2Vec理論與實踐(上)中介紹了CBOW模型,是指根據上下文來預測當前詞
  • 贈書|從阿里到Facebook,一線大廠這樣做深度學習推薦系統
    本文內容節選自《深度學習推薦系統》一書。由美國Roku推薦系統架構負責人、前Hulu高級研究員王喆精心編著,書中包含了這場革命中一系列的主流技術要點:深度學習推薦模型、Embedding技術、推薦系統工程實現、模型評估體系、業界前沿實踐…………深度學習在推薦系統領域掀起了一場技術革命,本書是一本致力於提高一線算法工程師們工業級推薦系統實踐能力的技術乾貨。
  • 【新書推薦】TensorFlow深度學習及實踐
    TensorFlow是2015年年底開源的一套深度學習框架,也是目前最活躍的深度學習框架之一。《TensorFlow深度學習及實踐》從深度學習的基礎講起,深入TensorFlow的基本框架、原理、原始碼和實現等各個方面,其目的在於降低學習門檻,為讀者解決問題提供詳細的方法和指導。