如何在PyMC3中包含分类分布作为观察数据?

时间:2016-09-09 22:38:41

标签: python pymc3 probability-theory

我有一个数据集,其中每个观测基本上是一系列噪声测量,其中一个测量包含信号。

原始观察数据 y

[[  1.93542253e-01   1.39657327e-04   7.53918636e-01   5.23994535e-02]
 [  6.44964587e-02   8.50087384e-01   1.09894665e-02   7.44266910e-02]
 [  1.68387463e-02   5.38121456e-01   6.98554551e-02   3.75184342e-01]
 ..., 
 [  5.79786789e-01   1.47417427e-02   3.15395731e-01   9.00757372e-02]
 [  8.66796124e-02   8.66999904e-02   4.47848127e-02   7.81835584e-01]
 [  8.18765043e-01   3.23448859e-03   5.61247840e-04   1.77439220e-01]]

我想根据这些测量数据将每个观察结果放入适当的聚类中。例如,上面的第一个数据点是从第三列绘制的,而上面的第二个数据点是从第二列绘制的。如果我从已知的原始分布中抽样并将这些样本作为分类的输入提供给模型,我可以取回原始分布。

从原始数据中采样 y_choice

[ 2.  3.  3.  1.  2.  2.  2.  2.  3.  3.  1.  2.  3.  0.  2.  0.  3.  1.
  3.  0.  2.  0.  3.  0.  2.  0.  1.  0.  3.  0.  2.  0.  0.  0.  3.  0.
  2.  0.  0.  3.  3.  1. ...

然而,这似乎是因为我选择的采样器不在PyMC模型中而丢失了信息。如何将实际观察到的数据 y 直接提供给模型?我猜测它与基于Dirichlet的另一个模型参数有关,但我还没有能够理解其工作原理。

以下操作的示例代码I'。我希望能够将 y 提供给模型并重新启动 true_probs ,但我只是设法让它与 y_choice一起使用到目前为止。

import numpy as np
from pymc3 import *
import pymc3 as pm
import pandas as pd
print 'pymc3 version: ' + pm.__version__


def generate_noisy_observations():
    y = np.ones((sample_size,k))
    for i in range(sample_size):
        #print("Iteration %d" % i)
        true_category = np.random.choice(k, size=1, p=true_probs)
        true_distribution = np.zeros(k)
        true_distribution[true_category] = 1
        noise_distribution = np.random.dirichlet(np.ones(k))

        noise = np.random.normal(0,1,k)

        distribution_weights = [0.9, 0.1]
        raw_distribution = (true_distribution*distribution_weights[0] + noise**2*distribution_weights[1] )/\       (np.sum(true_distribution*distribution_weights[0])+np.sum(noise**2*distribution_weights[1]))
        y[i] = raw_distribution
return y

def generate_choices_from_noisy_observations(y):
    y_choice = np.ones(sample_size)
    for i in range(sample_size):
        y_choice[i] = np.random.choice(k, size=1, p=y[i])
    return y_choice

sample_size = 1000

true_probs = [0.2, 0.1, 0.3, 0.4]
k = len(true_probs)


y = generate_noisy_observations()

y_choice = generate_choices_from_noisy_observations(y)

with pm.Model() as multinom_test:
    probs = pm.Dirichlet('a', a=np.ones(k))
    #data = Categorical('data',p = probs, observed = y)
    data = Categorical('data',p = probs, observed = y_choice)
    start = pm.find_MAP()
    trace = pm.sample(50000, pm.Metropolis())

pm.traceplot(trace[500:])

0 个答案:

没有答案