当前位置: 首页 > 编程日记 > 正文

只做好CTR预估远不够,淘宝融合CTR、GMV、收入等多目标有绝招

640?wx_fmt=jpeg

作者 | 吴海波

转载自知乎用户吴海波


【导读】一直以来,电商场景就存在 ctr、cvr、gmv、成交 uv 等多个目标,都是核心指标。理想情况下,提升 ctr 就能提升 gmv,但本文作者认为,在一定程度上, ctr 和 gmv 并不是完全一致。一般大幅的 ctr 提升,都会带来相关的 gmv 的提升,但小幅度的 ctr 提升就不一定了,有的时候还是负向的。

那是否只优化 GMV 就可以了呢?一方面,虽然电商公司最终追求 gmv,但是 ctr 之类的指标,一定程度上代表着用户体验,也需重点关注。另一方面,GMV等成交指标,比起点击率相关的指标,更难优化。成交比起点击,数据稀疏很多,且受更多的场外因素影响。

大数公司这个问题并不严峻,每个目标训练个模型,拍个公式在线上揉在一起也能用。且在大公司,不同模型各自有团队在做,也没有很强的融合意愿。而我们不行,由于淘宝的网络效应,决定了我们无法依靠 cpc 竞价的模式走向盈利。因此,只做好 ctr 预估并不够,如何融合 ctr、gmv、收入等目标,则成为我们重点要解决的问题。

去年 ESMM 出来时,我们已经做过一些相关尝试了,并没有很成功。当时的想法很朴素,希望从丰富的 ctr 样本中学习到一部分能够 generalization 的表达,辅助 cvr 的学习。ESMM 这篇论文给了我们进一步的信心。另外,还从dupn 的论文中借鉴了不少特征构建的想法,经过几个月的尝试,迭代了几版,拿到相对不错的结果。

模型总体策略

模型预估目标

用户在平台的行为遵循一定的顺序决策模式:impression->click->conversion

CVR 模型旨在预估用户在观察到曝光商品进而点击到商品详情页之后购买此商品的概率,即 pCVR=p(conversion|click, impression)。CVR 模型的目标是预估条件概率 pCVR,与其相关的两个概率为点击率 pCTR 和点击且转化率 pCTCVR,它们之间的关系如下:

640?wx_fmt=jpeg


模型结构

样本按照正负样本比例 =1:6 的比例进行采样,这里的正样本指的是点击正样本。

借鉴阿里妈妈提出的 ESMM 模型(完整空间多任务模型),使用全站用户行为序列数据(包括点击、加购、收藏等),使用多任务学习的思路,引入了两个辅助的学习任务,在完整的曝光样本空间,分别拟合 pCTR 和 pCTCVR,从而缓解传统 CVR 预估模型难以克服的样本选择偏差和训练数据稀疏的问题。

640?wx_fmt=jpeg

对于一个给定的展现,模型能够同时输出预估的 pCTR、pCVR、pCTCVR。模型主要由两个子网络组成,左边的子网络用来拟合 pCVR,右边的子网络用来拟合 pCTR。两个网络的输出结果相乘,即为 pCTCVR。具体反映在目标函数中:

640?wx_fmt=jpeg

即用 CTCVR 和 CTR 的监督信息训练网络,隐式学习 CVR。本次实验,只使用 MTL 模型的 CVR 网络产出的 CVR 预估分用于排序。

过程中一些有意思的点

预估偏置问题

一开始,我们希望直接采用 ctcvr 的结果,去替代线上的融合模型。但结果不太理想,我们做了很多数据分析,发现主要是由于 ctcvr 在预估上存在比较大的偏置。比如对订单量很少的样本,cvr 预估会明显偏高。而在数据量相对丰富的头部样本,预估的分数没有表现出差异,过于集中。

尝试了几种校准方案后,效果不是特别理想。但发现模型结构中的 cvr,校准的难度比 ctcvr 低,经过一段时间的尝试,上线效果还是不错的。

增加 attention 层的 share

