【推荐算法】特征域感知因子分解机(Field-aware Factorization Machines,FFM)
2021/6/30 17:24:47
本文主要是介绍【推荐算法】特征域感知因子分解机(Field-aware Factorization Machines,FFM),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
特征域感知因子分解机(Field-aware Factorization Machines,FFM)主要解决了FM的以下几个痛点:
- 更准确的特征embedding表达。FM中,每个特征只由一个embedding向量表达,这样虽然能增强模型的泛化性能,但是也大大削弱了模型的记忆能力。FFM在POLY_v2与FM中找到一个平衡,每个特征不再仅由一个embedding向量表示,而是对每个特征域都有一个embedding向量,使embedding表达更加准确。
算法
FFM引入特征域感知(field-aware)这一概念,使每一个特征对每一种特征域的组合都有一个单独的隐向量。这意味着FFM中每个特征包含一组隐向量。
\[\text{FFM}(\mathbf{w, x})=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+\sum_{i=1}^{n} \sum_{j=i+1}^{n}\left\langle\mathbf{v}_{i, f_{j}}, \mathbf{v}_{j, f_{i}}\right\rangle x_{i} x_{j} \]FFM无法使用FM这样的化简方法(自己看一下FM的化简公式就知道了),所以训练和推理的时间复杂度为\(O(kn^2)\)。
特征域一般表示某一种特征,例如,“职业”可以为一个特征域,其one-hot表示可能为000100
,则表示这个特征域包含6个特征。特征域也可以有更加灵活的定义,比如表示“用户”特征或者“物品”特征,而“用户”特征是由“职业”、“年龄”等特征的embedding进行pooling得到的。具体实现非常灵活,可以因地制宜。
模型输入
FFM的一阶部分可以直接复用LR,只需要额外实现各个特征域的二阶交叉。我们可以表示出每个特征的embedding向量组后,对特征域依次交叉。
class FieldAwareFactorizationMachine(torch.nn.Module): def __init__(self, field_dims, embed_dim): super().__init__() self.num_fields = len(field_dims) # 特征域数量 self.embeddings = torch.nn.ModuleList( [torch.nn.Embedding(sum(field_dims), embed_dim) for _ in range(self.num_fields)] ) # 每个特征的embedding向量组 self.offsets = np.array((0, *np.cumsum(field_dims)[:-1]), dtype=np.long) for embedding in self.embeddings: torch.nn.init.xavier_uniform_(embedding.weight.data) def forward(self, x): """ :param x: Long tensor of size ``(batch_size, num_fields)`` """ x = x + x.new_tensor(self.offsets).unsqueeze(0) xs = [self.embeddings[i](x) for i in range(self.num_fields)] ix = list() for i in range(self.num_fields - 1): for j in range(i + 1, self.num_fields): ix.append(xs[j][:, i] * xs[i][:, j]) # 特征域交叉 ix = torch.stack(ix, dim=1) return ix
最后,构建完整的FFM前向传播链路:
class FieldAwareFactorizationMachineModel(torch.nn.Module): def __init__(self, field_dims, embed_dim=10): super().__init__() self.linear = FeaturesLinear(field_dims) self.ffm = FieldAwareFactorizationMachine(field_dims, embed_dim) def forward(self, x): """ :param x: Long tensor of size ``(batch_size, num_fields)`` """ ffm_term = torch.sum(torch.sum(self.ffm(x), dim=1), dim=1, keepdim=True) x = self.linear(x) + ffm_term return torch.sigmoid(x.squeeze(1))
模型效果
设置:
数据集:ml-100k
优化方法:Adam
学习率:0.003
效果:
收敛epoch:6
train logloss: 0.48356
val auc: 0.78662
test auc: 0.78931
这篇关于【推荐算法】特征域感知因子分解机(Field-aware Factorization Machines,FFM)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-25安卓NDK 是什么?-icode9专业技术文章分享
- 2024-12-25caddy 可以定义日志到 文件吗?-icode9专业技术文章分享
- 2024-12-25wordfence如何设置密码规则?-icode9专业技术文章分享
- 2024-12-25有哪些方法可以实现 DLL 文件路径的管理?-icode9专业技术文章分享
- 2024-12-25错误信息 "At least one element in the source array could not be cast down to the destination array-icode9专业技术文章分享
- 2024-12-25'flutter' 不是内部或外部命令,也不是可运行的程序 或批处理文件。错误信息提示什么意思?-icode9专业技术文章分享
- 2024-12-25flutter项目 as提示Cannot resolve symbol 'embedding'提示什么意思?-icode9专业技术文章分享
- 2024-12-24怎么切换 Git 项目的远程仓库地址?-icode9专业技术文章分享
- 2024-12-24怎么更改 Git 远程仓库的名称?-icode9专业技术文章分享
- 2024-12-24更改 Git 本地分支关联的远程分支是什么命令?-icode9专业技术文章分享