通常机器学习在电商领域有三大应用,推荐、搜索、广告,这次我们聊聊三个领域里都会涉及到的商品排序问题。从业务角度,一般是在一个召回的商品集合里,通过对商品排序,追求GMV或者点击量最大化。进一步讲,就是基于一个目标下,如何让流量的利用效率最高。很自然的,如果我们可以准确的预估每个商品的gmv转化率或者点击率,就可以最大化的利用流量,从而收益最大。
2014年中旬来到蘑菇街,那时候蘑菇街刚刚开始尝试机器学习,在这3年中经历了很多变化,从模型的角度来讲,大致可以分为打造爆款、追求效率、提升品质。虽然在过程中经常和业务方互相challenge,但我们的理念始终是技术服务于业务,模型本身的迭代需配合业务目标才能发挥出最大的价值,因此选择模型迭代的路线,必须全盘考虑业务的情况。
在蘑菇街,机器学习的工程师不叫算法工程师,而叫策略工程师。因为这种流量分配和策略问题不单单是算法问题,而是涉及到生态的流量分配和生态建设的问题,所以我们把自己定位为策略工程师。所以在做任何一个模型优化或者是算法迭代的时候,除了线上ABTest 要拿到结果之外,还要对整个公司的定位、产品的形态、未来商家用户对你的策略的反应,有自己的定位和分析。
今天的主要内容会从三个阶段展开:

图 1
一、 导购到电商:爆款模型VS公式
一开始蘑菇街是导购平台,我们会把淘宝上很多好的商品,通过买手或者商家自己报名的方式挑出来,用瀑布流的方式展示,用户只要是从蘑菇街导过去,淘宝就会给我们分成。当时我们做得不错,活得很滋润。后来因为某些原因,被淘宝掐掉了。
后来被迫转型到垂直电商,刚开始做平台的时候,商家资源比较稀缺,我们为了让用户在平台刚开始起步的时候,不会因为我们做得不好而对用户造成伤害,做了买手优选。买手优选其实是一件很重的事情,我们当时有一个买手团队全是妹子,她们会把蘑菇街上的主要商品让商家寄送过来,然后做好几道的人工筛选,确保商品质量符合当前的品质和定位。在这样重成本的投入情况下,我们的流量买过来之后(大家知道,互联网很多公司早期的流量都是靠买的),我们希望能够得到足够的回报和利润,能够让商家愿意和我们玩下去,所以我们希望能挑出一些爆款,就是把质量比较好和卖的比较好的款挑出来。当时的情况并不是很理想,第一个阶段我们称之为小米加步枪的时代,如图 2 所示。

