ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【推荐算法】特征域感知因子分解机(Field-aware Factorization Machines,FFM)

2021-06-30 15:04:12  阅读:246  来源: 互联网

标签:特征 self torch Factorization aware field FFM embedding


特征域感知因子分解机(Field-aware Factorization Machines,FFM)主要解决了FM的以下几个痛点:

  1. 更准确的特征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

标签:特征,self,torch,Factorization,aware,field,FFM,embedding
来源: https://www.cnblogs.com/tmpUser/p/14954452.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有