这里写自定义目录标题
Task 2 Wide & Deep
1.动机
在CTR预估任务中,利用手工构造的交叉组合特征能够达到一个不错的效果
但是有以下缺点:
特征工程费时费力
模型是强行记住这些组合的,无法进行泛化
为了增加模型的泛化能力,添加了DNN,使用了Embedding,可以提高模型的泛化能力,但是这种方式因为数据的长尾的分布,导致长尾的特征不能学习
Wide and DEEP 模型就是使用记忆和泛化进行讨论的。模型能偶从历史数据中学习得到高频共现的特征进行组合,
可以使用特征之间的传递性,去探索历史数据中的从未出现过的特征组合
模型的结构和原理
模型的本身的结构是比较简单的,
从我的理解来看:即使一边使用较浅层的模型一遍使用较深层的模型
如何理解Wide 部分有利于增强模型的“记忆能力?Deep部分有利于泛化的能力?
wide 是一个广义的线形模型
输入包括两个部分:
1.原始的部分特征
2.原始特征的交叉特征
#(使用pad 编写,不好打公式,莫怪)
这里的意思就是想当于一个AND门
wide 的训练的时候是使用的优化器带L1正则的FTRL算法,而L1 FTLR 是非常注重模型的稀疏性的, 参数的大部分都是0,这就打所的模型的权重和特征向量的维度,就会是的wide模型训练完之后留下来的特征都是非常重要的。记忆能力就可以理解为是 最直接相关的能力
DEEP部分是一个DNN 的模型, 输入的特征主要分为两个类别,一类是数值的特征,一类是类别的特征,需要进行Embedding.
DNN模型随着层数的增加,就可以提高模型的泛化能力。
Wide 与Deep
W&D 模型是两个部分输出的结果起来进行联合训练,将deep wide 部分的输出重新使用一个逻辑回归模型进行最终的预测,处暑吹概率值。
3.代码实现
Wide 记住的历史数据中最常见的部分
Deep就是 DNN ,通过稠密向量来学习新的特征
针对当前的数据集实现,我们在wide 部分加入了所有可能的一阶特征,包括onehot都加进去
将发现高频、常见模式的特征都放在wide侧,对于deep部分,这里是放入了数值的特征和类别的特征
# Wide&Deep 模型的wide部分及Deep部分的特征选择,应该根据实际的业务场景去确定哪些特征应该放在Wide部分,哪些特征应该放在Deep部分
def WideNDeep(linear_feature_columns, dnn_feature_columns):
# 构建输入层,即所有特征对应的Input()层,这里使用字典的形式返回,方便后续构建模型
dense_input_dict, sparse_input_dict = build_input_layers(linear_feature_columns + dnn_feature_columns)
# 将linear部分的特征中sparse特征筛选出来,后面用来做1维的embedding
linear_sparse_feature_columns = list(filter(lambda x: isinstance(x, SparseFeat), linear_feature_columns))
# 构建模型的输入层,模型的输入层不能是字典的形式,应该将字典的形式转换成列表的形式
# 注意:这里实际的输入与Input()层的对应,是通过模型输入时候的字典数据的key与对应name的Input层
input_layers = list(dense_input_dict.values()) + list(sparse_input_dict.values())
# Wide&Deep模型论文中Wide部分使用的特征比较简单,并且得到的特征非常的稀疏,所以使用了FTRL优化Wide部分(这里没有实现FTRL)
# 但是是根据他们业务进行选择的,我们这里将所有可能用到的特征都输入到Wide部分,具体的细节可以根据需求进行修改
linear_logits = get_linear_logits(dense_input_dict, sparse_input_dict, linear_sparse_feature_columns)
# 构建维度为k的embedding层,这里使用字典的形式返回,方便后面搭建模型
embedding_layers = build_embedding_layers(dnn_feature_columns, sparse_input_dict, is_linear=False)
dnn_sparse_feature_columns = list(filter(lambda x: isinstance(x, SparseFeat), dnn_feature_columns))
# 在Wide&Deep模型中,deep部分的输入是将dense特征和embedding特征拼在一起输入到dnn中
dnn_logits = get_dnn_logits(dense_input_dict, sparse_input_dict, dnn_sparse_feature_columns, embedding_layers)
# 将linear,dnn的logits相加作为最终的logits
output_logits = Add()([linear_logits, dnn_logits])
# 这里的激活函数使用sigmoid
output_layer = Activation("sigmoid")(output_logits)
model = Model(input_layers, output_layer)
return model
4.思考
思考题作答:
-
将高频的常见模式的特征都放在wide
deep侧放入数值和分类的的特征 -
因为这样可以减少参数,可以将最重要的特征提取出来
3.不考虑稀疏性是为了提升模型的泛化能力