深度学习在CTR预估中的应用

1、转自

2、转自

3、深入FFM原理与实践

4、网络广告中,CPC、CPA、CPM 的定义各是怎样的?

如果只是做研究,而考虑数据集的特征工程,可以关注这个库

一、前言

深度学习凭借其强大的表达能力和灵活的网络结构在NLP、图像、语音等众多领域取得了重大突破。在广告领域,预测用户点击率(Click Through Rate,简称CTR)领域近年也有大量关于深度学习方面的研究,仅这两年就出现了不少于二十多种方法,本文就近几年CTR预估领域中学术界的经典方法进行探究, 并比较各自之间模型设计的初衷和各自优缺点。通过十种不同CTR深度模型的比较,不同的模型本质上都可以由基础的底层组件组成。

本文中出现的变量定义:

  • n: 特征个数,所有特征one-hot后 连接起来的整体规模大小
  • f: 特征field个数,表示特征类别有多少个
  • k: embedding层维度,在FM中是隐向量维度
  • H1: 深度网络中第一个隐层节点个数,第二层H2,以此类推。

二、深度学习模型

1. Factorization-machine(FM)

FM模型可以看成是线性部分的LR,还有非线性的特征组合xixj交叉而成,表示如下:

其中vi是第i维特征的隐向量,长度k<<n,包含k个描述特征的因子。参数个数为k*n。所有包含xi的非零组合特征都可以用来训练vi,缓解数据稀疏问题。图1是从神经网络的角度表示FM, 可以看成底层为特征维度为n的离散输入,经过embedding层后,对embedding层线性部分(LR)和非线性部分(特征交叉部分)累加后输出。

图1 FM模型结构

FM等价于FM + embedding,待学习的参数如下:

(1)LR部分: 1+n

(2)embedding 部分: n*k

FM下文中将作为各种网络模型的基础组件

2. Deep Neural Network(DNN)

图2是经典的DNN网络, 结构上看就是传统的多层感知机(MultiLayer Perceptron,简称MLP)。在MLP网络中,输入是原始的特征n维特征空间,假设第一层隐层节点数为H1,第二层为H2,以此类推。在第一层网络中,需要学习的参数就是n*H1。对于大多数CTR模型来说,特征体系都极其庞大而且稀疏,典型的特征数量级n从百万级到千万级到亿级甚至更高,这么大规模的n作为网络输入在ctr预估的工业界场景中是不可接受的。下面要讲到的大多数深度学习CTR网络结构,都围绕着如何将DNN的高维离散输入,通过embedding层变成低维稠密的输入工作来展开。

 

图2 DNN模型结构

DNN待学习参数: n*H1+H1*H2+H2*H3+H3*o(o为输出层大小,在ctr预估中为1)

DNN(后文称MLP)也将作为下文各种模型的基础组件之一

3. Factorization-machine supported Neural Networks (FNN)

在上述的DNN中,网络的原始输入是全部原始特征,维度为n,通常都是百万级以上。然而特征维度n虽然空间巨大,但如果归属到每个特征所属的field(维度为f),通常f维度会小很多。如果有办法将每个特征用其所属的field来表示,原始输入将大大减少不少。Factorisation-machine supported Neural Networks,简称FNN就是基于这种思想提出来的。

图3 FNN模型结构

FNN假设每个field有且只有一个值为1,其他均为0。x为原始输入的特征,它是大规模离散稀疏的。它可以分成n个field,每一个field中,只有一个值为1,其余都为0(即one hot)。 field i的输入可以表示成 x[start_i: end_i], Wi为field i的embedding矩阵。 z为embedding后的向量,是一个k维的向量,它由一次项wi ,二次项vi=(vi1,vi2,…vik) 组成,其中k是FM中二次项的向量的维度。而后面的l1,l2则为神经网络的全连接层的表示。

除此之外,FNN还具有以下几个特点:

  • FM参数需要预训练

FM部分的embedding需要预先进行训练,所以FNN不是一个end-to-end模型。在其他论文中,有试过不用FM初始化embedding, 而用随机初始化的方法,要么收敛速度很慢,要么无法收敛。有兴趣的同学可以实验验证下。

  • 无法拟合低阶特征

FM得到的embedding向量直接concat连接之后作为MLP的输入去学习高阶特征表达,最终的DNN输出作为ctr预估值。因此,FNN对低阶信息的表达比较有限。

  • 每个field只有一个非零值的强假设

FNN假设每个fileld只有一个值为非零值,如果是稠密原始输入,则FNN失去意义。对于一个fileld有几个非零值的情况,例如用户标签可能有多个,一般可以做average/sum/max等处理。

本质上讲,FNN = LR+DEEP = LR + embedding + MLP,参数如下

(1)LR部分: 1+n

(2)embedding部分: n*k

(3)MLP部分: f*k*H1+H1*H2+H2

可以看到,对比DNN,在进入MLP部分之前,网络的输入由n降到了f*k(f为field个数,几十到几百之间,k为隐向量维度,一般0~100)

4. Product-based Neural Network(PNN)

FNN的embedding层直接concat连接后输出到MLP中去学习高阶特征。PNN,全称为Product-based Neural Network,认为在embedding输入到MLP之后学习的交叉特征表达并不充分,提出了一种product layer的思想,既基于乘法的运算来体现体征交叉的DNN网络结构,如图4所示。

 

图4 PNN模型结构

对比FNN网络,PNN的区别在于中间多了一层Product Layer层。Product Layer层由两部分组成,左边z为embedding层的线性部分,右边为embedding层的特征交叉部分。除了Product layer不同,PNN和FNN的MLP结构是一样的。这种product思想来源于,在ctr预估中,认为特征之间的关系更多是一种and“且”的关系,而非add"加”的关系。例如,性别为男且喜欢游戏的人群,比起性别男和喜欢游戏的人群,前者的组合比后者更能体现特征交叉的意义。根据product的方式不同,可以分为inner product(IPNN)和outer product(OPNN),如图5所示。

 

图5 PNN (左图:IPNN; 右图:OPNN)

Product layer的输出为

  • Inner Product-based Neural Network

IPNN的叉项使用了内积g(fi, fj) = <fi, fj>。f个filed,两两求内积共计交叉项p部分的参数共f*(f-1)/2(f为特征的field个数,原始论文里用的N)个,线性部分z部分参数共f*k个。需要学习的参数为:

(1)FM部分: 1+ n + n*k

(2)product部分: (f*k + f*(f-1)/2)*H1

(3)MLP部分:H1*H2+H2*1

  • Outer Product-based Neural Network

OPNN用矩阵乘法来表示特征的交叉, g(fi, fj)=fifit。f个field两两求矩阵乘法,交叉项p共f*(f-1)/2*k*k个参数。线性部分z部分参数共f*k个。需要学习的参数为:

(1)FM部分: 1+ n + n*k

