陌路茶色/

FM相关原理介绍及代码学习

接下来会了解一些关于FM相关的知识,用来对我先前学习到的特征组合分析,同时也对比一下fm相关的方法和深度学习方法,包括一些代码实现。

FM

原理讲解

LR中每个特征都是独立的,如果需要考虑特征与特征直接的交互作用,可能需要人工对特征进行交叉组合,非线性SVM可以对特征进行kernel映射,但是在特征高度稀疏的情况下并不能很好地进行学习。
FM主要是为了解决数据稀疏的情况下,特征怎么组合的问题。
普通线性模型:
屏幕快照 2020-03-02 下午10.41.19.png
考虑特征与特征之间关系的多项式模型如下:
屏幕快照 2020-03-02 下午10.44.47.png
通常情况下考虑的是两阶的多项式模型,即特征两两组合的问题,如果观测样本中没有出现交互的特征分量,我们就不能对其参数进行估计。

FM的思路是为特征分量$x_i$引入辅助向量$v_i, (v_{i1},v_{i2},...,v_{ik})$,通过利用$v_iv_j^T$对$w_{ij}$来求解:
屏幕快照 2020-03-02 下午10.50.28.png
上图所示,可以将参数从原来的$\frac{n(n-1)}{2}$缩减为$nk$个,在稀疏的情况下,这样的表示方法打破了特征的独立性,能够更好的挖掘特征之间的相关性【这个我没有详细的梳理,详细见参考。。。】。
该公式右半部分可以由如下方式得到:
屏幕快照 2020-03-02 下午11.20.29.png
其中第一个等式的直观理解是:左边为矩阵的上三角,右边第一项为矩阵的值,第二项为对角线的值。
即:$上三角=\frac{1}{2}(矩阵-对角线)$

FFM

DeepFM

deepFM我目前处理的是离散的特征(因此下面讲解的也是离散特征),而非连续特征(连续特征应该可以直接映射)。比如有k个特征,会为每个特征对应的离散值编号(nlp中的构建词表),然后将得到的词表求解fm和mlp,具体见代码(我改写的,参考中torchfm有对应的源码,建议阅读以更深入的了解deepfm,参考中DeepFM全方位解析讲解的也挺好的)

class DeepFM(nn.Module):
    def __init__(self,pretrain_embed,vocab,config):
        super(DeepFM,self).__init__()
        self.config=config
        self.vocab=vocab
        self.embedding_first=nn.Embedding(len(vocab),1,padding_idx=len(vocab)-1)
        if pretrain_embed is not None:
            self.embedding_second=nn.Embedding.from_pretrained(pretrain_embed,padding_idx=len(vocab)-1,freeze=False)
        else:
            self.embedding_second=nn.Embedding(len(vocab),config.embed_size,padding_idx=len(vocab)-1)
        self.bias = torch.nn.Parameter(torch.zeros((1,)))
        
        layers = list()
        input_dim=config.seq_length*config.embed_size
        for embed_dim in config.mlp_dims:
            layers.append(torch.nn.Linear(input_dim, embed_dim))
            layers.append(torch.nn.BatchNorm1d(embed_dim))
            layers.append(torch.nn.ReLU())
            layers.append(torch.nn.Dropout(p=config.dropout))
            input_dim = embed_dim
        layers.append(torch.nn.Linear(input_dim, 1))
        self.mlp = torch.nn.Sequential(*layers)

    
    #x : [batch_size,seq_len]
    def forward(self,x):
        x,_=x
        embed_first=self.embedding_first(x) #[batch_size,seq_len,1]
        embed_second = self.embedding_second(x) # [batch_size,seq_len,embed_size]
        batch_size,seq_len,embed_size=embed_second.size()
        linear=torch.sum(embed_first,dim=1)+self.bias #[batch_size,1]
        ix=torch.sum(embed_second, dim=1) ** 2 - torch.sum(embed_second ** 2, dim=1) #[batch_size,embed_size]
        fm=0.5*torch.sum(ix, dim=1, keepdim=True) #[batch_size,1]
        mlp=self.mlp(embed_second.view(-1, seq_len*embed_size)) #[batch_size,1]
        out=linear+fm+mlp
        return torch.sigmoid(out.squeeze(1))

xDeepFM

照着论文读了一遍,大概理解了

参考

FM分解机及其变种
Factorzation Machines 学习笔记
torchfm
DeepFM全方位解析
xDeepFM: Combining Explicit and Implicit Feature Interactionsfor Recommender Systems

留下一条评论

暂无评论