爱奇艺品牌广告算法探索和实践

5,804 阅读29分钟

【i技术会】2020.03.11 《常用视频广告算法经验谈》分享会

爱奇艺的核心商业模式是优质视频内容+付费会员服务,在此之下是在线广告。 作为一家视频服务网站,其实除了我们主APP以外,爱奇艺还有很多别的APP,比如说爱奇艺体育、奇秀直播、爱奇艺文学等,这些APP也丰富了爱奇艺的变现手段。在爱奇艺2019年Q3的财报中,除了会员和广告以外,其它收入的占比现在也很高,目前在线广告是爱奇艺的第二大收入来源,Q2的收入大概是21亿元。

在国内大家一般会把广告分为品牌广告、效果广告两大类,通俗来讲,品牌广告的特点主要是追求曝光,注重品牌的长期价值,而效果广告更多注重短期的效果转化,直接刺激用户的消费行为。

在上图中,左边是看视频前出了一个明星代言某护肤品的广告,这就是一个比较典型的品牌广告。右边是一个信息流广告,这些广告的标语往往具有很强的诱导性,诱使大家去点击下载、安装,甚至付费,这些广告一般都是效果广告。

首先从视频内容角度出发,品牌广告往往比较热衷于一些头部的内容,比如说热门综艺大剧、电视剧等等,这些内容往往会覆盖更多用户,品牌广告主往往在这些内容上也会赋予比较高的溢价。效果广告更看重吸引用户,所以在一些中长尾的内容上,比如网络大电影、UGC的内容,出现效果广告的比例可能会更高。 从广告位的角度来说,因为品牌广告注重强曝光,所以在前贴片、开屏广告位上,品牌广告的占比会更多一些,这些广告位上用户的观感会比较强;在一些互动性比较强的广告位,比如说信息流、焦点图,这些广告位因为用户经常会刷新拖拽,所以点击率会相对高一点,所以效果广告的占比会更多一些。

品牌广告的核心目标是广告主希望在用户心里树立起一个品牌形象,主要有以下几个特点:快速接触大量用户、宣传品牌形象、提升中长期购买力和利润空间、排除完全不可能的人。一般来说,视频平台在和广告主签订品牌广告时,会约定广告的声量,因此品牌广告算法核心的一个优化目标就是保量。

整个品牌广告的业务流程大致可分为售前和执行两大阶段,售前也是广告主确定广告购买意向的过程。举个例子,比如说某奶粉品牌,希望将它的广告投放到未来2个月的视频前贴片广告位,覆盖北上广深观看母婴频道的女性。广告主会向爱奇艺发起询量,爱奇艺会反馈在定向条件下的最大可用库存,比如说是20万CPM;那么广告主会根据自己的预算和需求、销售沟通,最终广告主确定需要预定10万CPM的量,那么他们就进行排期、下单、审批,最后成为正式的广告合约订单。

执行阶段也就是订单的投放期,这个广告就是以10万CPM的保底量在整个投放期内进行投放。当然为了保证广告的效果可以触达更多人群,会把它预定量分配到两个月的每一天,然后每一天都会把当天未播放完的量累积到下一天。当两个月的投放期结束后,我们会和广告主进行最终的结算。

在这两个阶段里面,算法也提供了很多基础的服务支持。比如说在售前阶段我们主要是售前平台来提供询锁量的服务,通过算法保证在订单的定向条件下,预定量和价格的合理性,避免双方因违约造成损失。

另外,在执行阶段,我们会对投放效果进行优化,最核心的是库存分配,其次针对不同广告主的需求,包括广告位、广告产品的一些特点,也有一些其它的优化服务,目的是为了提升整个广告系统的投放效果,保证广告主和用户的利益。在此之外,还有一些基础的服务。比如库存预估服务就提供了很多基础数据的预估,供其它服务使用。

本次【i技术会】主要分享:常规库存预估、售前询锁量平台、在线库存分配和AI创可贴动态点位。

常规库存预估

