2016-04-13 4 views
2

Stellen Sie sich einen zugrunde liegenden Prozess vor, der eine Zahl aus einer Normalverteilung mit der Wahrscheinlichkeit $ \ alpha $ und aus einer gleichmäßigen Verteilung mit der Wahrscheinlichkeit $ 1 - \ alpha $ zeichnet. Die beobachtete Folge von Zahlen, die durch dieses Verfahren erzeugt folgt daher, eine Verteilung f $ $, die eine Mischung von 2 Komponenten und Mischungsgewichten von $ \ alpha $ und 1 $ - \ alpha $. Wie würden Sie diese Art der Mischung mit JAGS modellieren, wenn die beobachtete Sequenz die einzige Eingabe ist, aber die parametrischen Familien bekannt sind?Wie man eine Mischung finiter Komponenten aus verschiedenen parametrischen Familien mit JAGS modelliert?

Beispiel (in R):

set.seed(8361299) 
N <- 100 
alpha <- 0.3 
mu <- 5 
max <- 50 
# Which component to choose from? 
latent_class <- rbinom(N, 1, alpha) 
Y <- ifelse(latent_class, runif(N, min=mu, max=max), rnorm(N, mean=mu)) 

Die erzeugte (beobachtet) Y wie folgt aussieht: Generated Y

Mit JAGS, sollte es möglich sein, die Mischungsgewichte zu erhalten, sowie die Parameter, der bekannten Komponenten?

Antwort

2

Mischmodelle mit der gleichen parametrischen Verteilung sind in JAGS/BUGS ziemlich einfach, aber Mischmodelle mit variierenden parametrischen Antworten (wie Ihre) sind etwas komplizierter. Eine Methode besteht darin, den "Eindeutigkeitstrick" zu verwenden, wobei wir manuell die Wahrscheinlichkeit der Antwort berechnen (indem wir eine der beiden Verteilungen auswählen, wie durch den latenten Teil des Modells spezifiziert) und diese an die (falsche) Antwort eines Bernoulli-Prozesses anpassen jeder Datenpunkt. Zum Beispiel:

# Your data generation: 
set.seed(8361299) 
N <- 100 
alpha <- 0.3 
mu <- 5 
max <- 50 
# Which component to choose from? 
latent_class <- rbinom(N, 1, alpha) 
Y <- ifelse(latent_class, runif(N, min=mu, max=max), rnorm(N, mean=mu)) 

# The model: 
model <- "model{ 

    for(i in 1:N){ 

     # Log density for the normal part: 
     ld_norm[i] <- logdensity.norm(Y[i], mu, tau) 

     # Log density for the uniform part: 
     ld_unif[i] <- logdensity.unif(Y[i], lower, upper) 

     # Select one of these two densities: 
     density[i] <- exp(ld_norm[i]*norm_chosen[i] + ld_unif[i]*(1-norm_chosen[i])) 

     # Generate a likelihood for the MCMC sampler: 
     Ones[i] ~ dbern(density[i]) 

     # The latent class part as usual: 
     norm_chosen[i] ~ dbern(prob) 

    } 

    # Priors: 
    lower ~ dnorm(0, 10^-6) 
    upper ~ dnorm(0, 10^-6) 
    prob ~ dbeta(1,1) 
    mu ~ dnorm(0, 10^-6) 
    tau ~ dgamma(0.01, 0.01) 

    # Specify monitors, data and initial values using runjags: 
    #monitor# lower, upper, prob, mu, tau 
    #data# N, Y, Ones 
    #inits# lower, upper 
}" 

# Run the model using runjags (or use rjags if you prefer!) 
library('runjags') 

lower <- min(Y)-10 
upper <- max(Y)+10 

Ones <- rep(1,N) 

results <- run.jags(model, sample=20000, thin=1) 
results 

plot(results) 

Dies scheint Ihre Parameter ziemlich gut (Ihr Alpha-1-prob) zu erholen, aber achten Sie auf Autokorrelation (und Konvergenz).

Matt


EDIT: Da Sie verallgemeinern, um mehr als zwei Verteilungen gefragt, hier ist äquivalent (aber mehr verallgemeinerbare) Code:

