背景
在手淘的搜索场景中,除了正常的展现相关宝贝,还会有一些词的推荐,可以帮助用户更高效地找到想要的宝贝,如图:
图一 | 图二 | 图三 | 图四 |
锦囊细分为很多类型,比如图一是细选,图二是相关搜索、图三是选购热点、图四是属性锦囊。我们就细选这个场景,主要解决的问题是如何根据用户的搜索历史,在当前query下,为用户推荐更合适的细选锦囊词。这里的目标是预测用户对候选词的点击,衡量指标就是细选锦囊的点击率,以及后续的引导效率。
除了一些传统的特征之外。我们用一个隐向量来表示用户在当前搜索词下的购买、点击和浏览过的词(搜索Query、宝贝标题),在用户一次次历史搜索行为中不断更新这个序列模型。我们将用户在近一周内在每个叶子类目下的搜索Query、点击、浏览、购买行为定义为用户的短期行为。通过对用户的短期行为进行建模和分析,希望能够形成对用户长期个性化特征的补充,更为准确地发现用户的真实购买意图。同时,用户的行为是有着先后顺序和其内在逻辑的,而且一般情况下,最近几次行为的影响要大于之前的行为,但也并不绝对,用户对词的偏好也可能会有长距离依赖,因此需要引入一个有时序的模型来表达。本文就将lstm用户行为序列预测term的偏好 和 ctr预估相结合做了探索和应用,并在线下和线上取得了正向的效果。
历史工作
锦囊细选的排序经历过ipv值排序、LR、GBDT排序模型的优化。
在做深度学习尝试之前全量的排序就是GBDT版本,在正负训练样本1:2下得到的auc结果是0.67,也在线上指标得到过正向反馈。
本次深度学习的应用探索就是希望能在离线和在线上相比GBDT都能有所提升。
建模
数据
数据中的信息量决定了算法能达到的上限。这里的数据包括了样本和特征的选取两个方面。我们要预测用户最可能点击哪个候选词,对过去、对用户、对候选锦囊词越了解越好,希望能够采集到用户当时的行为状态(这个用户在什么时间什么地点以什么状态什么需求点击了锦囊词并引导成交或者离开),然后进行归因找到影响用户点击锦囊词的因素,构建用户图谱,最后在此基础上去做预测。
这个过程中,每个环节都会有信息损失,有些是因为采集不到,比如用户当时所处的环境,心情等等;有些是采集得到但是暂时没有办法用起来,比如用户的点击行为很可能收到周围宝贝图片的影响,目前图片的feature还没有参与进来;还有些是采集得到,也用的起来,但是因为加工手段造成的损失,比如时间窗口截取多久,特征离散分成几段等等。
我们能拿到的数据就是用户搜索过程中,锦囊词的曝光和点击。之前参与GBDT模型的统计特征有:
点击ctr、返回结果数、引导成交笔数、Query静态分、引导成交金额、引导点击数、客单价 等等。
顺着这个思路,我们扩展了词维度的特征:
锦囊候选词的裸id特征、当前搜索Query分词后的裸id特征、用户历史行为预测词的裸id特征)。
和用户维度的特征(用户历史点击过的锦囊词的裸id特征,用户偏好词的裸id类特征)
另外,我们还扩展了统计类特征:
1.将query+tag拼为一个新的结果q去查统计类特征
2.统计当前用户对每个候选tag的点击,购买、宝贝浏览等行为数据
label的设计就比较简单:点过的为1,没点过的为0
模型整体设计
整体框架参照了谷歌的Wide&Deep架构,里面嵌套了一个lstm预测模型。统计类、连续型特征作为Wide部分输入,裸的词id特征放到Deep部分输入。上图两个虚线框:
- Wide部分:统计类特征,比如候选词引导的ipv;以及用户的分档信息(年龄段、职业id、性别id、购买力id等)作为embedding层的输入
- Deep部分:
- 用户维度embedding:分析用户的<用户id,叶子类目>下的搜索Query,以及在这个Query下浏览、点击、成交过的宝贝。
每一次搜索行为作为一个时间步,提取该时间步下的重要词id(来源自成交的宝贝、Query的分词、点击浏览的宝贝等)作为embedding层的输入。这样就产出了具有时间序列的语料。 - Query维度embedding:当前搜索Query分词后抽取重要词的id,作为embedding层的输入。
多个词的向量线性加权得到固定长度的隐向量。 - Tag维度embedding:当前候选tag分词后直接作为embedding层的输入。
同样的,多个词的向量线性加权得到固定长度的隐向量。
- 用户维度embedding:分析用户的<用户id,叶子类目>下的搜索Query,以及在这个Query下浏览、点击、成交过的宝贝。
中间过了几层全连层,最上面sigmod层的输出值作为排序分。
loss函数设计
接下来设计我们的小目标,主要由两部分构成:
LSTM用户行为预测
这部分主要是对用户维度embedding的处理,如下图:
上图是一个时间步骤(一次搜索下对宝贝的行为)对词的embedding处理,顶层输出就是作为lstm一个时间步的输入x,如下图:
上图就是经典的LSTM时序。我们设计了固定长20个时间步,于是就用前19个时间步行为预测输出值和第20步真实值的差作为一个loss,使用L2范式
上图示例最后一个lstm单元,公式中的b对应就表征用户当前状态的隐向量,这个向量会输出到Wide and Deep模型结构参与联合优化,向量的值会在联合训练中得到更新。
这个loss在TensorFlow代码表现示例就是
lstm_loss = tf.nn.l2_loss(self.lstm_last_state_output - self._LSTM_O)
CTR预估
ctr预估模型结构借鉴了谷歌的Wide and Deep Learning,把连续型特征和裸的id类特征分开处理,毕竟有一些特征真的不适合做交叉
最上一层的先通过softmax函数计算,再计算它们的交叉熵作为最终的结果输出
这个loss在TensorFlow代码表现示例就是
click_loss = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(
labels=self.label, logits=self.global_res))
最终大模型的loss,就是这两个loss相加。整个在训练过程中做联合优化,
TensorFlow代码表现就是
self.loss = tf.reduce_mean( lstm_loss + click_loss )
实验与效果
离线效果
在pai平台上训练,使用一亿条预料做训练、测试,正负样本1:2,batch_size取1024,Learning Rate取0.0001。使用ada优化器,做了如下三组实验。
- DNN版本: 复用统计类特征,三层网络全连。这个实验目的是在相同的feature上对比模型差异。
- Wide & Deep版本: 在统计类特征基础加上termid类的裸特征
- LSTM版本:加入了LSTM用户行为序列的termid特征,使用lstm+ctr预估的联合训练
- 从AUC训练效果上看,中途迭代到7w轮左右是LSTM(0.728) > Wide & Deep(0.72) > DNN(0.68)。模型迭代时间则是反过来,符合预期。
在线效果
因为锦囊是独立的在线服务,我们把模型上到线上观察对比基准桶(GBDT版本)指标。
锦囊引导uv价值和转化率提升10个点,锦囊ctr提升6个点,引导点击提升7个点。
困难与挑战
锦囊是个独立的在线服务,从埋点、数据清洗、样本收集、特征统计等很多基建工作需要去做,有很多看似搬砖但同时也是最重要的地方。
在线的实时业务意味着有线上的正负向反馈。这对性能和模型的容量有所挑战,要求我们设计一个简单高效的模型能去做线上predict。
结论与改进
深度学习的优势在于对离散特征处理和强大的非线性拟合能力。本文就将lstm用户行为序列预测term的偏好 和 ctr预估 相结合做了探索和应用,减少对特征的人工处理,实现了端到端的训练,并在线下和线上取得了正向的效果。
将来还可以引入position bias作为特征放在最后一个隐层参与特征融合。模型结构上,在最顶层输出之前可以再加深层数,为了避免梯度消失可以引入ResNet。锦囊周围展现的图片特征也可以考虑进来。
另外,用户视觉热点,并不是简单的按照index的方式去check,而前端样式也会变化,比如下面两个图中用户视觉热点可能是覆盖在红色区域,两种展现方式的排序也应该考虑不同,这些都可以考虑进排序因子去尝试。
参考文献:
LSTM
Deep Learning based Recommender System: A Survey and New Perspectives
Wide & Deep Learning for Recommender Systems
http://blog.csdn.net/u010754290/article/details/47167979