声明:本模型复现笔记记录自己学习过程,如果有错误请各位老师批评指正。

本周复现了Wide&Deep Model、Wide Model、Deep Model、DeepFm Model、NFM Model

dataset:cretio数据集(选取了train 20000, test 5000)

Wide&Deep Model结合了Wide Model(LR)的记忆性和Deep Model的泛化能力,对于部署应用来说会提高用户的获取率和满意度,但是Wide&Deep的Wide part,需要专业的人员来发掘某些特征之间的共现关系,这就需要大量专业人工参与。

DeepFm Model 对Wide&Deep Model做了改进,对于Wide部分换成了FM Model具有了自动的特征组合能力。

NFM Model:是对FM、FFM的模型改进,FM、FFM其实就是一个二阶的特征交叉,它们会受到组合爆炸问题,限制了FM、FFM的表达能力。NFM 就利用DNN去拟合FM的二阶交叉特征。如果NFM一阶部分是线性模型,也可以看成是Wide&Deep的改进,只不过在Deep部分加了特征交叉池化层。

Wide&Deep Model


Wide部分的输入是原始特征(dense feature 和 经过Embeddings 的sparse feature)和交叉积特征转换数据

交叉积特征转换数据计算为:

Deep部分的输入是dense feature 和 经过Embeddings 的sparse feature

class Linear(nn.Module):def __init__(self, input_dim):super(Linear, self).__init__()self.Linear = nn.Linear(in_features = input_dim, out_features = 1)def forward(self, x):return self.Linear(x)class Dnn(nn.Module):def __init__(self, hidden_units, dropout = 0.):super(Dnn, self).__init__()self.dnn_network = nn.ModuleList([nn.Linear(layer[0],layer[1]) for layer in list(zip(hidden_units[:-1] , hidden_units[1:]))])self.dropout = nn.Dropout(p = dropout)def forward(self, x):for linear in self.dnn_network:x = linear(x)x = self.dropout(x)x = F.relu(x)return xclass WideandDeep(nn.Module):def __init__(self, feature_columns, hidden_units, dnn_dropout = 0.):super(WideandDeep, self).__init__()self.dense_feature_cols, self.sparse_feature_cols = feature_columns#embeddingself.embed_layers = nn.ModuleDict({'embed_' + str(i):nn.Embedding(num_embeddings = feat['feat_num'], embedding_dim = feat['embed_dim'])for i ,feat in enumerate(self.sparse_feature_cols)})hidden_units.insert(0, len(self.dense_feature_cols) + len(self.sparse_feature_cols) * self.sparse_feature_cols[0]['embed_dim'])self.dropout = nn.Dropout(p = dnn_dropout)self.dnn_network = Dnn(hidden_units,dnn_dropout)self.Linear = Linear(len(self.dense_feature_cols) + 1)self.final_linear = nn.Linear(hidden_units[-1]+ 1, 1)def forward(self, x):dense_inputs , sparse_inputs = x[:,:len(self.dense_feature_cols)], x[:,len(self.dense_feature_cols):]sparse_inputs = sparse_inputs.long()sparse_embeds = [self.embed_layers['embed_'+str(i)](sparse_inputs[:,i]) for i in range(sparse_inputs.shape[1])]sparse_embeds = torch.cat(sparse_embeds, axis = -1)dnn_input = torch.cat([sparse_embeds, dense_inputs], axis=-1)#n = 190000#a = [print(sparse_inputs[:,i].max()) for i in range(sparse_inputs.shape[1])]sparse_one_hot = [F.one_hot(sparse_inputs[:,i],sparse_inputs[:,i].max()+1)  for i in range(sparse_inputs.shape[1]) ]sparse_one_hot = torch.cat(sparse_one_hot,axis=-1)sparse_one_hot = torch.tensor(sparse_one_hot)#print(sparse_one_hot.shape)sparse_one_hot = sparse_one_hot.reshape(dense_inputs.shape[0],-1)c = torch.zeros(dense_inputs.shape[0] ,sparse_one_hot.shape[1] )for i in range(0,dense_inputs.shape[0]):c[i][1456]=1c[i][16123]=1cross = torch.prod(torch.pow(sparse_one_hot,c),axis = 1)cross = cross.reshape(-1,1)dense_input = torch.cat([dense_inputs,cross],axis=-1)#widewide_out = self.Linear(dense_input) # (,14)#print(wide_out.shape)#deepdeep_out = self.dnn_network(dnn_input)#(,64)#print(deep_out.shape)output = torch.cat([wide_out, deep_out] ,axis = -1 )outputs = F.sigmoid(self.final_linear(output))return outputs

