FFM算法解析及Python實現

1. 什麼是FFM?

經過引入field的概念,FFM把相同性質的特徵歸於同一個field,至關於把FM中已經細分的feature再次進行拆分從而進行特徵組合的二分類模型。算法

2. 爲何須要FFM?

在傳統的線性模型中,每一個特徵都是獨立的,若是須要考慮特徵與特徵之間的相互做用,可能須要人工對特徵進行交叉組合。非線性SVM能夠對特徵進行核變換,可是在特徵高度稀疏的狀況下,並不能很好的進行學習。因爲推薦系統是一個高度係數的數據場景,由此產生了FM系列算法,包括FM,FFM,DeepFM等算法。框架

3. FFM用在哪?

和FM算法同樣,FFM主要應用在推薦算法中的CTR點擊率預估(排序)問題,推薦系統通常能夠分紅兩個模塊,召回和排序。好比對於電影推薦,召回模塊會針對用戶生成一個推薦電影列表,而排序模塊則負責對這個電影列表根據用戶的興趣作排序。當把FFM算法應用到推薦系統中時,具體地是應用在排序模塊。學習

4. FFM長什麼樣?

FFM模型結構ui

線性部分你們都很熟悉,非線性部分是FFM的關鍵所在,而且與一樣有非線性部分的FM算法相比,FFM引入了field的概念。所以交叉項與FM算法的<vi , vj>不一樣,這裏的是<vi,fj , vj,fi>編碼

5. FFM交叉項的計算

如下圖網上流傳普遍的圖爲例:spa

其中,紅色部分對應的是Field,來自於原始特徵的個數;
藍色部分對應的是feature,來自於原始特徵onehot以後的個數。(連續型特徵不用one-hot)
對於特徵Feature:User=YuChin,有Movie=3Idiots、Genre=Comedy、Genre=Drama、Price四項要進行交叉組合:.net

綠色部分爲對應特徵one-hot以後的值,出現爲1,不出現爲0。對於連續型變量的處理,這裏採用的是使用實際值,固然,也能夠對連續型變量離散化處理,再進行one-hot。設計

6. FFM代碼分析

這裏咱們的FFM算法是基於Tensorflow實現的。blog

爲何用Tensorflow呢?觀察二次項,因爲field的引入,Vffm須要計算的參數有 nfk 個,遠多於FM模型的 nk個,並且因爲每次計算都依賴於乘以的xj的field,因此,沒法用fm的計算技巧(ab = 1/2(a+b)^2-a^2-b^2),因此計算複雜度是 O(n^2)。排序

所以使用Tensorflow的目的是想經過GPU進行計算。同時這也給咱們提供了一個思路:若是模型的計算複雜度較高,當不能使用CPU快速完成模型訓練時,能夠考慮使用GPU計算。好比Xgboost是已經封裝好能夠用在GPU上的算法庫,而那些沒有GPU版本的封裝算法庫時,例如咱們這次採用的FFM算法,咱們能夠藉助Tensorflow的GPU版本框架設計算法,並完成模型訓練。

代碼主要分三部分:

build_data.py

主要是完成對原始數據的轉化。主要包括構造特徵值對應field的字典。

FFM.py

主要包括線性部分及非線性部分的代碼實現。

tools.py

主要包括訓練集的構造。

這裏咱們主要分析 FFM.py,也就是模型的構建過程:

首先初始化一些參數,包括:

  • k:隱向量長度
  • f :field個數
  • p:特徵值個數
  • 學習率大小
  • 批訓練大小
  • 正則化
  • 模型保存位置等

代碼以下圖所示:

 

而後,構造了一個model類,主要存放:

  • 初始化的一些參數
  • 模型結構
  • 模型訓練op(參數更新)
  • 預測op
  • 模型保存以及載入的op

代碼以下圖所示:

 

以後,對模型構造部分代碼進行分析,可發現模型由兩部分組成,第一部分是下圖紅框內容,其實就是線性表達式 w^Tx+b,其中:

  • b shape(None,1)
  • x shape (batch_size,p)
  • w1 shape(p,1)    注:p爲特徵值個數

定義變量及初始化後,就能夠構造線性模型,代碼以下圖所示:

 

 

而後,定義一個Vffm變量用來存放交叉項的權重,並初始化。由於咱們已經瞭解到Vffm是一個三維向量,因此,v :shape(p,f,k) 。

以後是vi,fj、vj,fi的構造。由於v 有p行,表明共有p個特徵值,因此vifj = v[i, feature2field[j]],說人話就是第i個特徵值在第j個特徵值對應的field上的隱向量。

vjfi 的構造方法相似,因此vivj就能夠求出來.而後就是把交叉項累加,而後 reshape 成(batch_size,1)的形狀,以便與線性模型進行矩陣加法計算。

代碼以下圖所示:

  

下圖描述了全部交叉項的隱向量Vffm所處的位置。假設p=1六、f=三、k=6,16個項所屬的field爲{0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 1, 7: 1, 8: 1, 9: 1, 10: 2, 11: 2, 12: 2, 13: 2, 14: 2, 15: 2},共有120個交叉項,vifj和vjfi隱向量分別各有120個。其中:

