Modelo de ajuste para dos distribuciones normales en PyMC

10

Como soy un ingeniero de software que intenta obtener más estadísticas, tendrás que perdonarme incluso antes de que comience, este es un nuevo territorio serio ...

He estado aprendiendo PyMC y trabajando con algunos ejemplos muy (muy) simples. Un problema con el que no puedo trabajar (y no puedo encontrar ningún ejemplo relacionado) es ajustar un modelo a los datos generados a partir de dos distribuciones normales.

Digamos que tengo 1000 valores; 500 generados a partir de a Normal(mean=100, stddev=20)y otros 500 generados a partir de a Normal(mean=200, stddev=20).

Si quiero ajustar un modelo a ellos, es decir, determinar las dos medias y la desviación estándar única, usando PyMC. Sé que es algo parecido a ...

mean1 = Uniform('mean1', lower=0.0, upper=200.0)
mean2 = Uniform('mean2', lower=0.0, upper=200.0)
precision = Gamma('precision', alpha=0.1, beta=0.1)

data = read_data_from_file_or_whatever()

@deterministic(plot=False)
def mean(m1=mean1, m2=mean2):
    # but what goes here?

process = Normal('process', mu=mean, tau=precision, value=data, observed=True)

es decir, el proceso de generación es Normal, pero mu es uno de los dos valores. Simplemente no sé cómo representar la "decisión" entre si un valor proviene m1o no m2.

¿Quizás solo estoy tomando el enfoque equivocado para modelar esto? ¿Alguien puede señalarme un ejemplo? Puedo leer BUGS y JAGS para que todo esté bien realmente.

mat kelcey
fuente

Respuestas:

11

¿Estás absolutamente seguro de que la mitad proviene de una distribución y la otra mitad de la otra? Si no, podemos modelar la proporción como una variable aleatoria (que es algo muy bayesiano).

Lo siguiente es lo que haría, algunos consejos están integrados.

from pymc import *

size = 10
p = Uniform( "p", 0 , 1) #this is the fraction that come from mean1 vs mean2

ber = Bernoulli( "ber", p = p, size = size) # produces 1 with proportion p.

precision = Gamma('precision', alpha=0.1, beta=0.1)

mean1 = Normal( "mean1", 0, 0.001 ) #better to use normals versus Uniforms (unless you are certain the value is  truncated at 0 and 200 
mean2 = Normal( "mean2", 0, 0.001 )

@deterministic
def mean( ber = ber, mean1 = mean1, mean2 = mean2):
    return ber*mean1 + (1-ber)*mean2


#generate some artificial data   
v = np.random.randint( 0, 2, size)
data = v*(10+ np.random.randn(size) ) + (1-v)*(-10 + np.random.randn(size ) )


obs = Normal( "obs", mean, precision, value = data, observed = True)

model = Model( {"p":p, "precision": precision, "mean1": mean1, "mean2":mean2, "obs":obs} )
Cam.Davidson.Pilon
fuente
2
Promoción desvergonzada: acabo de escribir un artículo de blog sobre Bayes y pyMC literalmente 1 minuto antes de que publiques esto, así que te invito a que lo revises. The Awesome Power of Bayes - Part 1
Cam.Davidson.Pilon
¡increíble! Este enfoque para la mezcla de los dos medios es exactamente lo que estaba tratando de entender.
mat kelcey
No estoy seguro de comprender completamente el verdadero beneficio de modelado de decir que mean1 y mean2 están normalmente distribuidos en lugar de uniformes (lo mismo va realmente para que la precisión sea honesta, he estado usando Gamma desde que "alguien más lo hizo"). Tengo mucho que aprender :)
mat kelcey
Usar un uniforme, como en su ejemplo original, implica que usted sabe con absoluta certeza que la media no excede algún valor. Esto es algo patológico. Es mejor usar un normal, ya que permite que se consideren todos los números reales.
Cam.Davidson.Pilon
1
La elección de gamma tiene una razón matemática. La gamma es el conjugado previo de la precisión, ver la tabla aquí
Cam.Davidson.Pilon
6

Un par de puntos, relacionados con la discusión anterior:

  1. La elección de normal difuso versus uniforme es bastante académica a menos que (a) esté preocupado por la conjugación, en cuyo caso usaría lo normal o (b) existe una posibilidad razonable de que el valor verdadero pueda estar fuera de los puntos finales del uniforme . Con PyMC, no hay razón para preocuparse por la conjugación, a menos que desee usar específicamente una muestra de Gibbs.

  2. Una gamma en realidad no es una gran opción para un no informativo antes de un parámetro de varianza / precisión. Puede terminar siendo más informativo de lo que piensas. Una mejor opción es poner un uniforme antes de la desviación estándar, luego transformarlo en un cuadrado inverso. Ver Gelman 2006 para más detalles.

fonnesbeck
fuente
1
¡ah fonnesbeck es uno de los principales desarrolladores de pymc! ¿Puede mostrarnos un ejemplo de cómo codificar el punto 2?
Cam.Davidson.Pilon
gracias fonnesbeck y sí, por favor! a un ejemplo rápido del punto 2 :)
mat kelcey
1
de hecho, supongo que quieres decir algo en la línea de ... gist.github.com/4404631 ?
mat kelcey
Sí exactamente. Puedes hacer la transformación un poco más concisamente:tau = std_dev**-2
fonnesbeck
¿Cuál sería el lugar correcto para leer sobre el origen de esta relación entre precisión y std_dev?
user979