(2)product部分: (f*k + f*(f-1)/2*k*k)*H1

(3)MLP部分:H1*H2+H2*1

5. Wide & Deep Learning (Wide&Deep)

前面介绍的两种变体DNN结构FNN和PNN,都在embedding层对输入做处理后输入MLP,让神经网络充分学习特征的高阶表达,deep部分是有了,对高阶的特征学习表达较强,但wide部分的表达是缺失的, 模型对于低阶特征的表达却比较有限。google在2016年提出了大名鼎鼎的wide&Deep的结构正是解决了这样的问题。Wide&deep结合了wide模型的优点和deep模型的优点,网络结构如图6所示,wide部分是LR模型,Deep部分是DNN模型。

 

图6 Wide&Deep 模型结构

在这个经典的wide&deep模型中,google提出了两个概念,generalization(泛化性)和memory(记忆性)

  • Memory(记忆性)

wide部分长处在于学习样本中的高频部分,优点是模型的记忆性好,对于样本中出现过的高频低阶特征能够用少量参数学习;缺点是模型的泛化能力差,例如对于没有见过的ID类特征,模型学习能力较差。

  • Generalization(泛化性)

deep部分长处在于学习样本中的长尾部分,优点是泛化能力强,对于少量出现过的样本甚至没有出现过的样本都能做出预测(非零的embedding向量);缺点是模型对于低阶特征的学习需要用较多参才能等同wide部分效果,而且泛化能力强某种程度上也可能导致过拟合出现bad case.

除此之外,wide&deep模型还有如下特点

  • 人工特征工程

LR部分的特征,仍然需要人工设计才能保证一个不错的效果。因为LR部分是直接作为最终预测的一部分,如果作为wide部分的LR特征工程做的不够完善,将影响整个wide&deep的模型精度

  • 联合训练

模型是end-to-end结构,wide部分和deep部分是联合训练的

  • embedding层deep部分单独占有

LR部分直接作为最后输出,因此embedding层是deep部分独有的。

wide&deep 等价于LR + embedding + MLP,需要学习的网络参数有:

  1. LR: 1+n
  2. embedding部分:n*k
  3. MLP部分: f*k*H1 + H1*H2 + H2*1

6. Factorization-Machine based Neural Network (deepFM)

google提出的wide&deep框架固然强大,但由于wide部分是个LR模型,仍然需要人工特征工程。但wide&deep给整个学术界和工业界提供了一种框架思想。基于这种思想,华为诺亚方舟团队结合FM相比LR的特征交叉的功能,将wide&deep部分的LR部分替换成FM来避免人工特征工程,于是有了deepFM,网络结构如图7所示。

图7 DeepFM模型结构

比起wide&deep的LR部分,deeFM采用FM作为wide部分的输出,FM部分如图8所示。

 

图8 deepFM模型中的FM部分结构

除此之外,deepFM还有如下特点:

  • 低阶特征表达

wide部分取代WDL的LR,比FNN和PNN相比能捕捉低阶特征信息

  • embedding层共享

wide&deep部分的embedding层得需要针对deep部分单独设计;而在deepFM中,FM和DEEP部分共享embedding层,FM训练得到的参数既作为wide部分的输出,也作为DNN部分的输入。

  • end-end训练

embedding和网络权重联合训练,无需预训练和单独训练

deepFM等价于FM + embedding + DNN

(1)FM部分: 1+n

(2)embedding部分:n*k

(3)DNN部分: f*k*H1 + H1*H2+H1

通过embedding层后,FM部分直接输出没有参数需要学习,进入DNN部分的参数维度从原始n维降到f*k维。

7. Neural Factorization Machines (NFM)

前面的deepFM在embedding层后把FM部分直接concat起来(f*k维,f个field,每个filed是k维向量)作为DNN的输入。Neural Factorization Machines,简称NFM,提出了一种更加简单粗暴的方法,在embedding层后,做了一个叫做BI-interaction的操作,让各个field做element-wise后sum起来去做特征交叉,MLP的输入规模直接压缩到k维,和特征的原始维度n和特征field 维度f没有任何关系。网络结构如图9所示。

 

图9 NFM模型结构

这里论文只画出了其中的deep部分, wide部分在这里省略没有画出来。Bi-interaction听名字很高大上,其实操作很简单:就是让f个field两两element-wise相乘后,得到f*(f-1)/2个向量,然后直接sum起来,最后得到一个k维的向量。所以该层没有任何参数需要学习。

NFM等价于FM + embedding + MLP,需要学习的参数有:

(1)FM部分: 1+n

(2)embedding部分:n*k

(3)MLP部分: k*H1 + H1*H2+…+Hl*1

NFM在embedding做了bi-interaction操作来做特征的交叉处理,优点是网络参数从n直接压缩到k(比FNN和deepFM的f*k还少),降低了网络复杂度,能够加速网络的训练得到模型;但同时这种方法也可能带来较大的信息损失。

8. Attention Neural Factorization Machines (AFM)

前面提到的各种网络结构中的FM在做特征交叉时,让不同特征的向量直接做交叉,基于的假设是各个特征交叉对ctr结果预估的贡献度是一样的。这种假设其实是不合理的, 不同特征在做交叉时,对ctr预估结果的贡献度是不一样的。Attention Neural Factorization Machines,简称NFM模型,利用了近年来在图像、NLP、语音等领域大获成功的attention机制,在前面讲到的NFM基础上,引入了attention机制来解决这个问题。AFM的网络结构如图10所示。和NFM一样,这里也省略了wide部分,只画出了deep部分结构。

 

图10 AFM模型结构

AFM的embedding层后和NFM一样,先让f个field的特征做了element-wise product后,得到f*(f-1)/2个交叉项。和NFM直接把这些交叉项sum起来不同,AFM引入了一个Attention Net,认为这些交叉特征项每个对结果的贡献是不同的,例如xi和xj的权重重要度,用aij来表示。从这个角度来看,其实AFM其实就是个加权累加的过程。Attention Net部分的权重aij不是直接学习,而是通过如下公式表示

这里t表示attention net中的隐层维度,k和前面一样,为embedding层的维度。所以这里需要学习的参数有3个,W, b, h,参数个数共t*k+2*t个。得到aij权重后,对各个特征两两点积加权累加后,得到一个k维的向量,引入一个简单的参数向量pT,维度为k进行学习,和wide部分一起得到最终的AFM输出。

总结AFM的网络结构来说,有如下特点:

  • Attention Network

AFM的亮点所在,通过一个attention net生成一个关于特征交叉项的权重,然后将FM原来的二次项直接累加,变成加权累加。本质上是一个加权平均,学习xjxj的交叉特征重要性

  • Deep Network

没有deep,卒。

