初学推荐系统-04-FM (因子分解机:多特征的二阶特征交叉)

5 FM模型的引入

5.1.1 逻辑回归模型的及其缺点

FM模型其实就是一种思路,具体应用较少。

一般来说做推荐CTR预估时最简单的思路是将特征做线性组合(逻辑回归LR),传入sigmod中得到一个概率值,本质上是一个线性模型;也就是LR的缺点有:

  1. 这是一个线性模型
  2. 每个特征对最终输出的结果独立,需要手动进行特征交叉(xi*xj),比较麻烦。

5.1.2 改进,以及FM的引入

由于LR模型的上述缺陷(主要是手动做特征交叉比较麻烦),干脆就考虑所有的二阶交叉项,也就是将目标函数由原来的

\[y = w_0+\sum_{i=1}^nw_ix_i \]

改为

\[y = w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{i+1}^nw_{ij}x_ix_j \]

但这个式子有一个问题,只有当\(x_i\)\(x_j\)均不为0时这个二阶交叉项才会生效,后面这个特征交叉项本质是和多项式核SVM等价的.

FM模型使用了如下的优化函数,事实上做的唯一改动就是把\(w_{ij}\)替换成了\(\lt v_i,v_j\gt\),这实际上就有深度学习的意味在里面了,实质上就是给每个\(x_i\)计算一个embedding,然后将两个向量之间的embedding做内积得到之前所谓的\(w_{ij}\)好处就是这个模型泛化能力强 ,即使两个特征之前从未在训练集中同时出现,我们也不至于像之前一样训练不出\(w_{ij}\),事实上只需要\(x_i\)和其他的\(x_k\)同时出现过就可以计算出\(x_i\)的embedding:

\[y = w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n}\sum_{i+1}^n\lt v_i,v_j\gt x_ix_j \]

说明:

  1. \(\omega_{0}\)为全局偏置;
  2. \(\omega_{i}\)是模型第i个变量的权重;
  3. \(\omega_{ij} = < v_{i}, v_{j}>\) 特征i和j的交叉权重;
  4. \(v_{i}\) 是第i维特征的隐向量;
  5. $ <\cdot, \cdot>$ 代表向量点积;
  6. \(k(k<<n)\) 为隐向量的长度,包含 k 个描述特征的因子。
  7. embedding 有词嵌入的意思,它的其中一个作用是将稀疏向量变成了稠密的向量。

5.3. FM模型的应用

最直接的想法就是直接把FM得到的结果放进sigmoid中输出一个概率值,由此做CTR预估,事实上我们也可以做召回。

由于FM模型是利用两个特征的Embedding做内积得到二阶特征交叉的权重,那么我们可以将训练好的FM特征取出离线存好,之后用来做KNN(邻域算法)向量检索。

工业应用的具体操作步骤:

  • 离线训练好FM模型(学习目标可以是CTR)
  • 将训练好的FM模型Embedding取出
  • 将每个uid对应的Embedding做avg pooling(平均)形成该用户最终的Embedding,item也做同样的操作
  • 将所有的Embedding向量放入Faiss等
  • 线上uid发出请求,取出对应的user embedding,进行检索召回

5.4 调包实现

# -*- coding: utf-8 -*-
# 第一步安装,调包
from pyfm import pylibfm
from sklearn.feature_extraction import DictVectorizer
import numpy as np

if __name__ == '__main__':
    # 第二步:创建训练集并转换成one-hot编码的特征形式
    train = [
        {"user": "1", "item": "5", "age": 19},
        {"user": "2", "item": "43", "age": 33},
        {"user": "3", "item": "20", "age": 55},
        {"user": "4", "item": "10", "age": 20},
    ]
    # DictVectorizer() Transforms lists of feature-value mappings to vectors.
    dv = DictVectorizer()
    X = dv.fit_transform(train)
    print(X.toarray())

    # 第三步:创建标签, 这里简单创建了一个全1的标签:
    y = np.repeat(1.0, X.shape[0])

    # 第四步:训练并预测, 就和调用sklearn的包是一样的用法:
    fm = pylibfm.FM()
    fm.fit(X,y)
    ret= fm.predict(dv.transform({"user": "1", "item": "10", "age": 24}))
    print(ret)

打印结果:

[[19.  0.  0.  0.  1.  1.  0.  0.  0.]
 [33.  0.  0.  1.  0.  0.  1.  0.  0.]
 [55.  0.  1.  0.  0.  0.  0.  1.  0.]
 [20.  1.  0.  0.  0.  0.  0.  0.  1.]]
Creating validation dataset of 0.01 of training for adaptive regularization
-- Epoch 1
Training log loss: 0.36855
[0.99034247]
posted @ 2020-10-27 22:37  山枫叶纷飞  阅读(852)  评论(0)    收藏  举报