微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从具有 2 个预测变量的分层模型中绘制多个散点图

如何解决从具有 2 个预测变量的分层模型中绘制多个散点图

我是 python 和 pymc3 的新手。如果这个问题相当愚蠢,请原谅我。我有一个名为 toy_data.csv 的数据集:

batch_no batch_id pred1 pred2
12-150 1 1 70.26 10.766
12-150 1 2 65.72 10.512
12-150 1 6 55.44 7.78
12-150 1 4 63.554 12.552
12-150 1 5 61.66 10.95
12-150 1 3 65.44 10.808
12-190 2 3 55.68 6.36
12-190 2 4 67.36 7.38
12-190 2 1 78 9.32
12-190 2 2 70.12 8.554
12-190 3 5 60.68 9.568
12-190 3 3 68.694 9.634
12-190 3 2 56.118 11.474
12-190 3 4 58.54 9.31
12-190 3 6 65.08 10.604
13-999 4 6 56.73 9.754
13-999 4 3 55.492 9.4
13-999 4 2 51.556 9.802
13-999 4 1 53.748 8.85
13-999 4 5 59.054 9.204
13-999 4 4 49.77 9.468
13-999 4 7 58.266 9.954
13-999 4 8 57.78 9.38
14-140 5 2 69.68 12.086
14-140 5 1 68.5 10.438
14-140 5 6 71.7 11.624
14-140 5 3 63.68 11.058
14-140 5 4 62.02 10.498
14-140 5 5 61.94 10.95
14-140 5 9 57.22 10.164
14-140 5 7 54.44 9.798
14-140 5 8 60.82 10.784
14-290 6 1 56.2 9.566
14-290 6 1 50.06 9.23
14-290 6 2 50.76 10.646
14-290 6 2 46.98 8.38
14-700 7 2 92.8 11.532
14-700 7 1 81 9.522
14-700 7 3 75.62 10.004
14-700 8 2 71.44 10.076
14-889 8 1 55.2 8.1
14-889 8 3 71.18 9.412
14-889 8 4 53.24 7.138
14-900 9 3 50.08 7.744
14-900 9 1 47.138 8.294
14-900 9 4 68.56 11.362
14-900 9 1 69.34 11.584
14-900 9 2 63.14 10.77

我想从分层模型跟踪中获取相关批次和预测器来绘制它们并拟合 abline 线。最终输出是复制下面的图表,但不是灰度范围,我想显示每个批次的 abline。

Ideal output (sourced from github)

例如:

Abline = y_best_fit_i=(mu_a+a_i)+[(mu_b+b_i)*pred_i] 使用来自相应 x 变量(pred1 或 pred2)的均值和标准差对所有参数进行回缩。仅考虑 pred1,后缩放公式为 mu_a = (mu_a*pred1.std()) + pred1.mean()​​​;这将应用于 mu_b 和所有 a_i 和 b_i 值。但是,按照 pred1 均值和 std dev 的后缩放仅适用于来自 pred1 的跟踪,而不适用于 pred2(即它将适用于 mu_a、mu_b 和 a[0,0] 和 b[0,0],但不适用于a[0,1,0] 或 b[0,0])。我想只适用于 mu_a,mu_b,a[i,0] 和 b[i,0] 在我应该是 batch_no 的地方(见下表),如果可能的话,让它自动化。下表是跟踪的摘要

Summary Table

如果我能找到一种方法从跟踪本身获取数字以绘制最终图形,那就太好了。非常感谢任何帮助。

我用来建模的代码如下:

import pandas as pd
import numpy as np
import pymc3 as pm
from sklearn import preprocessing

seed = 68492
np.random.seed(seed)

data = pd.read_csv("toy_data.csv")    

# assigning variables
batch_no = data.iloc[:,0]
batch_id = (data.iloc[:,1])-1
point = data.iloc[:,2]
pred = data.iloc[:,3:5]
pred1 = data.iloc[:,3]
pred2 = data.iloc[:,4]


# creating indicators
n_pred = pred.shape[1]
n_batch = len(np.unique(batch_id))

# standarising variable
std_pred = preprocessing.scale(pred)


# Hierarchical model 
with pm.Model() as hierarchical_model1:

    # Hyperpriors
    mu_a = pm.normal('mu_a',mu=0,sigma=100)
    sigma_a = pm.Halfnormal('sigma_a',sigma=100)
    mu_b = pm.normal('mu_b',sigma=100)
    sigma_b = pm.Halfnormal('sigma_b',sigma=100)   
    

    # Intercept for each batch,distributed around group mean mu_a
    a = pm.normal('a',mu=mu_a,sd=sigma_a,shape=(n_batch,n_pred,1))
    # Slope for each batcht,distributed around group mean mu_b
    b = pm.normal('b',mu=mu_b,sd=sigma_b,1))
    
    # Model error
    eps = pm.HalfCauchy('eps',beta=5)
    
        
    # Expected value
    omega = (pm.math.dot(std_pred,b))[batch_id,1]
    tpoint_est = a[batch_id,1] + omega

         
    # Data likelihood
    y_like = pm.normal('y_like',mu=tpoint_est,sigma=eps,observed=point)
    