这里的库存是指广告库存,即平台可以为广告主提供的一个有效广告曝光的机会。库存预估,其实就是要预估未来多天各个广告位在一个多维度交叉下的库存数据,库存预估是品牌广告非常重要的一个部分,因为品牌广告的售卖特点,决定了整个订单的售卖和预定周期会非常长,每天预定的订单数量、每个订单的排期也不一样。 为了更好的去给广告主提供一个询量服务,包括线上投放的一个优化,我们准确的预估库存对我们整个服务的效果是有着很大的基础保证。

库存预估是一个典型的时序问题,时序语库模型在早期主要也是一些简单的统计模型,比如说:移动平均法、指数平滑法。慢慢的演变出了一些更复杂统计模型,比如说经典的ARIMA模型以及状态空间模型,ARIMA模型也是一个经典的状态空间模型,偶尔一些场合下,也会用来做时序预估。

那么,在2017年AlphaGo火了一把之后,深度学习就成为了一个热门话题,也有越来越多人把深度模型应用到持续预估上面去。比如说, DeepAR、MQ-R(C)NN、ST-RESNET核心都是通过深度学习的方法来解决时序预估。这些文章大部分都是在2017年下半年或者2018年发表,感兴趣的朋友可以去查阅。

爱奇艺在库存预估上最早采用的也是ARIMA模型,确切的说应该是Seasonal-ARIMA,就是在ARIMA的基础上加入了一个周期项,好处是模型落地非常快,但是我们发现一个问题,可以看到ARIMA模型的准确性不错,但是它的鲁棒性相对比较差,也是因为这个原因我们对ARIMA模型做优化,可以把优化后的叫Adaptive-ARIMA,核心就是在原有ARIMA的基础上加入了节假日的因子作为一个外部的解释变量。同时在数据预处理方面,如异常值的处理、数据的截断等上做了很多优化工作,让整个模型的鲁棒性得到了非常大的提升。

2018年的时候,我们开始着手用深度的方法解决时序预估问题,最早想到的就是用LSTM这种循环网络的模型进行预估,但是实际在操作过程中,我们发现一个比较严峻的问题,之前提到的几篇文章虽然也是做流量预估的,但是他们的最小粒度往往是分钟或者是10分钟这样一个级别;但是在品牌广告这个场景下,最小粒度是天,而且前几年整个视频行业的发展会非常快,要来做预估的话只能用近期数据,因此这样导致我的数据量相对比较少,样本量会相对比较少。另外一个问题是我们提供给广告主的定向条件非常多,如果我在每个维度下多维度交叉,都展开用深度的方式去预估的话,资源也是一个很大的问题。

为了解决刚刚提到的资源和样本不足问题,我们提出了一种基于层次聚类的LSTM预估模型,用了这个深度模型以后,模型的准确率和鲁棒性都得到比较大的提升。

层次聚类的LSTM预估模型,是给各个维度的库存定义了一个相似性,根据历史库存的波动和趋势,把这些波动和趋势和相近的一个维度聚合成一类,每一个聚类下共同训练一组参数,这样的话我们同时可以解决样本和资源问题。每个聚类因为有很多维度下的数据,它的样本量可以得到一个解决;同时,同一种聚类只训练一组参数的话,对整个资源的消耗也是比较大的节约,可以看到整个聚类以后,每个聚类里面库存的历史其实是相对比较接近的。另外在此基础上,我们做了一些其它的优化,节假日方面也做了优化。

售前询锁量平台

一个品牌广告订单从售开始,直到最后成为一个正式的线上单,其实整个流程非常长,首先是广告主会和销售沟通意向,销售和销售运营又会在询量下单上进行沟通,最终和广告主确认最终意向以后,媒介会帮助预定和下单,一个预订单还需要审核团队的审核,最后才能成为一个正式单,成为正式单以后,由执行来上传素材,最后才会变成大家看到的这样一个广告。

大概整个流程中,对应的各个模块都有服务的系统,在这些系统里面算法也起了很多的作用,我们把它统一称为询锁量服务,比如说一开始有销售跟销售运营要沟通询量,会通过一个询量的平台,然后请求算法的询量服务,告诉广告主,你这样一个定向条件下,有多少的库存可以使用,可以给你进行一个预定。

