DeepCTR 和 DeepMatch是知乎浅梦大神以及其他大佬开发的针对推荐系统排序召回算法训练推理的一套框架, 支持embedding matrix模块和类似tf estimator 的feature column,并继承大量排序,召回已有模型, 能够帮助学生和从业者很快搭建一套推荐算法架构。
可以通过pip install deepctr, pip install deepmatch安装包, 也可以去https://github.com/shenweichen/DeepCTR 下载源码放进自己项目里。
总体来说, Deepctr 有自己独特的feature_column结构体, 比如SparseFeat, VarLenSparseFeat, DenseFeat, 先构建这种feature_column,然后插入到模型中, 在输入的时候输入类似libsvm的格式(abc:1, def:2,ghi:3) , 其中libsvm 数据的key要和feature_column的key一致(数据变成libsvm 名字和feature_column名字对齐)。
# 用官方的代码举例
#1, 构建feature_column, 其中feat 是特征的英语名字
fixlen_feature_columns = [SparseFeat(feat, vocabulary_size=data[feat].nunique(),embedding_dim=4 )
for i,feat in enumerate(sparse_features)] + [DenseFeat(feat, 1,)
for feat in dense_features]
dnn_feature_columns = fixlen_feature_columns
linear_feature_columns = fixlen_feature_columns
# 2, 模型里面放feature_column
model = DeepFM(linear_feature_columns, dnn_feature_columns, task='binary')
3, 在调用model.fit时传入的是key 和feature_column特征名一样的类似libsvm数据, 数据变成libsvm 名字和feature_column名字对齐
train_model_input = {name:train[name] for name in feature_names}
test_model_input = {name:test[name] for name in feature_names}
history = model.fit(train_model_input, train[target].values, batch_size=256, epochs=10, verbose=2, validation_split=0.2, )
下面借鉴引用这篇博文(https://zhuanlan.zhihu.com/p/377916768)简单介绍数据输入和feature_column,DeepCTR中feature_column 用于构造特征列和处理输入,进行一定的数据处理, 关键是是模型中构建embedding matrix的基础。
feature_column大致可以分为三种:类别特征、数值特征和序列特征,因此feature_column.py中的类SparseFeat、DenseFeat、VarLenSparseFeat就是用来处理这三种特征的。只需要将原始特征转化为这三种特征列,之后就可以得到通用的特征输入,从而可调用models中的任意模型开始训练。
feature_column有几个重要的方法, build_input_features, input_from_feature_columns,get_linear_logit 对应意义如上图所示, 下面给一个例子
# create_embedding_matrix也是DeepCTR中原有方法,返回embedding matrix
embedding_matrix_dict = create_embedding_matrix(user_feature_columns + item_feature_columns, l2_reg_embedding,seed=seed,seq_mask_zero=True)
# 将所有特征列转为tensor
user_features = build_input_features(user_feature_columns)
user_inputs_list = list(user_features.values())
# 返回特征列对应在embedding_matrix_dict的特征值, 这个方法里有embedding_lookup
user_sparse_embedding_list, user_dense_value_list = input_from_feature_columns(user_features,
user_feature_columns,
l2_reg_embedding, seed=seed,
embedding_matrix_dict=embedding_matrix_dict)
user_dnn_input = combined_dnn_input(user_sparse_embedding_list, user_dense_value_list)
SparseFeat用于处理类别特征,如性别、国籍等类别特征,将类别特征转为固定维度的稠密特征。
SparseFeat(name, vocabulary_size, embedding_dim, use_hash, dtype, embeddings_initializer, embedding_name, group_name, trainable)
###########################################
vocabulary_size:不同特征值的个数或当use_hash=True时的哈希空间
embedding_dim:嵌入向量的维度
use_hash:是否使用哈希编码,默认False
dtype:默认int32
embeddings_initializer:嵌入矩阵初始化方式,默认随机初始化
embedding_name:默认None,其名字与name保持一致
group_name:特征列所属的组
traninable:嵌入矩阵是否可训练,默认True
将稠密特征转为向量的形式,并使用transform_fn 函数对其做归一化操作或者其它的线性或非线性变换。
DenseFeat(name, dimension, dtype, transform_fn)
###########################################
将稠密特征转为向量的形式,并使用transform_fn 函数对其做归一化操作或者其它的线性或非线性变换
Args:
name: 特征列名字
dimension: 嵌入特征维度,默认是1
dtype: 特征类型,default="float32",
transform_fn: 转换函数,可以是归一化函数,也可以是其它的线性变换函数,以张量作为输入,经函数处理后,返回张量
比如: lambda x: (x - 3.0) / 4.2)
"""
处理类似文本序列的可变长度类型特征。
VarLenSparseFeat ( sparsefeat, maxlen, combiner, length_name, weight_name, weight_norm)
###########################################
处理可变长度的SparseFeat,比如文本序列特征,对文本分词后,每个样本的文本序列包含的词数量是不统一的。
参数:
sparsefeat:属于SparseFeat的实例
maxlen:所有样本中该特征列的长度最大值
combiner:池化方法(mean,sum,max),默认是mean
length_name:特征长度名字,如果是None的话,表示特征中的0是用来填充的
weight_name:默认None,如果不为空,那么序列特征会与weight_name的权重特征进行相乘
weight_norm:是否对权重分数做归一化,默认True
"""
###################################
# 示例
varlen_feature_columns = [VarLenSparseFeat(SparseFeat('genres', vocabulary_size=len(key2index) + 1, embedding_dim=4), maxlen=max_len, combiner='mean',weight_name='genres_weight')]
(https://zhuanlan.zhihu.com/p/377916768))
SparseFeat和VarLenSparseFeat对象需要创建嵌入矩阵,嵌入矩阵的构造和查表等操作都是通过inputs.py模块实现的,该模块包含9个方法,每个方法的具体功能如下图所示:
embedding_lookup 在嵌入层方法input_from_feature_columns中调用
作用:从所有稀疏特征列中查询指定稀疏特征列(参数return_feat_list)的嵌入矩阵,以字典形式返回查询结果
参数:
sparse_embedding_dict:存储稀疏特征列的嵌入矩阵的字典
sparse_input_dict:存储稀疏特征列的名字和索引的字典
sparse_feature_columns:稀疏特征列列表,元素为SparseFeat
return_feat_list:需要查询的稀疏特征列,如果元组为空,默认返回所有特征列的嵌入矩阵
mask_feat_list:用于哈希查询
to_list:是否以列表形式返回查询结果,默认是False
DeepCTR & DeepMatch 训练框架兼容Keras 和 tf-estimator, 这边简单演示和keras的配合
# 建立模型
model = DSSM(user_feature_columns, item_feature_columns, user_dnn_hidden_units=opt.hidden_units,
item_dnn_hidden_units=opt.hidden_units,dnn_activation=dnn_activation, l2_reg_dnn=opt.l2_reg_dnn,
dnn_dropout=opt.dnn_dropout, neg_sampling=opt.neg_sampling)
# 设置优化器和loss
model.compile(optimizer=opt.optimizer, loss='binary_crossentropy')
# 解析获得数据, 我们这里使用libsvm格式
train_model_input, train_label = decoder.decode(train_data)
# 训练
history = model.fit(train_model_input, train_label, batch_size=opt.batchSize, epochs=1, initial_epoch=0, verbose=2, )
# 推理(DSSM获得物料塔向量)
pred_ans = model.predict(test_input, opt.batchSize)
上线时把tensorflow模型转化成pb文件,线上推理得分。
1,https://deepctr-doc.readthedocs.io/en/latest/Quick-Start.html
2,https://zhuanlan.zhihu.com/p/53231955
3,https://zhuanlan.zhihu.com/p/126282487
4,https://blog.csdn.net/qiyihan/article/details/113405530
5,http://www.manongjc.com/detail/11-ysjtzvifnfeejdi.html
6, https://blog.csdn.net/lijinze2/article/details/121689167?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6-121689167-blog-108864737.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6-121689167-blog-108864737.pc_relevant_default&utm_relevant_index=9
7,https://zhuanlan.zhihu.com/p/377900375
8,https://zhuanlan.zhihu.com/p/377916768