图 2
注:GMV,全称 Gross Merchandise Volume,指的是商品交易总量
一个很简单的问题,为什么我们要用机器学习的方式做流量分配或者说是流量排序,而不用销量直接排呢?比如,要让新商品排上来,直接按照上架时间排就可以了,为什么要用模型的方式去排呢?其实这就是策略问题,和策略工程师有关。它如果是一个生态,会有好几方的行为去相互影响。也就是说一个商品,如果只按历史销量去排序,这个历史销量可能是因为你给了它流量的情况下得到的这个销量。在机器学习里这种情况即是,它是有 bias 的,这种 bias 用一个公式是去不了的。如果你想做得好一些的话,需要考虑多种因素,比如说商家的质量、销量、商品的退货退款率等一起考虑,通过一堆的因素去看商品排第几名。这时就带来一个明显的问题,这么多因素每个应该占比占多少,而这个是人拍不出来的。而模型则非常适合解决这个问题。
当时在第一个产品上线的时候,公司比较偏业务驱动,在技术上没有太多的积累,没有集群,没有全链路打点系统。这里的集群是指高性能计算集群,比如你要搭 spark 是没有的,比如说你要做一些好的数据统计或者是数据分析,你要从用户进你的网站或者进你的 APP 到他整个决策过程中有一个完整的链路打点,而这个并不是一个很简单的事情。在这样几个比较困难的背景下,我们把问题做了一些简化——把排序问题转化为分类问题,就是转化为挑好商品的问题。这是什么意思呢?本来有 200 多万个商品需要排序,需要打分,不知道哪些是好的,哪些是坏的。这时候,我可以通过成交额、点击量等几个关键指标,把前面 TOP500 或者 TOP1000 的商品挑出来做正样本,然后再挑已经有足够曝光数量的商品,已经给用户展示过但是各方面表现并不是很好的商品当做负样本。这样就把排序的问题当成分类问题,这样学出来的模型,就是爆款模型。这个爆款模型它会告诉我每一个商品根据它的feature 的情况,它会成为爆款的概率是多少,根据概率值对全体的商品做排序的事情。建了这个模型之后,在 ABTEST 的情况下,整个 GMV 有 10% 以上的提升。
二、 做大做强:转化率模型+个性化
随着平台的快速发展,商家数、用户数增加很快,商品集合快速提升,这时候带来了很多问题。比如原来的买手团队 hold 不住这个量。大家把淘宝叫“万能的淘宝”,在淘宝上可以搜索到任何东西,商品丰富度非常大,它的生态非常强大。一个生态非常强大,它对用户的留存率就会非常高。我们作为一个垂直电商,如果想做得好,必须能够在一个领域里满足得比较好。比如我们是一个女性服装市场,服装本是一个非标品,如果款式不足就无法持续。这时候人工优选慢慢退出历史舞台,因为没有办法应对商家那么多商品。放弃了买手优选之后,商品就直接流进来了,以前我们关心爆款模型的时候,不需要关心商品的质量和商家的服务质量,而现在这就变成了比较严重的问题。
另外一个问题是以前的爆款很集中,很集中的时候商家马太非常严重,流量买过来之后集中被头部商家吃掉了。平台想做大的时候情况下,必须花更多的钱买流量,整体的效率是变低的。另外一个点,我们模型本身的 AUC 指标在当时已经到了 0.95 了,基本上没有任何的提升空间了。
另外一个问题可以比较直观的感受到,我只预测头部的,但有些商家一天卖几十单也可以活得很好,这种商品就很难有准确的概率去预估。把这个问题再细化一点,其实它是机器学习领域或者与互联网结合最紧密的问题,叫 CTR 预估问题。如果大家了解整个互联网的发展的话,可以说 CTR 是能够让谷歌或者阿里巴巴有今天高收入的一个重要技术,其实它是原来的互联网流量广告里的一个非常核心的技术。当时有一个笑话,就是因为有太多优秀的学生都去做 CTR 预估问题了,人工智能在才没有什么进展,但做这个除了赚钱还能做什么呢?这个领域在国外发展比较成熟,而且这几年还在不断的发展。

图 3
这个在业界一般有两条路:一种是大规模高维离散特征+LR;第二个是中低维连续特征+非线性模型。前者典型的代表是百度、Google,他们是能在千亿维度的特征去做模型,后面中低维度的代表是雅虎。不能说哪种更好,因为在机器学习领域有个 no free lunch 的原则。高维离散的优势很明显,它对模型的刻画非常细致,比如说它会把商品 ID 都丢进去,它基本上能对它历史上见过的东西全部都放进去。但它的劣势也非常明显,千亿维或者是千万维的特征,国内也没有几家公司可以让它跑起来。它对线上打分的系统也有非常高的要求,线上搜索引擎的一个 Query 过来,你需要在这么高维度的去查询出你相关的 feature,再去把这个商品或者文本的分数打出来,这不是一个简单的事情,还要涉及到特征的存储,另外它的可解释性也不是很好,因为维度太多了,很多文本编码都不知道它是干嘛的。
另外一个是中低维连续特征加上非线性模型,根据我们的了解,最近阿里也是偏这个方向。这个优点很明显,非线性模型对比 LR 在特征工程上有天然的优势,LR 非常依赖特征工程做得怎么样,但非线性模型这方面稍微好一点。我们自己和引擎做一些解耦,可以通过批量推分数的方式和引擎做解耦,这样线上打分系统的问题就可以部分被解决。但是劣势是预估速度慢,模型确定比较困难,调参困难,因为线性模型人是可以理解他是做什么的,但是非线性模型不知道它在干什么。尤其是现在的深度学习模型,理解起来就是偏黑盒的东西。
介绍完业界通用的两种技术之后,蘑菇街选择的是偏后一种,因为我们的系统在做模型或者做策略选择的时候,会考量当前的场景和系统工程团队对你支持的粒度,当时我们选择了中低维度连续特征和 LR。因为我们对非线性模型的掌控度比较低,所以选择了折中的模型。
接下来我们进行一个比较标准的机器学习的套路,从样本到特征到模型。
(1) 样本