重点难点:Wide部分的交叉积特征转换数据不容易复现,我通过观察数据,找到了一个组合特征。
这是实现交叉积特征转换数据的主要代码:
流程:所有sparse feature转成one_hot编码 ,设置C矩阵(函数中做指数),利用torch.pow和torch.prod完成函数运算,最后拼接到wide的输入。

       sparse_one_hot = [F.one_hot(sparse_inputs[:,i],sparse_inputs[:,i].max()+1)  for i in range(sparse_inputs.shape[1]) ]sparse_one_hot = torch.cat(sparse_one_hot,axis=-1)sparse_one_hot = torch.tensor(sparse_one_hot)#print(sparse_one_hot.shape)sparse_one_hot = sparse_one_hot.reshape(dense_inputs.shape[0],-1)c = torch.zeros(dense_inputs.shape[0] ,sparse_one_hot.shape[1] )for i in range(0,dense_inputs.shape[0]):c[i][1456]=1c[i][16123]=1cross = torch.prod(torch.pow(sparse_one_hot,c),axis = 1)cross = cross.reshape(-1,1)dense_input = torch.cat([dense_inputs,cross],axis=-1)#widewide_out = self.Linear(dense_input) # (,14)

效果:batch_size= 256,数据小容易过拟合,加入了L2正则化(0.005),dropout(0.3)

Wide Mode

仅仅是LR,输入数据是dense feature 和 经过embedding层的sparse feature

class Linear(nn.Module):def __init__(self, feature_columns, dnn_dropout = 0.):super(Linear, self).__init__()self.dense_feature_cols,self.sparse_feature_cols = feature_columns#embeddingself.embed_layers = nn.ModuleDict({'embed_'+str(i):nn.Embedding(num_embeddings = feat['feat_num'], embedding_dim = feat["embed_dim"])for i, feat in enumerate(self.sparse_feature_cols)})input_dim = len(self.dense_feature_cols) + len(self.sparse_feature_cols) * self.sparse_feature_cols[0]['embed_dim']self.Linear = nn.Linear(in_features = input_dim, out_features = 1)def forward(self, x):dense_inputs ,sparse_inputs = x[:,:len(self.dense_feature_cols)],x[:,len(self.dense_feature_cols):]sparse_inputs =  sparse_inputs.long()sparse_embeds = [self.embed_layers['embed_'+str(i)](sparse_inputs[:,i]) for i in range(sparse_inputs.shape[1])]sparse_embeds = torch.cat(sparse_embeds, axis = -1)wide_inputs = torch.cat([dense_inputs,sparse_embeds] , axis = -1)outputs = self.Linear(wide_inputs)return F.sigmoid(outputs)

效果: batch_size= 256,L2正则化(0.005),dropout(0.3)

Deep Model:

class Dnn(nn.Module):def __init__(self, feature_columns, hidden_units, dnn_dropout = 0.):super(Dnn, self).__init__()self.dense_feature_cols,self.sparse_feature_cols = feature_columns#embeddingself.embed_layers = nn.ModuleDict({'embed_'+str(i):nn.Embedding(num_embeddings = feat['feat_num'], embedding_dim = feat["embed_dim"])for i, feat in enumerate(self.sparse_feature_cols)})hidden_units.insert(0,len(self.dense_feature_cols) + len(self.sparse_feature_cols) * self.sparse_feature_cols[0]['embed_dim'])self.dnn_network = nn.ModuleList([nn.Linear(layer[0],layer[1]) for layer in list(zip(hidden_units[:-1], hidden_units[1:]))])self.dropout = nn.Dropout(p = dnn_dropout)self.final_linear = nn.Linear(hidden_units[-1], 1 )def forward(self, x):dense_inputs ,sparse_inputs = x[:,:len(self.dense_feature_cols)],x[:,len(self.dense_feature_cols):]sparse_inputs =  sparse_inputs.long()sparse_embeds = [self.embed_layers['embed_'+str(i)](sparse_inputs[:,i]) for i in range(sparse_inputs.shape[1])]sparse_embeds = torch.cat(sparse_embeds, axis = -1)dnn_inputs = torch.cat([dense_inputs,sparse_embeds] , axis = -1)for layer in self.dnn_network:dnn_inputs = layer(dnn_inputs)dnn_inputs = F.relu(dnn_inputs)output =  F.sigmoid(self.final_linear(dnn_inputs))return output

