Ho il sospetto che questa sia una domanda abbastanza insolita ed esplorativa, quindi per favore abbi pazienza.
Mi chiedo se si possa applicare l'idea di campionamento di importanza al campionamento di Gibbs. Ecco cosa intendo: nel campionamento di Gibbs, cambiamo il valore di una variabile (o blocco di variabili) alla volta, campionando dalla probabilità condizionale date le variabili rimanenti.
Tuttavia, potrebbe non essere possibile o facile campionare dalla probabilità condizionale esatta. Quindi, invece, proviamo da una distribuzione della proposta e utilizziamo, ad esempio, Metropolis-Hastings (MH).
Fin qui tutto bene. Ma ecco un percorso divergente: cosa succede se, invece di usare MH, usiamo la stessa idea usata nel campionamento per importanza, vale a dire campioniamo da e manteniamo un peso in peso del campione attuale?
Più in dettaglio: supponiamo di avere variabili e una distribuzione fattorizzata modo che . Manteniamo la probabilità di proposta utilizzata per campionare il valore corrente di ciascuna variabile . Ad ogni passaggio cambiamo un sottoinsieme delle variabili e aggiorniamo (solo i fattori di e che sono interessati). Prendiamo i campioni e il loro peso di importanza per calcolare qualunque statistica ci interessa.
Questo algoritmo sarebbe corretto? In caso contrario, eventuali motivi chiari perché no? Intuitivamente per me ha senso in quanto sembra fare la stessa cosa importante per il campionamento, ma con campioni dipendenti.
Ho implementato questo per un modello di camminata casuale gaussiana e ho osservato che i pesi diventano sempre più piccoli (ma non monotonicamente), quindi i campioni iniziali finiscono per avere troppa importanza e dominano la statistica. Sono abbastanza sicuro che l'implementazione non sia buggy, perché ad ogni passo comparo il peso aggiornato con un calcolo esplicito della forza bruta. Si noti che i pesi non scendono indefinitamente a zero, poiché sono dove sia che sono prodotti di un numero finito di densità, e ogni campione è ottenuto da una distribuzione normale che solo raramente sarà zero.
Quindi sto cercando di capire perché i pesi scendano in questo modo e se questa sia una conseguenza di questo metodo in realtà non corretto.
Ecco una definizione più precisa dell'algoritmo, applicata a una camminata casuale gaussiana sulle variabili . Il codice segue di seguito.
Il modello è semplicemente , con fisso su .
Il peso del campione corrente è , dove sono le densità gaussiane e sono le distribuzioni da cui sono stati campionati i valori correnti. Inizialmente, semplicemente campioniamo i valori in avanti, quindi e il peso iniziale è .
Quindi ad ogni passaggio scelgo per cambiare. Ho assaggiare un nuovo valore per da , in modo da questa densità diventa la nuova distribuzione proposta utilizzato per .
Per aggiornare il peso, lo divido per le densità e del vecchio valore secondo e e moltiplicare per le densità e di nuovo valore secondo e . Questo aggiorna il numeratore del peso.
Per aggiornare il denominatore , moltiplico il peso per la vecchia proposta (rimuovendolo così dal denominatore) e lo divido per .
(Poiché dal normale centrato su , è sempre uguale a quindi si annullano e l'implementazione non in realtà non li usano).
Come ho detto prima, nel codice comparo questo calcolo del peso incrementale con il calcolo esplicito effettivo solo per essere sicuro.
Ecco il codice di riferimento.
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);
}