1.追踪用户行为
获取数据,并完成Cookie Mapping。以下假设DSP已经做好了Cookie Mapping,每个用户有一个唯一的id标识。
2.受众选择(audience selection)
训练一个audience selection model, 该模型以在广告主的网站上发生转化行为(转化行为可以是注册成为用户,点击某个特定页面,购买产品。每个广告主对转化的定义不一样)的用户为正例,没有发生转化行为的用户为负例。去掉大多数转化概率非常小的用户,将目标用户根据转化概率高低分到不同的segments中。这样我们对每个campaign就找到了很多的目标用户,而且这些用户根据他们的质量高低,被分别放在不同的segments中。
3.通知exchange
DSP将这些目标用户的cookie告诉exchange,这样当有这些cookie的请求来的时候,exchange才会来向DSP的服务器发送请求。
4.Segment管理
人工来对每个campaign的做一些设定。他们根据每个campaign所属的行业特点,经济状况,决定开启哪些segments,关掉哪些segments。例如:对没钱的小公司的campaign, 那些用户转化概率小一些的segment就不要投广告了。他们还需要对每个segment设定一个基础出价(base price)。账户管理员可以拿到每个segment的平均预估转化概率,来辅助他们设定基础出价。这一步也是人工影响投放策略最主要的地方。
5.进行实时竞价
当exchange把请求发过来的时候,DSP会拿到以下信息:当前广告位的信息,当前用户的cookie和基本信息。DSP需要在100ms内,根据对当前用户的理解,并且考虑当前广告位,根据自己的bidding算法,来要决定是否要买这次展现,投放哪个campaign的广告,出价是多少(bidding),并向exchange返回出价信息?如果超过时间DSP没有响应,则exchange默认DSP放弃这次竞价。
6.展现广告
如果赢得了展现机会,则DSP返回创意,用户就会在该广告位看到该创意。
7.追踪转化
因为DSP在广告主的网站上埋了点,就能知道用户是否在这次展现之后进行了转化行为。根据这些数据统计转化率,每个转化平均成本等指标,汇总成报告给广告主。
针对ROI优化内容将针对受众定向算法,内部竞价算法这两个主要优化方向进行描述。
基于已有的数据,为广告主挖掘有价值的用户称为受众定向。受众定向算法的核心是训练一个Audience Selection Model, 该模型以在广告主的网站上发生转化行为(转化行为可以是注册成为用户,点击某个特定页面,购买产品。每个广告主对转化的定义不一样)的用户为正例,没有发生转化行为的用户为负例(正负例很不均匀,通常要做采样和结果修正)。得到模型后,对所有的用户预估对这个Campaign的转化概率p(c|u),即该用户u有多大的概率会在广告主的网站上发生转化行为(c表示conversion)。在没有转化的信息时,对于ROI优化可以使用CTR作为优化的目标,此时默认CTR到转化行为的概率是相同的。
受众定向算法通过两个模型实现:Low-level Model 和 High-level Model。其中涉及的数据库有用户ID数据库,URL ID数据库,广告活动数据库。
为了实现受众定向算法,受众定向算法需要建立和维护如下数据。
在Low-level Model中,需要对URL的特征空间进行压缩,将作为特征的URL建立数据库。该数据库需要初始进行建立,并且根据需要进行更新。
存储目前所有的用户ID及其对应的信息,该数据库需要初始进行建立,并且根据log数据需要进行更新。判断从Adx或者SSP端传来的用户是否在目前的用户数据库中,存在则对该次广告位和用户进行竞价,否则放弃该次竞价。其次,除了存储用户是否出现之外,同时记录每个用户访问过的URL ID信息,存储每个用户所在的平台,对于用户的所有标签信息进行存储。
存储目前活动的广告活动ID,该数据库需要初始进行建立并根据实际情况进行更新。 对于活动的描述信息,比如广告主,广告信息的标签描述也同用户数据库一样进行存储。
这个模型的作用是做初选。所有在该campaign对应的广告主网站上发生转化行为的用户作为正例,其他的用户作为负例。该模型的特征只有两类,就是广告campaign ID和用户历史访问过的URL。
历史访问过的URL反应了用户的兴趣特征,也有根据历史URL跟ODP(Open Dictionary Project)来给用户打标签的。根据Low-level Model确定audience 的URL访问与目前campaign的转化的关系。
特征压缩
所有可能的URL数就是特征空间的维数,对该特征进行One hot 编码,如果用户访问过某个URL,那么这个URL对应的那一维特征的取值就是1,否则就是0。在实现过程中,这样会导致特征空间维数太大,所以要做一个最基本的特征选择:去掉那些覆盖转化用户总数小于某个固定的转化数阈值(比如5)的特征。具体做法是超过设定阈值数的转化的用户所访问过的URL作为特征,低于阈值的转化用户访问的URL不作为特征。这样会显著减少特征的数量。
模型使用逻辑回归模型,训练算法采用L-BFGS算法。该模型对维度很高的URL进行了特征选择,最终的输出只有1维,处理完后URL特征就不再需要了,也是特征选择的一种方法,为下面的high-level Model做准备。
使用Low-level Model对每一个活动的campaign进行受众初步定向。实现方法是针对每个campaign,将用户数据库中的每个用户URL(即其访问过的URL)和campaign ID作为模型输入,输出是每个用户在该campaign上的转化率。
这个模型的作用是细选。模型的样本和Low-level Model一样,特征就不限于用户访问过的URL了,可以是这个用户的各种挖掘出来的属性标签,包括可解释的分类标签,不可解释的聚类id, topic id这是对用户浏览的网页文本进行LDA或PLSA分析的兴趣标签。
在我们的实现中的特征只包括两部分,除了一个是广告的Compaign,其他的都是用户相关的信息及用户属性标签,用于给用户和广告进行打分。用户打标签的工作是在建立模型之前就已经完成的,属于预处理的工作。此外将Low-level Model的输出值作为特征之一。
选择逻辑回归模型,但因为这个模型要预测的样本数比较少了(只有在Low-Level Model中的预测为1的用户才参与High-level Model的细分预测)。
计算针对所有用户进行所有的ad情况下的p(c|u,ad),由于ad和user是经过Low-level Model进行删选的,这样做的好处就是可以大大的减少工作量,如果针对每个campaign都进行训练一个模型将是很大的工作量。Audience selection算法是offline的,也即是预处理的,在exchange的请求到来前就已经对每个campaign都算好了。
划分和定价
每个campaign就会根据每个用户通过audience selection model预估的转化概率p(c|u,ad)选出目标用户,然后这些目标用户会根据不同的转化概率阈值划分到不同的segments中。例如p(c|u,ad)>0.01放到一个segment中,0.01>= p(c|u,ad) > 0.001放到另外一个segment中。每个campaign有大约10到50个segments左右。划分segments的作用一是方便账户管理员对每个segment设置基础出价,另外在后面介绍的bidding算法中将属于同一个segment的用户做无差别对待,相当于同属一个类。
对于不同的ad,相同的segment基础出价也是不同的,这是由于不同的广告所要求的ROI以及广告主的利润率是不同的。对于价格的设定,需要参考广告主所设定的“最高出价”,这里使用MaxPrice表示。最高出价与下面竞价算法中计算出来的最高的Φmax进行相处,然后乘以p(c|s,ad),即:
MaxPrice*p(c|s,ad)/Φmax
其中,p(c|s,ad)表示ad的第s个segment对于的转化概率,这里假设最高的转化概率为一。
当exchange发送请求时,DSP会接受到当前用户的cookie和一些最基本的用户信息,以及当前广告位的信息。DSP则需要找到这个用户所属的所有segments,而这些segments可能会对应多个campaign,选择最优的campaign的方法就是内部竞价的过程。
经过广告过滤,对于剩下的campaign候选,DSP会对他们都根据算法计算出最合适的出价,然后简单地选取出价最高的那个(出价反映了当前用户对该campaign的价值)。
前面的audience selection部分,我们已经对每个用户划分了segments,然后账户管理员又对每个segment给出了基础出价(base price),当时这个出价考虑的是这个用户和这个campaign的适合程度,并没有考虑当前广告位是否适合这个campaign投广告,是否适合这个用户。以基础出价为基准,根据当前广告位计算出一个调整因子Φ,最后的出价就是baseprice*Φ 。
因此我们全部的工作就是要计算这个价格系数Φ。
segments出了一个平均价格base price,当仅当一个展现的转化率是这个segments中用户的平均转化率的Φ倍,我们应该为这个展现出baseprice*Φ的出价。所以
Φ=p(c│ad,u,i) Ej [p(c|ad,u,j)]
其中,ad指的是广告campaign,u指的是用户,i是当前的广告位(inventory),c指的是转化。分母计算的是在所有广告位(用j指代)上的平均转化率。这个分母要计算起来很复杂,我们要遍历所有的广告位(inventory)。但我们知道:
p(c|ads,u)=Ej [p(c|ad,u,j)]=∑j p(c|ad,u,j)p(j)
因此有
Φ=p(c│ad,u,i)p(c|ad,u)
所以bidding算法的最核心部分,就是为每个campaign都建立两个模型来分别预估p(c|u,i)和p(c|u)。考虑到每个campaign的转化数据很少,这2个模型的训练数据很少,要训练这两个模型太难了。因此将同一个segment中的用户不做区分,从而可以把上式变为
Φ=p(c│ad,s,i)p(c|ad,s)
其中,s是segment。这样就只需要训练p(c|ad,s,i)和p(c|ad,s)。因为s的个数远小于u的个数,这2个模型的特征空间显著变小了,模型更容易得到更好的结果。事实上,也可以对i的部分做了类似的trick,它把类似的广告位聚合到一起,给予一个相同的inventory id。目的和把u变为s是类似的。
具体的建模方法如下。
要得到这个模型的训练数据,还有一个冷启动的过程。必须事先对这些segments在这些inventories上投放,然后把那些最终带来转化的展现标记为正例,没有最终带来转化的展现标记为负例。认为一次转化是由之前7天内该用户见到的最后一次展现带来的。
这个模型的特征只有两类,一类就是segment id, 另外一类就是inventory id。也就是说,每一个样本只有两个非0的特征,一个是segment id对应的那个特征,另外一个是inventory id对应的那个特征。
和p(c|s,i)模型基本一样,区别就是特征只有segment id。这两个模型的正例比例都非常低,因此进行了采样(sampling)和修正(recalibration)。