2014-10-23 5 views
2

Я пытаюсь реализовать байесовский PCA, используя PyMC-библиотеку для python. Но, я застрял где я определяю более низкие пространственные координаты ...bayesian pca using PyMC

Модели

х = Wz + е

где х векторы наблюдений, W представляет матрицу преобразования, и г - вектор с более низкой размерной координатой.

Сначала я определить распределение для матрицы преобразования W. Каждый столбец рисуется из нормального распределения (нулевое среднее, и идентичность ковариационной для простоты)

def W_logp(value): 
    logLikes = np.array([multivariate_normal.logpdf(value[:,i], mean=np.zeros(dimX), cov=1) for i in range(0, dimZ)]) 
    return logLikes.sum() 

def W_random(): 
    W = np.zeros([dimX, dimZ]) 
    for i in range(0, dimZ): 
     W[:,i] = multivariate_normal.rvs(mean=np.zeros(dimX), cov=1) 
    return W 

w0 = np.random.randn(dimX, dimZ) 

W = pymc.Stochastic(
    logp = W_logp, 
    doc = 'Transformation', 
    name = 'W', 
    parents = {}, 
    random = W_random, 
    trace = True, 
    value = w0, 
    dtype = float, 
    rseed = 116., 
    observed = False, 
    cache_depth = 2, 
    plot = False, 
    verbose = 0) 

Затем я хочу определить распределение по г, что снова является многомерным нормальным (нулевое среднее и ковариация тождеств). Тем не менее, мне нужно нарисовать z для каждого наблюдения отдельно, в то время как W является общим для всех из них. Итак, я попытался

z = pymc.MvNormal('z', np.zeros(dimZ), np.eye(dimZ), size=N) 

Однако pymc.MvNormal не имеет размер параметра. Поэтому возникает ошибка. Следующий шаг должен был бы

m = Data.mean(axis=0) + np.dot(W, z) 
obs = pymc.MvNormal('Obs', m, C, value=Data, observed=True) 

я не давал спецификации для C выше, так как это не имеет значения, на данный момент. Любые идеи, как реализовать?

Благодаря

EDIT

После ответа Криса Fonnesbeck, я изменил код следующим

numD, dimX = Data.shape 
dimZ = 3 
mm = Data.mean(axis=0) 

tau = pymc.Gamma('tau', alpha=10, beta=2) 
tauW = pymc.Gamma('tauW', alpha=20, beta=2, size=dimZ) 

@pymc.deterministic(dtype=float) 
def C(tau=tau): 
    return (tau)*np.eye(dimX) 

@pymc.deterministic(dtype=float) 
def CW(tau=tauW): 
    return np.diag(tau) 

W = [pymc.MvNormal('W%i'%i, np.zeros(dimZ), CW) for i in range(dimX)] 
z = [pymc.MvNormal('z%i'%i, np.zeros(dimZ), np.eye(dimZ)) for i in range(numD)] 
mu = [pymc.Lambda('mu%i'%i, lambda W=W, z=z: mm + np.dot(np.array(W), np.array(z[i]))) for i in range(numD)] 

obs = [pymc.MvNormal('Obs%i'%i, mu[i], C, value=Data[i,:], observed=True) for i in range(numD)] 

model = pymc.Model([tau, tauW] + obs + W + z) 
mcmc = pymc.MCMC(model) 

Но на этот раз, он пытается выделить огромное количество памяти (более 8 Гб), когда бег pymc.MCMC(model), с numD=45 и dimX=504. Даже когда я пробовал это только с numD=1 (поэтому создание только 1 z, mu и obs), он делает то же самое. Любая идея почему?

ответ

3

К сожалению, PyMC не просто позволяет вам определить векторы многомерных стохастик. Надеюсь, мы сможем это сделать в PyMC 3. На данный момент вам нужно будет указать это с помощью контейнера. Например:

z = [pymc.MvNormal('z_%i' % i, np.zeros(dimZ), np.eye(dimZ)) for i in range(N)] 
+0

Спасибо за ответ. Позвольте мне добавить еще один, есть ли способ использовать __plates__, как в графических моделях, в PyMC? В самом деле, было бы очень полезно иметь любой пример, сначала предоставляя графическую модель, а затем кодирующуюся в PyMC. – ahmethungari

+0

См. Мой EDIT в вопросе – ahmethungari

1

Что касается проблемы с памятью, попробуйте использовать другой бэкэнд для следов. Значение по умолчанию ("ram") хранит все в ОЗУ. Вместо этого вы можете попробовать что-то вроде "pickle" или "sqlite".

Что касается обозначения пластины, это может быть что-то, что мы могли бы предпринять для PyMC 3. Не стесняйтесь создавать проблему, предлагая это в our issue tracker.