Attention net学习得到的交叉项直接学些个pt参数就输出了,少了DNN部分的表达,对高阶特征部分的进一步学习可能存在瓶颈。另外,FFM其实也引入了field的概念去学习filed和featrue之间的权重。没有了deep 部分的AFM,和优化的FFM上限应该比较接近。

AFM等价于 FM + embedding + attention + MLP(一层),需要学习的参数有:

(1)FM部分参数:1+n

(2)Embedding部分参数: n*k

(3)Attention Network部分参数: k*t + t*2

(4)MLP部分参数:k*1

 

9. Deep&Cross Network(DCN)

在ctr预估中,特征交叉是很重要的一步,但目前的网络结构,最多都只学到二级交叉。LR模型采用原始人工交叉特征,FM自动学习xi和xj的二阶交叉特征,而PNN用product方式做二阶交叉,NFM和AFM也都采用了Bi-interaction的方式学习特征的二阶交叉。对于更高阶的特征交叉,只有让deep去学习了。为解决这个问题,google在2017年提出了Deep&Cross Network,简称DCN的模型,可以任意组合特征,而且不增加网络参数。图11为DCN的结构。

图11 DCN模型结构

整个网络分4部分组成:

(1)Embedding and stacking layer

之所以不把embedding和stacking分开来看,是因为很多时候,embedding和stacking过程是分不开的。前面讲到的各种 XX-based FM 网络结构,利用FM学到的v向量可以很好的作为embedding。而在很多实际的业务结构,可能已经有了提取到的embedding特征信息,例如图像的特征embedding,text的特征embedding,item的embedding等,还有其他连续值信息,例如年龄,收入水平等,这些embedding向量stack在一起后,一起作为后续网络结构的输入。当然,这部分也可以用前面讲到的FM来做embedding。为了和原始论文保持一致,这里我们假设X0向量维度为d(上文的网络结构中为k),这一层的做法就是简答的把各种embedding向量concat起来。

(2)Deep layer netwok

在embedding and stacking layer之后,网络分成了两路,一路是传统的DNN结构。表示如下

为简化理解,假设每一层网络的参数有m个,一共有Ld层,输入层由于和上一层连接,有d*m个参数(d为x0向量维度),后续的Ld-1层,每层需要m*(m+1)个参数,所以一共需要学习的参数有 d*m+m*(m+1)*(Ld-1)。最后的输出也是个m维向量Hl2

(3)Cross layer network

Embedding and stacking layer输入后的另一路就是DCN的重点工作了。假设网络有L1层,每一层和前一层的关系可以用如下关系表示

可以看到f是待拟合的函数,xl即为上一层的网络输入。需要学习的参数为wl和bl,因为xl维度为d, 当前层网络输入xl+1也为d维,待学习的参数wl和bl也都是d维度向量。因此,每一层都有2*d的参数(w和b)需要学习,网络结构如下。

经过Lc层的cross layer network后,在该layer最后一层Lc层的输出为Lc2的d维向量

(4)Combination Output Layer

经过cross network的输出XL1(d维)和deep network之后的向量输入(m维)直接做concat,变为一个d+m的向量,最后套一个LR模型,需要学习参数为1+d+m。

总结起来,DCN引入的cross network理论上可以表达任意高阶组合,同时每一层保留低阶组合,参数的向量化也控制了模型的复杂度。

DCN等价于embedding + cross + deep + LR

(1)embedding部分参数: 根据情况而定

(2)cross部分参数:2*d*Lc(Lc为cross网路层数)

(3)deep部分参数:d*(m+1)+m*(m+1)*(Ld-1) (Ld为深度网络层数,m为每层网络参数)

(4)LR 部分参数:1+d+m

10. Deep Interest Network (DIN)

最后介绍阿里在2017年提出的Deep Interest Network,简称DIN模型。与上面的FNN,PNN等引入低阶代数范式不同,DIN的核心是基于数据的内在特点,引入了更高阶的学习范式。用户的兴趣是多种多样的,从数学的角度来看,用户的兴趣在兴趣空间是一个多峰分布。在预测ctr时,用户embedding表示的兴趣维度,很多是和当前item是否点击无关的,只和用户兴趣中的局部信息有关。因此,受attention机制启发,DIN在embedding层后做了一个action unit的操作,对用户的兴趣分布进行学习后再输入到DNN中去,网络结构如图12所示

 

图12 DIN模型结构

DIN把用户特征、用户历史行为特征进行embedding操作,视为对用户兴趣的表示,之后通过attention network,对每个兴趣表示赋予不同的权值。

  • Vu:表示用户最终向量
  • Vi:表示用户兴趣向量(shop_id, good_id..)
  • Va:表示广告表示向量
  • Wi: 对于候选广告,attention机制中该兴趣的权重

可以看到,对于用户的每个兴趣向量Vi,都会通过学习该兴趣的权重Vi, 来作为最终的用户表示。

三、写在最后

前面介绍了10中深度学习模型的网络结构,总结起来可以用如下的所表示

各种CTR深度模型看似结构各异,其实大多数可以用如下的通用范式来表达,

  • input->embedding:

把大规模的稀疏特征ID用embedding操作映射为低维稠密的embedding向量

  • embedding层向量

concat, sum, average pooling等操作,大部分CTR模型在该层做改造

  • embedding->output:

通用的DNN全连接框架,输入规模从n维降为k*f维度甚至更低。

图13 通用深度学习模型结构

其中,embedding vector这层的融合是深度学习模型改造最多的地方,该层是进入深度学习模型的输入层,embedding 融合的质量将影响DNN模型学习的好坏。个人总结大体有以下4种操作,当然后续可能会有越来越多其他的变形结构。

图14 embedding层融合方式

另外,DNN部分,业界也有很多或state-of-art或很tricky的方法,都可以在里面进行尝试,例如dropout,在NFM的Bi-interaction中可以尝试以一定概率dropout掉交叉特征增前模型的泛化能力等。

 

写在最后

ctr预估领域不像图像、语音等领域具有连续、稠密的数据以及空间、时间等的良好局部相关性,ctr预估中的大多数输入都是离散而且高维的,特征也分散在少量不同的field上。要解决这样的一个深度学习模型,面临的第一个问题是怎么把输入向量用一个embedding层降维策划那个稠密连续的向量,如本文介绍的用FM去做预训练,或者和模型一起联合训练,或者其他数据源提取的embedding特征向量去做concat。其次,在宽和深的大战中,在google在提出了wide&deep的模型框架后,这套体系基本已成为业内的基本框架。无论wide部分或者deep怎么改造,其实本质上还是一些常见组件的结合,或者改造wide,或者改造deep,或者在wide和deep的结合过程中进行改造。

ctr预估领域方法变化层出不穷,但万变不离其宗,各种模型本质上还是基础组件的组合,如何结合自己的业务、数据、应用场景去挑选合适的模型应用,可能才是真正的难点所在。

四、参考文献

[1]Factorization Machines