当最终意向确定以后下单的时候,需要有个预定的操作,我们会反馈预定条件能不能满足,有多大的缺量风险,缺量风险是否能接受,通过确认以后才能变成一个正式的预定单。这里之所以预定和询量都要去请求的一个原因,在于询量的时间往往会提前比较久,询量到预定之间可能会有一个时间差,在这个过程中我们整个系统下单的预定情况,包括我们库存预估的结果都可能发生波动,所以在预定的时候又需要额外去请求。

当订单预定成功以后资源就会被这个订单给锁定,后续再有询量这份资源会被扣掉。当前我们整个流程中预定到审批的时间相对会比较短,因此整个库存的变化或者整个系统里面预定的一个变化相对比较小,后续也会考虑加入量审,针对一些预定到审批间隔比较长的一个订单,需要加进一步的一个审核。

在爱奇艺平台上,售卖的广告位、广告产品其实是非常多的,包括提到各种系统也非常多,为了更好的支持这些系统也对服务框架做了一些设置。首先是为了降低各个系统的对接成本,爱奇艺提供了一个统一API,无论是询量、预定、审核等平台,都可以通过统一的API进行接入,有专门的BrokerServer来去接收各个前端系统发来的请求,然后根据请求类型以及广告位、广告产品的信息分发到各个子服务,最后Broker汇总子服务的反馈结果给前端。

针对各个子服务的一个模型大概的框架是右边这样的,首先在数据方面,我们会有一个实时数据和离线数据,实时数据主要是实时去更新整个系统里面的售卖率,包括预定扣减的情况。离线数据有各种,比如说库存预估,一些基础的数据统计,包括一些模型的训练。

在线上针对不同的广告产品也会有不同的模型,包括像实时分配、算法模型、统计模型等等。目前绝大部分广告位新广告产品的介入,都可以通过配置方法,通过上述的几种模型来快速支持。

这里介绍一下常规贴片,也就是常规前贴片,前贴片是整个爱奇艺乃至长视频行业中最重要的一个广告资源位。

前贴片的订单非常多,可以提供给广告主的定向也非常多,为此针对这个前贴片广告的询量我们采用和其它竞品不太一样的方式。我们目前是通过一个回归模型的方式来进行询量,相当于是考虑了广告位未来可能的一个售卖情况,而不是针对当时询量时刻返回一个最大可用库存。

这样的好处是我们可以保证整个前贴片广告售卖的稳定性,包括订单的多样性,从而更好的利用用户的一个频次数据。目前我们采用的回归模型主要是FM,并且在此基础上我们又加入了非负参数学习、无Bias学习、代价敏感学习等,主要是为了使最后的结果更符合业务场景。其实,在这基础上,我们还做了包括标深的一个GroundTruth的校准和生成,在这个常规询量的回归模型里面,这也是个非常重要的问题。

这是一个最原始的FM模型训练后得到的结果。可以看到这个模型的阶段会非常大,并且一些参数会出现为负的情况。Bias太大带来一个问题,就是询问以后量结果相对会比较稳定,广告主加紧一些定向,会发现它的询量结果没有发生太大的波动,参数为负的一个影响可能就更大一点了,因为广告主会频繁到询量市场里面来改定向条件,比如说广告主发现他原先定向返回的量,并不能满足他的购买需求他可能会新增一些定向。

但是,如果出现参数为负的情况,可能出现就是广告主新增定向来询量以后返回给他的库存更少了,这显然符合大家的一个认知,会让广告主对询量的结果产生质疑。为了解决这个问题,我们采用了无Bias学习和非负参数学习,首先就是把Bias项给去掉了,并且在整个FM参数迭代过程中,加入了参数非负的限制。通过这两个优化以后,整个模型的询量自洽性相对会变的更好一些。

从售卖角度出发,我们假设整个模型的偏差是固定的情况下,显然少卖的损失会比超卖损失更大一点,超卖我们可以通过补量实收的方式来进行一个赔偿,但少卖的话直接收入就少了。所以,为了解决这个问题,我们加入了一个代价敏感学习,使得预估偏少的样本权重会变的更大,损失会变的更大一些。

同时因为我们整个系统,在之前的整个询量流程是一个人工的过程,为了保证人工到系统切换更平滑,也是有必要加入这样一个功能。在这些优化以后,我们算法的询量相比之前员工那个询量差异在一个可接受的范围内,准确性获得了进一步的提高,因此我们现在整个询量的系统,也从以前人工的方式,变成了一个系统询量。

