点击率预估与冷启动(一)

点击率预估与冷启动(一)

之前一篇文章和大家聊了下《转化率模型与校准》,今天咱们来聊聊点击率预估以及冷启动的问题。有些读者在看完之后可能会发现这两者之间的微妙的联系。废话不多说,开启今天的旅程。

 

0. 问题介绍

推荐系统和广告算法中,对于新用户或者新内容,记录很少,如果我们直接将历史点击率作为特征,会存在问题。比如

(1). 新用户A有2条浏览记录,1次点击,点击率50%

(2).老用户B有2条浏览记录,0次点击,点击率0%

A和B,只因为1次点击,点击率就相差50%,这不合理。显然,问题出现在A,B用户其实从本质上都属于新用户,他们的历史数据都太少了,历史点击率自然不准。

 

这就像我告诉一个朋友张三(绰号法外狂徒):我王者荣耀贼溜,澜100%胜率。实际上,我只打了两盘澜,其中一盘还是新手教学。朋友张三可能会多嘴问一句:你打了几盘澜啊?但是模型不会,没有专门调整过的模型只会默默接受我澜100%胜率的设定,然后给我匹配一堆最强王者。这就是冷启动问题。

 

1. 解决思路

已经2021年了,我们人类星球上的人工智能模型的计算能力还可以,但还是太“老实”,太“傻”(它们不像某些男人,明明很普通但却很自信)。所以如何让模型“自信”起来呢: 直接把预测结果告诉模型,别让模型自己去算,去猜。这句话乍一听是句废话,让我们翻译成学术语言吧: 给模型输入概率,而不是频率。

 

所以最好的办法是,利用用户的历史点击率,去计算用户之后点击的概率,再将这个概率输入模型。通过用户A的历史点击频率去计算用户A之后点击的概率,听起来不错,但又不太可行,因为这里的信息太少了。好在我们有“大数据”,我们可以利用所有用户的历史点击频率去预测用户A之后点击的概率,似乎有了点希望。那么具体是怎么实现的呢?大致需要两个步骤,一个是贝叶斯平滑,另一个是lia

 

(1).贝叶斯平滑

新用户A只有两条浏览记录,模型还不够认识用户A,怎么办?如果A用户能多几次浏览记录就好了。可是去哪里找那不存在的浏览记录呢?我们可以假定用户A和其他所有用户是差不多的,用其他用户的历史数据“构造”一些浏览记录,作为新用户A的浏览记录。这里“构造”出来的记录,可以理解成先验知识。当我们见过了很多用户之后,即使不认识新用户A,也会对A有个大概的“预期值”。贝叶斯平滑就是这样工作的,它通过“观测”所有用户数据,为新用户确定一个初始预期值 ,这个预期值就是“先验值”。而用户A自己真实的行为所产生的“预期值”,被称之为后验值。最后我们将先验值和后验值综合起来,计算一个贝叶斯平滑修正过的点击率。有了贝叶斯平滑之后,我们可以对点击率进行修正,让历史转化率这个频率值,更加接近用户真实点击的概率。

 

(2). 连续值与深度学习

通过上文,我们可以得到一个贝叶斯平滑后的点击率,那么直接把点击率特征输入深度神经网络,问题不就解决了吗?

 

只能说,对于大多数普通特征也许可以这样,但是点击率这种强特征,这样做太浪费了。原因如下:

 

近年来,推荐系统相关的深度网络模型层出不穷:DeepFM,Wide & Deep,Deep & Cross Network,Attentional Factorization Machine,xDeepFM,Deep Interest Network,AutoInt等,这些模型都有个共同特点:拥有FM层或者Attention层(Wide & Deep除外)。FM层和Attention层都能有效进行特征交叉,从而提高模型的精度。FM层和Attention层的输入都是向量,所以这些模型基本都需要让特征先进入embedding层,变成一个向量,再参与后面的特征自动交叉。

 

这时候,连续值特征就会很尴尬,他们无法像离散值特征一样进入嵌入层,从而无法参与后面的特征交叉,效果大打折扣。

 

目前将连续值转化成向量的解决方案主要有以下几种:

 

第一种方式是对连续值特征做离散化的分桶,之后将分桶后的离散值输入到embedding层得到最终的向量表达。分桶本质上就是做四舍五入近似,等距分桶是直接四舍五入,等频分桶是排序后对序做四舍五入,这两种方法都会影响精度,造成信息的损失。

 

