Neural Collaborative Filtering阅读笔记

2017-深度协同过滤
代码地址:pytorch版
https://github.com/hexiangnan/neural_collaborative_filtering
作者何向南
使用神经结构替换矩阵分解的内积

摘要

近几年来,深度学习在推荐系统领域应用不多,本文力争使用深度学习解决推荐系统领域的关键问题:隐式反馈的协同过滤
尽管最近也有一些工作将深度学习应用于推荐领域,但都主要集中在对辅助信息建模上,比如物品的文本描述、音乐的声学特征等等。
但对于协同过滤中的关键点,用户和物品的交互建模上仍然是矩阵分解MF,然后使用用户和物品的隐特征做内积。
本文提出了一种通用框架,NCF(Neural network- based Collaborative Filtering),基于神经网络的协同过滤,它把内积部分替换成了可以拟合任意函数的神经网络结构。
NCF是一个通用框架,可以表达并泛化到矩阵分解。为了提高NCF的非线性,本文提出使用MLP学习用户物品交互函数。最后在两个实际数据集上验证了NCF远优于sota方法。经验表明,使用深度神经网络能提供更好的推荐效果。

深度协同过滤

先说明如何使用强调隐式反馈二值性的概率模型学习NCF,再阐明NCF可以表达MF并泛化到MF。为了探索用于协同过滤的DNN结构,本文提出了一个NCF实例,使用MLP学习用户物品交互函数。
最后,本文提出一个在NCF框架下融合MF和MLP的新的深度矩阵分解模型,既有MF的线性优势,又利用MLP的非线性建模用户物品的隐特征。

通用框架

为了实现一个全神经网络的协同过滤,引入多层表示来建模用户物品交互,上一层的输出是下一层的输入。如下图所示,

  • 最底层的输入input layer由两个描述用户和物品的特征向量 v u U v^U_u vuU v i I v_i^I viI组成,它们可以被定制成各种各样的用户物品模型,比如上下文感知,基于内容,基于近邻等等
    鉴于本文集中于纯粹的协同过滤场景,只使用用户身份和物品独热编码的二值稀疏向量作为输入特征。使用通用特征表示作为输入的另一个好处是使我们的方法可以通过引入内容特征表示用户和物品来轻易解决冷启动问题。
  • 输入层之上是embedding layer,这是一个全连接层,将稀疏表示映射为稠密向量。得到的用户/物品embedding可以看做是隐因子模型中的隐向量。用户和物品的embedding随后喂给一个多层神经网络结构,本文称之为深度协同过滤层,将隐向量映射到预测分数。
  • Neural CF layers的每一层都可以定制化为挖掘用户物品交互的某种隐式结构。最后一层隐层X的维度决定了模型的表达能力。
  • 最后是输出层output layer,预测分值 y ^ u i \hat y_{ui} y^ui,训练也是通过最小化 y ^ u i \hat y_{ui} y^ui和目标值 y u i y_{ui} yui之间的pointwise loss进行的。
    我们注意到训练本文模型的另外一种方式是pairwise学习,比如使用贝叶斯个性化排序BPR和margin-based loss。由于本文的重点是神经网络建模部分,我们把pairwise learning的扩展部分作为未来工作。
    现在NCF的预测模型可以表达为: y ^ u i = f ( P T V u U , Q T V i I ∣ P , Q , ⊝ f ) \hat y_{ui} = f(P^T V_u^U, Q^T V_i^I|P, Q, \circleddash_f) y^ui=f(PTVuU,QTViIP,Q,f),其中 P ∈ R M X K P\in R^{MXK} PRMXK Q ∈ R N X K Q\in R^{NXK} QRNXK,分别表示用户和物品的隐因子矩阵, ⊝ f \circleddash_f f表示交互函数f的模型参数。
    函数f是一个多层神经网络,可以描述为 f ( P T V u U , Q T V i I ) = ϕ o u t ( ϕ X ( . . . ϕ 2 ( ϕ 1 ( P T V u U , Q T V i I ) ) . . . ) ) f(P^TV_u^U, Q^TV_i^I) = \phi_{out}(\phi_X(...\phi_2(\phi_1(P^T V_u^U, Q^TV_i^I))...)) f(PTVuU,QTViI)=ϕout(ϕX(...ϕ2(ϕ1(PTVuU,QTViI))...)),其中, ϕ o u t \phi_{out} ϕout ϕ x \phi_x ϕx分别表示输出层和第x层深度协同过滤层,Neural CF共有X层。