在线库存分配 首先库存分配是品牌广告算法最核心的一个模块之一。更好的库存分配算法,对完成之前我们提到品牌广告的核心优化目标保量是有非常大的帮助。

举个简单的例子,假设现在系统里面有两个订单,订单一是购买电视剧频道,预定量是400CPM,订单二购买了北京维度,然后预定量是800CPM。在库存方面,北京电视剧、北京综艺、上海电视剧、上海综艺各有400CPM的库存。

假设订单一的优先级是高于订单二的,比如说我们订单一在投放的过程按照上海电视剧均匀的去投放,各占200CPM。此时订单二在北京这个维度下,就只能获得600CPM的一个库存了,就会造成200CPM的缺量。

实际上品牌广告是一个提前售卖的过程,但在投放当天实际上我是可以提前知道北京电视剧这个维度它的库存是相对比较紧缺的,在投放的时候,虽然订单一的优先级更高,但是我可以把它全部投放到上海电视剧,这样订单二在北京维度就能获得800CPM的一个库存,这样整个系统就没有缺量了。因此怎么样去优化我们整个系统的库存分配,对完成保量这个目标是非常有帮助的。

整个库存分配的问题,可以这么来定义,首先我们的流量属性会非常多,常见的平台、城市、内容,还有一些比如说性别、年龄、站点等等,每个属性组合下都会形成一个流量单元,每个流量单元下都有一定的库存。

同样我们系统里面也会非常多的订单,订单有它的定向,只有当我们这个流量和订单的定向相匹配的时候,这个订单才有可能在这一次广告请求下或者说这个流量下进行曝光,这样就形成了库存和订单多对多的二分图,每个连线上都有一个需要我们去分配的量,就是代表这个流量单元下,我要把多少库存分配给这个订单。

这样一个问题,我们可以形式化的定义成右边这样一个优化问题,整个优化目标希望系统的一个缺量是最少的。下面有一些约束条件,包括供给端的约束、库存端的一些约束。

这样的问题,因为整个xij数量是非常多的,因为它要展开的情况可能接近于这样一个量级,这是一个显性的NP难的问题,然后关于这样的问题一些求解,也有一些比较现成的方法。比如说,比较经典的Shale算法,研究这块的朋友可以参考这个论文。

因为库存分配其实是全局优化问题,针对这样的全局优化问题我们怎么来进行A/B实验呢?首先我们通过UID哈希分桶的方式做一个线上流量切分,好处是保证流量相对比较均匀,并且有用户之间的频次,频次后面会有详细介绍,频次是互不干扰的。

其次我们会把订单的排期量,包括它的一些分桶控制,以及广告位下库存的实时消耗和校准,都进行一个分桶的切分,在算法侧会把各个桶的库存按照比例放大到百分百,相当于把原先的一个广告位变成多个;假设现在线上有三个分桶,相当于我们把原先管个广告位下的一个流量和订单变成了三份,这三份是互相独立不影响的,并且每一份的库存端供给和订单侧的需求都是一模一样的,唯一影响它的投放效果的就是库存分类算法,这样就变成了一个单因子的变量实验,可以用来验证分配算法的优化效果。

目前我们着力在解决得是精准定向和频次控制这两个问题,希望能和大家一起交流。

首先是精准定向,我们广告主的定向非常多,常规的比如说有一些城市的、频道的、平台的一些定向,这些定向是广告主会频繁定向的一些维度,我们把它称为常规定向。

在此基础上,我们会开放很多精准定向给到广告主,比如说性别、年龄的一些定向,包括视频Tag、人群包之类的一些定向,这些定向有一个特点,就是广告主这些定向的订单相对会比较稀疏,并且各个维度之间可能存在交集。

按照刚刚我定义的那个问题,如果我要去做这样一个分配问题,最直接的方法是把所有的维度进行一个展开,因为整个可提供的定向非常多,完全展开以后,库存端的维度数量会变得非常大,这样一个问题,我们整个线上求解是没法进行的。

