문제
간단한 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()
결과는 다음 이미지입니다 (빨간색 점선이 중심에 맞춰 짐).
문제가 어려운 경우에도 적절한 초기 값과 제약 조건으로 모델이 상당히 합리적인 추정치로 수렴되었습니다.
베이지안 접근 : MCMC
PyMC에서 모델을 계층 적 방식으로 정의합니다. centers
그리고 sigmas
2 개 센터와 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가이 문제에 적합하지 않습니까?
MCMC 방법이 느리다는 것을 알고 있지만 사소한 히스토그램 맞춤은 모집단을 해결하는 데 엄청나게 더 나은 것으로 보입니다.
proposal_distribution
및proposal_sd
이유를 사용하여Prior
범주 형 변수에 대한 더 나은 무엇입니까?