RTB撕开黑盒子 Part 0:Pacing: is everyone doing it wrong?
曾尝试为我们的RTB客户解决过Pacing问题,Pacing问题要解决的问题是:如果一个客户给你一笔预算,让你去运营一个广告推广计划,在一定的时间内投放广告,将这笔预算在指内的时间内,比较均匀地将预算消耗完。如果把预算消耗超出了,那就要自己贴钱了。如果没消耗完,这对于下次和客户合作的时候会有点丢脸。并且如果你不是均匀地进行消耗,你会发现自己面对着一堆愤怒的客户。比如几分钟就烧完客户50美元的预算。听起来很显然,是吧?但这问题比听起来要困难的多。
Doing it wrong
当Datacratic第一次将头伸进RTB时,控制预算消耗的主要工具就是一个日限额。我们用了48个小时才发现下面的方法是不可行的:我们设置了几种类型的过滤来决定何时对所有请求进行竞价。但结果是或是我们没有消耗完日预算,或是很快就烧完了预算,通常是后者。在实践中,我们是从0点开始购买展示,并在早晨晚些时候消耗完。
在日限额达到后就不再竞价
如果客户要求投放的时间是30-60天,采用上述的投放方式,看起来似乎还不算太糟:因为是按要求的时间将预算消耗完,并且每天消耗相同的金额。但我们有一点很不开心的是,每天有一大段时间我们是没有进行任何竞价的。于是我们加了一个小特性,对X%的流量进行竞价,当这个特性发布后,我们发现结果中有个非常有意思的现象:我们以前所购买的流量,实际上是一天之中最贵的流量!下图是一个流量较多的推方计划的平均胜出价格,它有一个很明显的规律:如果是从中午开始购买流量,CPM的价格是逐渐下降的,一直到午夜突然陡升近40%,CPM随后有些波动,然后在早晨下降后又上升,到中午达到峰值。然后又是一天新的循环开始。
可以看到每天午夜都会有价格的陡升
那么为什么会有午夜的这种价格陡升呢?按理说这应该是个充分竞争的市场,但午夜后的1分钟的流量真比2分钟前的流量多值40%吗?我们也没彻底搞清这个问题!我们当前的猜测是:竞争环境中一定有很多的DSP和我们刚开始一样:每天设置一个日限额,并在午夜重置日限额。这就意味着在午夜时对流量有很大的需求,因为如此,价格一下被抬高(也可能是其中一个DSP重置日限额后,它的出价比之前出价最高的DSP还高,使得这个小的流量价格陡升)。并且因为DSPs有着不同的日限额和流量控制策略,所以它们是在一天中不同的时间点消耗完的,这样就使得需求下降,进一步引起价格下降。从上图有一个规律不明显,但将多天的效果叠加,就得到了下图,可以看出在3点钟还有一个类似的陡升,3点钟是西海岸的午夜。
八月聚合平均后的每分钟的胜出价格
现在对于这种陡升也有一些其它的可能解释。可能是我们处在东北方这个位置,所以我们这个地区的请求流的组成有变化,所以这或许仅仅是一个地区的规律?尽管3点钟的陡升的现象让这种解释听不来不太可靠。午夜也恰好是我们开始竞价的时候,但我们的量是逐量的,并且我们的量不足以说明这种陡升。也可能是一些大的站点在午夜有一些最低出价的限制。或是其它DSPs很聪明地发现了午夜之后的点击率比午夜前几分钟高很多。我对这些解释充满了怀疑,读到我这篇文章的任何人有什么想法,我非常欢迎来与我讨论。但不管是什么原因,下面的结论都可能是成立的:如果你只想在一天中的几小时内投放广告,不要选择凌晨开始投放,10AM结束。
译注:不知道国内的DSP开发有没有做这个数据分析,我分析出来的结果和Datacratic的不太一样,但我现在还在爆流量的阶段,可能统计的量上不太够,但还是有些规律的。有机会大家一些讨论一下。
Closed-Loop Control to Rescue
我们先假设这一篇文章,在RTB圈子里引起了极大的关注,而这种凌晨的价格陡升现象消失了,或是你也许只想将预算均匀地在每天消耗,如何去做呢?上面提到过,我们可以每天对X%比例的流量进行竞价。最简单的办法就是,将日限额除以不加限制的每日消耗,得到竞价比例,这原则上能在凌晨消耗完日限额。但在实践中,只对固定比例的流量竞价,每天的曝光量会差异非常大,有时候会超出预算消耗(如果你没设置日限额)有时候会消耗不完预算。也许某些天你会得到一个变化量非常大的请求量,也许是因为你上流的SSP在做修改。(译注:如果你的请求量在在9点后是一条直线,这是因为google的QPS限制,这个可以让google的support team的人支持一下,这个曾经搞的我很困惑为什么请求量这么均匀)。也许SSP出了故障。而且竞价流量会有很大的变化,比如,突然间有大量增加(或大量减少)来自你定向地区的请求。(译注:这个现象很明显,我现在考虑了广告位的影响,请求的流量有时候会有大量的某个广告位的垃圾请求过来,导致我的出价曝光产生剧烈的变化)。也许是你的竞价逻辑本身会使消耗速度不一致。所有的这些因素都会造成你的消耗额是随时间变化而参差不齐的:
尽管设置的出价概率是个常数,消耗速度还是可能不均匀
那么解决方案是什么呢?对我们来讲这个问题是一个控制论的问题,并且我们从无反馈控制换成了反馈控制。如果你是想用概率来控制竞价,那么如果你设置完请求概率,然后竞价一周后分析结果后,这基本是无反馈控制。如果每天早晨你看一下前一天消耗是多少,然后相应地调整当天的竞价概率,那么这就是反馈控制的做法,反馈控制即是将输出的信息反馈到输入中去。这种方案很容易自动化,并且很自然地可以将反馈周期变短,将周期从天调整到几分钟。我们的RTB系统按这个方案重新设计了出价速度的实现,我们可以将与目标出价速度的差异控制到1-2%,我们只使用了简单的反馈机制:每2分钟,参考前2分钟的出价速度,设置下2分钟的‘正确出价速度’。所以,无论什么原因,我们假设少了20%的请求,比如在晚间,那么竞价概率会上升,使用消耗速度保持近似相等。还有一些更复杂的反馈控制方案,但这种基本的方案已经不错了。
上图是我们反馈控制的结果。注意,无反馈控制的输出看起来像Mordor的山(魔戒),而反馈控制的输出像是Shire的平原。
上图为真实的数据,进行了一点平滑以揭示深层的变化,Pace(蓝色,概率 * 1000)会在晚间流量下降时上升,消耗速度(绿色)会与目标消耗速度(红色)几乎保持一致。
和任何好的优化算法一样,它要做的就是完全按你的要求来做:它努力将消耗速度和目标消耗速度的差距降到最小。但是如果系统出现了一个严重的故障,导致一段时间不能竞价,当故障恢复后,这种方案将不会调整目标消耗速度来补偿前一段不能竞价造成的影响:
故障后,消耗速度没有进行补偿(斜率和以前的目标消耗速度斜率是一样的)
为了处理故障造成的影响,还有一些因为系统不完美,使得错误积累造成的超出预算,未到预算的问题,我们需要动态地调整消耗速度目标。我们重新定义一下我们反馈控制的优化目标:消耗速度始终保存与剩余消耗在剩余时间同一水平。这就意味着如果有一天或是一小时出了故障,无需人工干预,就可以在故障后调消耗速度目标进行补偿。这个系统还有一个很好的性质,它会在剩余消耗为0时,准确地自动停止。
很明显,你不会想在任何时间总是采用相同的消耗速度,事实上我认为你是肯定不会的。一个反馈控制系统可以支持几乎任何你想要的消耗速度的曲线。你可以采用竞价概率外的变量去控制(比如:真实的竞价价格,或是定向条件,或是任何你能想出来的方式)。最后,思维敏捷的读者可能发现一个问题,上面描述的方法只有当请求流量大于你的限额可以买的量的时候才有效,如果你的竞价概率设置到了100%也得不到你的日限额,甚至当你赢得所有的流量也不可能达预算,甚至对所有流量你都胜出也到不到预算。那上面的方法是无效的。