接下来会了解一些关于FM相关的知识,用来对我先前学习到的特征组合分析,同时也对比一下fm相关的方法和深度学习方法,包括一些代码实现。
FM
原理讲解
LR中每个特征都是独立的,如果需要考虑特征与特征直接的交互作用,可能需要人工对特征进行交叉组合,非线性SVM可以对特征进行kernel映射,但是在特征高度稀疏的情况下并不能很好地进行学习。
FM主要是为了解决数据稀疏的情况下,特征怎么组合的问题。
普通线性模型:
考虑特征与特征之间关系的多项式模型如下:
通常情况下考虑的是两阶的多项式模型,即特征两两组合的问题,如果观测样本中没有出现交互的特征分量,我们就不能对其参数进行估计。
FM的思路是为特征分量$x_i$引入辅助向量$v_i, (v_{i1},v_{i2},...,v_{ik})$,通过利用$v_iv_j^T$对$w_{ij}$来求解:
上图所示,可以将参数从原来的$\frac{n(n-1)}{2}$缩减为$nk$个,在稀疏的情况下,这样的表示方法打破了特征的独立性,能够更好的挖掘特征之间的相关性【这个我没有详细的梳理,详细见参考。。。】。
该公式右半部分可以由如下方式得到:
其中第一个等式的直观理解是:左边为矩阵的上三角,右边第一项为矩阵的值,第二项为对角线的值。
即:$上三角=\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
暂无评论