学习NCF

现有的pointwise方法大部分都是使用平方损失回归学习模型参数: L s q r = ∑ ( u , i ) ∈ y ⋃ y − w u i ( y u i − y ^ u i ) 2 L_{sqr}=\sum_{(u, i)\in y\bigcup y^- }w_{ui}(y_ui - \hat y_{ui})^2 Lsqr=(u,i)yywui(yuiy^ui)2,其中y表示Y中观测到的行为, y − y^- y表示负样本,可以是所有没观测到的行为也是未观测行为的采样, w u i w_{ui} wui是一个超参数,表示训练实例(u,i)的权重。然后平方损失的前提是观测数据是服从高斯分布的,本文认为这一点可能并不符合隐式反馈数据,因为隐式反馈的目标值 y u i y_{ui} yui是二分值0或1,表示u是否和i有交互。接下来,我们会提出一种学习pointwise NCF的概率方法,重点关注隐式反馈的二值属性。
鉴于隐式反馈的一元本质,可以把 y u i y_{ui} yui的值看做是标签,1表示物品i和用户u相关,0则无关。预测分数 y ^ u i \hat y_{ui} y^ui表示物品i和用户u的相关度。为了让NCF有这样的概率解释,需要限制输出 y ^ u i \hat y_{ui} y^ui的范围在[0,1]内,这一点使用概率函数(如Logistic函数或Probit函数)作为输出层 ϕ o u t \phi_{out} ϕout的激活函数非常容易做到。
由此,得到似然函数: p ( y , y − ∣ P , Q , ⊝ f ) = ∏ ( u , i ) ∈ y y ^ u i ∏ ( u , j ) ∈ y − ( 1 − y ^ u j ) p(y, y^-|P, Q, \circleddash_f) = \prod_{(u,i)\in y}\hat y_{ui} \prod_{(u,j)\in y^-}(1-\hat y_{uj}) p(y,yP,Q,f)=(u,i)yy^ui(u,j)y(1y^uj)
取负的对数似然,得到: L = − ∑ ( u , i ) ∈ y l o g y ^ u i − ∑ ( u , j ) ∈ y − l o g ( 1 − y ^ u j ) L=-\sum_{(u,i)\in y}log \hat y_{ui} - \sum_{(u,j)\in y^-}log(1-\hat y_{uj}) L=(u,i)ylogy^ui(u,j)ylog(1y^uj)
= − ∑ ( u , i ) ∈ y ⋃ y − y u i l o g y ^ u i + ( 1 − y u i ) l o g ( 1 − y ^ u i ) = -\sum_{(u,i) \in y\bigcup y^-} y_{ui}log\hat y_{ui} + (1-y_{ui}) log(1-\hat y_{ui}) =(u,i)yyyuilogy^ui+(1yui)log(1y^ui)
这也是最小化NCF的目标函数,可以通过SGD优化。这个目标函数和二值交叉熵损失是一样的,也就是log loss。
为了给NCF找到概率解法,本文把隐式反馈推荐问题定义为二分类问题。由于用于分类的log loss几乎从未被用于推荐场景,本文探索了这种方法并证明了其有效性。
对于负样本 y − y^- y,统一在每个迭代中从未观测行为中采样得到,采样率和观测行为数目有关。但非统一采样策略(例如物品流行度偏差)也许可以进一步提高效果,这也作为未来工作探索了。

泛化矩阵分解Generalized Matrix Factorization(GMF)