效果:batch_size= 256,L2正则化(0.005),dropout(0.3)

Wide&Deep Model VS Wide Model VS Deep Model

Wide&Deep Model 、 Wide Model 、 Deep Model 训练损失比较

Wide&Deep Model 、 Wide Model 、 Deep Model 训练AUC比较

Wide&Deep Model 、 Wide Model 、 Deep Model 测试集损失比较

Wide&Deep Model 、 Wide Model 、 Deep Model 测试集AUC比较

结论:Wide&Deep结合了记忆性和泛化性确实比朴素LR和朴素DNN效果好一点,论文中给出的三者的AUC几乎一样,文章中给出说明是利用cross-product feature去增加在线用户获取率,提高1%的效率对于大的互联网公司来说就可以获得巨大收益。

DeepFM


DeepFM对于Wide&Deep模型的改进是用FM替换了原来的Wide部分,加强了浅层网络部分特征组合的能力。同时,FM部分和DNN部分共享相同的EMbedding层。
左侧的FM部分对不同的特征域的EMbedding进行了两两交叉,即将Embedding向量当作原FM中的特征向量V。

class FM(nn.Module):def __init__(self, latent_dim, fea_num):super(FM, self).__init__()self.latent_dim = latent_dimself.w0 = nn.Parameter(torch.zeros([1,]))self.w1 = nn.Parameter(torch.rand([fea_num, 1]))self.w2 = nn.Parameter(torch.rand([fea_num, latent_dim]))def forward(self, inputs):   # 一阶first_order = self.w0 + torch.mm(inputs, self.w1)      # 二阶second_order = 1/2 * torch.sum(torch.pow(torch.mm(inputs, self.w2), 2) - torch.mm(torch.pow(inputs,2), torch.pow(self.w2, 2)),dim = 1,keepdim = True)        return first_order + second_order class Dnn(nn.Module):def __init__(self, hidden_units, dropout=0.):super(Dnn, self).__init__()self.dnn_network = nn.ModuleList([nn.Linear(layer[0], layer[1]) for layer in list(zip(hidden_units[:-1], hidden_units[1:]))])self.dropout = nn.Dropout(dropout)def forward(self, x):  for linear in self.dnn_network:x = linear(x)x = F.relu(x)    x = self.dropout(x) return xclass DeepFM(nn.Module):def __init__(self, feature_columns, hidden_units, dnn_dropout=0.):super(DeepFM, self).__init__()self.dense_feature_cols, self.sparse_feature_cols = feature_columns# embeddingself.embed_layers = nn.ModuleDict({'embed_' + str(i): nn.Embedding(num_embeddings=feat['feat_num'], embedding_dim=feat['embed_dim'])for i, feat in enumerate(self.sparse_feature_cols)})self.fea_num = len(self.dense_feature_cols) + len(self.sparse_feature_cols)*self.sparse_feature_cols[0]['embed_dim']hidden_units.insert(0, self.fea_num)self.fm = FM(self.sparse_feature_cols[0]['embed_dim'], self.fea_num)     self.dnn_network = Dnn(hidden_units, dnn_dropout)self.nn_final_linear = nn.Linear(hidden_units[-1], 1)def forward(self, x):dense_inputs, sparse_inputs = x[:, :len(self.dense_feature_cols)], x[:, len(self.dense_feature_cols):]sparse_inputs = sparse_inputs.long()       sparse_embeds = [self.embed_layers['embed_'+str(i)](sparse_inputs[:, i]) for i in range(sparse_inputs.shape[1])]sparse_embeds = torch.cat(sparse_embeds, dim=-1)x = torch.cat([sparse_embeds, dense_inputs], dim=-1)# Widewide_outputs = self.fm(x)# deepdeep_outputs = self.nn_final_linear(self.dnn_network(x))outputs = F.sigmoid(torch.add(wide_outputs, deep_outputs))return outputs

