在美团点评的联盟广告投放系统(DSP)中,广告从召回到曝光的过程需要经历粗排、精排和竞价及反作弊等阶段。其中精排是使用CTR预估模型进行排序,由于召回的候选集合较多,出于工程性能上的考虑,不能一次性在精排过程中完成候选集的全排序,因此在精排之前,需要对候选广告进行粗排,来过滤、筛选出相关性较高的广告集合,供精排使用。
本文首先会对美团点评的广告粗排机制进行概要介绍,之后会详细阐述基于用户、天气、关键词等场景特征的广告粗排策略。
广告粗排框架对引擎端召回的若干广告进行排序,并将排序的结果进行截断,截断后的候选集会被传递给广告精排模块处理。
粗排是为了尽可能在候选广告集合里找到与流量相关性较高的广告,一般以有效转化(通常包括点击后发生后续行为、电话、预约、购买等)为目标。流量因素通常包含媒体、用户(用户包含用户画像、历史搜索、历史点击等各类用户行为)因素。此外,还可包含流量外因素,如LBS、当前实时天气特征等。
考虑到不同流量所覆盖的特征不尽相同:如有的流量包含大量丰富的用户画像,而有的流量无用户画像,但有标识性较为明显的媒体特征,如P2P、母婴类媒体等,因此对于不同流量,会使用不同的粗排策略,以更好地应用流量特征。
下面将根据不同场景详细介绍各类粗排机制的离线模型,以及线上应用方案。
用户兴趣对于广告转化有着显著影响。在用户画像基础上,向不同兴趣的用户推荐不同类型的广告,对广告的点击和转化皆能带来较大提升。下面先对用户画像进行简要介绍,之后阐述我们是如何应用用户画像完成广告定向的。
用户画像
用户画像也称用户标签。美团点评的用户画像与用户的站内行为息息相关。用户的原始行为多为用户对店铺的浏览、点击、购买、点评、收藏等,用户画像主要是基于这些用户行为产出的统计型画像。除了原始行为,我们还整合了其他团队的数据,包含通过频繁集挖掘出的用户预估标签,以及一些产品上自定义标签等。此外,联盟广告独有的ADX数据源也被使用进来,ADX日均约数十亿次请求,涵盖了文学、金融、教育、母婴等各类媒体,我们将媒体带来的部分用户信息进行清洗,并整合到用户画像,从而提升用户画像的覆盖率和丰富性。融合以上所有数据源信息,我们产出了针对联盟广告的用户画像。
在策略应用的同时,考虑到产品投放,用户标签体系的设计采用了树状结构,以便于投放选择。
标签体系分为五大类:
- 与目前美团点评的商户分类体系强相关(因为广告主都来自于这些产品分类)的兴趣体系,如“美食/火锅”兴趣人群,“亲子/乐园”兴趣人群等。
- 自然属性,如用户的年龄、性别、常驻城市等。
- 社会属性,如职业、婚恋状态、受教育程度等。
- 心理认知,消费水平、时尚偏好等。
- 根据某些需求衍生的自定义标签,标签可以根据后续需求不断新增。
在工程方面,用户画像工程每日例行化运行一次,离线处理各数据源,并进行合并,产出设备ID粒度(IMEI或IDFA)的标准化用户标签。用户标签结果会从Hive表导入Redis缓存,以供线上加载使用。
离线建模
用户定向包含了两层含义:
- 策略应用,针对用户的不同兴趣,对召回的广告进行权重调整,以筛选出最适合用户的广告。
- 产品投放,广告精准定向,即某些广告只投放具有某些兴趣的人群,如幼儿教育的广告,只投放给家里有小孩的人群,以获取更好的投放效果。
本文所述的用户定向,仅指策略应用。
在用户定向上,我们使用了频繁集挖掘方案,因为用户标签与商户分类较为相似,直观上讲,规则的收益可能好于模型。使用频繁集方案,一方面可以挖掘出规则考虑不到的关联关系;另一方面,它的可解释性较强,且后期可以方便地进行人工干预。
我们抽取一段时间的用户点击历史数据,来挖掘用户兴趣与广告商户分类的关联关系。同时,考虑到转化(包含电话、预约、购买等种种行为)是一种强行为,我们将其等同于多次点击行为,进行升采样(如一次电话等于两次点击,等等)。之后使用Spark的ML库来进行频繁集挖掘。数据处理上,每条点击纪录会将广告商户的一级、二级、三级分类分别与用户标签关联,即一条记录会拆分成多份,分别使用不同级别的分类与用户标签关联,这样保证在计算频繁集的时候,各个层级分类都不会被遗漏。通过Spark的ML库找出大量频繁集后,剔除掉仅包含广告分类或仅包含用户标签的,仅保留两者共存集合。同时我们限制了用户标签在频繁项中的数量,使其不超过两个,以保证规则可以覆盖较多线上用户。接着,我们对标签与广告分类的关系进行打分,广告分类A与兴趣标签B的打分为:\(\frac{\sum(A \bigcap B)}{A}\)。
举例见下表:
“美食/火锅”更为大众化,因此访问量远大于“亲子/儿童乐园”,上列访问量虽为虚构,但与实际认知相符。上列表格想要说明的是,像“美食/火锅”这样的广告分类,可能与很多用户标签的共生次数都很高,但由于它本身是大众化的分类,因此分母取值也很大,则实际关联打分就会很小(除非是强相关兴趣)。用这种方式打分,可以筛选出指定标签下关联度较高的广告二级分类。
得到全部的频繁集及相应打分后,可线下进行人工筛选,剔除掉明显不符合认知的频繁项集。最终结果作为离线模型产出,写入MySQL。
检索端加载
检索端每天定时加载一次离线结果到内存中。对于实时广告请求,先从Redis读取当前用户设备的用户画像,然后根据用户实时位置等条件召回几百条广告后,对于当前流量中有用户画像的,根据离线训练结果,对广告进行打分及排序,排序后会根据线上的设置进行截断。用户定向的整体应用框架如下:
在业务引擎端,我们会进行A/B分流实验,随机划分一定百分比的流量作为实验流量,用于进行用户定向实验。之后,分析一段时间的累积实验结果,与base分流作对比,以检测用户定向策略带来的转化率提升,同时反馈给上游频繁集模型,用于干预调整离线产出模型。
实时天气情况对用户有一定影响。直观上来说,炎热的天气下,用户会更倾向于点击游泳馆的广告;而寒冷的天气下,飘着热气的星巴克广告会更受欢迎。有些广告行业则跟天气的关系不大,如非实时消费的结婚、摄影、亲子类广告。下面将介绍我们基于天气场景的离线模型及在线打分方案。
数据准备
天气基础数据包括温度、雨量、雪量、天气现象(大雨、雾霾等)、风力等级等。我们需要的天气数据,并不需要实时更新,原因如下:
① 从应用角度讲,由于天气情况在短时间内比较稳定,并不需要每时每刻都抓取天气数据; ② 第三方媒体对DSP(Demand-Side Platform)的响应时间有严格限制,如果每次广告请求都去请求天气数据,对广告引擎的性能将造成较大影响。因此我们以小时粒度来保存天气数据,即在确定的某个城市、某个小时内,天气情况是固定的。
天气数据包含两种: ① 线下模型使用的历史天气数据; ② 线上检索使用的当前天气数据。
两者在相同特征上的数据取值涵义要保证一致,即特征的一致性。美团配送团队对基础天气数据进行清洗和加工,每日提供未来72小时内的天气预报数据,同时保存了稳定的历史数据,与我们的需求完全吻合,因为我们使用了该数据。
离线建模
天气特征的离线模型选用了AdaBoost模型,该模型可使用若干简单的弱分类器训练出一个强大的分类器,且较少出现过拟合现象。考虑到要在线上检索端加载弱分类器进行计算,基础的弱分类器不能太过复杂(以免影响线上性能),基于以上考虑我们选用了AdaBoost常用的树桩模型(即深度为1的决策树)。
选定模型后,首先需要对原始数据进行处理,将其处理成适合决策树分类的特征。我们选定温度、湿度、降水量、降雪量、天气情况等特征。以温度举例,将其作为连续变量处理,对于特征为温度的决策树,训练合适的分割点,将温度归类到合适的叶子节点上;而对于天气情况icon-code,由于其仅有几个取值(正常、一般恶劣、非常恶劣等),因此当做离散值对待,进行one-hot编码,散列到有限的几个数值上(如1、2、3)。在树桩模型中,左右叶子节点分别对离散值进行排列组合(如左子树取1、3,右子树取2等),直到左右子树的均方误差值之和为最小。当然,对于离散值较多的情况,出于性能上考虑,多以连续值对待,并训练合适的分割点分离左右子树。
对特征进行处理后,可以应用模型对特征进行迭代处理。我们以转化为目标,搜集一段时间的历史点击数据,对数据进行特征化处理,最终训练出合适的离线模型。直观上来讲,天气对不同行业的转化影响有显著差异。某些行业对天气更为敏感,如餐饮、运动等,而有些行业则对天气不敏感,如亲子、结婚(因为转化一般不发生在当下)等,因此我们对不同的广告分类分别做训练,每个行业训练一个模型。考虑到在检索端需要对广告和天气的特征关系进行打分,因此分类模型不能完全满足我们的需求。最终我们选取了AdaBoost的改进版Gentle AdaBoost,有关该模型的论述网上有很多(根据文献1,在采用树桩模型时,该模型效果好于传统的离散AdaBoost),本文不再对其进行数学说明。算法大致流程如下图所示:
另外说明一下我们对该模型的一些工程处理,我们去掉了最后的感知器模型,直接使用回归函数的和作为打分。在每次迭代过程中,我们会保留当前错误率,当迭代达到一定次数,而错误率仍大于给定阈值时,则直接舍弃对该行业的训练,即在天气场景定向中,不对该行业的广告打分。
工程上,我们使用Spark进行特征处理和模型训练,并将最终结果写入在线缓存Tair中。其中key为一级及二级行业,value即为AdaBoost模型的多轮迭代结果,同时保留了最后一轮迭代的错误率。保留错误率的原因是在线上检索端加载模型时,可以动态配置错误率阈值,根据模型的错误率超过阈值与否来决定是否对广告打分。另外,考虑到线上加载迭代模型会牺牲性能,我们将迭代轮次控制在100次以内。
天气场景的离线数据和线上数据模型如下图所示:
经过Gentle AdaBoost训练出的多棵树模型,以JSON格式写入Tair中;线上在获取ADX请求后,根据Tair中已经写好的天气预报信息,加载当前小时当前城市的天气情况,检索端根据当前天气和模型,对广告进行打分和排序。
线上优化
广告检索端需要从Tair读取离线模型,来完成广告打分。由于第三方媒体对DSP响应时间要求较高,在线上做迭代模型的加载,是一个较为耗时的操作,因此需要做一些优化处理。我们一共做了三层优化处理:
模型缓存:对于检索端召回的几百条广告,对广告一级/二级分类进行缓存处理,对某条广告打分后,其对应的二级分类及相应模型加入缓存,而后续遇到来自同样二级行业的广告,将直接使用缓存模型。
打分缓存:由于我们使用了小时级的天气数据,因此对于指定的城市,在指定的小时内,天气状况完全一致,当广告一级/二级行业确定后,模型对于该广告的打分是确定的。因此我们对广告行业+城市的打分进行缓存处理,且每个整点清空一次缓存。对于已经打分过的城市+广告行业,可以直接从缓存中读取并使用打分结果。
性能与打分的折中:使用了前面两种缓存方案后,性能仍无法得到足够保证,此时我们需要考虑一个折中方案,牺牲一部分广告打分,以换取性能的提升。即我们使用动态配置的阈值来控制每次检索请求中模型迭代的轮次。举个例子,阈值设为200次,在整点时刻,前五个召回的广告的行业各不相同,且使用的模型分别迭代80、90、60、60、30次结束,则本次请求中我们只对前三个广告打分(80+90+60<200),并将广告打分进行缓存。后续召回广告,其二级分类若能命中缓存,则打分,否则不打分。在第二次广告请求过来时,同样沿用这个策略,对已经缓存的广告打分直接加载,否则迭代模型进行打分,直到达到迭代阈值200为止。通过打分缓存机制,可以保证前面牺牲掉的广告行业被逐步打分。使用该优化策略,可以完全确保上线后的性能,通过调整迭代轮次的阈值,控制打分与性能的折中关系。
通过以上三层优化处理机制,保证了AdaBoost这样的迭代模型可以在线上被加载使用。另外,我们还会考察离线模型中的错误率,通过线上动态调整阈值,舍弃一些错误率较高的模型,以达到效果的最优化。模型上线后,我们进行A/B testing,以检测使用天气场景模型带来的转化率提升。
用户在美团点评站内搜索的关键词,强烈地表达了用户的短期偏好。基于关键词定向(Query Targeting)是许多广告精准定向的利器。尤其对于闭环条件下的应用,如百度凤巢,淘宝的直通车,当用户在站内进行搜索,可以直接根据搜索词展示相关广告,引导用户在站内转化。一般来说,关键词定向的效果都非常出色。联盟的关键词定向,是通过对用户近期搜索词的分析,识别出用户感兴趣的店铺及店铺分类,进而在站外App为用户投放相关广告。下面将介绍联盟广告基于关键词特征的广告排序机制。
离线模型
离线模型需要根据用户搜索词分析出用户的偏好,对于大多数搜索引擎来说,需要使用NLP的相关技术和复杂的基础特征建设工作。对于美团点评的关键词搜索场景,由于大部分搜索词与美团点评店铺及店铺分类强相关(大部分搜索词甚至直接是店铺名称),且新词搜索量增长幅度不大,同时考虑到开发成本,我们的关键词定向舍弃了基础特征构建的方案,而是直接采用一套合理的离线分析模型,来构建搜索词和店铺分类的关系。
我们选用了TF/IDF模型,来构建关键词和用户偏好的关系。用这个方案原因是文章-词模型与词-店铺模型非常相似。该方案主要用于计算店铺分类(或商圈)与关键词的相关程度,也是对其打分的依据。该模型相关资料很多,不再做原理性阐述,此处仅举一例如下:
用户搜索词为“潮汕火锅”,计算“美食/火锅”的商家分类与该关键词的相似程度。
假设: c1 = 搜索“潮汕火锅”后的全部点击数, c2 = 搜索“潮汕火锅”后点击“美食/火锅”类目店铺的全部点击数, c3 = 搜索词总数, c4 = 搜索点击“美食/火锅”类目的词总数。则 $$tfidf = (c2 / c1) × log(c3 / (c4 + 1))$$由此计算出店铺分类与关键词的关系,取topN(根据存储大小及不同店铺对同一词的TF-IDF差距拟定)个店铺分类。
单店及商圈计算方法与此类似,它们的计算值会同时与店铺分类的TF-IDF进行比较,不作区分。(此处有一点需注意:如果用户搜索“中山公园 火锅”,可以预见店铺分类与商圈会同等重要,则最终产出两条独立打分规则,分别挂在店铺分类和商圈下面)。
我们使用Spark来构建离线模型,提取用户的搜索词和搜索后点击的店铺及店铺分类,运用上述方案来计算每个搜索词的关联店铺及店铺分类,设置阈值,保留分数较大的分类结果。
为了提升线上命中率,我们使用了点评分词系统,对长度较长的搜索词进行分词,同时保存原始词和切分后基础词的TF-IDF结果。为了方便线上快速检索,结果同样保存在Tair中。以检索词为key,关联店铺分类和店铺的TF-IDF打分作为value进行保存。
实时流计算
对于关键词定向,与用户定向的一个区别在于前者时效性要求很高,因此需要使用实时计算系统来处理用户行为,并将最后的结果保存在Tair集群。首先通过Kafka订阅用户行为实时流,以五分钟为时间片处理用户行为,查找用户ID和搜索词,如果搜索词过长,则进行分词,接着从Tair中查找出与该搜索词相关的店铺及店铺分类和打分(离线模型给出)。接下来会Tair中查找该用户ID是否有历史结果,若有,则读出,对之前的打分进行衰减(衰减方案见下文),并与当前新的打分进行合并;否则,将新的数据及时间戳写入Tair。该方案的流程图如下:
比较重要的部分是合并新来的数据与Tair里的老数据,合并时,如果新数据包含老数据中某些店铺(店铺分类),就直接使用新数据中的店铺(店铺分类)权重;否则,对老数据中的店铺(店铺分类)权重进行衰减,若衰减后权重小于给定的阈值,则直接将这个店铺(店铺分类)从合并数据中剔除。
衰减方案根据时间进行衰减。默认半衰期(即衰减权重从1衰减到0.5的时间长度)为72小时(不同的店铺分类给予不同的半衰期),使用牛顿冷却定律,参数计算公式为: 0.5 = 1 × e-α*时间间隔 ,解出α,并带入下面公式得到实际权重为:$$ w’ = w × e ^{-\alpha × 时间间隔} $$ 其中,w为老权重,w’为新权重。
检索端排序
检索端接收到广告请求,根据当前获取的用户ID,从Tair中读取用户偏好的店铺分类,与召回的广告进行匹配,当广告分类与召回广告匹配成功,则可将Tair读出的分数进行时间衰减后,作为该广告的最终打分。检索端采用与实时流同样的时间衰减方案,以保证一致性。举例如下:
用户A在早上8:30有火锅类搜索行为,Spark Streaming处理后进入Redis,假设此时最新时间戳为8:30,而该用户在11:00搜索亲子类商铺,Spark Streaming处理该条记录后,之前的火锅权重需要衰减,同时时间戳更新为11:00,假设此时立即有广告检索请求命中该用户,则此时用户火锅类偏好权重为11:00时权重;假设下午16:00有ADX请求命中该用户,则用户火锅类权重需要根据16:00到11:00的时间间隔继续衰减。
除了上述三种定向策略,还有其他基于上下文的定向,重定向等,它们方案各异,但大致思路与前述方案类似,本文不再详述。
在经过上述各类定向场景分别打分之后,需要对每个场景打分进行综合,因为不同的广告行业在不同场景下的重要性是不同的。如餐饮行业更注重距离和天气,而丽人、亲子等行业较注重媒体和用户画像。因此,不同行业下,各个定向打分的权重是不同的。我们使用模型的方式对各个场景打分进行权重的训练和预测。
综合打分我们采用了LR模型,分不同广告行业,以点击为样本,转化为模型,以各个场景下的前期打分为特征,进行混合打分权重的离线建模。 公式如下:$$h_\theta=g(\theta^{T})=\frac{1}{1+e^{-\theta^{T}x}}$$
其中θ是向量,θ0x0 + θ1x1 + …, + θnxn = \(\sum_{i=0}^n \theta _ix _i={\theta}^Tx\),其中,\(x _1\),…,\(x _n\)是各个场景定向下的具体打分,打分分布在[0,1]之间。
冷启动时,对每个场景打分给予一个默认权重,积累一定量数据后,使用离线模型训练出各个广告行业下的θ向量,并在引擎端加载使用。引擎端加载各个场景的广告打分,并根据广告行业加载打分权重,最终完成每个广告与当前的流量综合打分。
场景化定向综合考虑了当前流量的种种场景因素(用户、天气、媒体等),分别根据业务需求设计了不同的模型来构建广告打分机制,并对单个场景的广告打分进行综合。通过这种场景化的广告粗排机制,对召回的广告进行排序和筛选,可以保留相关性较强的广告,以用于后续的CTR排序和处理。从实际的A/B testing来看,使用了场景化排序机制的流量,其点击率和转化率的提升效果都较为显著。
展望未来,如何丰富各类场景特征(如天气、媒体的更多特征),引入更多的场景因素(如所处环境周边店铺、当前时间用户行为等),尝试不同的模型方案,都是下一步的可探索方向。
- Friedman J, Hastie T, Tibshirani R.(2000), Additive Logistic Regression: A Statistical View of Boosting, Annals of Statistics, 28, 337-307.
美团点评广告联盟团队招聘各类数据挖掘、算法,以及Java后台开发的技术人才,有兴趣的同学可以发送简历到suxin03#meituan.com。
马莹,美团点评高级算法工程师,2012年毕业于浙江大学,同年加入百度联盟研发部。2016年加入美团点评联盟广告部门,长期从事广告行业策略算法研究开发工作。专注于计算广告、用户画像、数据挖掘等方向。
一凡,美团点评高级算法工程师,现负责美团点评广告平台联盟广告网盟方向。2011年毕业于华中科技大学,毕业后先后就职于百度、腾讯,2014年加入点评平台,2016年加入美团点评联盟广告部,长期致力于计算广告算法优化、推荐算法、大数据挖掘等方向。
如发现文章有错误、对内容有疑问,都可以关注美团技术团队微信公众号(meituantech),在后台给我们留言。
分享一线技术实践,沉淀成长学习经验