因子分解机(FM)系列总结

2019-05-03  本文已影响0人  小透明苞谷

背景

FM

特点:

做法:

实现:

w0 = tf.Variable(tf.zeros([1]))
w = tf.Variable(tf.zeros([p]))
v = tf.Variable(tf.random_normal([k, p], mean=0, stddev=0.01))


linear_terms = tf.add(w0, tf.reduce_sum(tf.multiply(w, x), 1, keep_dims=True)) # n * 1

pair_interactions = 0.5 * tf.reduce_sum(
    tf.subtract(
        tf.pow(tf.matmul(x, tf.transpose(v)), 2),
        tf.matmul(tf.pow(x, 2), tf.transpose(tf.pow(v, 2)))
    ), axis=1, keep_dims=True)

y_hat = tf.add(linear_terms, pair_interactions)

lambda_w = tf.constant(0.001, name='lambda_w')
lambda_v = tf.constant(0.001, name='lambda_v')

l2_norm = tf.reduce_sum(
    tf.add(
        tf.multiply(lambda_w, tf.pow(w, 2)),
        tf.multiply(lambda_v, tf.pow(v, 2))
    )
)

error = tf.reduce_mean(tf.square(y - y_hat))
loss = tf.add(error, l2_norm)


注意:线性项和二次项是直接相加的(标量)

FFM

背景:

做法:

不足:

DeepFM

背景:

优点/做法:

DeepFM

Embedding层作用:

FM部分

FM

线性项(Addition Unit反映的是 1 阶的特征):
w_0+\sum_{i=1}^n{w_ix_i}

交叉项(内积单元反映的是 2 阶的组合特征对于预测结果的影响):
\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}w_{ij}x_ix_j = \frac 1 2 \sum_{l=1}^k[(\sum_{i=1}^n v_{i,f}x_i)^2-\sum_{i=1}^n v_{i,f}^2x_i^2)]
注意:此处是向量,fm的输出维度是field_size(一阶) + embedding_size(二阶)

DNN部分

DNN

output部分

\hat y = sigmoid(tf.concat([y_{fm\_first\_order}, y_{fm\_second\_order}, y_{deep}], axis=1))

注意是concat,不是add

# model
self.embeddings = tf.nn.embedding_lookup(self.weights['feature_embeddings'], self.feat_index) # N * F * K
feat_value = tf.reshape(self.feat_value,shape=[-1,self.field_size,1])
self.embeddings = tf.multiply(self.embeddings,feat_value)
​
print(self.embeddings.shape)                #none, field_size, embedding_size
print(self.weights['feature_bias'].shape)  #feature_size, 1
​
# first order term          #none, field_size
self.y_first_order = tf.nn.embedding_lookup(self.weights['feature_bias'],self.feat_index)
self.y_first_order = tf.reduce_sum(tf.multiply(self.y_first_order,feat_value),2)
self.y_first_order = tf.nn.dropout(self.y_first_order,self.dropout_keep_fm[0]) 
​
# second order term                # None * K
# sum-square-part
self.summed_features_emb = tf.reduce_sum(self.embeddings,1) # None * k
self.summed_features_emb_square = tf.square(self.summed_features_emb) # None * K
# squre-sum-part
self.squared_features_emb = tf.square(self.embeddings)
self.squared_sum_features_emb = tf.reduce_sum(self.squared_features_emb, 1)  # None * K
# second order
self.y_second_order = 0.5 * tf.subtract(self.summed_features_emb_square,self.squared_sum_features_emb)
self.y_second_order = tf.nn.dropout(self.y_second_order,self.dropout_keep_fm[1])
​
# Deep component
self.y_deep = tf.reshape(self.embeddings,shape=[-1, self.field_size * self.embedding_size])
self.y_deep = tf.nn.dropout(self.y_deep,self.dropout_keep_deep[0])
​
for i in range(0,len(self.deep_layers)):
 self.y_deep = tf.add(tf.matmul(self.y_deep,self.weights["layer_%d" %i]), self.weights["bias_%d"%i])
 self.y_deep = self.deep_layers_activation(self.y_deep)
 self.y_deep = tf.nn.dropout(self.y_deep,self.dropout_keep_deep[i+1])
 print("y_deep:" + str(self.y_deep.shape))
​
#----DeepFM---------
 self.out = tf.add(tf.matmul(concat_input, self.weights['concat_projection']), self.weights['concat_bias'])

参考:

上一篇 下一篇

猜你喜欢

热点阅读