FM/FFM算法的產生
我們使用傳統的線性模型(如邏輯迴歸)進行廣告CTR(廣告點擊率)、CVR(轉化率)預測時,往往遇到下面的問題:
數據集特徵極度稀疏。許多特徵如用戶的地區、職業等都是類別型特徵,其特徵取值非常多,但每個取值的出現次數很少,這樣我們對這些類別型特徵進行one_hot編碼後就會產生大量的零值特徵,這樣的特徵對於傳統的線性模型的預測會產生負面效果,導致模型的預測效果較差;
同樣地,由於類別型特徵的取值非常之多,轉換成one_hot編碼後會導致特徵空間大大擴張,這增加了訓練時的計算量,也使得模型的訓練變得困難;
傳統的線性模型沒有考慮特徵之間的相互關係,比如“化妝品”類商品與“女”性,“球類運動配件”的商品與“男”性,“電影票”的商品與“電影”品類偏好,這些特徵之間往往是有聯繫的。但傳統線性模型如邏輯迴歸模型只能通過手動構造組合特徵來考慮特徵與特徵之間的相互關係,而非線性SVM雖然可以對特徵進行核變換學習它的交叉特徵,但是在特徵高度稀疏的情況下,並不能很好的進行學習。
爲什麼線性SVM在和多項式SVM在稀疏條件下效果會比較差呢?
線性svm只有一維特徵,不能挖掘深層次的組合特徵;多項式svM交叉的多個特徵需要在訓練集上共現才能被學習到(即xi和xj需要同時不爲0纔對wij有訓練效果),否則wij就爲0,這樣對於測試集上的樣本而言這樣的特徵就失去了意義,因此在稀疏條件下,SVM表現並不能讓人滿意。
爲了解決以上三個問題,產生了FM與FFM系列算法。
FM算法原理推導
論文:Factorization Machines
論文地址:https://www.csie.ntu.edu.tw/~b97053/paper/Rendle2010FM.pdf 。
FM(Factorization Machines,因子分解機)主要是爲了解決數據稀疏的情況下,特徵怎樣組合的問題。
舉例:
x1年齡 x2北京 x3上海 x4深圳 x5男 x6女
用戶1 23 1 0 0 1 0
用戶2 31 0 0 1 0 1
特徵X有6個維度,年齡是連續值,城市和性別用one-hot表示,假設我們用最簡單的線性擬合來預測y值:
y = w 0 + ∑ i = 1 n w i x i
y=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}
y = w 0 + i = 1 ∑ n w i x i
實際中“北京的男性用戶”、“上海的女性用戶”這種組合特徵可能是有用的,即xixj(xi,xj都是one-hot特徵)同時爲1時可能是一個很有用的特徵,這種組合特徵是xi和xj的線性組合所無法表示的。這樣一來乘積xixj就成一個新的特徵。
爲了不錯過任何一個這種可能有用的組合特徵,我們窮舉所有的i,j組合,把二項特徵組合xixj都加到特徵中,即使其中某些xi不是one-hot特徵或者某些xixj不是有用的特徵也沒有關係,經過訓練後模型會把那些無用的特徵的係數訓練爲0。
模型公式變爲下面這樣:
y = w 0 + ∑ i = 1 n w i x i + ∑ i n ∑ j = i + 1 n w i j x i x j
y=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+\sum_{i}^{n} \sum_{j=i+1}^{n} w_{i j} x_{i} x_{j}
y = w 0 + i = 1 ∑ n w i x i + i ∑ n j = i + 1 ∑ n w i j x i x j
我們發現,加入二項組合後,模型的參數增加了n(n-1)/2個,這不但大大增加了計算量,同時由於大部分one_hot編碼中的xi和xj同時不爲0的樣本較少,這些二項組合的參數很難訓練。
FM模型推導
傳統的線性迴歸模型公式如下:
f ( x ) = w 0 + w 1 x 1 + w 2 x 2 + … + w n x n = w 0 + ∑ i = 1 n w i x i
\begin{aligned} f(x) &=w_{0}+w_{1} x_{1}+w_{2} x_{2}+\ldots+w_{n} x_{n} \\\\ &=w_{0}+\sum_{i=1}^{n} w_{i} x_{i} \end{aligned}
f ( x ) = w 0 + w 1 x 1 + w 2 x 2 + … + w n x n = w 0 + i = 1 ∑ n w i x i
其中(w0,w1…wn)爲模型參數,(x1,x2…xn)爲特徵。
我們在傳統的線性迴歸模型的基礎上,考慮任意2個特徵分量之間的關係,得到下面的二項式模型:
y = w 0 + ∑ i = 1 n w i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n w i j x i x j
y=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+\sum_{i=1}^{n-1} \sum_{j=i+1}^{n} w_{i j} x_{i} x_{j}
y = w 0 + i = 1 ∑ n w i x i + i = 1 ∑ n − 1 j = i + 1 ∑ n w i j x i x j
其中n表示樣本的特徵數量,這裏的特徵是離散化後的特徵。與線性模型相比,FM的模型多了後面的特徵組合的部分。二項組合特徵的參數一共有n(n−1)/2個,任意兩個參數都是獨立的。對於參數wi,只要這個樣本中對應的xi不爲0,則可以完成一次訓練;對於參數wij的訓練,需要這個樣本中的xi和xj同時不爲0,纔可以完成一次訓練。
在數據稀疏的實際應用場景中,二次項wij的訓練是非常困難的。因爲每個wij都需要大量xi和xj都不爲0的樣本。但在數據稀疏性比較明顯的樣本中,xi和xj都不爲0的樣本會非常稀少,這會導致wij不能得到足夠的訓練,容易導致參數wij不準確,最終將嚴重影響模型的性能。
假設有n個特徵維度, 爲了求解Wij,我們爲每個特徵維度xi引入一個輔助向量:
V i = ( v i 1 , v i 2 , … , v i k ) T
V_{i}=\left(v_{i1}, v_{i2}, \ldots, v_{ik}\right)^{T}
V i = ( v i 1 , v i 2 , … , v i k ) T
Vi是第i維特徵的隱向量,隱向量的長度爲k(k<<n)。
隱變量V是所有Vi組成的矩陣:
V = [ v 11 v 21 v 31 ⋯ v n 1 v 12 v 22 v 32 ⋯ v n 2 ⋮ ⋮ ⋮ ⋱ ⋮ v 1 k v 2 k v 3 k ⋯ v n k ] = [ V 1 V 2 ⋯ V n ]
V=\left[ \begin{array}{ccccc}{v_{11}} & {v_{21}} & {v_{31}} & {\cdots} & {v_{n 1}} \\\\ {v_{12}} & {v_{22}} & {v_{32}} & {\cdots} & {v_{n 2}} \\\\ {\vdots} & {\vdots} & {\vdots} & {\ddots} & {\vdots} \\\\ {v_{1 k}} & {v_{2 k}} & {v_{3 k}} & {\cdots} & {v_{n k}}\end{array}\right]=\left[ \begin{array}{c}{V_{1}} & {V_{2}} & {\cdots} & {V_{n}}\end{array}\right]
V = ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ v 1 1 v 1 2 ⋮ v 1 k v 2 1 v 2 2 ⋮ v 2 k v 3 1 v 3 2 ⋮ v 3 k ⋯ ⋯ ⋱ ⋯ v n 1 v n 2 ⋮ v n k ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤ = [ V 1 V 2 ⋯ V n ]
我們需要求出所有wij組成的矩陣W,這是一個nxn矩陣:
W = [ w 11 w 12 … w 1 n w 21 w 22 … w 2 n ⋮ ⋮ ⋱ ⋮ w n 1 w n 2 … w n n ]
W=\left[\begin{array}{cccc}{w_{11}} & {w_{12}} & {\dots} & {w_{1 n}} \\\\ {w_{21}} & {w_{22}} & {\dots} & {w_{2 n}} \\\\ {\vdots} & {\vdots} & {\ddots} & {\vdots} \\\\ {w_{n 1}} & {w_{n 2}} & {\dots} & {w_{n n}}\end{array}\right]
W = ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ w 1 1 w 2 1 ⋮ w n 1 w 1 2 w 2 2 ⋮ w n 2 … … ⋱ … w 1 n w 2 n ⋮ w n n ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤
W矩陣是一個對稱陣,只要它的值能保證矩陣正定,矩陣就可以進行如下分解:
w = V T V = [ v 11 v 12 v 13 ⋯ v 1 k v 21 v 22 v 23 ⋯ v 2 k ⋮ ⋮ ⋮ ⋱ ⋮ v n 1 v n 2 v n 3 ⋯ v n k ] [ v 11 v 21 v 31 ⋯ v n 1 v 12 v 22 v 32 ⋯ v n 2 ⋮ ⋮ ⋮ ⋱ ⋮ v 1 k v 2 k v 3 k ⋯ v n k ]
w=V^{T} V=\left[ \begin{array}{ccccc}{v_{11}} & {v_{12}} & {v_{13}} & {\cdots} & {v_{1 k}} \\\\ {v_{21}} & {v_{22}} & {v_{23}} & {\cdots} & {v_{2 k}} \\\\ {\vdots} & {\vdots} & {\vdots} & {\ddots} & {\vdots} \\\\ {v_{n 1}} & {v_{n 2}} & {v_{n 3}} & {\cdots} & {v_{n k}}\end{array}\right] \left[\begin{array}{ccccc}{v_{11}} & {v_{21}} & {v_{31}} & {\cdots} & {v_{n 1}} \\\\ {v_{12}} & {v_{22}} & {v_{32}} & {\cdots} & {v_{n 2}} \\\\ {\vdots} & {\vdots} & {\vdots} & {\ddots} & {\vdots} \\\\ {v_{1 k}} & {v_{2 k}} & {v_{3 k}} & {\cdots} & {v_{n k}}\end{array}\right]
w = V T V = ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ v 1 1 v 2 1 ⋮ v n 1 v 1 2 v 2 2 ⋮ v n 2 v 1 3 v 2 3 ⋮ v n 3 ⋯ ⋯ ⋱ ⋯ v 1 k v 2 k ⋮ v n k ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤ ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ v 1 1 v 1 2 ⋮ v 1 k v 2 1 v 2 2 ⋮ v 2 k v 3 1 v 3 2 ⋮ v 3 k ⋯ ⋯ ⋱ ⋯ v n 1 v n 2 ⋮ v n k ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤
V 的第j列便是第j維特徵的隱向量。這樣我們就把大小爲nxn的w矩陣分解成了nxk的V矩陣與kxn的V的轉置矩陣的乘積。
於是上面的二項式模型可寫成:
y ( x ) = w 0 + ∑ i = 1 n w i x i + ∑ i = 1 n ∑ j = 1 n < v i , v j > x i x j
y(x)=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+\sum_{i=1}^{n} \sum_{j=1}^{n}<v_{i}, v_{j}>x_{i} x_{j}
y ( x ) = w 0 + i = 1 ∑ n w i x i + i = 1 ∑ n j = 1 ∑ n < v i , v j > x i x j
這就是FM模型。
二次項的參數數量減少爲kn個,遠少於最初的二項式模型的參數數量。另外,參數因子化使得xhxi 的參數和xixj的參數不再是相互獨立的,因此我們可以在樣本稀疏的情況下相對合理地估計FM的二次項參數。具體來說,xhxi和xixj的係數分別爲<vh,vi>和<vi,vj>,它們之間有共同項vi。也就是說,所有包含"xi的非零組合特徵"(存在某個 j≠i,使得 xixj≠0)的樣本都可以用來學習隱向量vi,這很大程度上避免了數據稀疏性造成的影響。而在多項式模型中,whi和wij是相互獨立的。
FM模型既可以解決迴歸問題,也可以解決二分類問題。如可以採用平方差損失函數來求解迴歸問題,也可以採用交叉熵損失來求解分類問題。在進行二元分類時,輸出需要經過sigmoid變換,這與Logistic迴歸是一樣的。直觀上看,FM的複雜度是 O(kn2)。
FM模型的化簡
我們可以對上面的FM模型進行進一步化簡,降低時間複雜度。
∑ i = 1 n ∑ j = 1 n < v i , v j > x i x j
\sum_{i=1}^{n} \sum_{j=1}^{n}<v_{i}, v_{j}>x_{i} x_{j}
i = 1 ∑ n j = 1 ∑ n < v i , v j > x i x j
是一個完整的對稱矩陣,而下面的矩陣是這個對稱矩陣的上三角部分(不包含對角線):
∑ i = 1 n ∑ j = i + 1 n < v i , v j > x i x j
\sum_{i=1}^{n} \sum_{j=i+1}^{n}<v_{i}, v_{j}>x_{i} x_{j}
i = 1 ∑ n j = i + 1 ∑ n < v i , v j > x i x j
所以有下列對應關係:
∑ i = 1 n ∑ j = i + 1 n < v i , v j > x i x j = ( 1 2 ∑ i = 1 n ∑ j = 1 n < v i , v j > x i x j ) − ( 1 2 ∑ i = 1 n < v i , v i > x i x i )
\sum_{i=1}^{n} \sum_{j=i+1}^{n}<v_{i}, v_{j}>x_{i} x_{j}=(\frac{1}{2} \sum_{i=1}^{n} \sum_{j=1}^{n}<v_{i}, v_{j}>x_{i} x_{j})-(\frac{1}{2} \sum_{i=1}^{n}<v_{i}, v_{i}>x_{i} x_{i})
i = 1 ∑ n j = i + 1 ∑ n < v i , v j > x i x j = ( 2 1 i = 1 ∑ n j = 1 ∑ n < v i , v j > x i x j ) − ( 2 1 i = 1 ∑ n < v i , v i > x i x i )
即對稱矩陣減去對角線再除以2就是我們要求的對稱矩陣上三角部分。
把求和符號放到式子裏面,得:
∑ i = 1 n ∑ j = i + 1 n < v i , v j > x i x j = 1 2 ( ( ∑ i = 1 n ∑ j = 1 n ∑ f = 1 k v i , f v j , f x i x j ) − ( ∑ i = 1 n ∑ f = 1 k v i , f v i , f x i x i ) ) = 1 2 ( ( ∑ f = 1 k ∑ i = 1 n v i , f x i ∑ j = 1 n v j , f x j ) − ( ∑ i = 1 n ∑ f = 1 k v i , f v i , f x i x i ) )
\sum_{i=1}^{n} \sum_{j=i+1}^{n}<v_{i}, v_{j}>x_{i} x_{j} =\frac{1}{2}\left(\left(\sum_{i=1}^{n} \sum_{j=1}^{n} \sum_{f=1}^{k} v_{i,f} v_{j,f} x_{i} x_{j}\right)-\left(\sum_{i=1}^{n} \sum_{f=1}^{k} v_{i,f} v_{i,f} x_{i} x_{i}\right)\right) \\\\ =\frac{1}{2}\left(\left(\sum_{f=1}^{k} \sum_{i=1}^{n} v_{i,f} x_{i} \sum_{j=1}^{n} v_{j,f} x_{j}\right)-\left(\sum_{i=1}^{n} \sum_{f=1}^{k} v_{i,f} v_{i,f} x_{i} x_{i}\right)\right)
i = 1 ∑ n j = i + 1 ∑ n < v i , v j > x i x j = 2 1 ⎝ ⎛ ⎝ ⎛ i = 1 ∑ n j = 1 ∑ n f = 1 ∑ k v i , f v j , f x i x j ⎠ ⎞ − ⎝ ⎛ i = 1 ∑ n f = 1 ∑ k v i , f v i , f x i x i ⎠ ⎞ ⎠ ⎞ = 2 1 ⎝ ⎛ ⎝ ⎛ f = 1 ∑ k i = 1 ∑ n v i , f x i j = 1 ∑ n v j , f x j ⎠ ⎞ − ⎝ ⎛ i = 1 ∑ n f = 1 ∑ k v i , f v i , f x i x i ⎠ ⎞ ⎠ ⎞
vi,f是隱向量vi的第f個元素,vj,f是隱向量vj的第f個元素。由於vi,fxi跟j沒有關係,vj,fxj跟i沒有關係,因此
∑ i = 1 n v i , f x i ∑ j = 1 n v j , f x j = ( ∑ i = 1 n v i , f x i ) ( ∑ j = 1 n v j , f x j )
\sum_{i=1}^{n} v_{i,f} x_{i} \sum_{j=1}^{n} v_{j,f} x_{j}=\left(\sum_{i=1}^{n} v_{i,f} x_{i}\right)\left(\sum_{j=1}^{n} v_{j,f} x_{j}\right)
i = 1 ∑ n v i , f x i j = 1 ∑ n v j , f x j = ( i = 1 ∑ n v i , f x i ) ( j = 1 ∑ n v j , f x j )
上式就可繼續化簡爲
∑ i = 1 n ∑ j = i + 1 n < v i , v j > x i x j = 1 2 ( ∑ f = 1 k ( ∑ i = 1 n v i , f x i ) ( ∑ j = 1 n v j , f x j ) − ∑ i = 1 n ∑ f = 1 k v i , f v i , f x i x i ) = 1 2 ∑ f = 1 k ( ( ∑ i = 1 n v i , f x i ) ( ∑ j = 1 n v j , f x j ) − ∑ i = 1 n v i , f 2 x i 2 ) = 1 2 ∑ f = 1 k ( ( ∑ i = 1 n v i , f x i ) 2 − ∑ i = 1 n v i , f 2 x i 2 )
\sum_{i=1}^{n} \sum_{j=i+1}^{n}<v_{i}, v_{j}>x_{i} x_{j} =\frac{1}{2}\left(\sum_{f=1}^{k}\left(\sum_{i=1}^{n} v_{i,f} x_{i}\right)\left(\sum_{j=1}^{n} v_{j,f} x_{j}\right)-\sum_{i=1}^{n} \sum_{f=1}^{k} v_{i,f} v_{i,f} x_{i} x_{i}\right) \\\\ =\frac{1}{2} \sum_{f=1}^{k}\left(\left(\sum_{i=1}^{n} v_{i,f} x_{i}\right)\left(\sum_{j=1}^{n} v_{j,f} x_{j}\right)-\sum_{i=1}^{n} v_{i,f}^{2} x_{i}^{2}\right) \\\\ =\frac{1}{2} \sum_{f=1}^{k}\left(\left(\sum_{i=1}^{n} v_{i,f} x_{i}\right)^{2}-\sum_{i=1}^{n} v_{i,f}^{2} x_{i}^{2}\right)
i = 1 ∑ n j = i + 1 ∑ n < v i , v j > x i x j = 2 1 ⎝ ⎛ f = 1 ∑ k ( i = 1 ∑ n v i , f x i ) ( j = 1 ∑ n v j , f x j ) − i = 1 ∑ n f = 1 ∑ k v i , f v i , f x i x i ⎠ ⎞ = 2 1 f = 1 ∑ k ( ( i = 1 ∑ n v i , f x i ) ( j = 1 ∑ n v j , f x j ) − i = 1 ∑ n v i , f 2 x i 2 ) = 2 1 f = 1 ∑ k ⎝ ⎛ ( i = 1 ∑ n v i , f x i ) 2 − i = 1 ∑ n v i , f 2 x i 2 ⎠ ⎞
這樣時間複雜度就降爲O(kn)。把上式帶入到FM模型公式中,我們就得到了時間複雜度優化到O(kn)的FM模型公式。
梯度下降法求解W和V
梯度下降法求解梯度公式:
∂ y ( x ) ∂ θ = { 1 , if θ is w 0 x i , if θ is w i x i ∑ j = 1 n v j , f x j − v i f x i 2 , if θ is v i f
\frac{\partial y(x)}{\partial \theta} =\begin{cases}{1,} & {\text { if } \theta \text { is } w_{0}} \\\\ {x_{i},} & {\text { if } \theta \text { is } w_{i}} \\\\ {x_{i} \sum_{j=1}^{n} v_{j,f} x_{j}-v_{i f} x_{i}^{2},} & {\text { if } \theta \text { is } v_{i f}}\end{cases}
∂ θ ∂ y ( x ) = ⎩ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎧ 1 , x i , x i ∑ j = 1 n v j , f x j − v i f x i 2 , if θ is w 0 if θ is w i if θ is v i f
vj,f是隱向量vj的第f個元素。在根據x計算y時
∑ j = 1 n v j , f x j
\sum_{j=1}^{n} v_{j,f} x_{j}
j = 1 ∑ n v j , f x j
只與f有關,而與i無關,在每次迭代過程中,只需計算一次所有f的上式,就能夠方便地得到所有vi,f 的梯度。求vi,f 的梯度
∂ y ^ ∂ v i f
\frac{\partial \hat{y}}{\partial v_{i f}}
∂ v i f ∂ y ^
的時間複雜度爲O(1),對所有參數求偏導的總的時間複雜度爲O(kn)。化簡後的FM模型可以在線性時間訓練和預測,是一種非常高效的模型。
FM與SVM的區別
SVM的二元特徵交叉參數是獨立的,而FM的二元特徵交叉參數是兩個k維的向量vi、vj,交叉參數就不是獨立的,而是相互影響的;
FM可以在原始形式下進行優化學習,而基於kernel的非線性SVM通常需要在對偶形式下進行;
FM的模型預測是與訓練樣本獨立,而SVM則與部分訓練樣本(支持向量)有關。
FFM算法原理推導
論文:Field-aware Factorization Machines
論文地址:https://www.csie.ntu.edu.tw/~r01922136/slides/ffm.pdf 。
FFM(Field-aware Factorization Machines,場感知分解機)是對FM模型的改進。在FM中,原始特徵通過one-hot編碼新生成的特徵集合我們沒有用一個field來標識它們是由同一個原始類別型特徵生成的。而在FFM算法中,這種關係得到了保留,即那就是同一個原始特徵使用one_hot編碼生成的新特徵屬於同一個Field。
舉例:
field field1年齡 field2城市 field3性別
feature x1年齡 x2北京 x3上海 x4深圳 x5男 x6女
用戶1 23 1 0 0 1 0
用戶2 31 0 0 1 0 1
對於連續特徵,一個特徵就對應一個Field。或者對連續特徵離散化,一個分箱成爲一個特徵;對於離散特徵,採用one-hot編碼,同一種屬性的歸到一個Field。
FM對每一個新特徵學習一個長度爲k的隱式向量vi,共有nk個參數;FFM是對每一個新特徵學習f個長度爲k的隱式向量vifj,共有nkf個參數。即FFM有f個FM中的參數矩陣,針對每個field都有一個。從這個角度看,FM是FFM的f=1的特例。
假設樣本的n個新特徵屬於f個field,那麼FFM的二次項有nf個隱向量。而在FM模型中,每一維特徵的隱向量只有一個,FM的二次項共有n個隱向量。
FFM的模型公式如下:
y ( x ) = w 0 + ∑ i = 1 n w i x i + ∑ i = 1 n ∑ j = i + 1 n < v i , f j , v j , f i > x i x j
y(x)=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+\sum_{i=1}^{n} \sum_{j=i+1}^{n}<v_{i,f_{j}}, v_{j,f_{i}}> x_{i} x_{j}
y ( x ) = w 0 + i = 1 ∑ n w i x i + i = 1 ∑ n j = i + 1 ∑ n < v i , f j , v j , f i > x i x j
其中,fj是第j個特徵所屬的field。如果隱向量的長度爲k,那麼FFM的二次參數有nfk個,遠多於FM模型的nk個。此外,由於隱向量與field相關,FFM二次項並不能夠化簡,其預測複雜度是O(kn2)。
網上實現的FFM模型都沒有考慮非交叉特徵,即省略了常數項和一次項,實現的FFM模型公式如下:
ϕ ( w , x ) = ∑ j 1 , j 2 ∈ C 2 < w j 1 , f 2 , w j 2 , f 1 > x j 1 x j 2
\phi(\mathbf{w}, \mathbf{x})=\sum_{j_{1}, j_{2} \in C_{2}}<w_{j_{1}, f_{2}}, w_{j_{2}, f_{1}}> x_{j_{1}} x_{j_{2}}
ϕ ( w , x ) = j 1 , j 2 ∈ C 2 ∑ < w j 1 , f 2 , w j 2 , f 1 > x j 1 x j 2
其中,C2是非零特徵的二元組合,j1是特徵,屬於field f1,wj1,f2是特徵j1對fieldf2的隱向量。
如Yu-Chin Juan實現了一個C++版的FFM模型,源碼下載地址:https://github.com/ycjuan/libffm 。此FFM模型採用logistic loss作爲損失函數,和L2懲罰項,因此只能用於二元分類問題。
損失函數如下:
min w ∑ i = 1 L log ( 1 + exp ( − y i ϕ ( w , x i ) ) ) + λ 2 ∥ w ∥ 2
\min_{w} \sum_{i=1}^{L} \log \left(1+\exp \left(-y_{i} \phi\left(\mathbf{w}, \mathbf{x}_{i}\right)\right)\right)+\frac{\lambda}{2}\|\mathbf{w}\|^{2}
w min i = 1 ∑ L log ( 1 + exp ( − y i ϕ ( w , x i ) ) ) + 2 λ ∥ w ∥ 2
其中,yi取值−1或1,是第i個樣本的label,L是訓練樣本數量,λ是懲罰項係數。模型採用SGD優化算法。
在使用FFM模型時,我們最好進行數值型特徵的歸一化,因爲特徵中同時包含數值型特徵和類別型特徵,而類別型特徵進行one_hot編碼後的特徵取值只有0或1,較大的數值型特徵會造成模型學習時類別型特徵的參數變得很小,使得模型預測性能下降。
deepFM算法原理
論文:DeepFM: A Factorization-Machine based Neural Network for CTR Prediction
論文地址:https://arxiv.org/pdf/1703.04247.pdf 。
FM算法通過對於每一個特徵的隱變量內積來提取特徵組合,最後的結果也不錯,雖然理論上FM可以對高階特徵組合進行建模,但實際上因爲計算複雜度原因,一般都只用到二階特徵組合。對於大於二階的高階特徵組合來說,我們很自然想到多層神經網絡DNN。DeepFM算法同時使用了FM和DNN,其中FM算法負責對一階特徵以及由一階特徵兩兩組合而成的二階特徵進行特徵的提取,DNN算法負責對由輸入的一階特徵進行全連接等操作形成的高階特徵進行特徵的提取。
deepFM算法結構
DeepFM包含兩部分:FM部分與DNN部分,分別負責一二階特徵的提取和大於二階的高階特徵的提取。這兩部分共享同樣的輸入。對於特徵i,標量wi用於表示其一階權重。隱向量Vi用於表示特徵i與其他特徵之間的相互作用。Vi在FM部分是用於對2階特徵進行建模,即特徵之間的相互作用;Vi輸入到Deep部分則是用於進行大於二階的高階特徵建模。
DeepFM的預測結果可以寫爲:
y ^ = sigmoid ( y F M + y D N N )
\hat y=\operatorname{sigmoid}\left(y_{F M}+y_{D N N}\right)
y ^ = s i g m o i d ( y F M + y D N N )
FM部分
y F M = w 0 + ∑ i = 1 n w i x i + ∑ i = 1 n ∑ j = 1 n < v i , v j > x i x j
y_{F M}=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+\sum_{i=1}^{n} \sum_{j=1}^{n}<v_{i}, v_{j}>x_{i} x_{j}
y F M = w 0 + i = 1 ∑ n w i x i + i = 1 ∑ n j = 1 ∑ n < v i , v j > x i x j
FM算法中除了一階特徵的表示,還有2階的組合特徵表示。通過特徵的隱向量之間的內積表示2階的組合特徵。即計算Vi和Vj的內積,從而得到特徵i和特徵j的2階相互作用。這種方案就可以解決訓練數據集中很少出現或者不出現的特徵其權重很難訓練的問題。
注意:
雖然公式上yFM是所有部分都求和,是一個標量。但是實際上輸入到輸出單元的部分並不是一個標量,應該是一個向量。
實際實現中採用的是FM化簡之後的內積公式,最終的維度是:field_size+embedding_size(對應FM Layer中的神經元個數: Field數量+嵌入維度=F+k,其中F爲one-hot之前特徵維度,k爲embedding的特徵維度)。
field_size對應的是一階特徵的權重,embedding_size對應的是二階組合特徵的權重。由FM算法的化簡公式,最後可化簡爲:
1 2 ∑ f = 1 k ( ( ∑ i = 1 n v i , f x i ) 2 − ∑ i = 1 n v i , f 2 x i 2 )
\frac{1}{2} \sum_{f=1}^{k}\left(\left(\sum_{i=1}^{n} v_{i,f} x_{i}\right)^{2}-\sum_{i=1}^{n} v_{i,f}^{2} x_{i}^{2}\right)
2 1 f = 1 ∑ k ⎝ ⎛ ( i = 1 ∑ n v i , f x i ) 2 − i = 1 ∑ n v i , f 2 x i 2 ⎠ ⎞
上式是在[1,K]上的一個求和。 K就是Embedding後的維度,也就是embedding_size。也就是說,在DeepFM的FM模塊中,最後沒有對結果從[1,K]進行求和。而是把這K個數拼接起來形成了一個K維度的向量。
deep部分
deep部分是一個全連接神經網絡。由於CTR的輸入一般是極其稀疏的。因此需要重新設計網絡結構。具體實現中爲,在第一層隱含層之前,引入一個嵌入層(embedding)來完成將輸入向量壓縮到低維稠密向量。
在deepFM中,FM部分的隱向量與嵌入層的權重矩陣是共享的(隱向量作爲嵌入層的權重矩陣)。這種共享的策略又進一步通過反向傳播的方式影響了低階與高階的特徵組合。從而構建出更具有表徵能力的特徵。
嵌入層的表示如下:
a 0 = [ e 1 , e 2 , ⋯  , e m ]
a_{0}=\left[e_{1}, e_{2}, \cdots, e_{m}\right]
a 0 = [ e 1 , e 2 , ⋯ , e m ]
其中ei表示嵌入層的第i個field。a0爲輸入深度神經網絡的向量,前饋過程可以表示爲:
a l + 1 = σ ( W ( l ) a ( l ) + b ( l ) )
a_{l+1}=\sigma\left(W^{(l)} a^{(l)}+b^{(l)}\right)
a l + 1 = σ ( W ( l ) a ( l ) + b ( l ) )
嵌入層有兩個有趣的特性:
儘管不同field的輸入長度不同,但是embedding之後向量的長度均爲K;
在FM裏得到的隱變量Vik現在作爲嵌入層網絡的權重,Vik是嵌入層中第i個特徵連接到嵌入層第k個節點的權重。
對於第二點舉例說明:
假設我們的k=5,某個類別型特徵經過one_hot編碼後爲第5-15特徵,其隱向量按列排成矩陣如下:
[ V 5 , 1 , V 6 , 1 , V 7 , 1 , ⋯  , V 13 , 1 , V 14 , 1 , V 15 , 1 V 5 , 2 , V 6 , 2 , V 7 , 2 , ⋯  , V 13 , 2 , V 14 , 2 , V 15 , 2 V 5 , 3 , V 6 , 3 , V 7 , 3 , ⋯  , V 13 , 3 , V 14 , 3 , V 15 , 3 V 5 , 4 , V 6 , 4 , V 7 , 4 , ⋯  , V 13 , 4 , V 14 , 4 , V 15 , 4 V 5 , 5 , V 6 , 5 , V 7 , 5 , ⋯  , V 13 , 5 , V 14 , 5 , V 15 , 5 ]
\left[\begin{array}{c}{V_{5,1}, V_{6,1}, V_{7,1},\cdots, V_{13,1},V_{14,1}, V_{15,1} }\\\\ {V_{5,2}, V_{6,2}, V_{7,2},\cdots, V_{13,2},V_{14,2}, V_{15,2} }\\\\{V_{5,3}, V_{6,3}, V_{7,3},\cdots, V_{13,3},V_{14,3}, V_{15,3} } \\\\ {V_{5,4}, V_{6,4}, V_{7,4},\cdots, V_{13,4},V_{14,4}, V_{15,4} } \\\\
{V_{5,5}, V_{6,5}, V_{7,5},\cdots, V_{13,5},V_{14,5}, V_{15,5} }
\end{array}\right]
⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ V 5 , 1 , V 6 , 1 , V 7 , 1 , ⋯ , V 1 3 , 1 , V 1 4 , 1 , V 1 5 , 1 V 5 , 2 , V 6 , 2 , V 7 , 2 , ⋯ , V 1 3 , 2 , V 1 4 , 2 , V 1 5 , 2 V 5 , 3 , V 6 , 3 , V 7 , 3 , ⋯ , V 1 3 , 3 , V 1 4 , 3 , V 1 5 , 3 V 5 , 4 , V 6 , 4 , V 7 , 4 , ⋯ , V 1 3 , 4 , V 1 4 , 4 , V 1 5 , 4 V 5 , 5 , V 6 , 5 , V 7 , 5 , ⋯ , V 1 3 , 5 , V 1 4 , 5 , V 1 5 , 5 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤
同時,它也可看作嵌入層(embedding)的參數矩陣,按照神經網絡前向傳播的方式,embedding後的向量值應該表示爲:
[ V 5 , 1 , V 6 , 1 , V 7 , 1 , ⋯  , V 13 , 1 , V 14 , 1 , V 15 , 1 V 5 , 2 , V 6 , 2 , V 7 , 2 , ⋯  , V 13 , 2 , V 14 , 2 , V 15 , 2 V 5 , 3 , V 6 , 3 , V 7 , 3 , ⋯  , V 13 , 3 , V 14 , 3 , V 15 , 3 V 5 , 4 , V 6 , 4 , V 7 , 4 , ⋯  , V 13 , 4 , V 14 , 4 , V 15 , 4 V 5 , 5 , V 6 , 5 , V 7 , 5 , ⋯  , V 13 , 5 , V 14 , 5 , V 15 , 5 ] [ x 5 x 6 x 7 ⋯ x 13 x 14 x 15 ]
\left[\begin{array}{c}{V_{5,1}, V_{6,1}, V_{7,1},\cdots, V_{13,1},V_{14,1}, V_{15,1} }\\\\ {V_{5,2}, V_{6,2}, V_{7,2},\cdots, V_{13,2},V_{14,2}, V_{15,2} }\\\\{V_{5,3}, V_{6,3}, V_{7,3},\cdots, V_{13,3},V_{14,3}, V_{15,3} } \\\\ {V_{5,4}, V_{6,4}, V_{7,4},\cdots, V_{13,4},V_{14,4}, V_{15,4} } \\\\
{V_{5,5}, V_{6,5}, V_{7,5},\cdots, V_{13,5},V_{14,5}, V_{15,5} }
\end{array}\right]\left[\begin{array}{c}{x_{5}} \\\\ {x_{6}} \\\\ {x_{7}} \\\\ \cdots \\\\ {x_{13}} \\\\ {x_{14}} \\\\ {x_{15}} \end{array}\right]
⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ V 5 , 1 , V 6 , 1 , V 7 , 1 , ⋯ , V 1 3 , 1 , V 1 4 , 1 , V 1 5 , 1 V 5 , 2 , V 6 , 2 , V 7 , 2 , ⋯ , V 1 3 , 2 , V 1 4 , 2 , V 1 5 , 2 V 5 , 3 , V 6 , 3 , V 7 , 3 , ⋯ , V 1 3 , 3 , V 1 4 , 3 , V 1 5 , 3 V 5 , 4 , V 6 , 4 , V 7 , 4 , ⋯ , V 1 3 , 4 , V 1 4 , 4 , V 1 5 , 4 V 5 , 5 , V 6 , 5 , V 7 , 5 , ⋯ , V 1 3 , 5 , V 1 4 , 5 , V 1 5 , 5 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤ ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ x 5 x 6 x 7 ⋯ x 1 3 x 1 4 x 1 5 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤
上面矩陣相乘的結果就是一個5維向量,由於這10列特徵是一個類型型特徵one_hot編碼後而成,故右邊矩陣中只有一個值爲1,其他爲0。假設右邊矩陣中x7的值爲1,那麼矩陣相乘之後的結果爲:
[ V 7 , 1 V 7 , 2 V 7 , 3 V 7 , 4 V 7 , 5 ] ∗ x 7
\left[\begin{array}{c} {V_{7,1}} \\\\ {V_{7,2}} \\\\ {V_{7,3}} \\\\ {V_{7,4}} \\\\ {V_{7,5}} \end{array}\right] \ast x_{7}
⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ V 7 , 1 V 7 , 2 V 7 , 3 V 7 , 4 V 7 , 5 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤ ∗ x 7
實際上嵌入層(embedding)的參數矩陣與輸入向量相乘後得到是one-hot後有值的那一維特徵所對應的隱向量。
假如我們現在有兩個類別型特徵,我們看看FM中的二階組合特徵的隱向量權重矩陣如何得到。假如有兩個類別型特徵,其one_hot編碼後分別是第7個特徵和第20個特徵值爲1,則經過嵌入層(embedding)計算後得到的兩個矩陣,讓他們相乘後爲:
[ V 7 , 1 V 7 , 2 V 7 , 3 V 7 , 4 V 7 , 5 ] x 7 [ V 20 , 1 V 20 , 2 V 20 , 3 V 20 , 4 V 20 , 5 ] x 20 = < v 7 , v 20 > x 7 x 20
\left[\begin{array}{c} {V_{7,1}} \\\\ {V_{7,2}} \\\\ {V_{7,3}} \\\\ {V_{7,4}} \\\\ {V_{7,5}} \end{array}\right] x_{7} \left[\begin{array}{c} {V_{20,1}} \\\\ {V_{20,2}} \\\\ {V_{20,3}} \\\\ {V_{20,4}} \\\\ {V_{20,5}} \end{array}\right] x_{20}=<v_{7}, v_{20}>x_{7} x_{20}
⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ V 7 , 1 V 7 , 2 V 7 , 3 V 7 , 4 V 7 , 5 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤ x 7 ⎣ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎡ V 2 0 , 1 V 2 0 , 2 V 2 0 , 3 V 2 0 , 4 V 2 0 , 5 ⎦ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎤ x 2 0 = < v 7 , v 2 0 > x 7 x 2 0
這個乘積的結果就是FM中二階組合特徵的其中一項,而對於所有非0組合(embedding向量組合)求和之後,就是FM中所有的二階組合特徵的部分,FM中的一階特徵則直接在embedding之前對於特徵進行組合即可。
注意:
在deepFM中沒有用FM去預訓練隱向量V,並用V去初始化神經網絡。事實上,嵌入層(embedding)參數其實是全連接的權重,是通過神經網絡自己學習到的。我們是用的FM模塊中的隱向量是神經網絡學習到的嵌入層的權重(權重共享)。