Sospecho que esta es una pregunta bastante inusual y exploratoria, así que por favor tengan paciencia conmigo.
Me pregunto si se podría aplicar la idea del muestreo de importancia al muestreo de Gibbs. Esto es lo que quiero decir: en el muestreo de Gibbs, cambiamos el valor de una variable (o bloque de variables) a la vez, tomando muestras de la probabilidad condicional dadas las variables restantes.
Sin embargo, puede no ser posible o fácil tomar muestras de la probabilidad condicional exacta. Entonces, en cambio, tomamos muestras de una distribución de propuesta y usamos, por ejemplo, Metropolis-Hastings (MH).
Hasta aquí todo bien. Pero aquí hay un camino divergente: ¿qué sucede si, en lugar de usar MH, usamos la misma idea utilizada en el muestreo de importancia, es decir, tomamos muestras de y mantenemos un peso de importancia p / q de la muestra actual?
Más detalladamente: supongamos que tenemos variables y una distribución factorizada para que . Mantenemos la probabilidad de propuesta utilizada para muestrear el valor actual de cada variable . En cada paso cambiamos un subconjunto de las variables y actualizamos (solo los factores de y que están afectados). Tomamos las muestras y su peso de importancia para calcular cualquier estadística que nos interese.
¿Sería correcto este algoritmo? Si no, ¿alguna razón clara por qué no? Intuitivamente tiene sentido para mí, ya que parece estar haciendo lo mismo que hace el muestreo importante, pero en cambio con muestras dependientes.
Implementé esto para un modelo de caminata aleatoria gaussiana y observé que los pesos se hacen cada vez más pequeños (pero no monotónicamente), por lo que las muestras iniciales terminan teniendo demasiada importancia y dominan la estadística. Estoy bastante seguro de que la implementación no tiene errores, porque en cada paso comparo el peso actualizado con un cálculo explícito de la fuerza bruta del mismo. Tenga en cuenta que los pesos no bajan indefinidamente a cero, porque son donde y son productos de un número finito de densidades, y cada muestra se obtiene de una distribución Normal que rara vez será cero.
Así que estoy tratando de entender por qué los pesos bajan así, y si esto es una consecuencia de que este método no sea realmente correcto.
Aquí hay una definición más precisa del algoritmo, aplicada a una caminata aleatoria gaussiana en las variables . El código sigue a continuación.
El modelo es simplemente , con fijado en .
El peso de la muestra actual es , donde son las densidades gaussianas son las distribuciones a partir de las cuales se han muestreado los valores actuales. Inicialmente, simplemente muestreamos los valores de manera directa, por lo que y el peso inicial es .
Luego, en cada paso, elijo para cambiar. un nuevo valor para de , por lo que esta densidad se convierte en la nueva distribución propuesta propuesta para .
Para actualizar el peso, lo por las densidades y del valor anterior acuerdo con y , y multiplique por las densidades y del nuevo valor acuerdo con y . Esto actualiza el numerador del peso.
Para actualizar el denominador , multiplico el peso por la antigua propuesta (eliminándolo así del denominador) y lo por .
(Debido a que de la normal centrada en , siempre es igual a por lo que se cancelan y la implementación lo hace en realidad no los uso).
Como mencioné antes, en el código comparo este cálculo de peso incremental con el cálculo explícito real solo para estar seguro.
Aquí está el código de referencia.
println("Original sample: " + currentSample);
int flippedVariablesIndex = 1 + getRandom().nextInt(getVariables().size() - 1);
println("Flipping: " + flippedVariablesIndex);
double oldValue = getValue(currentSample, flippedVariablesIndex);
NormalDistribution normalFromBack = getNormalDistribution(getValue(currentSample, flippedVariablesIndex - 1));
double previousP = normalFromBack.density(oldValue);
double newValue = normalFromBack.sample();
currentSample.set(getVariable(flippedVariablesIndex), newValue);
double previousQ = fromVariableToQ.get(getVariable(flippedVariablesIndex));
fromVariableToQ.put(getVariable(flippedVariablesIndex), normalFromBack.density(newValue));
if (flippedVariablesIndex < length - 1) {
NormalDistribution normal = getNormalDistribution(getValue(currentSample, flippedVariablesIndex + 1));
double oldForwardPotential = normal.density(oldValue);
double newForwardPotential = normal.density(newValue);
// println("Removing old forward potential " + oldForwardPotential);
currentSample.removePotential(new DoublePotential(oldForwardPotential));
// println("Multiplying new forward potential " + newForwardPotential);
currentSample.updatePotential(new DoublePotential(newForwardPotential));
}
// println("Removing old backward potential " + previousP);
currentSample.removePotential(new DoublePotential(previousP));
// println("Multiplying (removing from divisor) old q " + previousQ);
currentSample.updatePotential(new DoublePotential(previousQ));
println("Final sample: " + currentSample);
println();
// check by comparison to brute force calculation of weight:
double productOfPs = 1.0;
for (int i = 1; i != length; i++) {
productOfPs *= getNormalDistribution(getValue(currentSample, i - 1)).density(getValue(currentSample, i));
}
double productOfQs = Util.fold(fromVariableToQ.values(), (p1, p2) -> p1*p2, 1.0);
double weight = productOfPs/productOfQs;
if (Math.abs(weight - currentSample.getPotential().doubleValue()) > 0.0000001) {
println("Error in weight calculation");
System.exit(0);
}