原有结构仅共享底层 embedding 表达,即 CVR-task 和 CTR-task 两个子网络的 embedding 层共享 embedding 向量(特征表示)词典。embedding 层的参数占据整个网络参数的绝大部分,需要大量的训练样本才能充分学习到。

由于 CTR 任务的训练样本量远远超过 CVR 任务的训练样本量,ESMM 模型中,embedding 共享的机制能够使得 CVR 子任务能够从只有曝光没有点击的样本中学习,从而可以极大缓解训练数据稀疏的问题。

在此基础上,鉴于行为序的重要作用,我们把行为序列的 attention 参数共享。对比原结构:ctr、cvr、ctcvr 的 auc 都有明显的提升。

DUPN类的特征

这个说法是我们内部发明的,其实一点也不严谨,只不过是我们借鉴了 dupn 那边论文中特征构建的方式。

不同的 ID 特征从不同规模上刻画了商品。比如 shop、brand、cid、sale 等属于比较泛化的特征,描述商品的一般特征;而商品 ID 属于非常个性化的特征,描述了商品的独特性。

在用户点击序列的基础上,拓展 dupn 的思路,根据用户当前或历史的行为,去预测用户的一些隐藏信息,比如偏好品牌、偏好类目、用户购买力、价格偏好、商品的评价数量、商品的价格、商品的销量、商品的喜欢数等泛化特征,这些信息与原始用户点击序列一起,会帮助模型学习商品表达。

训练本身的问题

虽然 ESMM 的思路很赞,但是联合训练本身就会带来新的问题,模型训练收敛更难了,且更慢了。在我们前期实践过程中,经常会发现 logit 飘了、nan 了,除了一些代码 bug 外,就需要精细的调参和数据清洗了。

训练速度慢,对我们也是一个很大的挑战。我们的集群资源有限,特别要训练 ctcvr 模型,对数据量的要求更高,也是我们在 ctcvr 上进展缓慢的另一个重要原因。

可以预见,如果我们再增加更多的目标 loss,这个问题会更尖锐。

一个小问题

在计算ctcvr_logits的时候,应该算sigmoid(ctr_logits) * sigmoid(cvr_logits) ,即两个网络的输出,做 sigmoid 之后再相乘。众所周知,TensorFlow 中是不提供单独的 cross entropy loss 计算函数的,只有softmax_cross_entropy_with_logits和sigmoid_cross_entropy_with_logits 两类。(不过现在Keras里有这种东西了,categorical_crossentropy 可以指明输入的是 logits 而非 softmax )。

重新实现了 sigmoid + loss 交叉熵函数,并对边界值进行了严格校验。但是 在 embedding 向量从 32 维扩展到 128 维是,会出现输出 Nan 的情况,调小优化器的学习率,可以暂时避免出现 Nan。

总结

这种 mutil-task 联合训练的方式,在我们线上实践中,比单独 ctr 和 cvr 模型分开训练,总体表现上要好不少,可以做到 ctr 不怎么降,gmv、收入有明显的提升。

再说个题外话,针对多目标的问题,我们还想过尝试 RL 。RL 最吸引我的是long term reward,我们可以在 reward 中引入多目标。但 RL 的问题太多了,而现有的技术,大多已经是基于实时的行为 seq 做,RL 目前没有给我特别大的吸引力。

最后,非常感谢参与其中的小伙伴们坚持不懈的努力。

原文链接:

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

(*本文为 AI 科技大本营转载文章,转载请联系原作者)

福利时刻

入群参与每周抽奖~

扫码添加小助手,回复:大会,加入福利群,参与抽奖送礼!

640?wx_fmt=jpeg

大会优惠票限时抢购中!此外,伯克利大学名师精髓课程移师北京。《动手学深度学习》作者、亚马逊首席科学家李沐线下亲授「深度学习实训营」,免费GPU资源,现场还将限量赠送价值85元的配套书籍一本,先到先得。原价1099元,限时专享CSDN 独家福利价199元识别海报二维码,即刻购票~

640?wx_fmt=jpeg

