Переключение между распределениями классов - PullRequest
1 голос
/ 13 января 2020

Я пытаюсь смоделировать ИК-спектры, рассматривая их как суммирование пиков, изменяющейся базовой линии и остаточного шума. Формы пиков и базовая модель со временем превратятся в более сложную модель, но я хочу начать с простого и наращивать сложность по мере того, как я go. На данный момент у меня есть пики Гаусса, постоянное смещение по оси Y и нормально распределенный шум. В зависимости от класса, к которому принадлежит спектр, смещение y по классу зависит от распределения A или B. В настоящее время я использую сгенерированные данные, которые выглядят следующим образом: моделируемый спектр для классов 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.

Проблема, с которой я столкнулся в этой базовой модели c, заключается в следующем:

  • Сейчас я переключаюсь между 2 классами, но также хотел бы переключаться между 4 классами или N-классами в этом отношении. , Обычно я бы использовал что-то вроде оператора регистра переключателя, но это недоступно. Как я могу добиться этого в текущем контексте?

Обратите также внимание, что: 1. Количество классов известно и фиксировано (2 или 4 в моем случае) 2. Для каждого спектра я знаю метку Y (к какому классу относится спектр)

В конце, цель состоит в том, чтобы ввести общие переменные для Y и спектральные наблюдения (x_s), чтобы (после логического вывода) я мог:

  1. установите переменную Y = z и выборку из распределения z
  2. установите (невидимый) спектр 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] в этом случай, но [0 | 1 | 2 | 3] для 4 классов), правильный индекс найден, но это решение дает ошибку:

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