Ich vermute, dass dies eine ziemlich ungewöhnliche und explorative Frage ist. Bitte nehmen Sie Kontakt mit mir auf.
Ich frage mich, ob man die Idee der Wichtigkeitsstichprobe auf Gibbs-Stichproben anwenden könnte. Ich meine Folgendes: Bei der Gibbs-Abtastung ändern wir jeweils den Wert einer Variablen (oder eines Variablenblocks), wobei wir aus der bedingten Wahrscheinlichkeit für die verbleibenden Variablen abtasten.
Es ist jedoch möglicherweise nicht möglich oder einfach, aus der genauen bedingten Wahrscheinlichkeit eine Stichprobe zu erstellen. Stattdessen probieren wir aus einer Angebotsverteilung und verwenden beispielsweise Metropolis-Hastings (MH).
So weit, ist es gut. Aber hier ist ein abweichender Weg: Was passiert, wenn wir anstelle von MH dieselbe Idee verwenden, die bei der Wichtigkeitsstichprobe verwendet wird, nämlich aus und ein Wichtigkeitsgewicht der aktuellen Stichprobe beizubehalten?
Im Detail: Nehmen wir an, wir haben die Variablen und eine faktorisierte Verteilung so dass . Wir behalten die Vorschlagswahrscheinlichkeit bei, mit der der aktuelle Wert jeder Variablen wird . Bei jedem Schritt ändern wir eine Teilmenge der Variablen und aktualisieren (nur die Faktoren von und , die betroffen sind). Wir nehmen die Stichproben und ihr Wichtigkeitsgewicht, um die Statistik zu berechnen, an der wir interessiert sind.
Wäre dieser Algorithmus korrekt? Wenn nicht, klare Gründe, warum nicht? Intuitiv macht es für mich Sinn, da es das gleiche zu tun scheint, was das Sampling von Wichtigkeit tut, aber stattdessen mit abhängigen Samples.
Ich habe dies für ein Gaußsches Random-Walk-Modell implementiert und festgestellt, dass die Gewichte immer kleiner (aber nicht monoton) werden, sodass die anfänglichen Stichproben zu wichtig sind und die Statistik dominieren. Ich bin mir ziemlich sicher, dass die Implementierung nicht fehlerhaft ist, da ich bei jedem Schritt das aktualisierte Gewicht mit einer expliziten Brute-Force-Berechnung vergleiche. Es ist zu beachten, dass die Gewichte nicht auf unbestimmte Zeit auf Null abfallen, da sie wobei sowohl als auch Produkte einer endlichen Anzahl von Dichten sind und jede Probe aus einer Normalverteilung erhalten wird, die nur selten Null ist.
Ich versuche zu verstehen, warum die Gewichte so sinken und ob dies eine Folge davon ist, dass diese Methode tatsächlich nicht korrekt ist.
Hier ist eine genauere Definition des Algorithmus, der auf einen Gaußschen Zufallslauf für die Variablen angewendet wird . Der Code folgt unten.
Das Modell ist einfach , wobei auf .
Das Gewicht der aktuellen Stichprobe ist , wobei die Gaußschen Dichten und die Verteilungen sind, aus denen die aktuellen Werte abgetastet wurden. Zunächst werden die Werte einfach vorwärts abgetastet, sodass und das Anfangsgewicht .
Dann wähle ich bei jedem Schritt zum Ändern. Ich probiere einen neuen Wert für aus , damit diese Dichte zur neuen verwendeten Angebotsverteilung für .
Um das Gewicht zu aktualisieren, dividiere ich es durch die Dichten und des alten Wertes gemäß und und multipliziere mit den Dichten und des neuen Wertes gemäß und . Dies aktualisiert den Zähler des Gewichts.
Um den Nenner zu aktualisieren , multipliziere ich das Gewicht mit dem alten Vorschlag (und entferne ihn so vom Nenner) und dividiere ihn durch .
(Da ich aus der auf zentrierten Normalen , ist immer gleich sodass sie sich aufheben und die Implementierung dies tut nicht wirklich benutzen).
Wie ich bereits erwähnt habe, vergleiche ich im Code diese inkrementelle Gewichtsberechnung mit der tatsächlichen expliziten Berechnung, nur um sicherzugehen.
Hier ist der Code als Referenz.
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);
}