图 4
工业界有 2 种常用的方式,第一种叫 ponitwise,另一种是 pairwise。point 是排序的时候,商品是单独的去考虑的,比如 A 就是A,不会去和 B 考虑,而 pair 是更接近用户真实的行为,比如说进淘宝搜索“连衣裙”,会出现一批商品,它是前后或者一组商品对比会对你造成决策上的影响,所以它是把两个两个的商品组合成样本,区分正副样本。第三种是 listwise,更真实,一次 query 看到 10 个,就是 10 个一起去做组,这种会更复杂。
前面这 2 种,我们在选择时对比了优劣势:第一种 point 样本构建比较简单,如果做 CTR 预估,这条日志如果被点了就是正样本,没有被点就是负样本,不需要考虑更多的东西。如果用 pair,一次出来假设 10 个商品,10 个商品每个两两组 pair,样本数就会爆炸,会产生很多噪音,因为用户不是每 2 种商品都会去组 pair 对。第二个好处是机器学习的训练样本里的 loss function 不需要修改,因为每个样本只是针对A,LR 或者 Xgboost 都是一条一条样本进来,如果你想组 pair,要么走 cheek,比如说把两个 pair 之间的样本,A 减 B,减出来的 feature 去做训练,去学习它的 loss function,另外一个就是改 loss function,这个成本会比较高一点。如果是改 loss function 的方式,它是通过支持 pair 对的方式去做,这个成本就会稍微偏高一些。然后如果你改 pair 对的 loss function 的话,你会带来预测的时候,因为离线训练没有关系,两个A-B、C-D 都可以减出来它的 feature,但如果真的线上打分的时候,一个 query 过来出现 10 个商品,你去排序,每个 pair 组一下,再去 A-B、C-D 的话,你的 RT 基本不用玩了,因为用户等半天你的结果都出不来。这个地方就会带来,如果你训练用 pair,预测用 point,又会有不一致,lambdamart 这方面有比较好的解决方案。当时我们评估了整体优势之后,还是选择 pointwise 这种方式。Pointwise 刻画样本的时候,是不考虑商品之间的关系的,也不考虑用户真实有没有比过其他,在信息上就会有丢失。
(2)特征
因为电商领域的特征比较可以分类。首先,电商领域基本是商品、店铺、用户三大类特征。如果说得细一点,比如说可以分为统计类,比如说这个商品历史上的点击率、曝光值、点击成交是偏连续值,它是有业务含义的用户行为的统计值。还有一些离散类,比如商品 ID,大家可能理解商品 ID 是毫无意义的东西,实际上它是一个非常有用的 feature。然后 Query 分词之后的 ID,然后它的价格、标签。其他还有一些没有归类,比如商品的描述——标题、描述,有一些商品在详情页面有一些特殊的描述,比如说图片,都可以放到里面。对特征处理的话,其实有一些常见的手段,比如说取个 log,做个平滑。平滑是很关键的,一般常见的有贝叶斯平滑和拉布拉斯平滑两种,剩下的就是交叉和离散化。交叉是因为我们是线性模型,本身模型在非线性空间是没有优势的。其实很多特征之间是有非线性关系的,但是我们人肉地去做一些交叉的事情,让模型去学习一些非线性的信息。
(3)模型

