CTR 平滑
在计算广告中,有时存在一些比较稀疏的数据,这时需要对这些数据进行平滑。例如,某个广告,只有三次浏览(Impression),0次点击(Click),那么点击率为0%?如果恰巧有一次点击,点击率为33%?显然这样不合理,这样的点击率预估就很不准确了。因此,我们需要一种可以对点击率平滑的方法。下面先介绍什么是 Beta 分布。
Beta 分布
关于 Bata 分布,可以参考这篇博文:http://blog.csdn.net/a358463121/article/details/52562940
简而言之,beta 分布是“概率的概率分布”,也就是关于概率的pdf。例如,我们希望观测的变量是投篮命中率。我们可以用均值来刻画它,也可以用beta分布来刻画它。假设科比的投篮命中率服从
r
~
为什么要这样刻画呢?因为有时候均值并不能良好地刻画命中率。例如,本周梅西射了2球,中了2球,其平均命中率为100%。这是因为样本太稀疏,无法表现出统计特性。假如梅西的命中率是服从 Beta(α,β) 分布的,那么我们本周的命中率可以被修正为 Beta(α+2,β+2) ,其pdf就会整体往右移。
点击率平滑
回到广告点击率,有着同样的问题。
这篇文章详细地介绍了广告点击率平滑的方法:Click-Through Rate Estimation for Rare Events in Online Advertising。其基本思想是,对于那些稀疏的数据,可以用相似类型的其它数据来修正。例如,在某个页面上有许多广告,假设其点击率r是服从Beta分布的。我们可以用统计的方法来估计出参数
α̂
和
β̂
。文中使用的是贝叶斯估计,具体推导可以参考文章。得到Beta分布后,就可用这个分布求出修正的点击率啦,
其中 Ci 是广告i的点击次数, Ii 是浏览次数。可见,当C和I比较大的时候,不太会受到 α,β 的影响;而比较小的时候,就会得到较大的修正,修正到更趋近于均值。直观上来看,当统计量不足的时候,我们更趋向于用均值来预估。
α , β 的迭代公式如下,其中 Ψ 是 digamma 函数, Ψ(x)=ddxlnΓ(x) 。
根据文中的迭代公式,可以用scipy简单实现。需要用到 digamma 函数。在实际计算过程中,我发现不太容易收敛,需要调整迭代次数。
def newBetaParam(C, I, alpha, beta):
newAlphaNumerator = np.sum(digamma(C + alpha) - digamma(alpha))
newBetaNumerator = np.sum(digamma(I - C + beta) - digamma(beta))
newDecomerator = np.sum(digamma(I + alpha + beta) - digamma(alpha + beta))
return alpha * newAlphaNumerator / newDecomerator,\
beta * newBetaNumerator / newDecomerator
def paramIteration(C, I, initAlpha, initBeta, iteration=1000):
alpha, beta = initAlpha, initBeta
for i in range(iteration):
newAlpha, newBeta = newBetaParam(C, I, alpha, beta)
if abs(newAlpha - alpha) < 1e-10 and abs(newBeta - beta) < 1e-10:
print('Stop, Iter={}'.format(i))
break
alpha, beta = newAlpha, newBeta
if i % 50 == 0:
print('Alpha: {:.03f}, Beta: {:.03f}, Iter={}'.format(alpha, beta, i))
return alpha, beta