【推荐系统】NCF神经协同过滤

NCF框架

NCF框架是本文要实现的3个模型的主体结构。

首先是输入层,分别包含两个特征向量vuv_uvuviv_ivi,描述了用户u和物品i。输入仅由一个用户向量和一个物品向量构成,它们分别是以one-hot编码的二值化稀疏向量。

接着是Embedding层,这是一个全连接层,用于将输入层的系数向量表示成一个稠密向量。

接着用户和物品的embedding向量被送入多层神经网络架结构中,这一层叫做神经协同过滤层(Neural CF Layer),它用于将潜在特征向量映射成预测分数(Score)。

在这里插入图片描述

class NCF(object):
    def __init__(self, config, latent_dim_gmf=8, latent_dim_mlp=8):
        self._config = config
        self._num_users = config['num_users']
        self._num_items = config['num_items']
        self._latent_dim_gmf = latent_dim_gmf
        self._latent_dim_mlp = latent_dim_mlp
        self._embedding_user_mlp =  torch.nn.Embedding(num_embeddings=self._num_users,embedding_dim=self._latent_dim_mlp)
        self._embedding_item_mlp =  torch.nn.Embedding(num_embeddings=self._num_items,embedding_dim=self._latent_dim_mlp)
        # 建立GMP模型的user Embedding层和item Embedding层,输入的向量长度分别为用户的数量,item的数量,输出都是隐式空间的维度latent dim
        self._embedding_user_gmf = torch.nn.Embedding(num_embeddings=self._num_users, embedding_dim=self._latent_dim_gmf)
        self._embedding_item_gmf = torch.nn.Embedding(num_embeddings=self._num_items, embedding_dim=self._latent_dim_gmf)
        
        # 全连接层
        self._fc_layers = torch.nn.ModuleList()
        for idx, (in_size, out_size) in enumerate(zip(config['layers'][:-1], config['layers'][1:])):
            self._fc_layers.append(torch.nn.Linear(in_size, out_size))

        # 激活函数
        self._logistic = nn.Sigmoid()
        
        
    @property
    def fc_layers(self):
        return self._fc_layers

    @property
    def embedding_user_gmf(self):
        return self._embedding_user_gmf

    @property
    def embedding_item_gmf(self):
        return self._embedding_item_gmf

    @property
    def embedding_user_mlp(self):
        return self._embedding_user_mlp

    @property
    def embedding_item_mlp(self):
        return self._embedding_item_mlp

    def saveModel(self):
        torch.save(self.state_dict(), self._config['model_name'])

    @abstractmethod
    def load_preTrained_weights(self):
        pass

    

GMF模型(广义矩阵分解)

pup_upu为用户u的潜在向量,$q_i为物品i的潜在向量。
则,神经协同网络的第一层映射函数为:
ϕ1(pu,qi)=pu⊙qi\phi_1(p_u,q_i) = p_u \odot q_iϕ1(pu,qi)=puqi
然后将此向量映射到输出层:
y^u,i=aout(hT(pu⊙qi))\hat{y} _{u,i} =a_{out}(h^T( p_u \odot q_i))y^u,i=aout(hT(puqi))
如果把aouta_{out}aout看作恒等函数,hhh全为1的单位向量,就变成了MF模型。

在这里插入图片描述

class GMF(NCF,nn.Module):
    def __init__(self, config, latent_dim_gmf):
        nn.Module.__init__(self)
        NCF.__init__(self, config = config, latent_dim_gmf=latent_dim_gmf)
        # 创建线性模型,输入:潜在特征向量, 输出:len =1
        self._affine_output = nn.Linear(in_features=self.latent_dim_gmf, out_features=1)
        
    @property
    def affine_output(self):
        return self._affine_output
    
    def forward(self, user_indices, item_indices):
        user_embedding = self._embedding_user_gmf(user_indices)
        item_embedding = self._embedding_item_gmf(item_indices)
        # 将user_embedding和user_embedding进行逐元素相乘
        element_product = torch.mul(user_embedding, item_embedding)
        # 通过s神经元
        logits = self._affine_output(element_product)
        rating = self._logistic(logits)
        
    def load_preTrained_weights(self):
        pass

MLP模型

简单的结合是不足以说明用户和物品之间的潜在特征。为了解决这个问题,我们需要向量连接的基础上增加隐藏层,可以使用标准的MLP来学习用户和物品潜在特征之间的相互作用。

在经过Embedding层后,将得到的用户和物品的潜在向量做连接(concatenation),即:
z1=ϕ1(pu,qi)=[puqi]z_1 = \phi_1(p_u, q_i) = \begin{bmatrix} p_u \\ q_i \end{bmatrix}z1=ϕ1(pu,qi)=[puqi]
接着将模型通过一层层感知层,激活函数选择ReLU函数。
ϕ2(z1)=a2(W2Tz1+b2)\phi_2(z_1) = a_2(W_2^{T}z_1 + b_2)ϕ2(z1)=a2(W2Tz1+b2)
以此类推。
到最后:
y^ui=σ(hTϕL(zL−1))\hat{y}_{ui} = \sigma{(h_T\phi_L(z_{L-1}))}y^ui=σ(hTϕL(zL1))

在这里插入图片描述

