fm對於特徵的組合僅限於二階,缺少對特徵之間深層次關係的抽取。因此,nfm提出來就是在fm的基礎上引入神經網路,實現對特徵的深層次抽取。nfm的模型結構圖如下所示:
模型的結構如上圖所示,首先輸入就是離散化的特徵,然後再進行embedding操作,獲得每乙個特徵的向量表示。接著就到了bi-interaction pooling層,這裡其實就是fm部分。fm的公式如下圖所示:
去掉最外層的累加號,我們得到的是乙個長度為k的向量,也就是embedding部分的長度。然後再對這個向量送入幾層全連線層即可,最後輸出ctr預估值。這就是nfm的整體思路。
權重構建,就是初始化一下embedding部分的資料,以及全連線部分的權重。然後就可以實現計算圖了。
權重部分如下:
def _initweights(self):
weights = dict()
# embedding
weights['feature_embedding'] = tf.variable(tf.random_normal(shape=[self.featuresize, self.embeddingsize],
mean=0.0, stddev=0.001), name='feature_embedding')
weights['feature_bias'] = tf.variable(tf.random_normal(shape=[self.featuresize, 1], mean=0.0, stddev=0.001), name='feature_embedding')
weights['bias'] = tf.variable(tf.random_normal(shape=[1]), name='bias')
# deep
weights['layers_{}'.format(0)] = tf.variable(tf.random_normal(shape=[self.embeddingsize, self.deeplayers[0]],
mean=0, stddev=0.001), name='layers_{}'.format(0))
weights['bias_{}'.format(0)] = tf.variable(tf.random_normal(shape=[1, self.deeplayers[0]]), name='bias_{}'.format(0))
for i in range(1, len(self.deeplayers)):
weights['layers_{}'.format(i)] = tf.variable(tf.random_normal(shape=[self.deeplayers[i-1], self.deeplayers[i]],
mean=0.0, stddev=0.001), name='bias_{}'.format(i))
weights['bias_{}'.format(i)] = tf.variable(tf.random_normal(shape=[1, self.deeplayers[i]]), name='bias_{}'.format(i))
weights['layers_output'] = tf.variable(tf.random_normal(shape=[self.deeplayers[-1], 1], mean=0.0, stddev=0.001),
name='layers_output')
weights['bias_output'] = tf.variable(tf.random_normal(shape=[1]), name='bias_output')
return weights
計算圖部分:
def _initgraph(self):
self.weights = self._initweights()
self.featureindex = tf.placeholder(shape=[none, none], dtype=tf.int32)
self.featurevalue = tf.placeholder(shape=[none, none], dtype=tf.float32)
self.label = tf.placeholder(shape=[none, 1], dtype=tf.float32)
self.dropoutkeepdeep = tf.placeholder(tf.float32, shape=[none], name='dropout_deep_deep')
self.trainphase = tf.placeholder(tf.bool, name='train_phase')
# embedding
self.embedding = tf.nn.embedding_lookup(self.weights['feature_embedding'], self.featureindex)
featurevalue = tf.reshape(self.featurevalue, shape=[-1, self.fieldsize, 1])
self.embedding = tf.multiply(self.embedding, featurevalue) # none fieldsize embeddingsize
# 一次項
self.yfirstorder = tf.nn.embedding_lookup(self.weights['feature_bias'], self.featureindex)
self.yfirstorder = tf.reduce_sum(tf.multiply(self.yfirstorder, featurevalue), 2)
# square->sum
self.squaredsum = tf.reduce_sum(tf.square(self.embedding), 1)
# sum->square
self.sumedsquare = tf.square(tf.reduce_sum(self.embedding, 1))
self.ysecondorder = 0.5 * tf.subtract(self.sumedsquare, self.squaredsum)
# deep
self.ydeep = self.ysecondorder
for i in range(0, len(self.deeplayers)):
self.ydeep = tf.matmul(self.ydeep, self.weights['layers_{}'.format(i)]) + self.weights['bias_{}'.format(i)]
self.ydeep = self.deeplayeractivation(self.ydeep)
self.ydeep = tf.nn.dropout(self.ydeep, self.dropoutdeep[i + 1])
# bias
# self.y_bias = self.weights['bias'] * tf.ones_like(self.label)
# out
self.out = tf.add_n([tf.reduce_sum(self.yfirstorder, axis=1, keep_dims=true),
tf.reduce_sum(self.ydeep, axis=1, keep_dims=true)])
ok,nfm就簡單介紹這些。思路相比與前面幾篇比較簡單,實現相對容易一些。 《推薦系統》 NFM模型
在ctr預估中,為了解決稀疏特徵的問題,學者們提出了fm模型來建模特徵之間的互動關係。但是fm模型只能表達特徵之間兩兩組合之間的關係,無法建模兩個特徵之間深層次的關係或者說多個特徵之間的互動關係,因此學者們通過deep network來建模更高階的特徵之間的關係。因此 fm和深度網路dnn的結合也就...
深度學習推薦模型 NFM
知乎 推薦nfm fm對於特徵的組合僅限於二階,缺少對特徵之間深層次關係的抽取。因此,nfm提出來就是在fm的基礎上引入神經網路,實現對特徵的深層次抽取。與fm 因式分解機 相似,nfm使用實值特徵向量。給定乙個稀疏向量x rn作為輸入,其中特徵值為xi 0表示第i個特徵不存在,nfm預估的目標為 ...
推薦演算法之好友推薦
寫點自己的理解,大牛請直接略過。好友推薦裡有推薦一些你可能認識的人,其中二度人脈是其中一種。比如 何炅和謝娜 在微博上相互關注,那用二度人脈的方法就是找和謝娜相互關注的人 如 張杰,海濤,某人 這時候 張杰,海濤,某人 就是何炅的二度人脈,排除掉何炅已經相互關注的張杰,剩下 張杰和某人 於是何炅發現...