# The model: 
model <- "model{ 
    for(i in 1:N){ 
     # Log density for the normal part: 
     ld_comp[i, 1] <- logdensity.norm(Y[i], mu, tau) 
     # Log density for the uniform part: 
     ld_comp[i, 2] <- logdensity.unif(Y[i], lower, upper) 
     # Select one of these two densities and normalise with a Constant: 
     density[i] <- exp(ld_comp[i, component_chosen[i]] - Constant) 
     # Generate a likelihood for the MCMC sampler: 
     Ones[i] ~ dbern(density[i]) 
     # The latent class part using dcat: 
     component_chosen[i] ~ dcat(probs) 
    } 
    # Priors for 2 parameters using a dirichlet distribution: 
    probs ~ ddirch(c(1,1)) 
    lower ~ dnorm(0, 10^-6) 
    upper ~ dnorm(0, 10^-6) 
    mu ~ dnorm(0, 10^-6) 
    tau ~ dgamma(0.01, 0.01) 
    # Specify monitors, data and initial values using runjags: 
    #monitor# lower, upper, probs, mu, tau 
    #data# N, Y, Ones, Constant 
    #inits# lower, upper, mu, tau 
}" 

library('runjags') 

# Initial values to get the chains started: 
lower <- min(Y)-10 
upper <- max(Y)+10 
mu <- 0 
tau <- 0.01 

Ones <- rep(1,N) 

# The constant needs to be big enough to avoid any densities >1 but also small enough to calculate probabilities for observations of 1: 
Constant <- 10 

results <- run.jags(model, sample=10000, thin=1) 
results 

Dieser Code für so viele Distributionen funktionieren wie Sie benötigen, aber exponentiell schlechtere Autokorrelation mit mehr Verteilungen erwarten.

+0

Großartig! AC sieht gut aus und das ESS ist größer als 10000 für mu und prob! Zuvor hatte ich angedeutet, dass ich die Wahl zwischen verschiedenen Distributionen treffen sollte, die auf "ob-wenn-noch-anders-in-winbugs-jags" basieren (http://stackoverflow.com/questions/15414303/choosing-different-distributions-based-). On-wenn-sonst-Bedingung-in-Winbugs-jags). In der akzeptierten Antwort wurde Y von beiden Verteilungen abgetastet und einer wurde basierend auf einer Indikatorvariablen ausgewählt. Aber dieser Code scheitert bei mir mit einem Syntaxfehler. Was denkst du über die vorgeschlagene Lösung? – jenzopr

+1

Diese Antwort scheint (im besten Fall) unvollständig für mich - es enthält ungültige Syntax für einen Start .... In jedem Fall wird dieser Ansatz für Sie nicht funktionieren, da die funktionale Form Ihrer Antwort anders ist - die andere Frage hat dcat für alles, aber Sie haben Dunif und Dnorm. Ein Standardansatz für die gleiche funktionale Antwort wäre das Indizieren des Parameters, z. Y [i] ~ dnorm (mus [norm_chosen [i]], taus [norm_chosen [i]]) würde für Ihr Beispiel funktionieren, wenn Sie eine Mischung aus Normalen wünschen (aber dann wiederum gibt es dnormmix dafür!). –

+0

Vielen Dank für die Erklärung! Zurück zu Ihrer Antwort versuche ich derzeit, den Übergang von zwei finiten Komponenten zu n finiten Komponenten zu machen.Ich habe darüber nachgedacht, dcat anstelle von dbern zu verwenden, um die latenten Klassen zu erzeugen: 'e [i] <- dcat (pi [1: 2]) für (k in 1: 2) { norm_chosen [i, k] < - (k == e [i])} ' Und verwende ' dichte [i] <- exp (ld_norm [i] * norm_chosen [i, 1] + ld_unif [i] * norm_chosen [i, 2]) ' stattdessen. Das Modell schlägt jedoch an einem bestimmten Punkt fehl, wobei der Knoten nicht mit den Elternknoten am Knoten Ones [40] übereinstimmt. Ich befürchte, dass die Dichte aus dem Rahmen geraten kann, wenn pi ein richtiger Prior fehlt? – jenzopr

Verwandte Themen