[2]Wide & Deep Learning for Recommender Systems

[3]Deep Learning over Multi-Field Categorical Data: A Case Study on User Response Prediction

[4]Product-based Neural Networks for User Response Prediction

[5]DeepFM: A Factorization-Machine based Neural Network for CTR Prediction

[6]Neural Factorization Machines for Sparse Predictive Analytics

[7] Attentional Factorization Machines: Learning the Weight of Feature Interactions via Attention Networks

[8]Deep & Cross Network for Ad Click Predictions

[9]Deep Interest Network for Click-Through Rate Prediction

 

 

 

深度学习在ctr预估领域的应用越来越多,新的模型结构层出不穷(从ctr预估问题看看f(x)设计—DNN篇)。但是这些模型如何验证是否有效,快速在工业界落地仍然存在一些问题:

* 开源的实现基本都是学术界的人在搞,距离工业应用还有较大的鸿沟
* 模型实现大量调用底层且低版本的API,兼容和性能很成问题
* 单机,放到工业场景下跑不动
* 迁移成本较高,每种算法都要从头开始搭一套

针对存在的问题做了一些探索,摸索出一套可行方案,有以下特性:

* 读数据采用Dataset API,支持 parallel and prefetch读取
* 通过Estimator封装算法f(x),实验新算法边际成本比较低,只需要改写model_fn f(x)部分
* 支持分布式以及单机多线程训练
* 支持export model,然后用TensorFlow Serving提供线上预测服务

 

按工业界的套路,完整的机器学习项目应该包含五个部分:特征框架,训练框架,服务框架,评估框架和监控框架,这里只讨论前三个框架。

特征框架 -- logs in,samples out

实验数据集用criteo,特征工程参考: https://github.com/PaddlePaddle/models/blob/develop/deep_fm/preprocess.py

#1 连续特征 剔除异常值/归一化
#2 离散特征 剔掉低频,然后统一编码(特征编码需要保存下来,线上预测的时候要用到)

对大规模离散特征建模是用DNN做ctr预估的优势,paper关注点大都放在ID类特征如何做embedding上,至于连续特征如何处理很少讨论,大概有以下3种方式:

--不做embedding
   |1--concat[continuous, emb_vec]做fc
--做embedding
   |2--离散化之后embedding
   |3--类似FM二阶部分, 统一做embedding, <id, val> 离散特征val=1.0

为了模型设计上的简单统一,采用第3种方式,感兴趣的读者可以试试前两种的效果。

 

训练框架 -- samples in,model out

训练框架用TensorFlow1.4,目前实现了DeepFM/wide_n_deep/NFM/AFM/FNN/PNN/Deep & Cross Network等算法,所有参数默认.

其实很多模型结构的表达能力都是同等的,性能上的差异主要是由于某些结构比其他结构更容易优化导致的。下图是FNN/Inner-PNN/DeepFM/DCN在同等超参下跑出来的AUC=0.8±0.003,区分不大。结构相对简单的FNN收敛较慢,但是AUC能够达到0.8! 其他更复杂的结构达不到这个baseline都是耍流氓。

以DeepFM为例来看看如何像搭积木一样来搭建模型结构。跟机器学习模型设计五要素对应,我们需要5大积木块:

#{x,y}          =    features + labels
#f(x)           =    Embedding + FM + MLP
#loss           =    logloss
#optimizer      =    Adam, Adagrad, GD, Momentum
#evaluation     =    AUC

#{x,y}

#1 1:0.5 2:0.03519 3:1 4:0.02567 7:0.03708 8:0.01705 9:0.06296 10:0.18185 11:0.02497 12:1 14:0.02565 15:0.03267 17:0.0247 18:0.03158 20:1 22:1 23:0.13169 24:0.02933 27:0.18159 31:0.0177 34:0.02888 38:1 51:1 63:1 132:1 164:1 236:1
def input_fn(filenames, batch_size=32, num_epochs=1, perform_shuffle=False):
    print('Parsing', filenames)
    def decode_libsvm(line):
        columns = tf.string_split([line], ' ')
        labels = tf.string_to_number(columns.values[0], out_type=tf.float32)
        splits = tf.string_split(columns.values[1:], ':')
        id_vals = tf.reshape(splits.values,splits.dense_shape)
        feat_ids, feat_vals = tf.split(id_vals,num_or_size_splits=2,axis=1)
        feat_ids = tf.string_to_number(feat_ids, out_type=tf.int32)
        feat_vals = tf.string_to_number(feat_vals, out_type=tf.float32)
        return {"feat_ids": feat_ids, "feat_vals": feat_vals}, labels

    # Extract lines from input files using the Dataset API, can pass one filename or filename list
    dataset = tf.data.TextLineDataset(filenames).map(decode_libsvm, num_parallel_calls=10).prefetch(500000)    # multi-thread pre-process then prefetch

    # Randomizes input using a window of 256 elements (read into memory)
    if perform_shuffle:
        dataset = dataset.shuffle(buffer_size=256)

    # epochs from blending together.
    dataset = dataset.repeat(num_epochs)
    dataset = dataset.batch(batch_size) # Batch size to use

    iterator = dataset.make_one_shot_iterator()
    batch_features, batch_labels = iterator.get_next()
    return batch_features, batch_labels

#f(x)/loss/optimizer/evaluation

