El problema
Quiero ajustar los parámetros del modelo de una población simple de mezcla 2-Gaussiana. Dada toda la exageración en torno a los métodos bayesianos, quiero entender si para este problema la inferencia bayesiana es una herramienta mejor que los métodos de ajuste tradicionales.
Hasta ahora, MCMC funciona muy mal en este ejemplo de juguete, pero tal vez simplemente pasé por alto algo. Entonces, veamos el código.
Las herramientas
Usaré python (2.7) + scipy stack, lmfit 0.8 y PyMC 2.3.
Puede encontrar un cuaderno para reproducir el análisis aquí.
Generar los datos
Primero vamos a generar los datos:
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])
El histograma de se samples
ve así:
un "pico amplio", los componentes son difíciles de detectar a simple vista.
Enfoque clásico: ajustar el histograma
Probemos el enfoque clásico primero. Usando lmfit es fácil definir un modelo de 2 picos:
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'
Finalmente ajustamos el modelo con el algoritmo simplex:
fit_res = model.fit(data, x=x_data, method='nelder')
print fit_res.fit_report()
El resultado es la siguiente imagen (las líneas discontinuas rojas son centros ajustados):
Incluso si el problema es un poco difícil, con valores iniciales adecuados y restricciones, los modelos convergieron en una estimación bastante razonable.
Enfoque bayesiano: MCMC
Defino el modelo en PyMC de forma jerárquica. centers
y sigmas
son la distribución previa de los hiperparámetros que representan los 2 centros y 2 sigmas de los 2 gaussianos. alpha
es la fracción de la primera población y la distribución anterior es aquí una Beta.
Una variable categórica elige entre las dos poblaciones. Entiendo que esta variable debe tener el mismo tamaño que los datos ( samples
).
Finalmente mu
y tau
son variables deterministas que determinan los parámetros de la distribución Normal (dependen de la category
variable por lo que cambian aleatoriamente entre los dos valores para las dos poblaciones).
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])
Luego ejecuto el MCMC con un número bastante largo de iteraciones (1e5, ~ 60s en mi máquina):
mcmc = pm.MCMC(model)
mcmc.sample(100000, 30000)
Además, los centros de los gaussianos no convergen también. Por ejemplo:
Entonces, ¿qué está pasando aquí? ¿Estoy haciendo algo mal o MCMC no es adecuado para este problema?
Entiendo que el método MCMC será más lento, pero el ajuste del histograma trivial parece funcionar inmensamente mejor en la resolución de las poblaciones.
fuente
proposal_distribution
yproposal_sd
y por qué el usoPrior
es mejor para las variables categóricas?actualizar:
Me acerqué a los parámetros iniciales de los datos cambiando estas partes de su modelo:
e invocando el mcmc con algo de adelgazamiento:
resultados:
Los posteriores no son muy agradables ... En la sección 11.6 del Libro BUGS , discuten este tipo de modelo y afirman que hay problemas de convergencia sin una solución obvia. Consulta también aquí .
fuente
mcmc.sample(60000, 3000, 3)
Además, la no identificabilidad es un gran problema para usar MCMC para modelos mixtos. Básicamente, si cambia las etiquetas en sus medios de clúster y las asignaciones de clúster, la probabilidad no cambia, y esto puede confundir al muestreador (entre cadenas o dentro de cadenas). Una cosa que podría intentar mitigar esto es usar los potenciales en PyMC3. Una buena implementación de un GMM con potenciales está aquí . El posterior para este tipo de problemas también es generalmente altamente multimodal, lo que también presenta un gran problema. Es posible que desee utilizar EM (o inferencia variacional).
fuente