Python 类分布之间的切换

Python 类分布之间的切换,python,theano,bayesian,pymc3,Python,Theano,Bayesian,Pymc3,我试图通过将红外光谱视为峰值、变化基线和残余噪声的总和来模拟红外光谱。峰值形状和基线模型最终将演变为更复杂的模型,但我希望从简单开始,并随着时间的推移逐渐增加复杂性。现在我有高斯峰,一个恒定的y偏移和正态分布的噪声。根据光谱所属的类别,y类偏移量来自分布A或B。目前我使用的生成数据如下所示: 我使用的模型(用PyMC3编码)看起来像: npeaks = 3 nclasses = 2 with pm.Model() as model: # priors amp = pm.Unif

我试图通过将红外光谱视为峰值、变化基线和残余噪声的总和来模拟红外光谱。峰值形状和基线模型最终将演变为更复杂的模型,但我希望从简单开始,并随着时间的推移逐渐增加复杂性。现在我有高斯峰,一个恒定的y偏移和正态分布的噪声。根据光谱所属的类别,y类偏移量来自分布A或B。目前我使用的生成数据如下所示:

我使用的模型(用PyMC3编码)看起来像:

npeaks = 3
nclasses = 2
with pm.Model() as model:
    # priors
    amp = pm.Uniform('amp', 0, x_s.max(), shape=(nclasses,npeaks))
    mu = pm.Normal('mu', mu=np.linspace(x_val.min(), x_val.max(), npeaks), sd=50, 
               shape=(nclasses,npeaks), transform=pm.distributions.transforms.ordered)
    sigma = pm.HalfNormal('sigma', sd=100, shape=(nclasses,npeaks))
    a_ = [pm.Normal('a_%d' % i, mu=0, sd=10, shape=(len(x_s),1)) for i in range(nclasses)]

    # spectral lines (per class)
    y_ = [pm.Deterministic('y_%d' % i, (amp[i] * np.exp(-(x_val - mu[i])**2/(2 * sigma[i]**2))).sum(axis=1) 
                       + a_[i]) for i in range(nclasses)]

    # labels (observed from the data, 0 or 1)
    theta = pm.Beta('theta', 1., 1.)
    label = pm.Bernoulli('label', p=theta, observed=Y)

    # switch to spectrum class A/B depending on label
    y_obs = pm.math.switch(pm.math.eq(label, 1), y_[0], y_[1])

    sigma_e = pm.Gamma('sigma_e', alpha=1., beta=1.)
    epsilon = pm.HalfNormal('epsilon', sd=sigma_e)

    y_pred = pm.Normal('y_pred', mu=y_obs, sd=epsilon, observed=x_s)
因此,根据训练数据(Y)中的标签,模型将切换到变量Y_0或Y_1

这个基本模型的问题是:

  • 我现在在两个类之间切换,但也希望在4个类之间切换,或者在这方面切换N个类。通常我会使用switch case语句之类的语句,但这不可用。在当前环境下,我如何实现这一点
还请注意: 1.类的数量是已知的和固定的(在我的例子中是2个或4个) 2.根据光谱,我知道标签Y(光谱所属的类别)

最后,目标是为Y和光谱观测(x_s)引入共享变量,以便(推断后)我可以:

  • 设置变量Y=z,并从分布z中采样
  • 设置一个(看不见的)光谱x_s[a]并从后验分布标签中取样,这样我就可以计算出光谱属于哪一类
  • 理想的解决方案如下:

    # labels (observed from the data, 0 or 1)
    theta = pm.Beta('theta', 1., 1.)
    label = pm.Bernoulli('label', p=theta, observed=Y)
    
    sigma_e = pm.Gamma('sigma_e', alpha=1., beta=1.)
    epsilon = pm.HalfNormal('epsilon', sd=sigma_e)
    
    y_pred = pm.Normal('y_pred', mu=y_[label], sd=epsilon, observed=x_s) 
    
    这样,无论标签代码是什么(在本例中为[0 | 1],但对于4个类为[0 | 1 | 2 | 3]),都可以找到正确的索引,但此解决方案会给出错误:

    `TypeError: list indices must be integers or slices, not ObservedRV`