写这篇笔记的来源:
昨天晚上在朋友圈刷到了朋友用R画的贝叶斯网络(也就是上图,图片已拿到授权。选的节点很多,个人觉得像宇宙,交叉的点不断的向外边发送信号,还怪好看的)。这时想起了,自己收藏夹有贝叶斯定理的解析(以前只是收藏了,没看,逃。)
然后用Python实现一个简单的贝叶斯定理的脚本。也是为了验证下是否理解了贝叶斯定理。
贝叶斯定理介绍:
Steve很害羞而且性格孤僻,虽然乐于助人,但却对周围的人或现实世界不太感兴趣,是一个温顺而又井井有条的人。他需要什么事都有条理、结构清晰、且热衷于钻研细节。
你觉得下面哪种说法可能性更大?
Steve是一个图书馆管理员----Steve是一个农民
这是kahnman和tversky的一个实验,根据他们的实验结果。当人们知道Steve是一个温顺而又井井有条的人的时候,大部分人都会说,Steve更可能是图书馆管理员,毕竟相较于农民,这更符合图书馆管理员的形象。
然而问题的关键不在于,人们对图书馆管理员和农民的特征形象认识是否有偏差。
而是,在做判断的时候,没人把农民和图书馆的比例信息考虑进去。
根据他们的论文给出:在美国,农民与图书馆管理员的数量之比是20:1。
我们是否在判断的时候,加入了比例因素的影响。
根据这个比例,我们假设有10名图书馆管理员和200名农民。当你看到“Steve是一个温顺而又井井有条的人”的时候,我们假定你第一感觉有40% 的图书馆管理员符合这个描述,而只有10%的农民符合这个描述。
这意味着,在这120个样本,大约有4名图书馆管理员符合这个描述,而大约有20名农民符合这个描述。我们从这24人随便抽一个,抽到图书馆管理员的概率16.7%。
即使有40%的图书馆管理员符合这个描述,比农民比例多了4倍,然而农民基数大呀。
贝叶斯有个基本理论:新证据不能直接凭空决定你的想法,而是根据新证据去更新你之前的判断(先验概率)。
例如上面的例子,我们限制了概率空间,再考虑比例。
贝叶斯给了我们一个新的思考方向,下面是贝叶斯公式:
P(A|B) 是B事件发生后A事件的概率。即B事件是已知的,而A事件未知。
P(A) 是先验概率"(Prior probability)即我们在不知道B事件发生的前提下,对A事件发生概率的一个主观判断.
这个判断并不是凭空的,例如未上线业务,没有数据的业务,我们可以用行业的平均值,或者竞品所采用的数值,作为初始指标,在后期根据运行情况,不断改变这个初始指标。
P(B|A)/P(B) 我们可以理解为新证据、新数据。根据新数据,算出一个影响因子。将P(A) 乘以这个影响因子,不断改变概率,使其符合真实概率。
P(B) 有全概率公式。P(B) = P(B|A1) * P(A1) + P(B|A2) * P(A2)
以+号为中间点,分为两部分。假如A1和A2构成一个问题的全部(即全部的样本空间)。那么事件B的概率,就等于A1乘以B对A1的条件概率+A2乘以B对A2的条件概率。
案例:
假设有两碗曲奇饼,碗A包含30个香草曲奇饼和10个巧克力曲奇饼,碗B这两种曲奇饼各20个。
现在假设你在不看的情况下随机地挑一个碗拿一块饼,得到了一块香草曲奇饼。
问题:从碗A拿到香草曲奇饼的概率是多少
我们先假设,A事件为从碗A,A'事件为从碗B,B事件为拿到香草曲奇饼
P(A) = P(A') = 1/2
因为只有两个碗,我们假设先验概率为1/2
P(B|A) = 30 / 40 = 3/4
这是从碗A拿到香草曲奇饼的概率,有30块香草曲奇饼,总共有40块饼干
P(B) = P(B|A)P(A) + P(B|A')P(A')= (3/4)(1/2) + (1/2)(1/2) = 0.625
这是全概率公式。+号左边的数值上边已经计算,而右边的是从碗B拿到香草曲奇饼的概率和先验概率相乘。
P(A|B) = P(A) * P(B|A) / P(B) = (1/2) * (3/4) / (5/8) = 0.6
将数字代入公式,求的从碗A拿到香草曲奇饼的概率是0.6
以下是Python代码
class simple_Bayesia(object):
"""docstring for simple_Bayesia"""
def __init__(self):
super(simple_Bayesia, self).__init__()
self.container = dict()
def set(self,prior_A,prior_B,bowl_A_vanilla,bowl_A_Chocolate,bowl_B_vanilla,bowl_B_Chocolate):
self.container['prior_A'] = prior_A # A的先验概率
self.container['prior_B'] = prior_B # B的先验概率
self.container['bowl_A_vanilla'] = bowl_A_vanilla # A碗的香草个数
self.container['bowl_A_Chocolate'] = bowl_A_Chocolate # A碗的巧克力个数
self.container['bowl_B_vanilla'] = bowl_B_vanilla # B碗的香草个数
self.container['bowl_B_Chocolate'] = bowl_B_Chocolate # B碗的巧克力个数
self.container['bowl_A']= self.container['bowl_A_vanilla']+self.container['bowl_A_Chocolate']
self.container['bowl_B']= self.container['bowl_B_vanilla']+self.container['bowl_B_Chocolate']
def print(self,bowl,cookie_name):
print("从碗{}获取{}的概率是:".format(bowl,cookie_name))
print(self.container['prior_'+bowl]*self.likelihood(bowl,cookie_name))
def likelihood(self,bowl,cookie_name):
#P(B|A) / P(B)
if bowl=='A':
other = 'B'
else:
other = 'A'
P_B_A = self.container['bowl_'+bowl+'_'+cookie_name]/self.container['bowl_'+bowl]
P_B = (self.container['bowl_'+bowl+'_'+cookie_name]/self.container['bowl_'+bowl])*self.container['prior_'+bowl] \
+ (self.container['bowl_'+other+'_'+cookie_name]/self.container['bowl_'+other])*self.container['prior_'+other]
return P_B_A / P_B
a = simple_Bayesia()
a.set(1/2,1/2,30,10,20,20)# 依次传递「A的先验概率、B的先验概率、A碗的香草个数、A碗的巧克力个数、B碗的香草个数、B碗的巧克力个数」
a.print('B','Chocolate')# 依此传递「从碗{}获取{}的概率,{}里的值」
运行结果:
参考文献:
1.https://www.youtube.com/watch?v=HZGCoVF3YvM
2.https://www.bilibili.com/video/BV1R7411a76r
3.https://zhuanlan.zhihu.com/p/27012448
4.https://zhuanlan.zhihu.com/p/37768413