def model_fn(features, labels, mode, params):
    """Bulid Model function f(x) for Estimator."""
    #------hyperparameters----
    field_size = params["field_size"]
    feature_size = params["feature_size"]
    embedding_size = params["embedding_size"]
    l2_reg = params["l2_reg"]
    learning_rate = params["learning_rate"]
    layers = map(int, params["deep_layers"].split(','))
    dropout = map(float, params["dropout"].split(','))

    #------bulid weights------
    FM_B = tf.get_variable(name='fm_bias', shape=[1], initializer=tf.constant_initializer(0.0))
    FM_W = tf.get_variable(name='fm_w', shape=[feature_size], initializer=tf.glorot_normal_initializer())
    FM_V = tf.get_variable(name='fm_v', shape=[feature_size, embedding_size], initializer=tf.glorot_normal_initializer())

    #------build feaure-------
    feat_ids  = features['feat_ids']
    feat_ids = tf.reshape(feat_ids,shape=[-1,field_size])
    feat_vals = features['feat_vals']
    feat_vals = tf.reshape(feat_vals,shape=[-1,field_size])

    #------build f(x)------
    with tf.variable_scope("First-order"):
        feat_wgts = tf.nn.embedding_lookup(FM_W, feat_ids) # None * F * 1
        y_w = tf.reduce_sum(tf.multiply(feat_wgts, feat_vals),1)

    with tf.variable_scope("Second-order"):
        embeddings = tf.nn.embedding_lookup(FM_V, feat_ids) # None * F * K
        feat_vals = tf.reshape(feat_vals, shape=[-1, field_size, 1])
        embeddings = tf.multiply(embeddings, feat_vals) #vij*xi
        sum_square = tf.square(tf.reduce_sum(embeddings,1))
        square_sum = tf.reduce_sum(tf.square(embeddings),1)
        y_v = 0.5*tf.reduce_sum(tf.subtract(sum_square, square_sum),1)	# None * 1

    with tf.variable_scope("Deep-part"):
        if FLAGS.batch_norm:
            if mode == tf.estimator.ModeKeys.TRAIN:
                train_phase = True
            else:
                train_phase = False

        deep_inputs = tf.reshape(embeddings,shape=[-1,field_size*embedding_size]) # None * (F*K)
        for i in range(len(layers)):
            #if FLAGS.batch_norm:
            #    deep_inputs = batch_norm_layer(deep_inputs, train_phase=train_phase, scope_bn='bn_%d' %i)
                #normalizer_params.update({'scope': 'bn_%d' %i})
            deep_inputs = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=layers[i], \
                #normalizer_fn=normalizer_fn, normalizer_params=normalizer_params, \
                weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='mlp%d' % i)
            if FLAGS.batch_norm:
                deep_inputs = batch_norm_layer(deep_inputs, train_phase=train_phase, scope_bn='bn_%d' %i)   #放在RELU之后 https://github.com/ducha-aiki/caffenet-benchmark/blob/master/batchnorm.md#bn----before-or-after-relu
            if mode == tf.estimator.ModeKeys.TRAIN:
                deep_inputs = tf.nn.dropout(deep_inputs, keep_prob=dropout[i])                              #Apply Dropout after all BN layers and set dropout=0.8(drop_ratio=0.2)
                #deep_inputs = tf.layers.dropout(inputs=deep_inputs, rate=dropout[i], training=mode == tf.estimator.ModeKeys.TRAIN)

        y_deep = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=1, activation_fn=tf.identity, \
                weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='deep_out')
        y_d = tf.reshape(y_deep,shape=[-1])

    with tf.variable_scope("DeepFM-out"):
        #y_bias = FM_B * tf.ones_like(labels, dtype=tf.float32)  # None * 1  warning;这里不能用label,否则调用predict/export函数会出错,train/evaluate正常;初步判断estimator做了优化,用不到label时不传
        y_bias = FM_B * tf.ones_like(y_d, dtype=tf.float32)     # None * 1
        y = y_bias + y_w + y_v + y_d
        pred = tf.sigmoid(y)

    predictions={"prob": pred}
    export_outputs = {tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: tf.estimator.export.PredictOutput(predictions)}
    # Provide an estimator spec for `ModeKeys.PREDICT`
    if mode == tf.estimator.ModeKeys.PREDICT:
        return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,export_outputs=export_outputs)

    #------bulid loss------
    loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=y, labels=labels)) + \
        l2_reg * tf.nn.l2_loss(FM_W) + l2_reg * tf.nn.l2_loss(FM_V)

    # Provide an estimator spec for `ModeKeys.EVAL`
    eval_metric_ops = {
        "auc": tf.metrics.auc(labels, pred)
    }
    if mode == tf.estimator.ModeKeys.EVAL:
        return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,eval_metric_ops=eval_metric_ops)

    #------bulid optimizer------
    if FLAGS.optimizer == 'Adam':
        optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate, beta1=0.9, beta2=0.999, epsilon=1e-8)
    elif FLAGS.optimizer == 'Adagrad':
        optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate, initial_accumulator_value=1e-8)
    elif FLAGS.optimizer == 'Momentum':
        optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.95)
    elif FLAGS.optimizer == 'ftrl':
        optimizer = tf.train.FtrlOptimizer(learning_rate)

    train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())

    # Provide an estimator spec for `ModeKeys.TRAIN` modes
    if mode == tf.estimator.ModeKeys.TRAIN:
        return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,train_op=train_op)

封装成estimator之后,调用非常简单

#train
python DeepFM.py --task_type=train --learning_rate=0.0005 --optimizer=Adam --num_epochs=1 --batch_size=256 --field_size=39 --feature_size=117581 --deep_layers=400,400,400 --dropout=0.5,0.5,0.5 --log_steps=1000 --num_threads=8 --model_dir=./model_ckpt/criteo/DeepFM/ --data_dir=../../data/criteo/

#predict
python DeepFM.py --task_type=infer --learning_rate=0.0005 --optimizer=Adam --num_epochs=1 --batch_size=256 --field_size=39 --feature_size=117581 --deep_layers=400,400,400 --dropout=0.5,0.5,0.5 --log_steps=1000 --num_threads=8 --model_dir=./model_ckpt/criteo/DeepFM/ --data_dir=../../data/criteo/

完整代码: lambdaji/tf_repos

 

服务框架 -- request in,pctr out

TensorFlow Serving 是一个用于机器学习模型 serving 的高性能开源库。它可以将训练好的机器学习模型部署到线上,使用 gRPC 作为接口接受外部调用。更加让人眼前一亮的是,它支持模型热更新与自动模型版本管理。这意味着一旦部署 TensorFlow Serving 后,你再也不需要为线上服务操心,只需要关心你的线下模型训练。

首先要导出TF-Serving能识别的模型文件

python DeepFM.py --task_type=export --learning_rate=0.0005 --optimizer=Adam --batch_size=256 --field_size=39 --feature_size=117581 --deep_layers=400,400,400 --dropout=0.5,0.5,0.5 --log_steps=1000 --num_threads=8 --model_dir=./model_ckpt/criteo/DeepFM/ --servable_model_dir=./servable_model/

默认以时间戳来管理版本,生成文件如下:

$ ls -lh servable_model/1517971230
|--saved_model.pb
|--variables
  |--variables.data-00000-of-00001
  |--variables.index

然后写一个client发送请求,这里用C++来写

PredictRequest predictRequest;
PredictResponse response;
ClientContext context;

predictRequest.mutable_model_spec()->set_name(model_name);
predictRequest.mutable_model_spec()->set_signature_name(model_signature_name); //serving_default
google::protobuf::Map<tensorflow::string, tensorflow::TensorProto>& inputs = *predictRequest.mutable_inputs();

//feature to tfrequest
std::vector<long>  ids_vec = {1,2,3,4,5,6,7,8,9,10,11,12,13,15,555,1078,17797,26190,26341,28570,35361,35613,
		35984,48424,51364,64053,65964,66206,71628,84088,84119,86889,88280,88283,100288,100300,102447,109932,111823};
