Suspeito que esta seja uma pergunta bastante incomum e exploratória, por isso, tenha paciência comigo.
Gostaria de saber se é possível aplicar a idéia de amostragem importante à amostragem de Gibbs. Aqui está o que quero dizer: na amostragem de Gibbs, alteramos o valor de uma variável (ou bloco de variáveis) de cada vez, amostrando a partir da probabilidade condicional, dadas as demais variáveis.
No entanto, pode não ser possível ou fácil amostrar a partir da probabilidade condicional exata. Então, em vez disso, coletamos amostras de uma distribuição de proposta e usamos, por exemplo, Metropolis-Hastings (MH).
Por enquanto, tudo bem. Mas eis um caminho divergente: o que acontece se, em vez de usar o MH, usarmos a mesma idéia usada na amostragem de importância, ou seja, coletamos amostras de e mantemos um peso de importância da amostra atual?
Mais detalhadamente: suponha que temos as variáveis e uma distribuição fatorada modo que . Mantemos a probabilidade da proposta usada para amostrar o valor atual de cada variável . Em cada etapa, alteramos um subconjunto das variáveis e atualizamos (apenas os fatores de e que são afetados). Tomamos as amostras e seu peso de importância para calcular qualquer estatística em que estamos interessados.
Esse algoritmo estaria correto? Caso contrário, existem razões claras por que não? Intuitivamente, faz sentido para mim, pois parece estar fazendo a mesma coisa que a amostragem de importância, mas com amostras dependentes.
Eu implementei isso para um modelo de caminhada aleatória gaussiana e observei que os pesos se tornam cada vez menores (mas não monotonicamente); portanto, as amostras iniciais acabam tendo muita importância e dominam a estatística. Tenho certeza de que a implementação não é de buggy, porque a cada passo eu comparo o peso atualizado com um cálculo explícito de força bruta. Observe que os pesos não diminuem indefinidamente para zero, porque são onde e são produtos de um número finito de densidades, e cada amostra é obtida de uma distribuição Normal que raramente será zero.
Então, estou tentando entender por que os pesos caem dessa maneira e se isso é uma conseqüência do fato de esse método não estar realmente correto.
Aqui está uma definição mais precisa do algoritmo, aplicada a uma caminhada aleatória gaussiana nas variáveis . O código segue abaixo.
O modelo é simplesmente , com fixo em .
O peso da amostra atual é , onde são as densidades gaussianas e são as distribuições das quais os valores atuais foram amostrados. Inicialmente, simplesmente amostramos os valores de maneira direta, então e o peso inicial é .
Em cada etapa, eu escolho para alterar. Eu um novo valor para de , portanto essa densidade se torna a nova distribuição de proposta usada para .
Para atualizar o peso, divido pelo densidades e de valor antigo de acordo com a e , e multiplicar pelo densidades e de novo valor de acordo com a e . Isso atualiza o numerador do peso.
Para atualizar o denominador , multiplico o peso pela proposta antiga (removendo-o do denominador) e divido-o por .
(Como eu do normal centrado em , é sempre igual a então eles são cancelados e a implementação não usá-los).
Como mencionei antes, no código eu comparo esse cálculo de peso incremental com o cálculo explícito real apenas para ter certeza.
Aqui está o código para referência.
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);
}