2016-11-29 5 views
10

pymc3에서 3 단계 로지스틱 회귀 모델을 만들려고합니다. 중간 레벨 계수는 최상위 계수에서 추정되는 최상위 레벨, 중간 레벨 및 개별 레벨이 있습니다. 그러나 중간 수준의 적절한 데이터 구조를 지정하는 데 어려움이 있습니다.pymc3에서 3 단계 로지스틱 회귀 모델 만들기

with pm.Model() as model: 
    # Hyperpriors 
    top_level_tau = pm.HalfNormal('top_level_tau', sd=100.) 
    mid_level_tau = pm.HalfNormal('mid_level_tau', sd=100.)  

    # Priors 
    top_level = pm.Normal('top_level', mu=0., tau=top_level_tau, shape=k_top) 
    mid_level = [pm.Normal('mid_level_{}'.format(j), 
          mu=top_level[mid_to_top_idx[j]], 
          tau=mid_level_tau) 
       for j in range(k_mid)] 

    intercept = pm.Normal('intercept', mu=0., sd=100.) 

    # Model prediction 
    yhat = pm.invlogit(mid_level[mid_to_bot_idx] + intercept) 

    # Likelihood 
    yact = pm.Bernoulli('yact', p=yhat, observed=y) 

나는 내가 mid_level 변수 목록이 아닌 적절한 pymc 컨테이너 사실에 관한 생각 (라인 16) 오류 "only integer arrays with one element can be converted to an index"을 받고 있어요 :

여기 내 코드입니다. (pymc3 소스 코드에서 Container 클래스가 보이지 않습니다.)

도움이 되셨을 것입니다.

편집 : 추가 일부 모의 데이터

y = np.array([0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0]) 
mid_to_bot_idx = np.array([0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 3, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 2, 2, 3, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 2, 3, 3, 2, 2, 3, 2]) 
mid_to_top_idx = np.array([0, 0, 1, 1]) 
k_top = 2 
k_mid = 4 

편집 # 2 :

1) : 없음이 완전히 만족하지 않지만

이 문제를 해결하기위한 몇 가지 방법이 될 것 같다 모델을 다음과 같이 다시 프레임 할 수 있습니다.

with pm.Model() as model: 
    # Hyperpriors 
    top_level_tau = pm.HalfNormal('top_level_tau', sd=100.) 
    mid_level_tau = pm.HalfNormal('mid_level_tau', sd=100.)  

    # Priors 
    top_level = pm.Normal('top_level', mu=0., tau=top_level_tau, shape=k_top) 
    mid_level = pm.Normal('mid_level', mu=0., tau=mid_level_tau, shape=k_top) 
    intercept = pm.Normal('intercept', mu=0., sd=100.) 

    # Model prediction 
    yhat = pm.invlogit(top_level[top_to_bot_idx] + mid_level[mid_to_bot_idx] + intercept) 

    # Likelihood 
    yact = pm.Bernoulli('yact', p=yhat, observed=y) 

중급 수준의 분산이 모든 중간 수준 그룹에 대해 일정하지 않은 경우로 확장하는 방법을 이해할 수 없습니다. 하나는 theano.tensor.stack 사용하여 Theano 텐서에 중간 수준의 계수를 포장 할 수

2) : 즉,

import theano.tensor as tt 
mid_level = tt.stack([pm.Normal('mid_level_{}'.format(j), 
          mu=top_level[mid_to_top_idx[j]], 
          tau=mid_level_tau) 
       for j in range(k_mid)]) 

는하지만 내 실제 데이터 세트에서 매우 느리게 실행하는 것 (30K 관찰) , 플로팅이 불편 해집니다 (각 mid_level 계수는 pm.traceplot을 사용하여 자체 추적을 얻습니다).

어쨌든 개발자의 조언/의견을 보내 주시면 감사하겠습니다. 이렇게 대체는 어떤 분포 (같은 pm.Normal)는 인자 수단의 벡터를 수신 할 수 있음을 표시 :

theta = pm.Deterministic('theta', pm.invlogit(sum(mid_level[i] for i in mid_to_bot_idx)+intercept)) 
yact = pm.Bernoulli('yact', p=theta, observed=y) 
+1

@ gung 지금은 괜찮아 보이니? – vbox

+0

고마워요. 파이썬에서의 코딩에 관한 질문은 여기서 다루지 않지만 [SO]에 관한 주제가 될 수 있습니다. 기다리면 여기에서 질문을 이전하려고 시도 할 것입니다. – gung

+3

필자는 이것이 오프 토픽 (off-topic)이라는 것에 동의하지 않는다 : 이것은 일반적인 파이썬 코딩 질문이 아니다. 이 질문은 성숙한 파이썬 통계 패키지를 사용하여 통계 모델을 구현하는 것입니다. 그 대답은 모델을 다른 방식으로 나타낼 수 있습니다. – JBWhitmore

답변

3

밝혀 용액 간단했다

1

약간 변화 (I은 세타에 yhat 변경된 주) 이 라인이

mid_level = pm.Normal('mid_level', 
         mu=top_level[mid_to_top_idx], 
         tau=mid_level_tau, 
         shape=k_mid) 

작품과

mid_level = [pm.Normal('mid_level_{}'.format(j), 
         mu=top_level[mid_to_top_idx[j]], 
         tau=mid_level_tau) 
      for j in range(k_mid)] 

. 동일한 방법을 사용하여 각 중간 수준 그룹의 개별 표준 편차를 지정할 수도 있습니다.

수정 : 수정 타이프

+0

나는 이것이 내가 바라는 것을하지 않는다고 생각한다. 이것은 모든 관측에 대해 세타의 단일 값을 얻기 위해 모든 계수를 합한 것 같습니다. top_level과 mid_level에 따라 각 관측마다 다른 테타가 필요합니다. 즉, 세타는 스칼라가 아닌 y와 동일한 길이의 벡터 여야합니다. 예를 들어, 다음 모델을 참조하십시오. http://nbviewer.jupyter.org/github/aflaxman/pymc-examples/blob/master/seeds_re_logistic_regression_pymc3.ipynb – vbox

+0

@vbox 네, 동의하는 경향이 있습니다. 원래 코드는 mid_to_bot_idx 배열로 mid_level 배열을 단순히 재정렬 (및 일부 값을 복제)했습니다. 코드에 표시된 것과 똑같이 구현했습니다. –

+0

보통 invlogit의 인수는 (x * beta + intercept)와 같습니다. 여기서 x는 피쳐이고 베타는 회귀 계수이며 절편은 바이어스 항입니다. –