class MLP(NCF, nn.Module):
    def __init__(self, config, latent_dim_mlp):
        nn.Module.__init__(self)
        NCF.__init__(self, config = config, latent_dim_mlp= latent_dim_mlp)
        self._affine_output = torch.nn.Linear(in_features=config['layers'][-1], out_features=1)
        
    @property
    def affine_output(self):
        return self._affine_output

    def forward(self, user_indices, item_indices):
        user_embedding = self._embedding_user_mlp(user_indices)
        item_embedding = self._embedding_item_mlp(item_indices)
        # 把潜在向量进行连接
        vector = torch.cat([user_embedding, item_embedding],dim=-1)
        
        for idx, _ in enumerate(range(len(self._fc_layers))):
            vector = self._fc_layers[idx](vector)
            vector = torch.nn.ReLU()(vector)
            
        logits = self._affine_output(vector)
        rating = self._logistic(logits)
        return rating
    
    def load_preTrained_weights(self):
        config = self._config
        gmf_model = GMF(config, config['latent_dim_gmf'])
        if config['use_cuda'] is True:
            gmf_model.cuda()
        # 加载GMF模型参数到指定的GPU上
        state_dict = torch.load(self._config['pretrain_gmf'])
                                #map_location=lambda storage, loc: storage.cuda(device=self._config['device_id']))
                                #map_location = {'cuda:0': 'cpu'})
        gmf_model.load_state_dict(state_dict, strict=False)

        self._embedding_item_mlp.weight.data = gmf_model.embedding_item_gmf.weight.data
        self._embedding_user_mlp.weight.data = gmf_model.embedding_user_gmf.weight.data
        
            
        
   
    

NeuMF模型

GMF应用了线性内核来模拟潜在的特征交互;MLP使用了非线性内核从数据中学习潜在特征,那么自然而然地想到,我们可以将这两个模型融合在NCF框架下。
为了使得融合模型具有更大的灵活性,我们允许GMF和MLP学习独立的Embedding,并结合两种模型的最后的输出。

对左边的GMF模型:
ϕGMF=puG⊙qiG\phi^{GMF} = p_u^G \odot q_i^GϕGMF=puGqiG
即 GMF模型的用户潜在向量和物品潜在向量做内积

对右边的MLP模型:
ϕMLP=aL(WLT(aL−1(...a2(W2T[puMqiM]+b2)...))+bL) \phi^{MLP} = a_L(W_L^T(a_{L-1}(...a_2(W_2^T\begin{bmatrix} p_u^M \\ q_i^M \end{bmatrix} + b_2)...)) + b_L)ϕMLP=aL(WLT(aL1(...a2(W2T[puMqiM]+b2)...))+bL)

综合MLP和GMF模型得到:
y^ui=σ(hT[ϕGMFϕMLP])\hat{y}_{ui} = \sigma(h^T \begin{bmatrix} \phi^{GMF} \\ \phi^{MLP} \end{bmatrix} )y^ui=σ(hT[ϕGMFϕMLP])

在这里插入图片描述

### NCF神经协同过滤算法概述 NCF(Neural Collaborative Filtering)是一种利用神经网络改进传统协同过滤技术的推荐算法。它通过引入深层结构来捕捉用户和物品之间的复杂交互关系,从而提升推荐系统的性能[^1]。 #### 数据表示与模型输入 在NCF中,用户的偏好和物品的属性被编码成向量形式。具体来说,每个用户 \( u \) 和每个物品 \( i \) 都会被映射到一个低维空间中的嵌入向量 \( p_u \) 和 \( q_i \),这些嵌入向量可以通过矩阵分解或其他初始化方法获得[^2]。 #### 模型架构 NCF的核心在于使用多层感知机(MLP, Multi-Layer Perceptron)来建模用户-物品间的隐式反馈数据。相比于传统的矩阵分解方法仅依赖于内积操作,NCF能够通过非线性变换捕获更复杂的模式。以下是其实现的关键部分: 1. **嵌入层** 用户和物品分别经过独立的嵌入层转换为其对应的低维稠密向量。这一过程类似于词嵌入的思想,旨在减少维度并保留语义信息。 2. **拼接与传递至MLP** 将上述两个嵌入向量简单地连接起来作为后续全连接层的输入。这种设计允许模型自由探索各种可能的关系组合而不局限于简单的点乘运算[^4]。 3. **预测评分** 经过多重隐藏层处理后的最终输出会送入激活函数(通常是Sigmoid),以估计目标变量——即给定条件下某特定用户对某个项目感兴趣的可能性大小。 另外值得注意的是,除了纯MLP路径外,还可以融合广义矩阵因子化(GMF)组件形成混合体系结构,进一步增强表达力。 ```python import tensorflow as tf from tensorflow.keras.layers import Input, Dense, Concatenate, Embedding, Flatten from tensorflow.keras.models import Model def create_ncf_model(num_users, num_items, latent_dim=8): user_input = Input(shape=(1,), name='user') item_input = Input(shape=(1,), name='item') # User embedding layer user_embedding_mlp = Embedding(input_dim=num_users, output_dim=latent_dim)(user_input) user_vec_mlp = Flatten()(user_embedding_mlp) # Item embedding layer item_embedding_mlp = Embedding(input_dim=num_items, output_dim=latent_dim)(item_input) item_vec_mlp = Flatten()(item_embedding_mlp) concat_vector = Concatenate()([user_vec_mlp, item_vec_mlp]) fc_layer_1 = Dense(64, activation='relu')(concat_vector) fc_layer_2 = Dense(32, activation='relu')(fc_layer_1) prediction = Dense(1, activation='sigmoid', name="prediction")(fc_layer_2) model = Model(inputs=[user_input, item_input], outputs=prediction) return model ``` 此代码片段展示了如何构建基本版的NCF框架,其中包含了必要的组成部分如Embedding Layer以及Fully Connected Layers等要素。 ### 总结 综上所述,NCF不仅继承了传统协同过滤的优点,还借助强大的神经网络提升了对于潜在因素的理解深度。这使得即使面对稀疏的数据集也能取得较好的效果^。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值