效果:batch_size= 256,L2正则化(0.006),dropout(0.4)

DeepFM VS Wide&Deep


结论: DeepFM具有自动进行特征组合的能力,效果还是比wide&deep效果要好。但是epoch=4前 wide&deep优于DeepFM的原因:我认为是FM的随机初始化导致的auc比wide&deep低。

NFM Model


NFM是对FM、FFM的模型改进,FM、FFM其实就是一个二阶的特征交叉,它们会受到组合爆炸问题,限制了FM、FFM的表达能力。

之前看到过一句话“深度学习网络理论上有拟合任何复杂函数的能力”,就是用DNN来拟合表达能力更强的函数。

NFM 就利用DNN去拟合FM的二阶交叉特征。

如果NFM一阶部分是线性模型,也可以看成是Wide&Deep的改进,只不过在Deep部分加了特征交叉池化层。
模型的其他层都与前面一样含义,新添加的是Bi-interaction Pooling layer。

Bi-interaction Pooling layer:

其中前一层中的Embeding层Vx = [ x1v1,x2v2,…,xnvn ]

在进行两两Embedding向量的元素积操作后,对交叉特征向量取和,得到池化层的输出向量。

然后再把该向量输入到下一层的DNN中,进行进一步的交叉特征。

注意: 设计模型时不要忘了一阶函数。

class Dnn(nn.Module):def __init__(self, hidden_units, dropout=0.):super(Dnn, self).__init__()self.dnn_network = nn.ModuleList([nn.Linear(layer[0], layer[1]) for layer in list(zip(hidden_units[:-1], hidden_units[1:]))])self.dropout = nn.Dropout(dropout)def forward(self, x):  for linear in self.dnn_network:x = linear(x)x = F.relu(x)    x = self.dropout(x) return xclass NFM(nn.Module):def __init__(self, feature_columns, hidden_units, dnn_dropout=0.):super(NFM, self).__init__()self.dense_feature_cols, self.sparse_feature_cols = feature_columns# embeddingself.embed_layers = nn.ModuleDict({'embed_' + str(i): nn.Embedding(num_embeddings=feat['feat_num'], embedding_dim=feat['embed_dim'])for i, feat in enumerate(self.sparse_feature_cols)})self.fea_num = len(self.dense_feature_cols) + self.sparse_feature_cols[0]['embed_dim']hidden_units.insert(0, self.fea_num)self.bn = nn.BatchNorm1d(self.fea_num)     self.dnn_network = Dnn(hidden_units, dnn_dropout)input_dim  = len(self.dense_feature_cols)  + len(self.sparse_feature_cols) * self.sparse_feature_cols[0]['embed_dim']self.Linear = nn.Linear(input_dim,32)self.nn_final_linear = nn.Linear(hidden_units[-1], 1)def forward(self, x):dense_inputs, sparse_inputs = x[:, :len(self.dense_feature_cols)], x[:, len(self.dense_feature_cols):]sparse_inputs = sparse_inputs.long()      sparse_embeds = [self.embed_layers['embed_'+str(i)](sparse_inputs[:, i]) for i in range(sparse_inputs.shape[1])]L_sparse_embeds = torch.cat( sparse_embeds,axis = -1)sparse_embeds = torch.stack(sparse_embeds)     sparse_embeds = sparse_embeds.permute((1, 0, 2))embed_cross = 1/2 * (torch.pow(torch.sum(sparse_embeds, dim=1),2) - torch.sum(torch.pow(sparse_embeds, 2), dim=1))  #widelr_input = torch.cat([dense_inputs,L_sparse_embeds],axis = -1)lr_output = self.Linear(lr_input)#print(lr_output.shape)# deepx = torch.cat([embed_cross, dense_inputs], dim=-1)x = self.bn(x)dnn_outputs = self.nn_final_linear(self.dnn_network(x)+ lr_output)#jointoutputs = F.sigmoid(dnn_outputs )return outputs

效果:batch_size= 256,L2正则化(0.003),dropout(0.25)

NFM VS DeepFM VS Wide&Deep


Wide&Deep、DeepFM模型是使用的拼接操作,而不是Bi-Interaction.
拼接操作最大的缺点是他并没有考虑任何特征组合信息,全部依靠后面的DNN去学习特征组合,但是DNN的学习优化非常困难。
使用Bi-Interaction就考虑到了二阶组合特征,使得输入到DNN层中数据包含更多的信息,减轻了DNN的学习困难。

