0.Reference
美團FFM: https://tech.meituan.com/2016/03/03/deep-understanding-of-ffm-principles-and-practices.html
CMUpdf: http://www.cs.cmu.edu/~wcohen/10-605/2015-guest-lecture/FM.pdf
CSDN: http://www.52caml.com/head_first_ml/ml-chapter9-factorization-family/
知乎: https://zhuanlan.zhihu.com/p/37963267
1.FM理解
核心思想: 二階特徵組合
FM = LR + Wij<xi,xj> 對於特徵xi,xj的組合
Wij只能被xi,xj非零項計算,而原始類別轉爲的ont-hot數據非常稀疏
如何有效計算Wij?
W矩陣 = VTV, W(nn大小)用V(nK計算)
轉化爲NK的權重矩陣
1.W矩陣的參數量減少爲nk個,原來是n(n-1)/2
2.推導化簡:
轉化線性求解問題
http://www.algo.uni-konstanz.de/members/rendle/pdf/Rendle2010FM.pdf
3.FM 和 二次多項式的SVM區別在哪裏?
超參數k(隱向量長度),反映FM模型的表達力
。
2.FFM理解
核心:每一位特徵和其他field關係都用一個隱向量表徵
FM: 屬於FFM的特殊情況,每一維特徵都相當於一個field
e.g. 特徵i,對於特徵j的組合關係爲:
特徵i對於類別j的隱向量Vi,fj (dot點乘) 特徵j對於類別i的隱向量Vj,fi
隱向量的參數矩陣可以理解爲:
f個field,n維原始特徵,隱向量的長度是k; 參數數量=fnk
note:
1.一個類別特徵可能意味着500維的one-hot特徵,非常稀疏
2.FFM輸入可以省去值爲0的特徵index(其對於模型的訓練不起作用)
3.將源特徵歸一化,主要使得數值特徵歸一化到(0,1)之間 (歸一化方法??)
3.1 FM圖片
3.2 FFM圖片
4.代碼實現
# demo0: https://www.jiqizhixin.com/articles/2018-07-16-17
# demo1: https://realxuan.github.io/2018/10/18/FM(Factorization%20Machine)%E6%A8%A1%E5%9E%8B/
# demo2: http://nowave.it/factorization-machines-with-tensorflow.html
class FM(Model):
def __init__(self,input_dim=None,output_dim=1,factor_orider=10,opt_algo='gd',learning_rate=le-2,l2_w=0,l2_v=0,random_seed=23):
super().__init__(self)
#定義計算圖
self.graph = tf.Graph()
with self.graph.as_default():
if random_seed is not None:
tf.set_random_seed(random_seed)
#定義參數節點
self.X = tf.sparse_placeholder(tf.float32, shape=[None, input_dim], name="X")
self.y = tf.placeholder(tf.float32, shape=[None, output_dim], name="y")
self.V = tf.get_variable("v", shape=[input_dim, factor_orider], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.3))
self.W = tf.get_variable("Weights", shape=[n, 1], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.3))
self.b = tf.get_variable("Biases", shape=[1, 1], dtype=tf.float32, initializer=tf.zeros_initializer())
#定義模型
#一階部分
xw = tf.sparse_tensor_dense_matmul(self.X, self.W)
xv = tf.square(tf.sparse_tensor_dense_matmul(self.X, self.V))
#二階部分 multiply是矩陣對應元素相乘,matmul是矩陣乘法
fm_hat = tf.reduce_sum(tf.square(tf.sparse_tensor_dense_matmul(self.X ,self.V)) - (tf.sparse_tensor_dense_matmul(tf.multiply(self.X,self.X), tf.multiply(self.V,self.V))), axis=1, keep_dims=True) / 2
#fm函數
logits = tf.reshape(b+xw+fm_hat,[-1])
#通過sigmoid函數計算預測值
self.y_ = tf.sigmoid(logits)
#Loss = 交叉熵Error + l2正則
self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=self.y)) +l2_w * tf.nn.l2_loss(xw) + l2_v * tf.nn.l2_loss(xv)
#模型的優化器
self.optimizer = get_optimizer(opt_algo, learning_rate, self.loss)
#初始化模型參數
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())