關于FM算法,已經有很多文章将原理講的很清楚了,這裡記錄一下個人的想法以及實踐中的處理方式,如有不對,還請指正。
1. FM算法原理
FM算法的輸出由2部分組成,分别為線性層和二階互動層,公式為:

而對于輸入資料x,從原論文給出的圖中,可以知道既然包含了數值特征,也包含了類别特征。對于類别特征處理方式為
One-Hot
編碼。
2. 實踐中的問題
2.1 線性層中的離散特征
前面提到了
FM
一部分輸出為線性層,但我們知道對于離散特征進行獨熱編碼後,是很稀疏的。如果就這樣直接與數值特征拼接後送入線性層,這會造成很多參數訓練不充分。
閱讀DeepCTR的代碼,其中對類别特征如何送入線性層有如下的處理方式:
- 對類别特征進行
編碼,不過送入線性層的離散特征編碼後次元為Embedding
;dim=1
- 将編碼後的類别特征,再與數值特征進行拼接,送入線性層;
至于數值特征,可以做一個歸一化操作,比如
MinMaxScaler(),StandardScaler()
;對于長尾資料,還可以取對數
log()
。
2.2 互動層中的數值特征
按照原文的意思,無論是數值特征還是類别特征都需要進行兩兩互動;但實踐中,一般隻對類别特征做特征互動處理。
其實,這裡的每個特征 x i x_i xi對應的隐向量 v i v_i vi,其實與
Embedding
意思是一樣的。
對于數值特征,不同的數值可能各不相同,并不适合做
Embedding
。如果要做,也應該先對數值特征進行分桶,轉換為離散特征,在做
Embedding
.
2.3 複雜度
論文中,将二階互動項進行了改寫,降低了複雜度。
起初,我并不認為這樣做在程式設計友善帶來了多大的友善。
因為,可以利用文法,每次取出兩個不一樣的特征,然後進行互動,最後将它們相加即可。其實,這樣做,計算複雜度到了 O ( k n 2 ) O(kn^2) O(kn2)。
化簡後,n的求和符号其複雜度都為 O ( n ) O(n) O(n),而關于k的求和本質是加法;是以最終複雜度降為 O ( k n ) O(kn) O(kn);