原文链接:http://tecdat.cn/?p=24191
在这篇文章中,我将集中探讨一个给定一个短数据序列的推断概率的例子。我将首先介绍如何用贝叶斯办法进行冀望推理的实践,而后在 Python 中实现该实践,以便咱们可能解决这些想法。为了使文章更容易了解,我将只思考一小组候选概率。我可能最小化推理的数学难度,同时依然可能失去十分好的后果,包含先验、似然和后验图。
具体来说,我将思考以下状况:
- 计算机程序输入一个由 1 和 0 组成的随机字符串。例如,一个示例输入可能是:
- 指标是推断程序用于生成 D 的 0 的概率。咱们应用符号 p0 示意 0 的概率。当然这也意味着 1 的概率必须是 p1=1−p0。
- 如上所述,咱们只思考一组候选概率。具体来说,对下面的数据序列应用候选 p0=0.2,0.4,0.6,0.8。咱们如何明智地在这些概率中进行抉择,以及咱们对后果有多大把握?
概率
我的出发点是写出数列的概率,就如同我晓得 0 或 1 的概率一样。当然,我不晓得这些概率——找到这些概率是咱们的指标——但这是先验的有用的中央。例如,咱们的示例数据系列的概率,不须要具体阐明 p0 的值,能够写成:
我应用 p1=1−p0 来写出 p0 的概率。我还能够以更紧凑的形式写出上述概率:
下面给出的概率的模式称为 伯努利过程。我也能够用十分通用的形式来写这个概率,而不是具体对于数据系列 D 或概率 p0,如:
n0 和 n1 示意数据系列中 0 和 1 的数量。
通过替换相干的计数和概率,我能够将个别模式与特定示例分割起来。我首先计算下面给出的数据系列和概率的似然值:
查看后果,我发现 p0 = 0.6 的可能性最大,略高于 p0 = 0.8。这里有几点须要留神:
- 我有最大似然值(在思考的值中)。我能够提供答案 p0=0.6 并实现。
- 概率(似然)的总和 不是 1—— 这意味着我没有正确归一化对于 p0 的概率品质函数(pmf),我试图推断的参数。贝叶斯推理的一个指标是为 p0 提供一个适当归一化的 pmf,称为后验。
进行上述计算的能力使我可能很好地利用贝叶斯定理并取得所需的后验 pmf。在持续探讨贝叶斯定理之前,我想再次强调 似然函数 的个别模式:
写下对 数似然 也很有用:
因为当我在上面创立一些 Python 代码时,这种模式减少了数值稳定性。须要明确的是,我应用的是天然(以 e 为底)对数,即 loge(x)=ln(x)。
先验
我曾经决定了局部先验——抉择 p0∈{0.2,0.4,0.6,0.8} 作为我将思考的一组概率。剩下的就是为每个候选 p0 调配先验概率,这样我就能够从正确归一化的先验 pmf 开始。假如先验相等,这是一种推理:
其中应用 A1 示意我所做的假如。以上信息形成了 先验的 pmf。
贝叶斯定理和后验
接下来,我应用 下面定义的 似然 和 先验 pmf 来推断 p0 的潜在值。也就是说,我将应用贝叶斯定理来计算 给定似然和先验的 后验 pmf。 后验 有模式:
换句话说,这是 _给定数据序列_ D _和假如_ A1_的_ p0 _的概率,_我能够应用贝叶斯定理计算后验:
其中先验 P(p0|A1)是红色,似然 P(D|p0) 是彩色,后验 P(p0|D,A1)是蓝色的。
这使我的 p0 信息从假如 (A1) 更新到假如 + 数据(d,A1) :
我能够通过定义 边际似然函数 来简化贝叶斯定理:
我能够将贝叶斯定理写成以下模式:
后验局部应该被看作是一组方程,对应于 p0 的每个候选值,就像咱们对似然和先验所做的那样。
最初,对于实践,我计算了 p0 的后验 pmf。让咱们从计算根据开始(我晓得下面的似然和先验的所有值):
因而,贝叶斯定理中的分母等于 9.57440e-04。当初,实现后验 pmf 计算。
第一,
第二,
第三,
最初,
回顾
在 Python 代码之前,让咱们略微回顾一下后果。应用数据和贝叶斯定理我曾经从 先验的 pmf
到 后验 pmf
在贝叶斯设置中,这个后验 pmf 是咱们推断 p0 的答案,反映了咱们对给定假如和数据的参数的常识。通常人们想报告一个繁多的数字,但这个后验反映了相当多的不确定性。一些抉择是:
- 报告 p0 的 _最大后验_值——在本例中为 0.6。
- 报告 _后验平均值_、_后验中位数_ ——应用_后验_ pmf 进行计算。
- 包含后验方差或置信区间来形容预计中的不确定性。
然而,报告的推论,沟通不确定性是工作的一部分。在实际操作中,前面的图的确有助于实现工作。所以,让咱们来到实践,在 Python 中实现这些想法。
用 Python 编写推理代码
首先,代码导入 numpy 和 matplotlib。应用 ggplot 款式来绘图。
imprt matlli.pplt as plt
# 应用 mapltlb 样式表
try:
pl.stye.use('gglot')
首先,我创立了一个类来解决 似然 。该类接收数据序列并提供一个接口,用于计算给定概率 p0 的 似然。你可能在办法中找到对数似然方程(对于边际状况须要特地留神)。
class liihd:
def \_\_int\_\_(elf,dat):
"""二进制数据"""
slff._possa(data)
def \_pss\_a(slf,data):
tep = \[str(x) for x in dta\]
for s in \['0', '1'\]:
slf.cnts\[s\] = emp.ount(s)
if len(tmp) != sum(ef.conts.valus()):
rase Exepon("!")
def \_prcs\_pobites(self, p0):
"""解决数据."""
n0 = slf.couts\['0'\]
n1 = slf.conts\['1'\]
if p0 != 0 and p0 != 1:
# 例子
log_dta = n0*np.og(p0) + \
n1*np.log(1.-p0)
p\_daa = np.ep(opr\_dta)
elif p0 == 0 and n0 != 0:
# 如果不是 0,p0 就不是 0
lordta= -np.inf
prta = np.exp(lor_daa)
elif p0 == 0 and n0 == 0:
## 数据与 p0 = 0 统一
logpr_data = n1*np.log(1.-p0)
prdat = np.exp(lor_dta)
elif p0 = 1 and n1 != 0:
# 如果 n1 不是 0 p0 就不是 1
loprta = -np.inf
paa = np.exp(lgpaa)
elif p0 == 1 and n1 == 0:
ordta = n0*np.log(p0)
prta = np.xp(lgp_dta)
def prb(self, p0):
"""获取数据的概率"""
p\_at, \_ = sef.pcrbbes(p0)
retrn prdta
def lo_pb(sef, p0):
"""获取数据对数概率"""
_, lp\_at = slf.p\_plie(p0)
reurn lor_ta
接下来我为 先验的 pmf 创立一个类。给定 p0 的候选值列表,默认状况下会创立一个平均先验。如果须要其余,能够传递先验概率来笼罩此默认值。上面我举个例子。
class pri or:
def \_\_ni\_\_(self, pls, pobs=Nne):
""" 先验
列表: 容许的 p0’列表
P_pos: \[可选 \]先验概率
"""
if p_prbs:
# 确保先验正态
nom = sum(p_pbs.vaes())
sel.lopct = {p:np.log(_prbs\[p\]) - \
np.log(nrm) for p in p_lst}
else:
n = len(p_is)
sef.lo\_pict = {p:-np.log(n) for p in p\_lst}
def \_\_iter\_\_(self):
rturn ier(sre(slf.lopit))
def lgpob(self, p):
"""获取 p 0 的对数 / 先验概率."""
if p in sef.ogpdt:
return sf.og_ic\[p\]
else:
return -np.inf
def prob(slf, p):
"""获取 p 0 的先验概率."""
if p in slf.gt:
retun np.ep(sf.o_pt\[p\])
else:
reurn 0.0
最初,我为 后验 结构一个类,它采纳数据和先验类的一个实例结构后验 pmf。plot() 办法提供了一个十分好的推理可视化,包含 先验 、 似然 和 后验的图。
请留神,后验的所有计算都是应用对数概率实现的。这对于数值精度来说是相对必要的,因为概率可能变化很大,可能十分小。
class posir:
def \_\_it\_\_(slf, da ta, p ior):
"""数据:作为列表的数据样本"""
sel.lod = lklio(dta)
lf.prr = prir
self.possior()
def \_pocss\_ostrior(elf):
"""应用传递的数据和先验解决后验。"""
nuts = {}
deniaor = -npnf
for p in slf.prir:
netor\[p\] = sef.lieioo.logrob(p) + \
slf.riorog_rob(p)
if nurts\[p\] != -np.inf:
deoior = nplgxp(eoior,
ners\[p\])
# 保留贝叶斯定理中的分母
sef.lo_lielod = deoiato
# 计算后验
slf.ogict = {}
for p in slf.pior:
elf.lopct\[p\] = umros\[p\] - \
slf.lmllio
def logpob(self, p):
"""获取通过 p 的对数后验概率"""
if p in self.loic:
retrn self.ogdt\[p\]
else:
retrn -np.inf
def prob(self, p):
"""获取通过的 p 的后验概率"""
if p in sl.lo_pdit:
rtrn np.exp(sef.lct\[p\])
else:
rurn 0.0
def plot(slf):
"""绘制推理后果"""
f, ax= plt.sbs3, 1, ise=(8, 6), hae=Tre)
# 从先验中获取候选概率
x = \[p for p in elf.prir\]
# 绘制先验 ob(p) for p in x\])
ax\[0\].sem y1,inf='-, meft'', bef = -')
# 绘图似然
ax\[1\].stem(x, y, lifm= -',aerf t=ko bafmt=w')
# 绘图后验
ax\[2\].tm,y3 if='b-, mmt=bo, sefm-')
例子
让咱们测试一下代码。首先,我将复制咱们在实践例子中所做的例子,以确保一切正常:
# 数据
data1
# 先验
A1 = prior(\[0.2, 0.4, 0.6, 0.8\])
# 后验
pt1 = postior(da1, A1)
plot()
请留神后验 pmf 如何很好地表明 p0=0.6 和 p0=0.8 都有很大的概率——这里存在不确定性!这是有情理的,因为咱们只有一个长度为 10 的数据系列,而且只有四个候选概率。另外,请留神:
- 先验和后验中所有数字的总和为 1,反映这些是适合的 pmfs。
接下来,让咱们思考设置一个强先验——偏好 p0 的一个值。应用咱们的 Python 代码很容易看到这个先验对后果后验的影响:
# 先验 - 将按类标准化
A2
# 后验
po2 = ptror(data, A2)
pot()
留神以下几点:
- 后验和似然不再具备雷同的形态。
- p0=0.2,0.4 的后验概率_绝对于它们的先验概率_都 _降落了,_ 因为它们对于提供的数据序列的似然性很低。以相似的形式,p0=0.6,0.8 的后验概率_绝对于它们的先验概率_有所 _减少_。
最初,让咱们用更多的候选概率 (这里是 100) 和更长的数据序列来做一个例子。
# 设置为 0 的概率
p0 = 0.2
# 设置 rng 种子为 4
np.andom.ed(4)
# 生成据
da2= np.roie(\[0,1\], p=\[p0, 1.-p0\])
# 先验
A3 = pir(np.aane)
# 后验
ps3 = porir(daa2, A3)
plot()
留神几点:
- 后验有一个很好的润滑的形态 - 我解决的概率看起来像是一个间断的值。
- 留神这个数据量的似然值 (y 轴) 很小。
最受欢迎的见解
1.matlab 应用贝叶斯优化的深度学习
2.matlab 贝叶斯隐马尔可夫 hmm 模型实现
3.R 语言 Gibbs 抽样的贝叶斯简略线性回归仿真
4.R 语言中的 block Gibbs 吉布斯采样贝叶斯多元线性回归
5.R 语言中的 Stan 概率编程 MCMC 采样的贝叶斯模型
6.Python 用 PyMC3 实现贝叶斯线性回归模型
7.R 语言应用贝叶斯 层次模型进行空间数据分析
8.R 语言随机搜寻变量抉择 SSVS 预计贝叶斯向量自回归(BVAR)模型
9.matlab 贝叶斯隐马尔可夫 hmm 模型实现