Factorization Machines
FM算法是一种能够降低特征工程复杂性的模型,它能够处理高维稀疏数据。特征被分为一阶以及二阶交互,一阶项是原始特征的线性组合,二阶项则是特征对之间的交互。FM算法通过将输入数据映射到一个稠密向量空间中来处理高维稀疏数据,然后在该向量空间上进行计算,从而解决了传统的LR以及SVM等模型在处理高维稀疏数据时遇到的困难。
1.1 FM模型的损失函数
假设我们有一个输入的样本$x$, 包含了$n$个特征,我们将其为$ x = {x_1, x_2,…,x_n}$,以及对应的标签$y \in {0,1}$,其中每个特征一阶权重被表示为$w_i$, 且每一个特征值有一个对应的稠密向量$v_i \in R^k$。FM算法的目标是学习这组权重参数$w={w_0, w_1,…,w_n, v_1,…,v_n}$来最小化预测误差。其损失函数定义如下:
\[\displaystyle \hat{y}( x ) := w_0 + \sum_i^n w_i x_i + \sum_{i=1}^n \sum_{j=i+1}^n \langle v_i \cdot v_j \rangle x_i x_j \qquad (1)\]原始的计算代价为$O(kn^2)$. 如果我们希望将计算的代价降低到$O(kn)$,可以利用类似$ab = \frac{1}{2}[(a + b)^2 - (a^2 + b^2)]$的思路来对上面的式子中的最后一项进行变换,得到下面的式子:
\[\displaystyle \hat{y}( x) := w_0 + \sum_i^n w_i x_i + \frac{1}{2} \sum_{f=1}^k \left [ (\sum_{i=1}^n v_{i,f} x_i)^2 - \sum_{i=1}^n v_{i,f}^2 x_i^2 \right ] \qquad (2)\]其中$k$是每一个特征的dim的值(在AlphaFM的实现中,使用的是8),$n$是整个算法所使用的特征的总数(这个值通常比较大,有可能达到几百万或者上亿)
1.2 FM模型的推理(召回场景)
上面的公式很好地诠释了损失函数,但如果我们要把FM模型用在推荐系统的召回阶段,我们如何才能做到快速召回大量的Items? 我们需要把召回
看做是一个用户向量
$V_{u_j}$跟物品向量
$V_{i_k}$的匹配问题:为一个用户找到大量的推荐物品,本质是为$V_{u_j}$找到最相似的一组$V_{i_k}$,其中$k \in {1,2,…,N_i}$,其中$N_i$是物品的总数。
我们将公式$(1)$中各计算项按照所属关系,可以拆分为用户
和物品
两大类别,这些项可以分为如下的三情况:
用户
特征及其内部的交叉特征物品
特征以及内部的交叉特征用户
和物品
之间的交叉特征
所以我们可以将这个匹配公式定义成如下的样子:
\[\begin{align*} 匹配度 &= \sum Item特征一阶权重项 + \sum Item特征内部交叉项 + \sum User特征一阶权重项 + \sum User特征内部交叉项 + \sum User特征 \times item特征 \\ \end{align*}\]由于User特征一阶权重以及User特征内部交叉对于对于所有要召回的item都是相等的, 因此直接去掉, 所以上面的公式可以写作:
\[\begin{align*} 匹配度 &= \sum Item特征一阶权重项 + \sum Item特征内部交叉 + \sum User特征 \times item特征 \\ &= \sum_{i=1}^{N_i}w_i x_i + \sum_{i=1}^{N_i}\sum_{j=i+1}^{N_i}\langle v_i \cdot v_j\rangle x_i x_j + \sum_{i=1}^{N_u} \sum_{j=1}^{N_i} \langle v_i \cdot v_j \rangle x_i x_j \\ &= \langle 1, \sum_{i=1}^{N_u} v_i x_i \rangle \cdot \langle \sum_{i=1}^{N_i} x_i w_i + \sum_{j=1}^{N_i} \sum_{k=j+1}^{N_i} \langle v_j \cdot v_k \rangle x_j x_k, \sum_{j=1}^{N_i} v_j x_j \rangle \\ &\overset{def}{=} E_{user} \cdot E_{item} \\ \end{align*}\]其中,$N_u, N_i$分别表示属于User特征和属于Item特征的数量。
注意到在上面的式子中,我们已经在最后将匹配度
写成了向量的内积形式。第一个向量$E_{\text{user}}$表示用户的向量;第二个向量$E_{\text{item}}$是表示item的向量。
其中, $E_{item}$可以在模型训练完成后,计算并存储到向量数据库;而$E_{\text{user}}$则在用户发起推荐请求的时候,根据用户信息以及当前上下文动态计算得到。
所谓召回,实际上是计算
\[\begin{align*} \underset{ \pi \in \Omega }{arg\:max}\sum_{j=1}^{Top_k} E^U_k \cdot E^I_{ \pi(j) } \end{align*}\]其中$\Omega$是Item所有可能排序的集合,$\pi$是其中一种排序;$\pi(j)$表示在这个排序下的第$j$个位置对应的Item的序号; $E^U_k$和$E^I_j$分别代表用户$k$以及物品$j$所对应的向量 (分别跟前面对应的$E_{user}$以及$E_{item}$类似); $Top_k$是需要召回的物品数量。