图 5
这里可以进一步讲整个模型是怎么做的。这里有两个模型,我们都做了。第一个模型是 LR(Logistic regression),它是线性的,用的非常多。百度在 14 年之前,在深度学习没有像现在应用出来之前,LR 效果是最好的。业界上有各种模型各种迭代,但他们的 LR 是最好的,他们的 LR 做到千亿维度的 feature,在凤巢那边。它有一个好处是,它支持你调试,可解释性强,非常适合你通过这样的模型去理解业务分布是怎样的。它的劣势是你要做非常多的特征工程的事情,如果特征工程做得不好,这个模型就不太好。第二个的 Xgboost+LR 的模型,是 Facebook 在 15 年提出来的,他们说效果非常好。我们拿过来用了之后确实比较好,它有一个非常好的地方,它是开源工具,它背后是实现了 gbm 的算法,它可以自动帮你找到一些非常多的特征,一些高维的抽象的特征,在人肉做一些特征事情上减少很多工作量,这样就可以在样本上或者其他地方发力。这其实是一个效率问题,并不是说 LR 不可以做出这样的模型,但你付出的成本是有本质的差距的。Xgboost+LR 我们遇到的问题是,它的泛化能力偏弱,因为它模型的原理是算残差的值,所以它的数字节点切得非常细。在切的过程中,如果突然有一天数据分布突然变化比较大的时候,很多切出来的 feature 的特征是不对的,这时候用它有一些问题。它的模型也比较复杂,如果两百多棵树,每棵树有 4 层,这是非常典型的 Xgboost 的结构,这时候要很难理解这个模型到底帮你做出了什么事情。所以调试要困难一些,很多时候你是通过自己设计 case了解这个模型是什么情况。
这两个模型,第一个模型 LR 是概率模型,预估转化率概率模型去替换爆款模型,它的线下AUC 可以涨 0.17%,线上转化率可以增长 8%。而我们用 Xgboost+LR,线下 AUC 涨 5%,线上转化率可以涨 5%,而且带来个性化的特征加入变得比较容易。
这里还有一些思考可以和大家分享。我们把数据挖掘和机器学习理解为挖矿的行为,如果对挖矿有一些了解的话,大家可以知道不是说前期挖得越快越好,如果说前期挖的太猛,把矿搞塌了,后面的东西其实就挖不出来了。为什么这么说呢?你在设计你的策略的时候,你要考虑对你的生态的影响,对你当时情况的了解,有没有把目前的数据挖到比较细致的状态,这样子可以去调整。如果整个生态都玩坏了,大家都没得玩了。几种做法,像样本、特征和模型是互相影响,比如把 point 升级到 pair,要不要升级到 pair,或者说要不要把模型从 LR 升级到 Xgboost+LR,这里都是有权衡的。一个比较直观的标准是,它会有一些离线评估。比如说当前的样本分布它的 AUC 是多少,比如在爆款模型中,它的 AUC 已经到 0.95 了,那我设计的那套样本已经对线上没有价值了,我需要进一步的让我的样本里含有更多的信息,让它变得复杂,更接近用户真实的行为,这样子 AUC 会降下来,模型就有空间了。模型如果用LR 做,我发现我的 AUC 是涨了,但是加特征加的很累。但是我用 Xgboost,我会发现不停的加特征还是会涨 AOC,那么我会评估一下两边的工作的优缺点。比如说我用 LR,其实我一直知道我是做什么的,但是我用 Xboost,我不知道这些加进去做对线上造成的影响,这时候监控就要做得更好。所以,我把它整体理解成一个互相影响的动态过程。
为了让我们的流量效率变得更高,我们还做了个性化的事情。个性化的方案一般有2种事情,一种是标签类个性化,一种是偏推荐的行为粒度相似个性化,比如你买了又买,看了又看。第一种是业务方非常喜欢的,比如你给了他一批高购买力用户,他很开心,比如说新进来的商家,品类比较高,就定位到高品类的用户上,然后直接推给他了。但标签类涉及到准确率和召回的问题,如果想做得准,用户覆盖率就不够,比如在蘑菇街的平台上大部分是女性,偏可爱或者是偏韩版。但你出一个波希米亚风格,你 tag 是打出了了,但是用户只有几千个,你招一批这样的商家,这些用户流量不足以支撑它在蘑菇街的发展,这样很快会遇到这样的瓶颈,你想做得准覆盖的量不够,覆盖量够的时候又不准,效果又没有了。
另外一种是不管它的解释性是什么,因为你用户的行为会自己帮我做个性化,你看了这个商品或者你买了这个商品然后我给你推荐这个商品,这种偏推荐的做法。这样刻画非常细致,因为这就是淘宝以前说的千人千面的技术,而且技术场景和推荐是一样的,是互相迁移,一套技术支撑了好几个场景。但问题是业务方不喜欢,你做出来的东西,线上效果很好,但他不知道怎么用。蘑菇街选择的第 2 种方案,因为在快速发展的阶段,我们希望能够让我们的流量回报率更高一些,推荐这种个性化的方式效果会更明显,在全局上的指标会更好看。推荐和这种个性化的方式结合是可以有 2 种方式的,第一种是初排,用排序系统出排,然后再用个性化做一层二次排序。第二种就是把个性化的特征打包,直接扔到初排的模型里,让模型学完就是一个个性化模型。但是第二种模式的成本会高一些,至今为止我们还没有上线。第一种我们迭代了半年的样子,累计 GMV 带来 10% 以上的收益。

图 6
简单介绍一下初排模型的架构,最下面是数据源,上来之后主要是 Hadoop 的生态,HDFS 到 hive,再上来就是 spark。所以刚才有人问 spark 在电商领域的应用,基本上机器学习的话,spark 已经支持非常很好了,可能在使用过程中会遇到一些问题,但它的社区非常活跃,基本上可以找到问题的解答。通过spark 模型产出之后,有特征的管理平台。再根据我们搜索引擎去把分数推上去,搜索引擎在前端有流量分发和 query 的改写。个性化加入之后,有个用户行为(接 kafka 存储东西),这边有一个 UPS,这里有个精排系统,和引擎是两层。也就是说引擎出牌召回之后,会在精排里做一些个性化的设置,用户的设置是从精排里去取得的,这样就完成了个性化的排序框架。

