本文是学习《贝叶斯方法 概率编程与贝叶斯推断》重点参考了这个教程
import numpy as np
import pymc3 as pm
import matplotlib.pyplot as plt
import os
# 加载数据并且展示
count_data=np.loadtxt("data/txtdata.csv")
plt.figure(figsize=(12.5,3.5))
n_count_data=len(count_data)
plt.bar(np.arange(n_count_data),count_data,color="#348ABD")
plt.xlabel("days")
plt.ylabel("number of messages")
plt.title("did the model change?")
plt.xlim(0,n_count_data)
plt.show()
bayesian_opitimization_2_0.png
初步假设,在时间之前短信数量服从泊松分布,在时间之后短信数量服从泊松分布.这样就有了三个参数,,,我们的目标呢就是根据证据给出这三个参数的概率分布。(注意!是参数的概率分布!!这是贝叶斯推断的核心!!)
为了进行推断呢,我们首先给这三个参数一个初始的先验分布,因为先验分布是要根据证据不断更新的,相当于一个初始值,会在后续的调整中不断地接近真实值,所以我们先验可以给的随意一些。是个离散值,最常见是用一个离散的均匀分布就完事了,,是连续值,我们用一个指数分布。有人就说啦,凭啥呀?为啥用这些做先验呢?没有凭啥,我们只是想给一个先验分布而已,你要是想用别的分布完全也可以,甚至,你可以不用已知的分布,直接一个个值的指定,也没毛病,自创一个分布。都行。
接下来的东西呢,为了方便编程,我们用到了Pymc3这个库,这是一个专门针对概率相关问题进行编程的库。还是那句话,用了方便,不用也行
# 先验分布
with pm.Model() as model:
alpha=1.0/count_data.mean()
lambda_1=pm.Exponential("lambda_1",alpha)
lambda_2=pm.Exponential("lambda_2",alpha)
tau=pm.DiscreteUniform("tau",lower=0,upper=n_count_data)
# get likelihood
lbds=np.zeros(n_count_data)
lbds[:tau]=lambda_1
lbds[tau:]=lambda_2
target=pm.Poisson("target",observed=lbds)
# 学习方法1: MAP。返回的是一个参数的数值,而不是分布! 这玩意就是极大似然求导吧(不是,要区分MLE和MAP),但是这个tau是怎么求出来的,不可导吧。 参考这篇文章https://zhuanlan.zhihu.com/p/40024110
map_estimate=pm.find_MAP(model=model)
print(map_estimate)
{'lambda_1_log__': array(-9.1772865), 'lambda_2_log__': array(-9.1772865), 'tau': array(37), 'lambda_1': array(0.00010336), 'lambda_2': array(0.00010336)}
# 学习方法2:MCMC
import arviz as az
with model:
trace=pm.sample(500,return_inferencedata=False)
az.plot_trace(trace)
display(az.summary(trace,round_to=2))
Multiprocess sampling (4 chains in 4 jobs)
CompoundStep
>NUTS: [lambda_2, lambda_1]
>Metropolis: [tau]
Sampling 4 chains for 1_000 tune and 500 draw iterations (4_000 + 2_000 draws total) took 10 seconds.
There was 1 divergence after tuning. Increase `target_accept` or reparameterize.
The number of effective samples is smaller than 25% for some parameters.
bayesian_opitimization_6_4.png
网友评论