注:基于现有案例教程
鸢尾花数据来源于seaborn中自带的数据集,很多类似的都会自带这个数据集
代码如下:
import pymc3 as pm
import pandas as pd
import scipy.stats as stats
import theano.tensor as tt
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
if __name__=='__main__':
#载入数据集
iris = sns.load_dataset("iris")
#花萼长度这一特征(自变量)来区分 setosa 和 versicolor 这两个种类
df = iris.query("species == ('setosa', 'versicolor')")
y_0 = pd.Categorical(df['species']).codes
x_n = 'sepal_length'
x_0 = df[x_n].values
#上面已经将数据已经表示成了合适的格式,用PyMC3来建模
#用with语句定义了一个上下文管理器 context manager ,并定义了一个新的模型对象,这个对象是模型中随机变量的容器
with pm.Model() as model_0:
#上下文中定义了两个具有正态分布先验的随机性随机变量
alpha = pm.Normal('alpha', mu=0, sd=10)
beta = pm.Normal('beta', mu=0, sd=10)
#两个确定变量:theta 和 bd。theta 是对变量 mu 应用逻辑函数之后的值,bd 是一个有边界的值,用于确定分类结果
mu = alpha + pm.math.dot(x_0, beta)
theta = pm.Deterministic('theta', 1 / (1 + pm.math.exp(-mu)))
bd = pm.Deterministic('bd', -alpha / beta)
#二元分类->伯努利可能性
yl = pm.Bernoulli('yl', theta, observed=y_0)
start = pm.find_MAP()
step = pm.NUTS()
#step 参数指定特定的采样器(迭代器)来替换默认的迭代器NUTS
trace_0 = pm.sampling.sample(500, step, start) # 本地运行时,推荐将迭代次数设置为大于 1000 次,这里是500+默认500=1000
varnames = ['alpha', 'beta', 'bd']
pm.traceplot(trace_0, varnames)
theta = trace_0['theta'].mean(axis=0)
idx = np.argsort(x_0)
plt.plot(x_0[idx], theta[idx], color='b', lw=3);
#绘制一条横跨当前图表的垂直/水平辅助线,x:恒坐标,
plt.axvline(trace_0['bd'].mean(), ymax=1, color='r')
bd_hpd = pm.hpd(trace_0['bd'])
#水平防线,x1和x2之间填充
plt.fill_betweenx([0, 1], bd_hpd[0], bd_hpd[1], color='r', alpha=0.5)
#绘制折线图
plt.plot(x_0, y_0, 'o', color='k')
theta_hpd = pm.hpd(trace_0['theta'])[idx]
#y1和y2之间填充
plt.fill_between(x_0[idx], theta_hpd[:, 0], theta_hpd[:, 1], color='b', alpha=0.5)
plt.xlabel(x_n, fontsize=16)
plt.ylabel(r'$\theta$', rotation=0, fontsize=16)
plt.show()
运行结果:
这张图表示了花萼长度与花的种类(setosa = 0, versicolor =1)之间的关系。蓝色的 S 型曲线表示 theta 的均值,这条线可以解释为:在知道花萼长度的情况下花的种类是 versicolor 的概率。