python - 如何处理 pymc3 确定性变量的形状

标签 python theano pymc3

我一直致力于在 pymc3 中建立和运行一些心理物理行为数据的层次模型。总体上给我留下了深刻的印象,但是在尝试跟上 Theano 和 pymc3 的速度之后,我得到了一个大部分有效的模型,但是有几个问题。

构建代码是为了将 Weibull 的参数化版本拟合到七组数据。每个试验都被建模为二元伯努利结果,而阈值(thact 的输出作为 y 值,用于拟合高度、宽度和高程的高斯函数(典型高斯上的 a、c 和 d)。

使用参数化 Weibull 似乎工作得很好,现在 Weibull 的斜率是分层的,而阈值分别适合每个数据 block 。但是 - 我从 k 和 y_est 得到的输出让我相信它们的大小可能不正确,并且与概率分布不同,它看起来不像我可以指定形状(除非有一种 theano 方法来做到这一点我还没有找到 - 尽管从我读过的内容来看,在 theano 中指定形状很棘手)。

最终,我想使用 y_est 来估计高斯高度或宽度,但是现在的输出导致令人难以置信的困惑,我认为这源于 y_est 和 k 的大小问题。任何帮助都会很棒 - 下面的代码应该模拟一些数据,然后是模型。该模型在拟合每个单独的阈值和获得斜率方面做得很好,但在处理其余部分时会分崩离析。

感谢您的观看 - 到目前为止,我对 pymc3 印象深刻!

编辑:好的,所以 y_est.tag.test_value.shape 输出的形状看起来像这样

y_est.tag.test_value.shape
(101, 7)
k.tag.test_value.shape
(7,)

我认为这就是我遇到麻烦的地方,尽管它可能只是我构建得不好。 k 具有正确的形状(每个 unique_xval 一个 k 值)。 y_est 正在为每个难度级别输出一整套数据 (101x7) 而不是单个估计(每个 unique_xval 一个 y_est)。有什么方法可以指定 y_est 获取 df_y_vals 的特定子集来控制它吗?

#Import necessary modules and define our weibull function
import numpy as np
import pylab as pl    
from scipy.stats import bernoulli

#x stimulus intensity
#g chance (0.5 for 2AFC)
# m slope
# t threshold
# a performance level defining threshold 
def weib(x,g,a,m,t):
    k=-np.log(((1-a)/(1-g))**(1/t))
    return 1- (1-g)*np.exp(- (k*x/t)**m);

#Output values from weibull function
xit=101
xvals=np.linspace(0.05,1,xit)
out_weib=weib(xvals, 0.5, 0.8, 3, 0.6)

#Okay, fitting the perfect output of a Weibull should be easy, contaminate         with some noise
#Slope of 3, threshold of 0.6


#How about 5% noise!

noise=0.05*np.random.randn(np.size(out_weib))
out=out_weib+noise

#Let's make this more like a typical experiment - 
#i.e. no percent correct, just one or zero
#Randomly pick based on the probability at each point whether they got the trial right or wrong
trial=np.zeros_like(out)
for i in np.arange(out.size):
    p=out_weib[i]
    trial[i] = bernoulli.rvs(p)

#Iterate for 6 sets of data, similar slope (from a normal dist), different thresh (output from gaussian)
#Gauss parameters=

true_gauss_height = 0.3
true_gauss_width = 0.01
true_gauss_elevation = 0.2

#What thresholds will we get then? 6 discrete points along that gaussian, from 0 to 180 degree mask

x_points=[0, 30, 60, 90, 120, 150, 180]

x_points=np.asarray(x_points)
gauss_points=true_gauss_height*np.exp(-    ((x_points**2)/2*true_gauss_width**2))+true_gauss_elevation

import pymc as pm2
import pymc3 as pm
import pandas as pd

slopes=pm2.rnormal(3, 3, size=7)
out_weib=np.zeros([xvals.size,x_points.size])

for i in np.arange(x_points.size):
    out_weib[:,i]=weib(xvals, 0.5, 0.8, slopes[i], gauss_points[i])

#Let's make this more like a typical experiment - i.e. no percent correct, just one or zero
#Randomly pick based on the probability at each point whether they got the trial right or wrong
trials=np.zeros_like(out_weib)

for i in np.arange(len(trials)):
    for ii in np.arange(gauss_points.size):
        p=out_weib[i,ii]
        trials[i,ii] = bernoulli.rvs(p)

#Let's make that data into a DataFrame for pymc3
y_vals=np.tile(xvals, [7, 1])

df_correct = pd.DataFrame(trials, columns=x_points)
df_y_vals = pd.DataFrame(y_vals.T, columns=x_points)
unique_xvals=x_points

import theano as th

with pm.Model() as hierarchical_model:
    # Hyperpriors for group node
    mu_slope = pm.Normal('mu_slope', mu=3, sd=1)
    sigma_slope = pm.Uniform('sigma_slope', lower=0.1, upper=2)

#Priors for the overall gaussian function - 3 params, the height of the gaussian
#Width, and elevation

gauss_width = pm.HalfNormal('gauss_width', sd=1)
gauss_elevation = pm.HalfNormal('gauss_elevation', sd=1)

slope = pm.Normal('slope', mu=mu_slope, sd=sigma_slope,     shape=unique_xvals.size)

thresh=pm.Uniform('thresh', upper=1, lower=0.1, shape=unique_xvals.size)

k = -th.tensor.log(((1-0.8)/(1-0.5))**(1/thresh))
y_est=1-(1-0.5)*th.tensor.exp(-(k*df_y_vals/thresh)**slope)

#We want our model to predict either height or width...height would be easier.
#Our Gaussian function has y values estimated by y_est as the 82% thresholds
#and Xvals based on where each of those psychometrics were taken.
#height_est=pm.Deterministic('height_est', (y_est/(th.tensor.exp((-unique_xvals**2)/2*gauss_width)))+gauss_elevation)
height_est = pm.Deterministic('height_est', (y_est-gauss_elevation)*th.tensor.exp((unique_xvals**2)/2*gauss_width**2))

#Define likelihood as Bernoulli for each binary trial
likelihood = pm.Bernoulli('likelihood',p=y_est, shape=unique_xvals.size, observed=df_correct)

#Find start
start=pm.find_MAP()
step=pm.NUTS(state=start)
#Do MCMC
trace = pm.sample(5000, step, njobs=1, progressbar=True) # draw 5000 posterior samples using NUTS sampling

最佳答案

当你说“有没有办法指定 y_est 获取 df_y_vals 的特定子集来控制它”时,我不确定你到底想做什么。你能为每个 y_est 值描述你应该使用什么 df_y_vals 值吗? df_y_vals 的形状是什么? y_est 应该是什么形状? (7,)?

我怀疑你想要的是使用 numpy advanced indexing 索引到 df_y_vals ,它在 PyMC 中的工作方式与在 numpy 中的相同。没有更多信息,很难准确地说。

关于python - 如何处理 pymc3 确定性变量的形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30055969/

相关文章:

python - Unpickling 失败,__new__() 恰好需要 1 个参数(给定 2 个)

python - 填充 Pandas 中缺失的索引

python - Windows 上的 Theano 与 Anaconda : how to setup BLAS?

python - 为什么我无法在 theano 中评估 reshape 的张量变量?

python - 从 pymc2 到 PyMC3 的 CAR 模型

python-3.x - 具有随机效应的多级回归中变量的解释

python - 如何以交互方式更新 matplotlib imshow() 窗口?

python - 由属性确定的唯一数据库条目

python - 如何卸载 Keras?

python - 将 numpy 函数转换为 theano