FM模型简介与推导

一、FM简介

在一般的回归线性模型中,模型可表示为 y = b + ∑ i n w i x i y=b+\sum_{i}^n{w_ix_i} y=b+inwixi然而这样的线性模型并未考虑到特征与特征之间交叉的影响,当加入特征交叉时,模型可表示为 y = b + ∑ i n w i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n w i j x i x j y=b+\sum_{i}^n{w_ix_i}+\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}w_{ij}x_ix_j y=b+inwixi+i=1n1j=i+1nwijxixj
从上面的式子可以很容易看出,组合部分的特征相关参数共有 n ( n − 1 ) / 2 n(n−1)/2 n(n1)/2个。但是某些情况下 x i x_i xi为categorical特征,需要通过one-hot编码处理,因而样本的特征就会变的稀疏。在大规模稀疏特征存在的场景下,比如CTR预估和推荐排序,这些场景的最大特点就是特征的大规模稀疏,此时满足 x i x_i xi x j x_j xj都不为0的情况非常少,这样将导致 w i j w_{ij} wij无法通过训练得出。
为了解决这一问题,FM对于每个特征,学习一个大小为 k k k的一维向量,于是特征 x i x_i xi与特征 x j x_j xj的特征组合权重值,通过特征对应的向量 v i v_i vi v j v_j vj的内积表示。因此FM模型可表示为 y = b + ∑ i n w i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n < v i , v j > x i x j y=b+\sum_{i}^n{w_ix_i}+\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}\leftx_ix_j y=b+inwixi+i=1n1j=i+1nvi,vjxixj
FM对特征的处理方式本质上是在对特征进行embedding化表征。那么为什么说FM的这种特征embedding模式,在大规模稀疏特征应用环境下比较好用?为什么说它的泛化能力强呢?根据上式,即使在训练数据里两个特征并未同时在训练实例里同时出现过,但是因为FM是学习了单个特征的embedding,并不依赖某个特定的特征组合是否出现过,所以只要特征 x i x_i xi和其它任意特征组合出现过,那么就可以学习自己对应的embedding向量。于是,尽管样本中并没有 x i x_i xi x j x_j xj这样的特征组合,但他们与其他特征有过组合并学习到了自身的embedding,就可以通过内积算出这个新特征组合的权重。因而FM模型泛化能力强。

二、梯度推导

FM模型简介与推导_第1张图片
经过这样的简化之后,再对FM中需要训练学习的参数计算梯度
对于 b b b ∂ y ∂ b = 1 \frac{\partial y}{\partial b}=1 by=1
对于 w i w_i wi ∂ y ∂ w i = x i \frac{\partial y}{\partial w_i}=x_i wiy=xi
对于 v i f v_{if} vif ∂ y ∂ v i f = x i ∑ i = 1 n v i f − v i f x i f 2 \frac{\partial y}{\partial v_{if}}=x_i\sum_{i=1}^nv_{if}-v_{if}x_{if}^2 vify=xii=1nvifvifxif2

三、FM与其他模型的联系

https://medium.com/@yaoyaowd/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAfm%E5%92%8C%E7%B1%BB%E4%BC%BC%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95-8e9cf836d146

四、FM代码

import tensorflow as tf
class fm(object):
    """
    """

    def _init_graph(self,feature_dim,vector_dim,learning_rate):
        self.input_x = tf.placeholder(tf.int32, [None, feature_dim], name="input_x")
        self.input_y = tf.placeholder(tf.float32, [None, 1], name="input_y")

        #input_x shape is [B, N], w shape is [N,1], v shape is [N, K]
        w0 = tf.Variable(tf.random_uniform([1]))
        w = tf.Variable(tf.truncated_normal([feature_dim, 1]))
        linear_part = tf.add(w0, tf.matmul(self.input_x, w))

        v = tf.Variable(tf.truncated_normal([feature_dim, vector_dim]))
        head = tf.pow(tf.matmul(self.input_x, v), 2)
        tail = tf.matmul(tf.pow(self.input_x, 2), tf.pow(v, 2))
        pair_part = 0.5*tf.reduce_sum(head - tail)

        final = tf.add(linear_part, pair_part)
        lambda_w = tf.constant(0.0001)
        lambda_v = tf.constant(0.0001)
        w_l2_loss = tf.reduce_sum(tf.multiply(lambda_w, tf.pow(w, 2)))
        v_l2_loss = tf.reduce_sum(tf.multiply(lambda_v, tf.pow(v, 2)))
        l2_loss = tf.add(w_l2_loss, v_l2_loss)
        error = 0.5*tf.reduce_mean(tf.pow(self.input_y - final, 2))
        self.loss = tf.add(error, l2_loss)
        self.optimal = tf.train.AdagradOptimizer(learning_rate=learning_rate)
        self.train_op = self.optimal.minimize(self.loss, global_step=self._global_step)

你可能感兴趣的:(机器学习,机器学习,FM)