WideDeep Model、Wide Model(LR)、Deep Model、DeepFm Model、NFM Model复现笔记相关推荐

  1. 推荐系统8---FNN、DeepFM与NFM(FM在深度学习中的身影重现)

    1,前言 Wide&Deep模型开启深度学习时代的组合模型之后,后面的模型都是在Wide&Deep的基础上进行各种方式的模型组合,以应对不同的模型任务.从大的角度看,模型的改进方向主要 ...

  2. deep deepfm wide 区别_FM算法和DeepFM算法

    FM 线性模型的二阶特征组合 $w_ij$是固定的. 对于n个特征的模型,相比组合之前参数量级增加量级是$n^2$: n个特征组合后是n(n-1)/2,比如有(n=)1000个特征增加近50万个参数. ...

  3. Wide Deep、DeepFM系列算法原理与优缺点对比

    一.Wide & Deep模型 Wide & Deep Learning 模型的核心思想是结合广义线性模型的记忆能力(memorization)和深度前馈神经网络模型的泛化能力(gen ...

  4. 【NLP】词袋模型(bag of words model)和词嵌入模型(word embedding model)

    本文作为入门级教程,介绍了词袋模型(bag of words model)和词向量模型(word embedding model)的基本概念. 目录 1 词袋模型和编码方法 1.1 文本向量化 1.2 ...

  5. 推荐系统(5)-深度推荐模型-AutoRec、DeepCrossing、NeuralCF、PNN、WideDeep、FNN、DeepFM、NFM

    GBDT+LR 1. AutoRec-2015 2. Deep Crossing-2016 3. NeuralCF-2016 4. PNN-2016 5. Wide&Deep-2016 6. ...

  6. Deep Learning(深度学习)学习笔记整理(二)

    本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流 [1]Deep learning简介 [2]Deep Learning训练过程 [3]Deep Learning模型之: ...

  7. Deep Learning(深度学习)学习笔记整理系列三

    Deep Learning(深度学习)学习笔记整理系列 声明: 1)该Deep Learning的学习系列是整理自网上很大牛和机器学习专家所无私奉献的资料的.具体引用的资料请看参考文献.具体的版本声明 ...

  8. 【转载】Deep Learning(深度学习)学习笔记整理系列

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0  2013-0 ...

  9. Deep Learning(深度学习)学习笔记整理系列之(三)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

最新文章

  1. 自定义国内maven镜像包设置settings.xml
  2. 通过Live Writer Blog客户端来写blog
  3. Http协议(4)—HTTP认证机制
  4. 【编译原理】如何根据EBNF编写代码?
  5. 杂项:TMT(数字媒体产业)
  6. hdu1861 游船出租【模拟】
  7. 嵌入式linux入门六步曲
  8. 中国各省份省会的坐标
  9. Unity Editor 查找资源依赖、反向查找资源依赖Dependencies
  10. 联想笔记本电脑换掉原装系统后无法进BIOS不完美解决办法
  11. 1062lcd在dxp哪个库_protel dxp 2004 元件库中的常用元件所在位置
  12. 报错:for..in loops iterate over the entire prototype chain, which is virtually never what you want.
  13. “互联网+”拯救了星巴克
  14. 用css实现文字抖动特效
  15. Python Qt6快速入门-嵌入PyQtGraph图表
  16. XSS第一节,XSS档案
  17. UV灯固化设备紫外能量值如何定期检测
  18. VUE学习(六) 高德地图常用功能总结
  19. 达梦数据库在linux下的安装步骤
  20. 微信支付与支付宝支付

热门文章

  1. Pandas处理表格基础
  2. PyQt模拟微信聊天页面开发
  3. 三菱模拟量fx3u4da_模拟量输出模块FX3U-4DA手册三菱FX3U-4DA安装使用手册 - 广州凌控...
  4. 体育直播android,500体育直播
  5. 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例25
  6. 新零售如何做到线上线下相结合?
  7. 谷歌浏览器,查找CSS选择器
  8. 雷达的工作原理示意图_雷达的工作原理是什么
  9. 人脸扫描建模_人脸识别中的特征建模方法与流程
  10. 块存储服务(Cinder)安装配置,这一篇就够了!