vifj隱向量: {(3, 0), (11, 2), (2, 1), (6, 2), (5, 1), (7, 2), (4, 0), (1, 2), (12, 2), (8, 1), (2, 2), (4, 1), (1, 1), (3, 2), (0, 0), (13, 2), (8, 2), (7, 1), (4, 2), (1, 0), (14, 2), (0, 1), (9, 2), (6, 1), (3, 1), (2, 0), (5, 2), (0, 2), (10, 2)},共29個不一樣的隱向量。
vjfi隱向量: {(12, 1), (9, 1), (3, 0), (11, 2), (8, 0), (15, 1), (14, 0), (4, 0), (12, 2), (9, 0), (8, 1), (15, 0), (14, 1), (11, 1), (5, 0), (10, 0), (13, 2), (7, 1), (6, 0), (11, 0), (10, 1), (1, 0), (14, 2), (13, 1), (7, 0), (15, 2), (12, 0), (2, 0), (13, 0)},共29個不一樣的隱向量。

而vifj和vjfi相加起來共有48個各不相同的隱向量。也就是說,下圖展現的每個隱向量都有用,即都能在模型中找到,且不少交叉項的隱向量同樣。

舉個栗子:

v1,15表明着第1個特徵值在第15個特徵值對應的field(field=2)上的隱向量。即v1,15 = v[1, feature2field[15]] = Vffm[1,2] ,其中v1,15的shape = (1,6)。

 

最後,就是loss的定義。這裏要注意咱們以前在構造訓練集時已經把輸出的(0,1)分類轉化爲(-1,1)分類。

核心加劇點是關注loss的計算公式,此時的計算公式是-1/1作二分類的時候經常使用的loss計算方法。

7.  總結

7.1 FFM 算法流程

7.1.1 輸入部分

  1. 類別型特徵對應的變量的值映射爲0到n-1

  2. 連續型變量保持原樣,不作處理,只需把變量名映射爲n便可。(也可按實際狀況進行離散化處理)

  3. 根據每一特徵所屬的field,構造字典:每一field的取值,例如:field爲0,那麼{0:0,0:1,0:2} 。key爲field,value爲變量值或變量名的映射

  4. 構造feature2field字典,本質就是把步驟3中的field字典的k-v交換位置

  5. 最終模型的輸入數據爲(None,n+1),其中n個離散變量的特徵,取值爲0/1,1個連續變量的特徵,取值爲連續值(須要歸一化)

7.1.2 輸出部分

  1. 輸出y 由0/1分類轉換爲-1/1分類

  2. 構造字典{1:n+2,-1:n+3}做爲輸出

  3. 構造訓練集須要的字典field_dict,包括輸入數據和輸出數據,例如:{‘c1’:{1008:0,1001:1},'c2':{0:6,1:7}}

7.2 注意事項

  1. 原始FFM論文中的結論:隱向量的維度 k值的調整提高效果不明顯。

  2. 爲了使用FFM方法,全部的特徵必須轉換成「field_id:feat_id:value」格式,field_id表明特徵所屬field的編號,feat_id是特徵編號,value是特徵的值。

  3. numerical數值型的特徵比較容易處理,只需分配單獨的field編號,如用戶評論得分、商品的歷史CTR/CVR等。優勢是快速簡單,不須要預處理,可是缺點也很明顯,離羣點影響,值的波動大等。所以可對numerical數值型特徵採用連續值離散化或分箱下的連續值離散化的方法,將其轉化爲categorical類別型特徵。

  4. categorical類別型特徵須要通過One-Hot編碼成數值型,編碼產生的全部特徵同屬於一個field,而特徵的值只能是0或1,如用戶的性別、年齡段,商品的品類id等。

  5. 樣本歸一化。FFM默認是進行樣本數據的歸一化,若不進行數據樣本的歸一化,很容易形成數據inf溢出,進而引發梯度計算的nan錯誤。所以,樣本層面的數據是推薦進行歸一化的。

  6. 特徵歸一化。CTR/CVR模型採用了多種類型的源特徵,包括數值型和categorical類型等。可是,categorical類編碼後的特徵取值只有0或1,較大的數值型特徵會形成樣本歸一化後categorical類生成特徵的值很是小,沒有區分性。例如,一條用戶-商品記錄,用戶爲「男」性,商品的銷量是5000個(假設其它特徵的值爲零),那麼歸一化後特徵「sex=male」(性別爲男)的值略小於0.0002,而「volume」(銷量)的值近似爲1。特徵「sex=male」在這個樣本中的做用幾乎能夠忽略不計,這是至關不合理的。所以,將源數值型特徵的值歸一化也是很是必要的。

  7. 省略零值特徵。從FFM模型的表達式能夠看出,零值特徵對模型徹底沒有貢獻。包含零值特徵的一次項和組合項均爲零,對於訓練模型參數或者目標值預估是沒有做用的。所以,能夠省去零值特徵,提升FFM模型訓練和預測的速度,這也是稀疏樣本採用FFM的顯著優點。

8. 參考文獻

[1] 深刻FFM原理與實踐

[2] FM系列算法解讀(FM+FFM+DeepFM

[3] 推薦算法之FFM:原理及實現簡介

相關文章
相關標籤/搜索