其次是这里还有一个比较麻烦的点,就是像人群包这样的属性,不同定向之间是有交集的,比如在我们平台上的一个用户,他可能是黄晓明的粉丝,也可能是一个古装剧的粉丝,对于任何一个人群包来说,这个用户都有属于和不属于两种状态,要穷举人群包这样一个属性,把它变成互不相交的流量单元的话,我们N个人群包就有2^N种组合,线上配图的人群包可能每天都会有上百个,这样一个维度展开是完全无法估量的,所以我们无法通过这样的一种简单方式来实现。

另外品牌广告比较重要的问题就是频次问题,所谓的频次问题就是广告主会限制每个用户在一个周期内观看这个广告的次数,频次问题对整个分配的影响非常大。

举个例子,假设我们现在系统里有ABC三个用户,这三个用户在一段周期内分别提供了一个库存、两个库存、七个库存,假设一个订单没有频次的约束,这10个库存对他来说都是可用的,但是假设广告主在这个订单上加了一个限制条件,比如说周期内频控一次,ABC三个用户个只能提供一个库存给这个订单使用,所以在频次控一次的情况下,这个订单可用库存就变成了3,同样在频控两次的情况下,这个订单可用库存变成了5。

因此,不同的频控条件下,即使这两个订单定向流量属性一样,它的可用库存差别也会非常大,因此频控对整个分配的影响会非常大。

首先关于精准定向这一块的话,我们通过一个分层的库存模型方式来解决,我们会按核心维度构建基本的流量单元,这里主要是平台、地域和频道,在此基础下,每个细分的核心维度下,都会维护各自的长尾定向库存结构,包括性别、年龄等等,它们之间是彼此互不干扰的。

整个订单的扣减实际上是有顺序的,当我们扣减的订单没有长尾定向时,我只需要在我的核心定向下进行一个扣减,只有当分配到有长尾定向的订单时,我才会把核心定向的扣减延迟扣减到下面各个长尾定向,比如我现在扣减过程中出现了定向难的单子,我会计算这个订单的库存,会把之前没有任何长尾定向的订单在核心维度上扣减的比例,按照均匀的方式扣减到男女和未知性别用户上,在此基础上我再去计算当前男性用户还有多少库存。

因为长尾定向之前也介绍了,定向他们的订单相对比较少,绝大部分订单我在扣减的时候,只需要考虑核心的定向维度,整个扣减的复杂度相对会变得比较低。

另外像人群包这样的定向,我只维护各个定向各自的库存结构,并不考虑彼此的交级,如果有同时定向的情况下,我们暂时的处理方法是按照正交的方式来处理的,当然这样一个扣减方式,从精准度来说,比相对完全展开有一定的损失,但是从计算效率、资源来说,得到了非常大的节约,并且针对这些有长尾定向的订单,彼此直接忽略这个定向的话,效果还是得到了很大的提高。

并且整个扣减过程也很简单,因为对于有长尾定向的订单而言,我只需要记录它在每个核心维度下的可用占比,我这里标注为fij,我可以过xij尖等于xij×fij的方式来进行替换,替换以后,整个算法的求解过程并没有受到任何影响,只会在最后引擎在线上代理选单时做一个调节,因为引擎天然在侯选订单筛选的时候,已经做了一个流量的筛分,所以对订单而言,在这个维度下可用库存已经变成了si×fij,整个求解和最后的选单过程的嵌入是相对比较顺利的,整个投放我们之前也验证了,对线上有较大效果的提升。

关于频次的问题,频次对订单可能库存影响非常大,还是刚才那个例子,订单一周频控一次,是三个库存,一周频控两次,是五个库存,但是其实这里的一个假设条件都是说这个系统里面可能只有一个订单,当系统里面有多个订单的时候,这个问题会变得更复杂。

比如系统里面已知订单1频控一次,并且把可以占的库存全占掉了,比如ABC都占了一个库存,此时订单虽然周期频控还是两次,但是它的可用库存就会变成了3个,而不是之前的5个。 当这个系统里面订单非常多、用户非常多的时候这个关系会非常复杂,并且怎么样更好的在用户上进行投放也是很重要的问题,假设刚刚那个频控一次的订单需求量是1,这个订单当展示在用户A或者B的时候,都会导致订单2的可用库存变成了4个,只有当它投放在用户C上面的时候,才会让订单2的可用库存还是5个,这样的话对订单2而言的话,它的可用库存会变得更多。