with hierarchical_model1:
    hier_trace = pm.sample(draws = 4000,tune = 1000,chains = 2)
    hier_out = pm.summary(hier_trace)

解决方法

这是我所拥有的,它应该可以解决批处理/预测循环问题并作为 你真正想做的事情的骨架。我无法遵循缩放和重新缩放。我也无法理解长度为 1 的 3dr 维度 但我一直把它放在那里。

请注意,我使用的是建立在 xarray 之上的 ArviZ(PyMC3 的依赖项) 使用基于标签的索引和自动广播。而且我实际上正在使用添加到 ArviZ(开发版)和 PyMC3 3.11.1 的最新功能。您可以使用 pip install git+git://github.com/arviz-devs/arviz.git 安装 ArviZ 开发版。

我首先对模型进行了一些更改,以定义具有命名维度的变量的形状:

coords = {
    "batch": np.arange(n_batch),"pred_num": ["pred1","pred2"],"one": [1]
}
with pm.Model(coords=coords) as hierarchical_model1:
    ...

    # Intercept for each batch,distributed around group mean mu_a
    a = pm.Normal('a',mu=mu_a,sd=sigma_a,dims=("batch","pred_num","one"))
    # Slope for each batcht,distributed around group mean mu_b
    b = pm.Normal('b',mu=mu_b,sd=sigma_b,"one"))
    
    ...

其余代码完全相同,除了在我添加 kwarg return_inferencedata=True 的地方进行采样时。

采样后,我从 pred 数组创建了一个 xarray 数据集,以便利用我上面提到的 xarray 提供的自动广播。因为我已经设置了 return_inferencedata=True 我已经有了所有的变量 在 xarray 对象的模型中。要创建一个 xarray 变量,我们必须提供 值、维度名称和坐标变量:

import xarray as xr
pred_ds = xr.DataArray(
    pred,dims=("x","pred_num"),coords={"pred_num": coords["pred_num"]}
).to_dataset(name="pred")
post = hier_trace.posterior
y_ds = (post["mu_a"]+post["a"])+(post["mu_b"]+post["b"])*pred_ds
y_ds # in jupyter you'll see a nice html interactive summary
# here is the plain text output
# <xarray.Dataset>
# Dimensions:   (batch: 9,chain: 4,draw: 1000,one: 1,pred_num: 2,x: 48)
# Coordinates:
#   * pred_num  (pred_num) <U5 'pred1' 'pred2'
#   * chain     (chain) int64 0 1 2 3
#   * draw      (draw) int64 0 1 2 3 4 5 6 7 8 ... 992 993 994 995 996 997 998 999
#   * batch     (batch) int64 0 1 2 3 4 5 6 7 8
#   * one       (one) int64 1
# Dimensions without coordinates: x
# Data variables:
#     pred      (chain,draw,batch,pred_num,one,x) float64 1.938e+03 ... 67.98

然后我们可以使用 ArviZ 遍历所需的变量并生成一个子图 对于每个批次和 pred 的组合。虽然看起来很奇怪,因为 根本没有重新缩放。

import matplotlib.pyplot as plt
fig,axes = plt.subplots(n_pred,n_batch,figsize=(11,5),sharex=True,sharey="row")
x = np.arange(len(batch_id))

第一步是创建我们将用于绘图的 suplots,以及一个虚拟变量来表示 x。

from arviz.labels import BaseLabeller
labeller = BaseLabeller()
iterator = az.sel_utils.xarray_var_iter(
    y_ds.squeeze().transpose("chain","draw","x","batch"),combined=True,skip_dims={"x",}
)

然后我们创建这个迭代器对象,标签器纯粹是美学的(并且有详细的文档here)。第一步是转置 y_ds。这也是审美, 如果批次维度出现在之前,那么在绘图时我们不会在同一行看到所有的 pred1。 combined=Trueskip_dims 表示我们不想迭代链或 x 维度中的值(默认情况下,ArviZ 从不迭代绘制。现在我们可以使用这个循环获取数组的迭代器 chain,x 维度,因此我们可以绘制 HDI,均值...并获得类似于问题中示例的图:

for ax,(_,sel,isel,values) in zip(axes.ravel(),iterator):
    az.plot_hdi(x,values,ax=ax)
    ax.plot(x,values.mean(axis=(0,1)))
    ax.set_title(labeller.make_label_vert("y",isel))
fig.tight_layout()

plot

请注意,yaxis 仅在行之间共享,pred1 和 pred2 的比例是一个数量级不同的,即使它们与此绘图布局看起来相似。

旁注:我遇到了很多分歧,大多数rhat值都在推荐的1.01以上。我很确定 NUTS 没有收敛,你可能不应该相信这些结果。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。