码农不识贝叶斯,虽知数据也枉然
The following article is from 喔家ArchiSelf
(点击上方蓝字,快速关注我们)
作者:伯乐在线 - abel_cao,个人公号:喔家ArchiSelf(ID:wireless_com)
http://python.jobbole.com/88318/
数据的重要性毋庸置疑,但是如何让数据产生价值呢?
对一个全栈老码农而言,经常在开发或者研发管理的时候遇到各种预测、决策、推断、分类、检测、排序等诸多问题。面对“你的代码还有 bug 么?”这样的挑战,一种理智的回答是,我们已经执行了若干测试用例,代码中存在bug的可能性是百分之零点几。也就是说,我们对当前程序中没有bug的信心是百分之九十九点几。这实际上就是一直贝叶斯思维,或者说使用了贝叶斯方法。不论我们看到,还是没有看到,它都在那里,熠熠生辉。
如果预测当前软件有没有bug呢?还是要从贝叶斯定理看起。
贝叶斯定理的浅解
对老码农来说,贝叶斯定理的概率表达相对清晰,理解起来会相对容易。回忆一下我们学过的概率论,联合概率是满足交换律的,即:
P(A and B) = P (B and A)
对联合概率以条件概率展开:
P(A and B ) = P(A) P(B|A)
P(B and A ) = P(B) P(A|B)
从而得到:
P(A) P(B|A) = P(B) P(A|B)
简单的变换一下,得到:
大功告成,这就是神奇的贝叶斯定理。其中:
P(B) 为先验概率,即在得到新数据前某一假设的概率;
P(B|A) 为后验概率,即在观察到新数据后计算该假设的概率;
P(A|B)为似然度,即在该假设下得到这一数据的概率;
P(A)为标准化常量,即在任何假设下得到这一数据的概率。
还可以加点料,在计算P(A)的时候,可以用加法定理表示:
P(A) = P(A and B) + P(A and B_) = P(A|B)P(B)+ P(A|B_) P(B_)
从而有:
其中B_ 是与B相反的事件。就测试与bug 之间的估算而言,《贝叶斯推断的思想》一文给出了贝叶斯推断的结果,其中就使用了这样的方法。
贝叶斯方法
贝叶斯方法是一个非常通用的推理框架,用客观的新信息更新我们最初关于某个事物的信念后,就会得到一个新的改进了的信念。通过引入先验的不确定性,允许了初始推断的错误,获得了更新的证据后,也没有放弃初始的推断,而是调整为更符合目前的证据。
但是,P(A|B) 和 P(B|A) 之类的经常让人混淆,@待字闺中的陈老师给出了理解的一个关键点,区分出规律和现象,就是将A看成“规律”,B看成“现象”,那么贝叶斯公式看成:
陈老师在《这的理解贝叶斯公式吗》和《又一个生活中的贝叶斯应用》给出了几个通俗易懂的例子,这里不再赘述。
回归到码农生活,我们在改善系统功能的时候,通常的一个手段是AB测试。AB测试是用来检测两种不同处理方式的差异化程度的一种统计设计模式,例如两个网站谁会带来更高的转化率,这里的转化可以是用户的购买、注册、或其他的行为。AB测试的关键点在于组别之间只能容许一个不同点。实验后的分析一般都是用假设检验完成的,例如均值差异检验或者比例差异检验,往往涉及Z分数或令人困惑的p值,而用贝叶斯方法则会自然的多。
对A,B两个网站的转化概率进行建模。转化率在0~1之间,可采用Beta分布。如果先验是Beta(a1,b1),且 观测到N次访问里有X次转化,那么此时的后验分布是Beta(a1+X,b1+N-X). 假设先验是Beta(1,1),等价于【0,1】上的均匀分布,则示例代码如下:
from spicy.stats import beta
a1_prior = 1
b1_prior =1
visitors_A = 12345 // 网站A的访问人数
visitors_B = 1616 // 网站B的访问人数
conversions_from_A = 1200 // 网站A的转化人数
conversions_from_B = 15 0 // 网站B的转化人数
posterior_A = beta(a1_prior+ conversions_from_A,b1_prior + visitors_A -conversions_from_A)
posterior_B = Beta(a1_prior+converiosns_from_B,b1_prior + visitors_B-conversions_from_B)
// 对后验概率进行采样,用rvs方法生成样本
samples = 20000
samples_posterior_A = posterior_A.rvs(samples)
samples_posterior_B = posterior_B.rvs(samples)
// 对后验概率进行比较
print (samples_posterior_A > samples_posterior_B).mean()
使用贝叶斯方法,是从思考数据是如何产生的开始。
1)什么随机变量能过描述这些统计数据
2)确实概率分布的所需参数
3)参数对应早期行为,或后期行为,定义各种变化点
4)定义参数的概率分布
5)参数概率分布的变量选择,直到一个可以假设的均匀分布
对先验及后验概率的选择,针对应用场景而定。就先验分布而言,除了常见的分布外,还有:
* Gamma分布,指数随机变量的推广
* 威沙特分布 ,是所有半正定矩阵的分布,是一个协方差矩阵的适当的先验。
* Beta分布,随机变量定义在0到1之间,使其成为概率和比例的热门选择。
* 幂律分布,满足公司规模和公司数量之间的关系
在AB测试中使用了Beta分布, 应用了一个Beta先验分布连同二项式生成的观测数据形成一个Beta后验分布这一原理。
当面对多种对象之间的因果关系的时候,贝叶斯方法演变成为了贝叶斯网络。
贝叶斯网络
贝叶斯网络是为了解决不定性和不完整性问题而提出的,在多个领域中获得了广泛应用。贝叶斯网络是基于概率推理的图形化网络,而贝叶斯公式则是这个概率网络的基础。贝叶斯网络中的每个点代表一个随机变量,都是具有实际含义、需要人为设计的,点和点之间的边代表不确定的因果关系,例如 节点E直接影响到节点H,即E→H,则用从E指向H的箭头建立结点E到结点H的有向弧(E,H),权值(即连接强度)用条件概率P(H|E)来表示。
实际上,如果事物之间的关系能够用一条链串起来,形成了贝叶斯网络的一个特例——马尔可夫链,换个角度看, 贝叶斯网络是马尔可夫链的非线性扩展。贝叶斯网络中当某点的一个证据出现后,整个网络中事件的概率都会变化。
简单地,由于多个变量间存在着可能的依赖性,贝叶斯网络说明了其中的联合条件概率分布,允许在变量的子集间定义条件独立性。使用贝叶斯网络的过程与使用贝叶斯方法的过程是类似的:
通过多个离散变量建立网络,是一个有向无环图
参数的设置或学习,即对DAG进行遍历,计算各节点的概率表
网络推理,对因果关系得到置信概率
推理结果
例如, 社交网络中不真实账户的检测问题。首先确定网络中的随机变量:
* 账户的真实性 A
* 头像的真实性 H
* 发帖即日志的密度 L
* 好友的密度 F
使用观测值示例化H,L,F,把随机值赋给A,得到
P(A|H,L,F) = P(H|A)P(L|A)P(F|A,H)
然后就可以在社交网络中尝试使用该推理结果了。在《算法杂货铺——分类算法之贝叶斯网络》一文中对这一例子给出了相对详细的说明。
可以说,贝叶斯方法席卷了整个概率论,并将应用延伸到各个问题领域,所有需要作出概率预测的地方都可以见到贝叶斯方法的影子,特别地,贝叶斯方法对机器学习能够有什么帮助呢?
贝叶斯与机器学习
机器学习在业界炙手可热,但我们在机器学习里同样会遇到预测、决策、分类、检测等问题,贝叶斯方法同样大有用武之地。
机器学习中有大量的模型,如线性模型、非线性模型,可以采用贝叶斯方法来做模型的预测。也就是说,某一场景可能采用的模型是无限多的,可以用概率分布去描述它。对于假设的先验,对新来的样本做预测如计算它的似然,然后用前面推出来的后验分布做积分,这个给定模型下样本的似然,就是所有可能模型的分布。
机器学习中模型的选择和比较也是一个常见的问题。例如,在分类问题时,我们使用线性模型还是深度学习的非线性模型呢?贝叶斯方法是这样考虑的: 用A 表示一个模型类别,可能是线性模型,B 表示另一个模型类别,可能是非线性模型。在同样的数据集X下,计算在A,B 情况下观察到训练集的似然Ma,Mb,然后比较Ma和Mb,这是贝叶斯方法做模型选择的一个基本规则。
实际上, 贝叶斯定理是信息处理的一种准则, 输入是一个先验分布和一个似然函数,输出是一个后验分布。对机器学习中的模型本身,也可以通过贝叶斯方法尝试改进,例如贝叶斯SVM, 高斯过程的贝叶斯等等。
另外,贝叶斯方法对深度学习而言,至少在调参的这一环节还是很有用的。在神经网络中,每一层参数如卷积核的大小和数量等,都不会在深度学习中被模型自动优化的,需要手工指定,这或许就是贝叶斯优化。
感慨一下,码农不识贝叶斯,虽知数据也枉然呀!
其他参考资料:
《贝叶斯方法-概率编程与贝叶斯推断》
《贝叶斯思维:统计建模的python学习法》
《数学之美番外篇:平凡而又神奇的贝叶斯方法》
《Bayesian Method for Machine Learning》www.cs.toronto.edu/~radford/ftp/bayes-tut.pdf
看完本文有收获?请转发分享给更多人
关注「Python开发者」,提升Python技能