本节解释MF是如何作为NCF框架的特例的。MF是推荐领域最流行的模型,关于MF的研究非常多,NCF能复现它也就复现了一大波分解模型。
由于输入层是one-hot编码,embedding层得到的向量可以视为用户或物品的隐向量。用户隐向量 P u P_u Pu改写为 P T V u U P^TV_u^U PTVuU,物品隐向量q_i改写为 Q T v i I Q^Tv_i^I QTviI
定义第一层Neural CF层的映射函数为: ϕ 1 ( P u , q i ) = P u ⨀ q i \phi_1 (P_u, q_i) = P_u \bigodot q_i ϕ1(Pu,qi)=Puqi,其中 ⨀ \bigodot 表示向量的元素积,即点积。
再把向量映射到输出层: y ^ u i = a o u t ( h T ( p u ⨀ q i ) ) \hat y_{ui} = a_{out}(h^T(p_u \bigodot q_i)) y^ui=aout(hT(puqi)),其中, a o u t a_{out} aout和h分别表示激活函数和输出层的边权重。显然,如果 a o u t a_{out} aout设置成恒等函数,h设置成全1的向量,这就是一个MF模型了。
在NCF框架下,MF可以轻易泛化和扩展。例如,如果允许h从没有统一限制的数据中学习,就会得到一个能赋予隐向量维度不同权重的MF模型变种。而且如果使用非线性函数作为 a o u t a_{out} aout,就可以把MF泛化到非线性场景,比线性MF更有表达能力。本文实现了一个这样的NCF框架下泛化版本的MF模型,其中 a o u t a_{out} aout使用sigmoid函数 σ ( x ) = 1 / ( 1 + e − x ) \sigma (x)=1/(1+e^{-x}) σ(x)=1/(1+ex),使用log loss从数据中学习函数h,命名为GMF(Generalized Matrix Factorization)

多层感知机MLP(Multi-Layer Perceptron)

由于NCF使用两个通路建模用户和物品,最直觉的方法就是把这两路特征拼接起来。这种设计方式在多模型深度学习应用非常广泛。然而,简单地向量拼接并不能表示用户和物品的隐特征之间的交互,不足以对协同效果建模。为了解决这个问题,本文提出在拼接向量的基础上增加隐层,使用标准MLP学习用户和物品隐特征之间的交互。这样一来,模型就极具灵活性以及 P u P_u Pu q i q_i qi之间的非线性,不像GMF那样只使用固定的元素积。
更精确地说,NCF框架下的MLP模型被定义为: z 1 = ϕ 1 ( p u , q i ) = [ p u q i ] z_1=\phi_1(p_u, q_i)= \left[ \begin{matrix} p_u \\ q_i \end{matrix} \right] z1=ϕ1(pu,qi)=[puqi]
ϕ 2 ( z 1 ) = a 2 ( W 2 T z 1 + b 2 ) \phi_2 (z_1) = a_2(W_2^T z_1 + b_2) ϕ2(z1)=a2(W2Tz1+b2)
. . . . . ..... .....
ϕ L ( z L − 1 ) = a L ( W L T z L − 1 + b L ) \phi_L (z_{L-1}) = a_L (W_L^Tz_{L-1}+b_L) ϕL(zL1)=aL(WLTzL1+bL)
y ^ u i = σ ( h T ϕ L ( z L − 1 ) ) \hat y_{ui} = \sigma (h^T \phi_L (z_{L-1})) y^ui=σ(hTϕL(zL1))
其中, W x W_x Wx b x b_x bx a x a_x ax分别表示第x层的权重矩阵,偏置矩阵,激活函数。MLP的激活函数可以随意挑选,sigmoid,tanh,ReLU或者其他都行。
关于激活函数:

  • 1.sigmoid函数会限制每个神经元的值在(0,1)范围,这一点可能会限制模型性能,而且会出现梯度饱和,即当神经元输出接近0或1的时候神经元会停止学习
  • 2.tanh通常是更好的选择,但也只是某种程度上的缓解sigmoid的问题,因为tanh可以看做是sigmoid的rescaled版本, ( t a n h ( x / 2 ) = 2 σ ( x ) − 1 ) (tanh(x/2)=2\sigma(x)-1) (tanh(x/2)=2σ(x)1)
  • 3.本文选择了ReLU,ReLU更具有生物学上的可能性(???),不会梯度饱和,而且它更支持稀疏激活函数,更适合稀疏数据且不易过拟合。据本文的经验判断ReLU比tanh的性能稍好,比sigmoid有明显优势
    网络结构的设计上遵循了单塔模式,底层最宽,逐层减少神经元个数。上层隐藏单元数较小有利于学习数据中更抽象的特征。本文按照经验采用的是逐层减半的方式。整体网络结构如上图2所示

