RecSys19 | FiBiNET:结合特征重要性和双线性特征交互进行 CTR 预估

点击上方“AI派”,选择“设为星标
最新分享,第一时间送达! 640?wx_fmt=gif

640?wx_fmt=png

文章作者:沈伟臣 阿里巴巴算法工程师

编辑整理:Hoh Xil

出品社区:DataFun

注:欢迎转载,转载请注明出处


▌简介

最近忙于工作,没怎么看新的论文,今天把之前写的一点记录分享一下~

本文主要介绍新浪微博机器学习团队发表在 RecSys19 上的一项工作:FiBiNET: Combining Feature Importance and Bilinear feature Interaction for Click-Through Rate Prediction

文章指出当前的许多通过特征组合进行 CTR 预估的工作主要使用特征向量的内积或哈达玛积来计算交叉特征,这种方法忽略了特征本身的重要程度。提出通过使用 Squeeze-Excitation network ( SENET ) 结构动态学习特征的重要性以及使用一个双线性函数来更好的建模交叉特征。

下面对该模型进行一个简单的介绍并提供核心代码实现以及运行 demo,细节问题请参阅论文。

模型结构

1. 整体结构

640?wx_fmt=png

图中可以看到相比于我们熟悉的基于深度学习的 CTR 预估模型,主要增加了 SENET Layer  Bilinear-Interaction Layer 两个结构。下面就针对这两个结构进行简单的说明。

2. SENET Layer

SENET Layer 的主要作用是学习不同特征的一个重要程度,对重要特征加权,对蕴含信息量不多的特征进行削弱。对于该结构的更详细的介绍可以参考论文:Squeeze-and-Excitation Networks

该使用特征组的 embedding 向量作为输入,产生一个特征组权重向量 

640?wx_fmt=png

最后将原始特征组 embedding 向量 640?wx_fmt=png 乘上 640?wx_fmt=png 得到一组新的 embedding 向量:

640?wx_fmt=png

具体来说,分为3个步骤:

① Squeeze

640?wx_fmt=png

这一步主要是对每个特征组中的 embedding 向量进行汇总统计量的操作。文章使用了池化操作来对原始特征组 embedding 向量 640?wx_fmt=png 进行压缩表示得到统计向量:

640?wx_fmt=png

其中640?wx_fmt=png表示第640?wx_fmt=png个特征的全局信息。640?wx_fmt=png可以通过如下的平均池化的方式计算得到: 

640?wx_fmt=png

当然,也可以使用最大池化的方式,文章表示平均池化效果要好于最大池化。

② Excitation

这一步基于特征组的压缩统计量来学习特征组的重要性权重,文章使用两层的神经网络来学习。第一层为一个维度缩减层,第二层为维度提升层。形式化表示为:

640?wx_fmt=png

其中640?wx_fmt=png是一个向量,640?wx_fmt=png640?wx_fmt=png是激活函数,需要学习的参数为:

640?wx_fmt=png

640?wx_fmt=png为缩减比例参数。

③ Re-Weight

这一步利用 Excitation 操作得到的特征重要性权重来对原始的特征组 embedding 向量重新赋权, 新的 embedding 向量通过如下的方式计算得到:

640?wx_fmt=png

其中 640?wx_fmt=png

3. Bilinear-Interaction

传统的特征交叉方式广泛采用了内积 ( fm,ffm 等 ) 和哈达玛积 ( AFM,NFM 等 )。而这两种方式在稀疏数据上很难有效对特征交叉进行建模。文章提出结合内积和哈达玛积并引入一个额外的参数矩阵 640?wx_fmt=png 来学习特征交叉,

640?wx_fmt=png

交叉向量640?wx_fmt=png可以通过以下三种方式计算得到:

① Field-All Type

640?wx_fmt=png这种情况下,所有特征组交叉时共享一个参数矩阵640?wx_fmt=png,额外参数量为 640?wx_fmt=png

② Field-Each Type

640?wx_fmt=png这种情况下,每个特征组 i 维护一个参数矩阵 640?wx_fmt=png ,额外参数量为 640?wx_fmt=png

③ Filed-Interaction Type

640?wx_fmt=png每对交互特征640?wx_fmt=png都有一个参数矩阵640?wx_fmt=png,额外参数量为:

 640?wx_fmt=png

最终,交叉层由原始的特征组 embedding 向量 640?wx_fmt=png 以及 SENET 层输出的 embedding 向量 640?wx_fmt=png 分别得到交叉向量 640?wx_fmt=png 和 640?wx_fmt=png,其中 640?wx_fmt=png 为向量。

4. Combination Layer

组合层将交叉向量640?wx_fmt=png640?wx_fmt=png进行拼接操作,得到结果向量:

640?wx_fmt=png

若直接对 640?wx_fmt=png 向量中的元素进行求和并使用一个 sigmoid 函数输出,则得到一个浅层的 CTR 预估模型,若将该向量输入深度神经网络,则得到一个深度 CTR 预估模型。