推荐阅读

  • IBM重磅开源Power芯片指令集?国产芯迎来新机遇?

  • KDD 2019高维稀疏数据上的深度学习Workshop论文汇总

  • 说出来你可能不信,现在酒厂都在招算法工程师

  • 姚班三兄弟3万块创业八年,旷视终冲刺港股

  • 2019 AI ProCon日程出炉:Amazon首席科学家李沐亲授「深度学习」

  • AI Top 30+案例评选等你来秀!

  • 福利 | 马上为你安排和大咖面对面交流的机会,不可错过

  • 92年小哥绞尽脑汁骗得价值800万比特币, 破案后警方决定还给受害者

  • 他是叶问制片人也是红色通缉犯, 他让泰森卷入ICO, 却最终演变成了一场狗血的罗生门……


640?wx_fmt=png

你点的每个“在看”,我都认真当成了喜欢

相关文章:

Android监听HOME按键

2019独角兽企业重金招聘Python工程师标准>>> <!-- lang: java --> class HomeKeyEventBroadCastReceiver extends BroadcastReceiver {static final String SYSTEM_REASON "reason";static final String SYSTEM_HOME_KEY "homekey";// …

OpenCV代码提取:merge/split函数的实现

对OpenCV中的merge/split函数进行了实现&#xff0c;经测试&#xff0c;与OpenCV3.1结果完全一致。merge实现代码merge.hpp&#xff1a;// fbc_cv is free software and uses the same licence as OpenCV // Email: fengbingchun163.com#ifndef FBC_CV_MERGE_HPP_ #define FBC_…

DeepMind提图像生成的递归神经网络DRAW,158行Python代码复现

作者 | Samuel Noriega译者 | Freesia编辑 | 夕颜出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导读】最近&#xff0c;谷歌 DeepMInd 发表论文( DRAW: A Recurrent Neural Network For Image Generation&#xff09;&#xff0c;提出了一个用于图像生成的递归神…

其他进制的数字

JS中如果需要表示16进制的数字,则需要以0X开头 0X10 八进制数字以0开头 070 070有些浏览器会以8进制解析,但是有些则用10进制解析,10进制为70,8进制为56 所以parseint() 第二个参数可以设定进制,比如 parseint(“070”,10)代表以10进制解析070 2进制以0b开头,但是不是所有浏览…

java中的移位运算符

移位运算符是在数字的二进制形式上进行平移。主要有左移&#xff08;<<&#xff09;、带符号右移&#xff08;>>&#xff09;以及无符号右移&#xff08;>>>&#xff09;。左移运算符&#xff08;<<&#xff09;的运算规则为&#xff1a;按二进制形…

C++11中nullptr的使用

在C语言中&#xff0c;NULL实际上是一个void* 的指针&#xff0c;然后把void* 指针赋值给其它类型的指针的时候&#xff0c;会隐式转换成相应的类型。而如果用一个C编译器来编译的时候是要出错的&#xff0c;因为C是强类型的&#xff0c;void* 是不能隐式转换成其它指针类型的。…

埃森哲、亚马逊和万事达卡抱团推出的区块链项目有何神通?

据外媒报道&#xff0c;今日埃森哲宣布了一项新的区块链项目&#xff0c;该项目为基于区块链的循环供应链&#xff0c;将与万事达卡和亚马逊共同合作。据官方介绍&#xff0c;这个基于区块链的循环供应链能够让客户识别供应链上的小规模供应商和种植者&#xff0c;例如&#xf…

小团队如何玩转物联网开发?

近几年来&#xff0c;物联网发展迅速&#xff1a;据中商产业研究院《2016——2021年中国物联网产业市场研究报告》显示&#xff0c;预计到2020年&#xff0c;中国物联网的整体规模将达2.2万亿元&#xff0c;产业规模比互联网大30倍。与之相反的是&#xff0c;物联网开发者在开发…

Build Boost C++ libraries for x32/x64 VC++ compilers on Windows

2019独角兽企业重金招聘Python工程师标准>>> Boost is a set of libraries for the C programming language that provide support for tasks and structures such as linear algebra, pseudorandom number generation, multithreading, image processing, regular …

C++11中auto的使用

在C语言中&#xff0c;就有了auto关键字&#xff0c;它被当作是一个变量的存储类型修饰符&#xff0c;表示自动变量(局部变量)。它不能被单独使用&#xff0c;否则编译器会给出警告。在C11标准中&#xff0c;添加了新的类型推导特性。在C 11中&#xff0c;使用auto定义的变量不…

攻和防谁更厉害?AI技术在恶意软件检测中的应用和对抗

AI技术的发展为网络安全带来新机遇的同时&#xff0c;黑客也在逐渐利用AI漏洞建立对抗样本以躲避攻击&#xff0c;双方在各自领域的更多尝试也将是AI技术发展的一场新博弈。那么&#xff0c;在应用中&#xff0c;如何利用AI检测技术与恶意软件展开对抗&#xff1f; 腾讯安全技术…

一文看懂机器学习中的常用损失函数

作者丨stephenDC编辑丨zandy来源 | 大数据与人工智能&#xff08;ID: ai-big-data&#xff09;导语&#xff1a;损失函数虽然简单&#xff0c;却相当基础&#xff0c;可以看做是机器学习的一个组件。机器学习的其他组件&#xff0c;还包括激活函数、优化器、模型等。本文针对机…

Using Apache2 with JBoss AS7 on Ubuntu

大体思路同《Using Apache Web Server with Jboss AS 7》一致&#xff0c;但在Ubuntu上的操作与之前有些区别。 这里仍然演示mod_proxy的配置。 首先加载相应的模块。Ubuntu中加载模块和卸载模块均可以通过命令操作&#xff0c;与其对应的命令分别是a2enmod和a2dismod。 启用…

OpenCV代码提取:rotate函数的实现

OpenCV中并没有直接提供实现rotate的函数&#xff0c;这里通过getRotationMatrix2D和warpAffine函数实现rotate&#xff0c;并增加了一个crop参数&#xff0c;用来判断是否进行crop。目前支持uchar和float两种类型&#xff0c;经测试&#xff0c;与OpenCV3.1结果完全一致。公式…

在 Node.js 中用子进程操作标准输入/输出

翻译&#xff1a;疯狂的技术宅原文&#xff1a;http://2ality.com/2018/05/chi... 本文首发微信公众号&#xff1a;jingchengyideng欢迎关注&#xff0c;每天都给你推送新鲜的前端技术文章 在本中&#xff0c;我们在 Node.js 中把 shell 命令作为子进程运行。然后异步读取这些进…

再见,Python 2.x

整理 | 屠敏来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;在技术的长河中&#xff0c;软件、工具、系统等版本的迭代本是常事&#xff0c;但由于使用习惯、版本的兼容性、易用性等因素&#xff0c;很多用户及开发者在使用或做开发的过程中&#xff0c;并不愿意及…

Android UI系列-----CheckBox和RadioButton(1)

主要记录一下CheckBox多选框和RadioGroup、RadioButton单选框的设置以及注册监听器 1.CheckBox 布局文件&#xff1a; <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android…

C++中struct的使用

C语言继承了C语言的struct&#xff0c;并且加以扩充。在C语言中struct是只能定义数据成员&#xff0c;而不能定义成员函数的。而在C中&#xff0c;struct类似于class&#xff0c;在其中既可以定义数据成员&#xff0c;又可以定义成员函数。结构类型是用户定义的复合类型&#x…

填报表中也可以添加 html 事件

在实际的项目开发中&#xff0c;填报表的应用十分广泛。 多数情况下&#xff0c;填报表会作为整个项目的一部分配合需求灵活使用&#xff0c;但有时也会受大项目环境的影响&#xff0c;产生一些特别的要求。比如&#xff0c;通常报表单元格的数据类型大多是文本&#xff0c;有时…

60+业内技术专家,9大核心技术专题,AI ProCon倒计时一周!

2018 年&#xff0c;由 CSDN 举办的第一届 AI 开发者大会喊出“只讲技术&#xff0c;拒绝空谈”&#xff0c;两天会议时间&#xff0c;国内外几十家顶尖科技企业讲述了其主流技术及其应用案例&#xff0c;真正引领国内开发者紧跟技术浪潮。一年过去&#xff0c;在你还未有所觉察…

密码学研究-数字签名

引入&#xff1a;提到签名&#xff0c;大家都不陌生&#xff0c;大家知道&#xff0c;重大的文件一般都要领导签名&#xff0c;来确保这个文件的真实有效。而一些比较重要的合同&#xff0c;比如买房的购房合同&#xff0c;都要盖“骑缝章”&#xff0c;这个骑缝章&#xff0c;…

C++11中shared_ptr的使用

在C中&#xff0c;动态内存的管理是通过一对运算符来完成的&#xff1a;new&#xff0c;在动态内存中为对象分配空间并返回一个指向该对象的指针&#xff0c;可以选择对对象进行初始化&#xff1b;delete&#xff0c;接受一个动态对象的指针&#xff0c;销毁该对象&#xff0c;…

colly源码学习

colly源码学习 colly是一个golang写的网络爬虫。它使用起来非常顺手。看了一下它的源码&#xff0c;质量也是非常好的。本文就阅读一下它的源码。 使用示例 func main() {c : colly.NewCollector()// Find and visit all linksc.OnHTML("a[href]", func(e *colly.HTM…

可惜了,你们只看到“双马会”大型尬聊

作者 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;导读&#xff1a;2019 年 8 月 29 日&#xff0c;世界人工智能大会&#xff08;WAIC&#xff09;在上海正式拉开帷幕。开幕式上&#xff0c;最让人瞩目的莫过于阿里巴巴前 CEO 马云与特斯拉 CEO Elon Musk …

Java 过滤特殊字符的 正则表达式

Java正则表达式学习&#xff1a; 因为正则表达式是一个很庞杂的体系&#xff0c;此例仅举些入门的概念&#xff0c;更多的请参阅相关书籍及自行摸索。 \\ 反斜杠 \t 间隔 (\u0009) \n 换行 (\u000A) \r 回车 (\u000D) \d 数字 等价于[0-9] \D 非数字 等价于[^0-9] \s 空…

C++11中unique_ptr的使用

在C中&#xff0c;动态内存的管理是通过一对运算符来完成的&#xff1a;new&#xff0c;在动态内存中为对象分配空间并返回一个指向该对象的指针&#xff0c;可以选择对对象进行初始化&#xff1b;delete&#xff0c;接受一个动态对象的指针&#xff0c;销毁该对象&#xff0c;…

从这篇YouTube论文,剖析强化学习在工业级场景推荐系统中的应用

作者 | 吴海波转载自知乎用户吴海波【导读】本文作者根据两篇工业界背景的论文解答了 RL 在推荐场景需要解决的问题与困难&#xff0c;以及入门需要学习得相关知识点。2 个月前&#xff0c;业界开始流传 youtube 成功将 RL 应用在了推荐场景&#xff0c;并且演讲者在视频中说是…

java中两个Integer类型的值相比较的问题

转载自&#xff1a; https://www.cnblogs.com/xh0102/p/5280032.html 两个Integer类型整数进行比较时&#xff0c;一定要先用intValue()方法将其转换为int数之后再进行比较&#xff0c;因为直接使用比较两个Integer会出现问题。 总结&#xff1a; 当给Integer直接赋值时&#x…

C#共享内存实例 附源码

原文 C#共享内存实例 附源码 网上有C#共享内存类&#xff0c;不过功能太简单了&#xff0c;并且写内存每次都从开头写。故对此进行了改进&#xff0c;并做了个小例子&#xff0c;供需要的人参考。 主要改进点&#xff1a; 通过利用共享内存的一部分空间(以下称为“数据信息区”…

C++11中weak_ptr的使用

在C中&#xff0c;动态内存的管理是通过一对运算符来完成的&#xff1a;new&#xff0c;在动态内存中为对象分配空间并返回一个指向该对象的指针&#xff0c;可以选择对对象进行初始化&#xff1b;delete&#xff0c;接受一个动态对象的指针&#xff0c;销毁该对象&#xff0c;…