Task4 NFM

NFM
模型局限
传统的FM模型仅局限于线性表达和二阶交互,作者提出一种将FM融合进DNN的策略,组合了FM的建模低阶特征交互能力和DNN学习高阶特征交互和非线性的能力,形成了深度学习时代的神经FM模型(NFM)

y ^ N F M ( x ) = w 0 + ∑ i = 1 n w i x i + f ( x ) \hat{y}{N F M}(\mathbf{x})=w{0}+\sum_{i=1}^{n} w_{i} x_{i}+f(\mathbf{x}) y^NFM(x)=w0+i=1nwixi+f(x)
改进的思路就是用一个表达能力更强的函数来替代原FM中二阶隐向量内积的部分。神经网络可以充当。
在这里插入图片描述

  • 1 input和embedding层

把稀疏离散特征处理成稠密低维的,先one-hot,再通过embedding

  • 2 Bi-Interaction Pooling layer

在Embedding层和神经网络之间加入了特征交叉池化层是本网络的核心创新(PNN加的是product_layer)
f B I ( V x ) = ∑ i = 1 n ∑ j = i + 1 n x i v i ⊙ x j v j f_{B I}\left(\mathcal{V}{x}\right)=\sum{i=1}^{n} \sum_{j=i+1}^{n} x_{i} \mathbf{v}{i} \odot x{j} \mathbf{v}_{j} fBI(Vx)=i=1nj=i+1nxivixjvj

其中第 k k k维的操作: ( v i ⊙ v j ) k = v i k v j k \left(v_{i} \odot v_{j}\right){k}=\boldsymbol{v}{i k} \boldsymbol{v}_{j k} (vivj)k=vikvjk

一定要注意这个地方不是两个隐向量的内积,而是元素积,也就是这一个交叉完了之后k个维度不求和,最后会得到一个 k k k维向量

Bi-Interaction层不需要额外的模型学习参数,更重要的是它在一个线性的时间内完成计算,和FM一致的,即时间复杂度为 O ( k N x ) O\left(k N_{x}\right) O(kNx) N x N_x Nx为embedding向量的数量。

3 隐藏层
公式如下: z 1 = σ 1 ( W 1 f B I ( V x ) + b 1 )   z 2 = σ 2 ( W 2 z 1 + b 2 )   … …   z L = σ L ( W L z L − 1 + b L ) \begin{aligned} \mathbf{z}{1}=&\sigma{1}\left(\mathbf{W}{1} f{B I} \left(\mathcal{V}{x}\right)+\mathbf{b}{1}\right) \ \mathbf{z}{2}=& \sigma{2}\left(\mathbf{W}{2} \mathbf{z}{1}+\mathbf{b}{2}\right) \ \ldots \ldots \ \mathbf{z}{L}=& \sigma_{L}\left(\mathbf{W}{L} \mathbf{z}{L-1}+\mathbf{b}_{L}\right) \end{aligned} z1=σ1(W1fBI(Vx)+b1) z2=σ2(W2z1+b2)  zL=σL(WLzL1+bL)

sigma是激活函数,不是sigmoid

4 预测层
NFM模型的前向传播过程总结如下: y ^ N F M ( x ) = w 0 + ∑ i = 1 n w i x i   + h T σ L ( W L ( … σ 1 ( W 1 f B I ( V x ) + b 1 ) … ) + b L ) \begin{aligned} \hat{y}{N F M}(\mathbf{x}) &=w{0}+\sum_{i=1}^{n} w_{i} x_{i} \ &+\mathbf{h}^{T} \sigma_{L}\left(\mathbf{W}{L}\left(\ldots \sigma{1}\left(\mathbf{W}{1} f{B I}\left(\mathcal{V}{x}\right)+\mathbf{b}{1}\right) \ldots\right)+\mathbf{b}_{L}\right) \end{aligned} y^NFM(x)=w0+i=1nwixi +hTσL(WL(σ1(W1fBI(Vx)+b1))+bL)

实现了FM和DNN的无缝连接, 也会用到像Dropout和BatchNormalization这样的技术来缓解过拟合和在过大的改变数据分布。

1 linear part: 这部分是有关于线性计算,也就是FM的前半部分 w 1 x 1 + w 2 x 2... w n x n + b w1x1+w2x2...wnxn+b w1x1+w2x2...wnxn+b的计算。我们用了一个get_linear_logits函数实现,得到linear的输出
2 dnn part: 这部分是后面交叉特征的那部分计算,FM的最后那部分公式f(x)。 这一块主要是针对离散的特征,这个计算我们用了get_bi_interaction_pooling_output函数实现, 得到输出之后又过了DNN网络,最后得到dnn的输出

模型的最后输出结果,就是把这两个部分的输出结果加和(当然也可以加权),再过一个sigmoid得到

NFM中的特征交叉与FM中的特征交叉有何异同,分别从原理和代码实现上进行对比分析
FM的特征交叉是低维的特征交叉,代码就是过一个线性的全连接层
NFM由于有DNN所以有高维的交叉,先过一个池化层,再过一个DNN的网络

以下是基于PyTorch实现的NFM推荐算法代码,供参考: ``` import torch import torch.nn as nn import torch.nn.functional as F class NFM(nn.Module): def __init__(self, feature_dim, embedding_dim, hidden_dim, output_dim, dropout_prob): super().__init__() self.feature_dim = feature_dim self.embedding_dim = embedding_dim self.hidden_dim = hidden_dim self.output_dim = output_dim self.dropout_prob = dropout_prob self.embedding = nn.Embedding(feature_dim, embedding_dim) self.linear1 = nn.Linear(embedding_dim, hidden_dim) self.linear2 = nn.Linear(hidden_dim, output_dim) self.linear3 = nn.Linear(embedding_dim, output_dim) self.dropout = nn.Dropout(dropout_prob) def forward(self, x): # Embedding layer x_emb = self.embedding(x) # Bi-Interaction layer sum_square = torch.sum(x_emb, dim=1) ** 2 square_sum = torch.sum(x_emb ** 2, dim=1) bi_interaction = 0.5 * (sum_square - square_sum) # MLP layer mlp_output = F.relu(self.linear1(self.dropout(bi_interaction))) mlp_output = self.linear2(self.dropout(mlp_output)) # Output layer output = self.linear3(x_emb.mean(dim=1)) + mlp_output return output ``` 其中,`feature_dim`为特征维度,`embedding_dim`为嵌入维度,`hidden_dim`为隐层维度,`output_dim`为输出维度,`dropout_prob`为dropout概率。 在模型的前向传播过程中,首先通过`nn.Embedding`层将输入的离散特征转化为嵌入向量,然后通过Bi-Interaction Layer计算二阶交叉特征,再通过MLP Layer进行非线性变换,最后将MLP输出和原始嵌入向量的平均值相加得到最终输出。 使用时,可以像以下代码一样初始化并训练模型: ``` # 初始化模型 model = NFM(feature_dim, embedding_dim, hidden_dim, output_dim, dropout_prob) # 定义损失函数和优化器 criterion = nn.BCEWithLogitsLoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # 训练模型 for epoch in range(num_epochs): for inputs, targets in dataloader: optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() optimizer.step() ``` 其中,`feature_dim`、`embedding_dim`、`hidden_dim`、`output_dim`、`dropout_prob`、`learning_rate`、`num_epochs`等参数需要根据具体情况进行设置,`dataloader`是一个PyTorch的`DataLoader`对象,用于加载训练数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值