图 7
三、品质升级:人群个性+EE
接下来会讲一下品质升级,主要是人群个性和 EE。EE 又叫多臂老虎机,是一种赌博的策略。经过快速成长到一年 GMV 成长到百亿级别的平台之后,一个问题是商家怎么玩蘑菇街的行为形成了,但有一些行为是我们不太想要的。另外用户对平台的认知逐步形成,会认为蘑菇街价格偏低廉,年纪比较轻,比较可爱。当时我们公司基于一个判断,整体中国的消费者习惯会升级。如果继续走爆款、性价比,将来很难从百亿级别突破再上一个台阶。在这样的情况下想做品质的升级,这对我们比较明显的冲击就是不能通过策略的短期的 ABtest 看出效果,比如说以前的平台上 T 恤都是几十块钱,现在非要引进出卖 300 块钱的 T 恤,这时候这些品牌商能做得好才奇怪了。但为了品牌提升,要把品牌商家引进来,需要让平台的生态变得更健康,这时候如果做 ABtest,必然看到全局的 GMV 有下降。这时候要有权衡,这时候我们策略组和业务方有一些偏差,我们策略组会比较数据导向,但业务方会比较偏哲学,但是这些问题不是不可以平衡的。在讲哲学的公司,哲学是老板讲的,但业务团队,需求方说哲学可以拍回去。高层定哲学,这时候要看每个阶段应该用什么数据指标来看,如果再吹一吹,可以理解为蘑菇街在做一些供给侧改革的事情。就是说我们做这些事情的时候,虽然有损失,但是方向是对的,是有希望的。
当时做的第一个方案是实时人群个性化引导, 刚才提到 tag 的个性化作用不是很大,是基于说你想在全局上拿到收益,如果只是想让生态引入更多更有趣的用户行为时,你是可以这样做的,比如你可以给用户打上一些标签,根据实时进行标签的分类,比如说购买力,找到高、中、低档的用户,比如说有些对商品质量特别敏感的商户,比如有些用户喜欢逛但不喜欢买,有些用户不喜欢逛但喜欢买的,这些都可以分出来。

图 8

图 9
然后我们针对这种情形做了系统设计,前面这个是基于 kafka,它是 spark stream 做的,基于流式处理,有 kafka 的用户数据接入进来之后,有一个实时统计和离线统计的用户分群的算法。依靠一个 UPS 系统,我们可以通过一些概率引导他可能偏好的商品。这可以有效减少用户升级带来的损失。很多用户进来看到的排序,除了他本身的个性化之外,还会被一些我们希望扶持的店,引导他希望关注的人群。
收益评估
当时我们设计了几个评估指标,分了人群,总要知道是否设置对。重要的指标是这个人群回来的时候,是否还是这个指标,也就是说分群的稳定性、流失率是怎样的,我们看这些指标在未来一段时间内趋于稳定的状态,就是两者之间的差距在逐渐减少。在几次模型的迭代之后,流失率在持续减少,最后,我们发现我们 APP 的大部分用户都可以分群了。在这种策略下,我们可以做到全局 gvm,c t r 在一些损失的情况下,让我们需要扶持的对象的流量涨 30%。
另外一种策略叫 explore 和 exploit,就是 EE,这个策略核心要解决的爆光bias,即你以前没看过或者没有买,不能说这个用户就是不买高价,那是因为你没有给他看高价商品。他把一个事情分 2 个阶段,一个是展示,试一试,另外一个是通过试的结果收割现在的收益。有几种比较常见的做法:一是把做AB的流量切入到一些小桶,让这些小桶通过EE的模式走策略,这样模型里就有很多EE的样本,是无偏的,进来之后会影响模型的整体迭代,这样你的生态会因为策略被改进;另外一种是把业务方定的新款,扶持新款的业务放到EE的流量上,让它快速迭代出哪些新品是真正有效的。EE 最直接策略就是随机,让每个商品展示 5 分钟,这就是随机的人群策略。用得很多的是 UCB,会根据每次展示的时间、收益、测速去算出下一次能展现的概率。
未来的话,现在我们已经在做了,但还没有结果。比如我们在深度学习和 CTR 预估和排序,还有就是强化学习和业务的结合,我们也会做更多尝试。比如说刚才的 EE 就是强化学习业务当中的一块,这一块阿里已经比我们走在前面了,我们会投入更多的精力做这方面的事情。
更多流量、广告、搜索、算法相关内容, 敬请关注“美丽联合数据技术”公众号