实验结果对比

文章在 criteo 和 avazu 两个公开数据集上进行了大量的对比实验,这里只贴出 FiBiNET 相比于其他模型的一个对比结果,其他实验细节请参阅论文~

1. 浅层 FiBiNET

640?wx_fmt=png

2. 深层 FiBiNET

640?wx_fmt=png

3. 核心代码

这边只简单贴一下运行部分的代码,预处理和构造参数的代码请参考 github.com/shenweichen/:

https://github.com/shenweichen/DeepCTR/blob/master/deepctr/layers/interaction.py


4. SENET Layer

Z = tf.reduce_mean(inputs,axis=-1,)A_1 = tf.nn.relu(self.tensordot([Z,self.W_1]))A_2 = tf.nn.relu(self.tensordot([A_1,self.W_2]))V = tf.multiply(inputs,tf.expand_dims(A_2,axis=2))

5. Bilinear Interaction Layer

if self.type == "all":    p = [tf.multiply(tf.tensordot(v_i,self.W,axes=(-1,0)),v_j) for v_i, v_j in itertools.combinations(inputs, 2)]elif self.type == "each":    p = [tf.multiply(tf.tensordot(inputs[i],self.W_list[i],axes=(-1,0)),inputs[j]) for i, j in itertools.combinations(range(len(inputs)), 2)]elif self.type =="interaction":    p = [tf.multiply(tf.tensordot(v[0],w,axes=(-1,0)),v[1]) for v,w in zip(itertools.combinations(inputs,2),self.W_list)]

6. 运行用例

首先确保你的python版本为2.7,3.4,3.5或3.6,然后pip install deepctr[cpu]或者pip install deepctr[gpu], 再去下载一下demo 数据:

https://github.com/shenweichen/DeepCTR/blob/master/examples/criteo_sample.txt

然后直接运行下面的代码吧!

import pandas as pdfrom sklearn.metrics import log_loss, roc_auc_scorefrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import LabelEncoder, MinMaxScalerfrom deepctr.models import FiBiNETfrom deepctr.inputs import  SparseFeat, DenseFeat,get_fixlen_feature_namesif __name__ == "__main__":    data = pd.read_csv('./criteo_sample.txt')    sparse_features = ['C' + str(i) for i in range(1, 27)]    dense_features = ['I' + str(i) for i in range(1, 14)]    data[sparse_features] = data[sparse_features].fillna('-1', )    data[dense_features] = data[dense_features].fillna(0, )    target = ['label']    # 1.Label Encoding for sparse features,and do simple Transformation for dense features    for feat in sparse_features:        lbe = LabelEncoder()        data[feat] = lbe.fit_transform(data[feat])    mms = MinMaxScaler(feature_range=(0, 1))    data[dense_features] = mms.fit_transform(data[dense_features])    # 2.count #unique features for each sparse field,and record dense feature field name    fixlen_feature_columns = [SparseFeat(feat, data[feat].nunique())                           for feat in sparse_features] + [DenseFeat(feat, 1,)                          for feat in dense_features]    dnn_feature_columns = fixlen_feature_columns    linear_feature_columns = fixlen_feature_columns    fixlen_feature_names = get_fixlen_feature_names(linear_feature_columns + dnn_feature_columns)    # 3.generate input data for model    train, test = train_test_split(data, test_size=0.2)    train_model_input = [train[name] for name in fixlen_feature_names]    test_model_input = [test[name] for name in fixlen_feature_names]    # 4.Define Model,train,predict and evaluate    model = FiBiNET(linear_feature_columns, dnn_feature_columns, task='binary')    model.compile("adam", "binary_crossentropy",                  metrics=['binary_crossentropy'], )    history = model.fit(train_model_input, train[target].values,                        batch_size=256, epochs=10, verbose=2, validation_split=0.2, )    pred_ans = model.predict(test_model_input, batch_size=256)    print("test LogLoss", round(log_loss(test[target].values, pred_ans), 4))    print("test AUC", round(roc_auc_score(test[target].values, pred_ans),  4))

参考文献

1. FiBiNET: Combining Feature Importance and Bilinear feature Interaction for Click-Through Rate Prediction

https://arxiv.org/pdf/1905.09433.pdf

2. Squeeze-and-Excitation Networks

http://openaccess.thecvf.com/content_cvpr_2018/papers/Hu_Squeeze-and-Excitation_Networks_CVPR_2018_paper.pdf

嘉宾介绍

沈伟臣,阿里巴巴算法工程师,硕士毕业于浙江大学计算机学院。对机器学习,强化学习技术及其在推荐系统领域内的应用具有浓厚兴趣。


(完)





640

人人都是数据分析师,人人都能玩转Pandas | Numpy 精品系列教程汇 | 我是如何入门机器学习的呢 | 谷歌机器学习43条黄金法则


640

640?wx_fmt=png


长按,识别二维码,加关注


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值