GMF和MLP混合

本文已经提出了NCF的两种实例:

  • GMF使用线性核建模交互的隐特征
  • MLP使用非线性核学习交互函数
    如何才能在NCF框架下融合二者使其互相加强呢?直观的方法是让GMF和MLP共享同一个embedding层,然后联合交互函数的输出。这种方式和Neural Tensor Network(NTN)的方式很像。
    联合GMF和一层MLP的模型可以看做是: y ^ u i = σ ( h T a ( p u ⨀ q i + W [ p u q i ] + b ) ) \hat y_{ui}=\sigma(h^T a(p_u \bigodot q_i + W \left[ \begin{matrix} p_u \\ q_i \end{matrix} \right] +b )) y^ui=σ(hTa(puqi+W[puqi]+b))
    但,GMF和MLP共享embedding可能会限制混合模型的性能,例如,这样以来,GMF和MLP必须使用相同维度的embeddings,对于不同的数据集这两种模型对应的最优向量维度各不相同,这种方案可能无法获得最优组合。
    为了让混合模型更具灵活性,我们允许GMF和MLP分别学习embedding,仅在最后的隐层中联合两个模型。模型结构如下图所示:

公式表示如下:
ϕ G M F = p u G ⨀ q i G \phi^{GMF}=p_u^G \bigodot q_i^G ϕGMF=puGqiG
ϕ M L P = a L ( W L T ( a L − 1 ( . . . a 2 ( W 2 T [ p u M q i M ] + b 2 ) . . . ) ) + b L ) \phi^{MLP} = a_L(W_L^T(a_{L-1}(...a_2(W_2^T \left[ \begin{matrix} p_u^M \\ q_i^M \end{matrix} \right] +b_2) ...)) + b_L) ϕMLP=aL(WLT(aL1(...a2(W2T[puMqiM]+b2)...))+bL)
y ^ u i = σ ( h T [ ϕ G M F ϕ M L P ] ) \hat y_{ui} = \sigma(h^T \left[ \begin{matrix} \phi^{GMF} \\ \phi_{MLP} \end{matrix} \right]) y^ui=σ(hT[ϕGMFϕMLP])
其中, p u G p_u^G puG p u M p_u^M puM表示GMF和MLP部分的用户embedding, q i G q_i^G qiG q i M q_i^M qiM则是物品embedding。如前文所述,使用ReLU作为MLP的激活函数。
这个模型联合了MF的线性核DNN的非线性共同建模用户物品隐结构,称之为NeuMF(Neural Matrix Factorization)。

预训练

由于NeuMF的目标函数是非凸的,基于梯度的优化方法只能找到局部最优解。本文建议使用GMF和MLP的预训练模型初始化NeuMF。
先随机初始化GMF和MLP并训练到收敛。再用这些模型参数作为NeuMF的对应部分的初始化。唯一需要调整的是输出层,这两个模型的拼接权重如下:
h ⟵ [ α h G M F ( 1 − α ) h M L P ] h \longleftarrow \left[ \begin{matrix} \alpha h^{GMF} \\ (1-\alpha)h^{MLP} \end{matrix} \right] h[αhGMF(1α)hMLP],其中 h G M F h^{GMF} hGMF h M L P h^{MLP} hMLP分别表示GMF和MLP的预训练的h向量, α \alpha α是决定两个模型比重的超参数。
使用Adam从头开始训练GMF和MLP模型,实验证明,在这两个模型上,Adam方法比SGD收敛更快,节省学习率调试。但把预训练模型喂入NeuMF之后,本文采用SGD优化而不是Adam,因为Adam需要保存用于参数更新的动量信息,预训练模型初始化后不必保存动量信息。

你可能感兴趣的:(推荐系统,NCF)