std::vector<float> vals_vec = {0.05,0.006633,0.05,0,0.021594,0.008,0.15,0.04,0.362,0.1,0.2,0,0.04,
		1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
tensorflow::TensorProto feat_ids;
for (uint32_t i = 0; i < ids_vec.size(); i++) {
	feat_ids.add_int64_val(ids_vec[i]);
}
feat_ids.mutable_tensor_shape()->add_dim()->set_size(1);	//batch_size
feat_ids.mutable_tensor_shape()->add_dim()->set_size(feat_ids.int64_val_size());
feat_ids.set_dtype(tensorflow::DataType::DT_INT64);
inputs["feat_ids"] = feat_ids;

tensorflow::TensorProto feat_vals;
for (uint32_t i = 0; i < vals_vec.size(); i++) {
	feat_vals.add_float_val(vals_vec[i]);
}
feat_vals.mutable_tensor_shape()->add_dim()->set_size(1);	//batch_size
feat_vals.mutable_tensor_shape()->add_dim()->set_size(feat_vals.float_val_size());	//sample size
feat_vals.set_dtype(tensorflow::DataType::DT_FLOAT);
inputs["feat_vals"] = feat_vals;

Status status = _stub->Predict(&context, predictRequest, &response);

完整代码: lambdaji/tf_repos

 

生产环境对时耗和性能的要求较高,而DNN的计算量比LR的简单查表操作大得多,往往需要在效果和性能之间做折中. 这个环节比较考验工程能力, 下图是wide_n_deep model放到线上环境的真实数据,可以看到:

截距部分15ms:对应解析请求包,查询redis/tair,转换特征格式以及打log等
斜率部分0.5ms:一条样本forward一次需要的时间

一个比较有意思的现象是:随着进一步放量,平均时耗不升反降,怀疑TF-Serving内部做了cache类的优化.

 

感兴趣的小伙伴可以fork下来折腾折腾,项目地址:https://github.com/lambdaji/tf_repos

最后提前祝大家新年炼丹愉快!

 

参考资料:

https://github.com/wnzhang/deep-ctr

https://github.com/Atomu2014/product-nets

https://github.com/hexiangnan/attentional_factorization_machine

https://github.com/hexiangnan/neural_factorization_machine

https://github.com/ChenglongChen/tensorflow-DeepFM

https://zhuanlan.zhihu.com/p/32563337

https://zhuanlan.zhihu.com/p/28202287

 

CGO参考:携程个性化推荐算法实践

携程基础业务研发部-数据产品和服务组,专注于个性化推荐、自然语言处理、图像识别等人工智能领域的先进技术在旅游行业的应用研究并落地产生价值。

目前,团队已经为携程提供了通用化的个性化推荐系统、智能客服系统、AI平台等一系列成熟的产品与服务。

携程作为国内领先的 OTA,每天向上千万用户提供全方位的旅行服务,如何为如此众多的用户发现适合自己的旅游产品与服务,挖掘潜在的兴趣,缓解信息过载,个性化推荐系统与算法在其中发挥着不可或缺的作用。

而 OTA 的个性化推荐一直也是个难点,没有太多成功经验可以借鉴,本文分享了携程在个性化推荐实践中的一些尝试与摸索。

推荐流程大体上可以分为3个部分,召回、排序、推荐结果生成,整体的架构如下图所示。

《CGO参考:携程个性化推荐算法实践》

召回阶段,主要是利用数据工程和算法的方式,从千万级的产品中锁定特定的候选集合,完成对产品的初步筛选,其在一定程度上决定了排序阶段的效率和推荐结果的优劣。

业内比较传统的算法,主要是CF[1][2]、基于统计的 Contextual 推荐和LBS,但近期来深度学习被广泛引入,算法性取得较大的提升,如:2015年 Netflix 和 Gravity R&D Inc 提出的利用 RNN的Session-based 推荐[5],2016年Recsys上提出的结合 CNN 和 PMF 应用于 Context-aware 推荐[10],2016年 Google 提出的将 DNN 作为 MF 的推广,可以很容易地将任意连续和分类特征添加到模型中[9],2017年IJCAI会议中提出的利用LSTM进行序列推荐[6]。

2017年携程个性化团队在AAAI会议上提出的深度模型aSDAE,通过将附加的 side information 集成到输入中,可以改善数据稀疏和冷启动问题[4]。

对于召回阶段得到的候选集,会对其进行更加复杂和精确的打分与重排序,进而得到一个更小的用户可能感兴趣的产品列表。

携程的推荐排序并不单纯追求点击率或者转化率,还需要考虑距离控制,产品质量控制等因素。

相比适用于搜索排序,文本相关性检索等领域的 pairwise 和 listwise 方法,pointwise 方法可以通过叠加其他控制项进行干预,适用于多目标优化问题。

工业界的推荐方法经历从线性模型+大量人工特征工程[11] -> 复杂非线性模型-> 深度学习的发展。Microsoft 首先于2007年提出采用 Logistic Regression 来预估搜索广告的点击率[12],并于同年提出 OWLQN 优化算法用于求解带L1正则的LR问题[13],之后于2010年提出基于L2正则的在线学习版本Ad Predictor[14]。

Google 在2013年提出基于L1正则化的LR优化算法FTRL-Proximal[15]。2010年提出的 Factorization Machine 算法[17] 和进一步2014年提出的 Filed-aware Factorization Machine[18] 旨在解决稀疏数据下的特征组合问题,从而避免采用LR时需要的大量人工特征组合工作。

阿里于2011年提出 Mixture of Logistic Regression 直接在原始空间学习特征之间的非线性关系[19]。

Facebook 于2014年提出采用 GBDT 做自动特征组合,同时融合Logistic Regression[20]。

近年来,深度学习也被成功应用于推荐排序领域。Google 在2016年提出wide and deep learning 方法[21],综合模型的记忆和泛化能力。

进一步华为提出 DeepFM[15] 模型用于替换wdl中的人工特征组合部分。阿里在2017年将 attention 机制引入,提出 Deep Interest Network[23]。

携程在实践相应的模型中积累了一定的经验,无论是最常用的逻辑回归模型(Logistic Regression),树模型(GBDT,Random Forest)[16],因子分解机(FactorizationMachine),以及近期提出的 wdl 模型。

同时,我们认为即使在深度学习大行其道的今下,精细化的特征工程仍然是不可或缺的。

基于排序后的列表,在综合考虑多样性、新颖性、Exploit & Explore等因素后,生成最终的推荐结果。

本文之后将着重介绍召回与排序相关的工作与实践。

一、数据

机器学习=数据+特征+模型

在介绍召回和排序之前,先简单的了解一下所用到的数据。携程作为大型 OTA 企业,每天都有海量用户来访问,积累了大量的产品数据以及用户行为相关的数据。实际在召回和排序的过程中大致使用到了以下这些数据:

产品属性:产品的一些固有属性,如酒店的位置,星级,房型等。

产品统计:比如产品一段时间内的订单量,浏览量,搜索量,点击率等。

用户画像:用户基础属性,比如年纪,性别,偏好等等。

用户行为:用户的评论,评分,浏览,搜索,下单等行为。

值得注意的是,针对统计类信息,可能需要进行一些平滑。例如针对历史 CTR 反馈,利用贝叶斯平滑来预处理。

二、召回

召回阶段是推荐流程基础的一步,从成千上万的Item中生成数量有限的候选集,在一定程度上决定了排序阶段的效率和推荐结果的优劣。

而由OTA的属性决定,用户的访问行为大多是低频的。这就使得user-item的交互数据是极其稀疏的,这对召回提出了很大的挑战。

在业务实践中,我们结合现有的通用推荐方法和业务场景,筛选和摸索出了几种行之有效的方法:

Real-timeIntention

我们的实时意图系统可以根据用户最近浏览下单等行为,基于马尔科夫预测模型推荐或者交叉推荐出的产品。这些候选产品可以比较精准的反应出用户最近最新的意愿。

BusinessRules

业务规则是认为设定的规则,用来限定推荐的内容范围等。例如机票推酒店的场景,需要通过业务规则来限定推荐的产品只能是酒店,而不会推荐其他旅游产品。

Context-Based

基于 Context 的推荐场景和 Context 本身密切相关,例如与季候相关的旅游产品(冬季滑雪、元旦跨年等)。

《CGO参考:携程个性化推荐算法实践》

LBS

基于用户的当前位置信息,筛选出的周边酒店,景点,美食等等,比较适用于行中场景的推荐。

地理位置距离通过 GeoHash 算法计算,将区域递归划分为规则矩形,并对每个矩形进行编码,筛选 GeoHash 编码相似的 POI,然后进行实际距离计算。

CollaborativeFiltering

协同过滤算法是推荐系统广泛使用的一种解决实际问题的方法。携程个性化团队在深度学习与推荐系统结合的领域进行了相关的研究与应用,通过改进现有的深度模型,提出了一种深度模型 aSDAE。

该混合协同过滤模型是 SDAE 的一种变体,通过将附加的 side information 集成到输入中,可以改善数据稀疏和冷启动问题,详情可以参见文献[4]。

SequentialModel

现有的矩阵分解(Matrix Factorization)方法基于历史的 user-item 交互学习用户的长期兴趣偏好,Markov chain 通过学习 item 间的 transition graph 对用户的序列行为建模[3]。

事实上,在旅游场景下,加入用户行为的先后顺序,从而能更好的反映用户的决策过程。我们结合 Matrix Factorization 和 Markov chain 为每个用户构建个性化转移矩阵,从而基于用户的历史行为来预测用户的下一行为。

在旅游场景中,可以用来预测用户下一个目的地或者 POI。

除此之外,也可以使用 RNN 来进行序列推荐,比如基于 Session 的推荐[5],使用考虑时间间隔信息的 LSTM 来做下一个 item 的推荐等[6]。

此外,一些常见的深度模型(DNN, AE,CNN等)[7][8][9][10]都可以应用于推荐系统中,但是针对不同领域的推荐,需要更多的高效的模型。

随着深度学习技术的发展,相信深度学习将会成为推荐系统领域中一项非常重要的技术手段。

以上几种类型的召回方法各有优势,在实践中,针对不同场景,结合使用多种方法,提供给用户最佳的推荐,以此提升用户体验,增加用户粘性。

三、排序

以工业界在广告、搜索、推荐等领域的实践经验,在数据给定的条件下,经历了从简单线性模型+大量人工特征工程到复杂非线性模型+自动特征学习的演变。

在构建携程个性化推荐系统的实践过程中,对于推荐排序这个特定问题有一些自己的思考和总结,并将从特征和模型这两方面展开。

Model

个性化排序模型旨在利用每个用户的历史行为数据集建立其各自的排序模型,本质上可以看作多任务学习(multi-task learning)。

事实上,通过加入 conjunctionfeatures,也就是加入 user 和 product 的交叉特征,可以将特定的 multi-task 任务简化为单任务模型。

梳理工业界应用的排序模型,大致经历三个阶段,如下图所示:

《CGO参考:携程个性化推荐算法实践》

本文并不准备详细介绍上图中的算法细节,感兴趣的读者可以查看相关论文,以下几点是我们的一些实践经验和体会。

  • 在实践中选用以LR为主的模型,通过对数据离散化、分布转换等非线性处理后使用LR。一般的,采用L1正则保证模型权重的稀疏性。
  • 在优化算法的选择上,使用 OWL-QN 做 batch learning,FTRL 做 online learning。
  • 实践中利用因子分解机(FactorizationMachine)得到的特征交叉系数来选择喂入LR模型的交叉特征组合,从而避免了繁杂的特征选择工作。一般的受限于模型复杂度只进行二阶展开。
  • 对于三阶以上的特征组合可以利用基于 mutual information 等方法处理。已有针对高阶因子分解机(HighOrder FM)的研究,参见文献[24]。
  • 对于 Wide and Deep Learning,将 wide 部分替换 gbdt 组合特征,在实验中取得了较好的效果,并将在近期上线。
  • 后续的工作将针对如何进行 wide 部分和 deep 部分的 alternatingtraining 展开。
  • Feature Engineering

事实上,虽然深度学习等方法一定程度上减少了繁杂的特征工程工作,但我们认为精心设计的特征工程仍旧是不可或缺的, 其中如何进行特征组合是我们在实践中着重考虑的问题。一般的,可以分为显式特征组合和半显式特征组合。

显式特征组合

对特征进行离散化后然后进行叉乘,采用笛卡尔积(cartesian product)、内积(inner product)等方式。

在构造交叉特征的过程中,需要进行特征离散化;针对不同的特征类型,有不同的处理方式。

1. numerical feature

无监督离散化:根据简单统计量进行等频、等宽、分位点等划分区间

有监督离散化:1R方法,Entropy-BasedDiscretization (e.g. D2,MDLP)

2. ordinal feature(有序特征)

编码表示值之间的顺序关系。比如对于卫生条件这一特征,分别有差,中,好三档,那么可以分别编码为(1,0,0),(1,1,0),(1,1,1)。

3. categorical feature (无序特征)

《CGO参考:携程个性化推荐算法实践》

离散化为哑变量,将一维信息嵌入模型的bias中,起到简化逻辑回归模型的作用,降低了模型过拟合的风险。

离散特征经过OHE后,每个分类型变量的各个值在模型中都可以看作独立变量,增强拟合能力。一般的,当模型加正则化的情况下约束模型自由度,我们认为OHE更好。

利用 feature hash 技术将高维稀疏特征映射到固定维度空间

半显式特征组合

区别于显式特征组合具有明确的组合解释信息,半显式特征组合通常的做法是基于树方法形成特征划分并给出相应组合路径。

一般做法是将样本的连续值特征输入 ensemble tree,分别在每颗决策树沿着特定分支路径最终落入某个叶子结点得到其编号,本质上是这些特征在特定取值区间内的组合。

ensemble tree 可以采用 Gbdt 或者 random forest 实现。每一轮迭代,产生一棵新树,最终通过 one-hotencoding 转化为 binary vector,如下图所示。

《CGO参考:携程个性化推荐算法实践》

以下几点是我们在实践中的一些总结和思考。

在实验中发现如果将连续值特征进行离散化后喂入 gbdt,gbdt 的效果不佳,AUC 比较低。

这是因为 gbdt 本身能很好的处理非线性特征,使用离散化后的特征反而没什么效果。

xgboost 等树模型无法有效处理高维稀疏特征比如 user id 类特征,可以采用的替代方式是:将这类 id 利用一种方式转换为一个或多个新的连续型特征,然后用于模型训练。

需要注意的是当采用叶子结点的 index 作为特征输出需要考虑每棵树的叶子结点并不完全同处于相同深度。

实践中采用了 Monte Carlo Search 对 xgboost 的众多参数进行超参数选择。

在离线训练阶段采用基于 Spark 集群的 xgboost 分布式训练,而在线预测时则对模型文件直接进行解析,能够满足线上实时响应的需求。

此外,在实践发现单纯采用 xgboost 自动学到的高阶组合特征后续输入LR模型并不能完全替代人工特征工程的作用;

可以将原始特征以及一些人工组合的高阶交叉特征同 xgboost 学习到的特征组合一起放入后续的模型,获得更好的效果。

四、总结

完整的推荐系统是一个庞大的系统,涉及多个方面,除了召回、排序、列表生产等步骤外,还有数据准备与处理,工程架构与实现,前端展现等等。

在实际中,通过把这些模块集成在一起,构成了一个集团通用推荐系统,对外提供推服务,应用在10多个栏位,60多个场景,取得了很好的效果。

本文侧重介绍了召回与排序算法相关的目前已有的一些工作与实践,下一步,计划引入更多地深度模型来处理召回与排序问题,并结合在线学习、强化学习、迁移学习等方面的进展,优化推荐的整体质量。

References

[1] Koren, Yehuda,Robert Bell, and Chris Volinsky. “Matrix factorization techniques forrecommender systems.” Computer 42.8 (2009).
[2] Sedhain, Suvash,et al. “Autorec: Autoencoders meet collaborative filtering.” Proceedingsof the 24th International Conference on World Wide Web. ACM, 2015.
[3] Rendle, Steffen,Christoph Freudenthaler, and Lars Schmidt-Thieme. “Factorizingpersonalized markov chains for next-basket recommendation.” Proceedings ofthe 19th international conference on World wide web. ACM, 2010.
[4] Dong, Xin, etal. “A Hybrid Collaborative Filtering Model with Deep Structure forRecommender Systems.” AAAI. 2017.
[5] Hidasi, Balázs,et al. “Session-based recommendations with recurrent neuralnetworks.” arXiv preprint arXiv:1511.06939 (2015).
[6] Zhu, Yu, et al.”What to Do Next: Modeling User Behaviors by Time-LSTM.” Proceedingsof the Twenty-Sixth International Joint Conference on Artificial Intelligence,IJCAI-17. 2017.
[7] Barkan, Oren,and Noam Koenigstein. “Item2vec: neural item embedding for collaborativefiltering.” Machine Learning for Signal Processing (MLSP), 2016 IEEE 26thInternational Workshop on. IEEE, 2016.
[8] Wang, Hao,Naiyan Wang, and Dit-Yan Yeung. “Collaborative deep learning forrecommender systems.” Proceedings of the 21th ACM SIGKDD InternationalConference on Knowledge Discovery and Data Mining. ACM, 2015.
[9] Covington, Paul,Jay Adams, and Emre Sargin. “Deep neural networks for youtuberecommendations.” Proceedings of the 10th ACM Conference on RecommenderSystems. ACM, 2016.
[10] Kim, Donghyun, et al. “Convolutional matrix factorization fordocument context-aware recommendation.” Proceedings of the 10th ACMConference on Recommender Systems. ACM, 2016.[11] https://mli.github.io/2013/03/24/the-end-of-feature-engineering-and-linear-model/[12] Richardson, Matthew, Ewa Dominowska, and Robert Ragno.”Predicting clicks: estimating the click-through rate for new ads.”Proceedings of the 16th international conference on World Wide Web. ACM, 2007[13] Andrew, Galen, and Jianfeng Gao. “Scalable training of L1-regularized log-linear models.” Proceedings of the 24th internationalconference on Machine learning. ACM, 2007.[14] Graepel, Thore, et al. “Web-scale bayesian click-through rateprediction for sponsored search advertising in microsoft’s bing searchengine.” Omnipress, 2010.
[15] McMahan, H. Brendan, et al. “Ad click prediction: a view fromthe trenches.” Proceedings of the 19th ACM SIGKDD international conferenceon Knowledge discovery and data mining. ACM, 2013.
[16] Chen, Tianqi, and Carlos Guestrin. “Xgboost: A scalable treeboosting system.” Proceedings of the 22nd acm sigkdd internationalconference on knowledge discovery and data mining. ACM, 2016.
[17] Rendle, Steffen. “Factorization machines.” Data Mining(ICDM), 2010 IEEE 10th International Conference on. IEEE, 2010.
[18] Juan, Yuchin, et al. “Field-aware factorization machines forCTR prediction.” Proceedings of the 10th ACM Conference on RecommenderSystems. ACM, 2016.
[19] Gai, Kun, et al. “Learning Piece-wise Linear Models fromLarge Scale Data for Ad Click Prediction.” arXiv preprint arXiv:1704.05194(2017).
[20] He, Xinran, et al. “Practical lessons from predicting clickson ads at facebook.” Proceedings of the Eighth International Workshop onData Mining for Online Advertising. ACM, 2014.
[21] Cheng, Heng-Tze, et al. “Wide & deep learning forrecommender systems.” Proceedings of the 1st Workshop on Deep Learning forRecommender Systems. ACM, 2016.
[22] Guo, Huifeng, et al. “DeepFM: A Factorization-Machine basedNeural Network for CTR Prediction.” arXiv preprint arXiv:1703.04247(2017).
[23] Zhou, Guorui, et al. “Deep Interest Network for Click-ThroughRate Prediction.” arXiv preprint arXiv:1706.06978 (2017).
[24] Blondel, Mathieu, et al. “Higher-orderfactorization machines.” Advances in Neural Information ProcessingSystems. 2016.
[25] http://breezedeus.github.io/2014/11/20/breezedeus-feature-hashing.html
[26] https://en.wikipedia.org/wiki/Categorical_variable
[27] https://www.zhihu.com/question/48674426
[28] 多高的AUC才算高?https://zhuanlan.zhihu.com/p/24217322

文:携程技术中心

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值