因此怎么去优化这个频次问题对整个线上效果投放影响会非常大,我们先不考虑整个系统里面所有订单互相挤占的因素,去计算出来一个fij撇表示这个频控下的可用库存,我们在计算订单扣减顺序时,会把fij撇的约束考虑进去,相同定向下,这个fij撇越小,那么它会越优先进行一个扣减。

其次,就是在整个分配的计算过程中,对它的分配概率做了一个fij撇了一个约束,后面的fij,其实就是刚才提到的一个长尾定向,求解是一样的。再通过这样的方式,对整个频次有频控订单的投放效果,也是得到了很大效果上的提升。

AI创可贴的动态点位

首先所谓的AI创可贴是通过AI技术来识别视频中的台词、明星、场景等内容,然后给各个视频时间节点打上各个标签,然后广告通过定向相关的一些标签来进行投放,使得整个广告投放更符合视频内容。

上图中,当视频中出现买单这个词的时候,我们同时展现了一个支付宝的广告,可以看到整个广告的展示跟视频内容相对是比较契合的。右边是一个点位的示意图,可以看到这一帧的画面上,其实我们可以打出非常多的点位,包括有一些场景的点位、明星的点位、表情、台词等等,每一帧都可以打上那么多标签的情况下,怎么来选择合适的点位来进行广告投放呢?

我们把这个解决方法称为两阶段的一个动态点位模型,首先视频的点位是通过抽取一些关键帧,通过图像相关的一些深度模型打上各种各样的点位。这些点位存入到HBase,里面会有点位的各种信息。算法侧会有一个定时的预分配任务,预分配任务主要是根据各种业务规则对AI里面同步过来的所有点位进行一次预筛选,业务规格会非常多,包括说两次广告展现不能超过1分钟,相同的一个点位在同一个视频内不能曝光多次,包括前2分钟之内不能出广告等等。

在这些业务规格基础上,还会考虑标签整个商业价值、潜在的库存,以及它的历史售卖率情况,使得预分配以后,保留的点位,广告点位的一个整体商业价值是最大化。把这个预分配以后的结果会同步到一个实时分配的服务,实时服务主要是有两块: 1、跟投放相关的。它的一个优化目标是使得整体的缺量最小化。 2、跟询锁量相关的。我们是要一个优化目标使整个询量结果最大。

因为实时分配不管是引擎投放还是询锁量,对整个系统的响应时间都有比较大的要求,因此我们如果每次都对全量数据做实时分配,显然这个效率上是不能满足的,所以就有了预分配这一步,目前我们整个预分配会有每天全量,后面会有个增量更新逻辑。全量,一般需要2-3个小时,增量大概是30-40分钟。

刚才提到了预分配需要考虑的一个重要因素,就是标签价值,然后标签价值是通过下图中的公式来定义的。存量一次可能要2-3个小时,每一天都要这么去分配时间上是没法接受的,所以我们并没有针对每一天预定情况去进行优化。目前是对每一个视频做一个顺序的预分配,然后目标是使得保存下来标签点位的标签价值最大化。

具体的一个流程,首先会把所有点位做一个随机的排序,然后通过动态规划或者贪心算法使得最后保留的点位价值是最大的,并且我所有的点位可以任意的去预定和投放,并不会触发任何业务规则的约束。

在此基础上,把每个标签每个视频预处理完以后的点位给到一个实时分配,整个实时分配系统跟之前的库存分配类似也是定义了一个优化目标,整体优化目标使得分配点位商业价值是最小的,这样可以保证剩余的那些未分配的视频它的商业价值更大,这样从售卖角度,可以更好的去进行后续的售卖。

为了使所有的标签都具备售卖的价值,防止在后续询量过程中某些标签广告主想买,但是因为它的整体历史售卖率、商业价值比较低的原因,导致我们可以报给广告主的库存较少,所以每分配完一部分视频以后会更新这个标签价值,对于那些被分配保留下来点位比较少的标签会提高它的权重。