MCMC 및 PyMC를 사용한 2- 가우스 혼합 모델 추정


10

문제

간단한 2- 가우스 혼합 모집단의 모형 매개 변수를 적합하게 만들고 싶습니다. 베이지안 방법에 대한 과대 광고가 주어지면이 문제에 대해 베이지안 추론이 전통적인 피팅 방법보다 더 나은 도구인지 이해하고 싶습니다.

지금까지 MCMC는이 장난감 예제에서 성능이 좋지 않지만 아마도 간과했을 것입니다. 코드를 보자.

도구들

파이썬 (2.7) + scipy stack, lmfit 0.8 및 PyMC 2.3을 사용합니다.

분석을 재현하는 노트북은 여기 에서 찾을 수 있습니다

데이터 생성

먼저 데이터를 생성하자 :

from scipy.stats import distributions

# Sample parameters
nsamples = 1000
mu1_true = 0.3
mu2_true = 0.55
sig1_true = 0.08
sig2_true = 0.12
a_true = 0.4

# Samples generation
np.random.seed(3)  # for repeatability
s1 = distributions.norm.rvs(mu1_true, sig1_true, size=round(a_true*nsamples))
s2 = distributions.norm.rvs(mu2_true, sig2_true, size=round((1-a_true)*nsamples))
samples = np.hstack([s1, s2])

히스토그램은 samples다음과 같습니다.

데이터 히스토그램

"광범위한 피크"의 경우, 구성 요소는 눈으로보기가 어렵습니다.

고전적인 접근 방식 : 히스토그램 맞추기

먼저 고전적인 접근 방식을 시도해 봅시다. 사용 lmfit를 이 2 피크 모델을 정의하기 쉽습니다 :

import lmfit

peak1 = lmfit.models.GaussianModel(prefix='p1_')
peak2 = lmfit.models.GaussianModel(prefix='p2_')
model = peak1 + peak2

model.set_param_hint('p1_center', value=0.2, min=-1, max=2)
model.set_param_hint('p2_center', value=0.5, min=-1, max=2)
model.set_param_hint('p1_sigma', value=0.1, min=0.01, max=0.3)
model.set_param_hint('p2_sigma', value=0.1, min=0.01, max=0.3)
model.set_param_hint('p1_amplitude', value=1, min=0.0, max=1)
model.set_param_hint('p2_amplitude', expr='1 - p1_amplitude')
name = '2-gaussians'

마지막으로 단순 알고리즘을 사용하여 모델을 적합시킵니다.

fit_res = model.fit(data, x=x_data, method='nelder')
print fit_res.fit_report()

결과는 다음 이미지입니다 (빨간색 점선이 중심에 맞춰 짐).

NLS 맞춤 결과

문제가 어려운 경우에도 적절한 초기 값과 제약 조건으로 모델이 상당히 합리적인 추정치로 수렴되었습니다.

베이지안 접근 : MCMC

PyMC에서 모델을 계층 적 방식으로 정의합니다. centers그리고 sigmas2 개 센터와 2 가우시안의 2 sigmas를 나타내는 하이퍼 파라미터에 대한 전과 배포합니다. alpha첫 번째 모집단의 비율이며 이전 분포는 여기 베타입니다.

범주 형 변수는 두 모집단 중에서 선택합니다. 이 변수는 데이터와 크기가 같아야한다는 것을 이해하고 있습니다 ( samples).

마지막으로 mu하고 tau정규 분포 (그들이에 좌우의 파라미터를 결정하는 결정적인 변수는 category그들이 임의로 두 집단에 대한 두 값 사이를 전환 할 수 있도록 변수).

sigmas = pm.Normal('sigmas', mu=0.1, tau=1000, size=2)
centers = pm.Normal('centers', [0.3, 0.7], [1/(0.1)**2, 1/(0.1)**2], size=2)
#centers = pm.Uniform('centers', 0, 1, size=2)

alpha  = pm.Beta('alpha', alpha=2, beta=3)
category = pm.Categorical("category", [alpha, 1 - alpha], size=nsamples)

@pm.deterministic
def mu(category=category, centers=centers):
    return centers[category]

@pm.deterministic
def tau(category=category, sigmas=sigmas):
    return 1/(sigmas[category]**2)

observations = pm.Normal('samples_model', mu=mu, tau=tau, value=samples, observed=True)
model = pm.Model([observations, mu, tau, category, alpha, sigmas, centers])

그런 다음 꽤 긴 반복 횟수로 내 MCMC를 실행합니다 (시스템에서 1e5, ~ 60 초).

mcmc = pm.MCMC(model)
mcmc.sample(100000, 30000)

그러나 결과는 매우 이상합니다. 예를 들어 trace (첫 번째 모집단의 비율)는 0.4로 수렴하는 경향이 있으며 매우 강한 자기 상관을 갖습니다.α

MCMC 알파 요약

또한 가우시안 중심도 수렴하지 않습니다. 예를 들면 다음과 같습니다.

MCMC centers_0 요약

이전 선택에서 알 수 있듯이 이전 모집단 분수 대한 베타 분포를 사용하여 MCMC 알고리즘을 "도움"하려고했습니다 . 또한 센터와 시그마에 대한 이전 배포판은 상당히 합리적입니다.α

무슨 일이야? 내가 잘못했거나 MCMC가이 문제에 적합하지 않습니까?

