NFM模型

含义

NFM模型是将FM与DNN进行融合,通过引入特征交叉池化层将FM与DNN进行衔接,这样就组合了FM的建模低阶特征交互能力和DNN学习高阶特征交互和非线性的能力。
在上一节DEEPFM中,我们已经知道,FM只能将两个特征进行重组,而不能将高阶特征进行重组,并且FM是线性组合,将DNN引入,可以提升FM进行特征交互能力和学习非线性表达的能力。
NFM公式
在这里插入图片描述
与FM公式相比,红色部分被一个表达能力更强的函数替代,特征之间的交互不局限于两个特征,也不局限与线性组合了。
NFM在fm得到二阶的交叉特征之后,加入了一个网络,将二阶特征再进行合并,进而就可以提取高阶交叉特征,因此增强了FM的表达能力。
NFM得隐藏层是全连接层,预测层
在这里插入图片描述
池化层:
常见的池化层
它实际上是一种形式的降采样。有多种不同形式的非线性池化函数,而其中“最大池化(Max pooling)”是最为常见的。它是将输入的图像划分为若干个矩形区域,对每个子区域输出最大值。直觉上,这种机制能够有效地原因在于,在发现一个特征之后,它的精确位置远不及它和其他特征的相对位置的关系重要。池化层会不断地减小数据的空间大小,因此参数的数量和计算量也会下降,这在一定程度上也控制了过拟合。通常来说,CNN的卷积层之间都会周期性地插入池化层。
池化的作用:
池化操作后的结果相比其输入缩小了。池化层的引入是仿照人的视觉系统对视觉输入对象进行降维和抽象。在卷积神经网络过去的工作中,研究者普遍认为池化层有如下三个功效:

1.特征不变性:池化操作是模型更加关注是否存在某些特征而不是特征具体的位置。其中不变形性包括,平移不变性、旋转不变性和尺度不变性。
平移不变性是指输出结果对输入对小量平移基本保持不变,例如,输入为(1, 5, 3), 最大池化将会取5,如果将输入右移一位得到(0, 1, 5),输出的结果仍将为5。对伸缩的不变形,如果原先的神经元在最大池化操作后输出5,那么经过伸缩(尺度变换)后,最大池化操作在该神经元上很大概率的输出仍是5.
2.特征降维(下采样):池化相当于在空间范围内做了维度约减,从而使模型可以抽取更加广范围的特征。同时减小了下一层的输入大小,进而减少计算量和参数个数。
3.在一定程度上防止过拟合,更方便优化。
4.实现非线性(类似relu)。
5.扩大感受野。

思考题
NFM中的特征交叉与FM中的特征交叉有何异同,分别从原理和代码实现上进行对比分析
1、FM模型只将特征组合为双特征,也就是说不能学习更高阶的特征组合,但是NFM加入了DNN,因此就能学习2阶以上的特征。
2、FM的特征组合,是线性的,就是组合特征之间,是线性组合。而NFM使用一个函数取代了原来的线性部分,因此特征之间不局限于线性组合了。

问题
如何确定输入应该进入linear input还是dnn input??这种分割是按照什么标准的??还是完全人为判断???

好的,下面是基于 PyTorch 实现 NFM 算法的代码,同时使用 AUC 进行评估: 首先,我们需要导入必要的库: ```python import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import roc_auc_score ``` 接着,我们定义 NFM 模型的代码如下: ```python class NFM(nn.Module): def __init__(self, num_feats, embed_dim, hidden_dim): super(NFM, self).__init__() self.embedding_layer = nn.Embedding(num_feats, embed_dim) self.linear_layer = nn.Linear(embed_dim, hidden_dim) self.interaction_layer = nn.Sequential( nn.Linear(embed_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, 1), nn.Sigmoid() ) def forward(self, x): embeddings = self.embedding_layer(x) square_sum = torch.sum(embeddings, dim=1) ** 2 sum_square = torch.sum(embeddings ** 2, dim=1) linear = self.linear_layer(torch.mean(embeddings, dim=1)) interaction = torch.sum(self.interaction_layer(embeddings), dim=1) output = linear + interaction - square_sum + sum_square return output ``` 在这里,我们将 NFM 模型分为三个部分: 1. `embedding_layer`:嵌入层,将输入的特征进行嵌入,得到每个特征的向量表示。 2. `linear_layer`:线性层,对特征嵌入后得到的向量进行平均,得到一个一维向量,并通过一个全连接层进行线性变换。 3. `interaction_layer`:交互层,对每个特征嵌入后得到的向量进行交互计算,并通过一系列层进行非线性变换,最后得到一个交互权重。 在 `forward` 函数中,我们首先计算了平方和以及和的平方,然后分别对线性部分和交互部分进行计算,最后将线性部分、交互部分、平方和以及和的平方相加得到最终的输出。 接下来,我们定义训练函数和测试函数: ```python def train(model, train_loader, optimizer, criterion): model.train() for batch_idx, (X, y) in enumerate(train_loader): optimizer.zero_grad() output = model(X) loss = criterion(output, y) loss.backward() optimizer.step() def test(model, test_loader): model.eval() y_true = [] y_pred = [] with torch.no_grad(): for batch_idx, (X, y) in enumerate(test_loader): output = model(X) y_true.extend(y.tolist()) y_pred.extend(output.tolist()) auc = roc_auc_score(y_true, y_pred) print('AUC:', auc) ``` 在这里,我们定义了一个训练函数和一个测试函数。训练函数中,我们首先将模型设为训练模式,然后对于每一个 batch 进行一次前向传播、计算 loss、反向传播和更新参数的操作。测试函数中,我们将模型设为评估模式,然后对于测试集中的每一个样本进行一次前向传播,并记录真实标签和预测概率,最后计算 AUC。 最后,我们读取数据、初始化模型、定义损失函数和优化器,并开始训练和测试: ```python # 读取数据 train_data = torch.Tensor([[1, 2, 3, 0], [4, 5, 6, 1], [7, 8, 9, 0], [10, 11, 12, 1]]) test_data = torch.Tensor([[1, 2, 3, 1], [4, 5, 6, 0], [7, 8, 9, 1], [10, 11, 12, 0]]) train_loader = torch.utils.data.DataLoader(train_data, batch_size=2, shuffle=True) test_loader = torch.utils.data.DataLoader(test_data, batch_size=2, shuffle=True) # 初始化模型 model = NFM(num_feats=4, embed_dim=2, hidden_dim=4) # 定义损失函数和优化器 criterion = nn.BCEWithLogitsLoss() optimizer = optim.Adam(model.parameters(), lr=0.01) # 训练和测试 for epoch in range(10): train(model, train_loader, optimizer, criterion) test(model, test_loader) ``` 在这里,我们使用了一个简单的数据集作为示例,共有 4 个样本,每个样本都有 4 个特征,其中前三个特征是类别型特征,最后一个特征是二分类标签。在初始化模型时,我们将类别型特征嵌入到 2 维向量中,然后将线性层和交互层的隐藏维度都设置为 4。在优化器中,我们使用了 Adam 算法作为优化器,学习率为 0.01。在训练过程中,我们进行了 10 轮迭代,每轮迭代后都对模型进行一次测试,并输出 AUC。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值