第二种方式也是离散化,不过是有监督的离散化。它借鉴了决策树的思路,枚举所有分割点,找到一组分割点,使分割后的数据组的信息熵增益最大。这里有个比较trick的做法:直接用一部分数据训练一个lightGBM模型,然后解析模型文件,里面记录了lightGBM模型选出来的最优分割点,直接可以用。需要注意的是,有监督的离散化用到了数据的标签,所以可能会带来数据穿越的问题。为了避免这个问题,建议训练lightGBM模型的数据和深度学习的数据不要重合。

 

第三种方法来自AutoInt论文,非常巧妙。它先用前面两种方法对连续值特征Z做离散化,得到Z',之后将Z'输入embedding层得到向量emd(Z'),最后用embedding层的输出emd(Z')再乘以Z。这其实是基于一个朴素的思想:既然离散化后的特征会损失精度,那么就将原始特征再一次输入模型。

 

最后一种方法来自2019和2020年腾讯广告算法大赛冠军团队的成员郭达雅大佬。他的方法灵感来自于NLP顶会ACL2016的论文《Key-Value Memory Networks for Directly Reading Documents》,在介绍郭佬的方法之前,先带大家回顾下这篇paper。

 

这是一篇16年的paper,在今天用在推荐或者广告领域仍然效果显著,不得不说CV和NLP在学术上面确实领先于推荐广告一大步。这篇paper的核心是提出了一种基于Key-Value的记忆网络,原本是用来解决QA问题的,不过简单改进后,可以用来构造续值特征的专属embedding层。Key-Value Memory Networks的结构如下:

点击率预估与冷启动(一)

这种网络与普通网络最大的区别是可以方便的引入先验知识,即图中的Knowledge Source模块。该模块相当于是一个内嵌在神经网络中的“搜索引擎”,对于输入的任何一个Question,先在Knowledge Source中做一次搜索,然后将搜索结果也作为神经网络的输入。为什么说它是内嵌在神经网络中呢?因为搜索结果与Question之间存在一个相似度,这个相似度的计算是依赖神经网络的,并且通过梯度下降进行优化。模型主要分为三个部分:Key hashing, Key addressing和Value reading。

 

Key hashing

Key hashing是离线计算好的。它的输入是Question和Knowledge Source。Question是QA中的Q,比如“如何打开王者荣耀”。Knowledge Source是一个类似*的数据库,里面记录了各种词汇,实体和知识。

 

Key hashing就是把所有Question里面的常用词(出现次数大于某个阈值)挑出来,然后给这些词一个编号,组成一个字典。字典的key是这些常用词,value是常用词编号。

 

Key addressing

Key addressing就是去Knowledge Source里面寻找Question中的词汇和短语。比如找到了:“如何”, “打开”,“王者荣耀”等词。Question“如何打开王者荣耀”会有一个训练出的Question embedding值,同时,"如何",“打开”,“王者荣耀”等词也都有各自的embedding值,被称为Key embeddings。用Question embedding分别乘以每一个Key embedding,再经过一次Softmax,就可以得到Question与各个Key的相似度权重P。具体公式如下:

 

点击率预估与冷启动(一)

Key hashing和Key addressing用上述模型解决了一个问题:Question与Knowlege Source中相近词汇的相关性。比如对于Question"如何打开王者荣耀",可以得到一个相似度权重P字典{"如何":0.1,"打开":0.3,"王者荣耀":0.6}。

 

Value reading

value reading是键值储存网络的核心部分。还记得我们上文有个key embedding,对应的,Key-Value Memories还有个value embedding,它的输入是Knowledge Source里面每个词的id。对value embedding以上文的p为权重加权求和,便得到我们需要的向量o,具体公式如下:

点击率预估与冷启动(一) 

和传统的深度神经网络相比,键值储存网络可以方便的让先验知识以键值对的方式输入模型(图中的Key-Value Memories)。这意味着,神经网络的输入值可以直接是多个键值对组成的字典。举个例子,传统神经网络只能将数字作为特征,比如:身高(173),体重(90)或者年龄(25)。而键值储存网络可以将兴趣 ({‘篮球’:0.5,'足球':0.2,'台球':0.1}) 作为特征,直接输入给模型。字典特征的key是实体,使用Label Encoding后可以进入embedding层,value是其权重。键值储存网络可以方便的将输入的字典特征转化成上文的向量o。

 

回到最开始的问题,我们想找到一个将连续值转成向量的方法,但上文却一直在讲键值储存网络,为什么?另外郭佬的方法究竟是怎么做的?先卖个关子,欲知后事如何,请听下回分解。

 

欢迎关注微信公众号:计算广告那些事儿

点击率预估与冷启动(一)

上一篇:在电脑上微信如何多开


下一篇:WPS恢复未保存历史文件