MCMC 방법이 느리다는 것을 알고 있지만 사소한 히스토그램 맞춤은 모집단을 해결하는 데 엄청나게 더 나은 것으로 보입니다.

답변:


6

PyMC가이 모델에 대한 샘플을 그리는 방식으로 인해 문제가 발생합니다. PyMC 설명서의 5.8.1 섹션에 설명 된대로 배열 변수의 모든 요소가 함께 업데이트됩니다. 이와 같은 작은 배열의 center경우 문제가되지 않지만 큰 배열의 category경우 수용 률이 낮습니다. 당신은 수락 비율을 통해 볼 수 있습니다

print mcmc.step_method_dict[category][0].ratio

설명서에서 제안 된 솔루션은 스칼라 값 변수의 배열을 사용하는 것입니다. 또한 기본 선택 사항이 잘못되어 제안서 배포 중 일부를 구성해야합니다. 나를 위해 작동하는 코드는 다음과 같습니다.

import pymc as pm
sigmas = pm.Normal('sigmas', mu=0.1, tau=1000, size=2)
centers = pm.Normal('centers', [0.3, 0.7], [1/(0.1)**2, 1/(0.1)**2], size=2)
alpha  = pm.Beta('alpha', alpha=2, beta=3)
category = pm.Container([pm.Categorical("category%i" % i, [alpha, 1 - alpha]) 
                         for i in range(nsamples)])
observations = pm.Container([pm.Normal('samples_model%i' % i, 
                   mu=centers[category[i]], tau=1/(sigmas[category[i]]**2), 
                   value=samples[i], observed=True) for i in range(nsamples)])
model = pm.Model([observations, category, alpha, sigmas, centers])
mcmc = pm.MCMC(model)
# initialize in a good place to reduce the number of steps required
centers.value = [mu1_true, mu2_true]
# set a custom proposal for centers, since the default is bad
mcmc.use_step_method(pm.Metropolis, centers, proposal_sd=sig1_true/np.sqrt(nsamples))
# set a custom proposal for category, since the default is bad
for i in range(nsamples):
    mcmc.use_step_method(pm.DiscreteMetropolis, category[i], proposal_distribution='Prior')
mcmc.sample(100)  # beware sampling takes much longer now
# check the acceptance rates
print mcmc.step_method_dict[category[0]][0].ratio
print mcmc.step_method_dict[centers][0].ratio
print mcmc.step_method_dict[alpha][0].ratio

proposal_sdproposal_distribution옵션에 설명되어 섹션 5.7.1 . 중심의 경우, 데이터 양으로 인해 기본값보다 훨씬 작은 사후의 표준 편차와 대략 일치하도록 제안을 설정했습니다. PyMC는 제안서의 너비 조정을 시도하지만 수락 률이 시작하기에 충분히 높은 경우에만 작동합니다. 의 경우 category기본값 proposal_distribution = 'Poisson'이 좋지 않은 결과를 제공합니다 (이 이유는 모르겠지만 바이너리 변수에 대한 합리적인 제안처럼 들리지는 않습니다).


고마워, 이것은 거의 참을 수 없을 정도로 느리지 만 실제로는 유용합니다. 당신은 잠시의 의미를 설명 할 수 proposal_distributionproposal_sd이유를 사용하여 Prior범주 형 변수에 대한 더 나은 무엇입니까?
user2304916

고마워, 톰 나는 Poisson이 여기서 이상한 선택이라는 것에 동의합니다. 나는 문제를 열었다 : github.com/pymc-devs/pymc/issues/627
twiecki

2

σ

sigmas = pm.Exponential('sigmas', 0.1, size=2)

최신 정보:

모델의 다음 부분을 변경하여 데이터의 초기 매개 변수에 가깝습니다.

sigmas = pm.Exponential('sigmas', 0.1, size=2)
alpha  = pm.Beta('alpha', alpha=1, beta=1)

그리고 약간 숱이있는 mcmc를 호출하여 :

mcmc.sample(200000, 3000, 10)

결과 :

알파

센터

시그마

후자는 그리 좋지 않습니다 ... 버그 서적 11.6 절에서 이러한 유형의 모델에 대해 논의하고 명백한 해결책이없는 수렴 문제가 있다고 진술합니다. 여기도 확인 하십시오 .


좋은 지적입니다. 저는 지금 감마를 사용하고 있습니다. 그럼에도 불구하고 알파 추적은 항상 0.4가 아닌 0이됩니다. 내 예제에 숨어있는 바보 같은 버그가 있는지 궁금합니다.
user2304916

Gamma (.1, .1)를 시도했지만 Exp (.1)가 더 잘 작동하는 것 같습니다. 또한 자기 상관 률이 높으면 약간 얇아 질 수 있습니다. 예 :mcmc.sample(60000, 3000, 3)
jpneto

2

또한 비 식별성은 혼합 모델에 MCMC를 사용하는 데 큰 문제가됩니다. 기본적으로 클러스터 평균 및 클러스터 할당에서 레이블을 전환하면 가능성이 변경되지 않으며 샘플러 (체인 간 또는 체인 내)를 혼동시킬 수 있습니다. 이를 완화하기 위해 시도 할 수있는 한 가지는 PyMC3에서 잠재력 을 사용 하는 것입니다. 잠재력을 가진 GMM의 좋은 구현이 여기에 있습니다 . 이러한 종류의 문제에 대한 사후도 일반적으로 매우 복합적이며 큰 문제도 제기합니다. 대신 EM (또는 변형 추론)을 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.