O Método de Monte Carlo, embora funcione, nem sempre é eficiente. Veremos a seguir um exemplo disso.
13.1 Exemplo 1: Estimativa de
Neste exemplo, vamos estimar a probabilidade onde . Este é um evento raro, com probabilidade pequena. O valor exato dessa probabilidade é: Aplicaremos o método de Monte Carlo simulando valores de e calculando a proporção dos valores que são maiores que 4.5.
set.seed(0)# Valor exato de P(Z > 4.5)valor_exato <-log(pnorm(4.5, 0, 1, lower.tail =FALSE))cat("Valor exato (log(P(Z > 4.5))):", valor_exato, "\n")
Valor exato (log(P(Z > 4.5))): -12.59242
Mostrar código
# Simulação Monte Carlon <-100000z <-rnorm(n, 0, 1)# Estimativa Monte Carlo de P(Z > 4.5)p_estimada <-mean(1* (z >4.5))cat("Estimativa Monte Carlo de P(Z > 4.5):", p_estimada, "\n")
Estimativa Monte Carlo de P(Z > 4.5): 0
Mostrar código
# Logaritmo da estimativa Monte Carlolog_p_estimada <-log(p_estimada)cat("Logaritmo da estimativa Monte Carlo:", log_p_estimada, "\n")
Logaritmo da estimativa Monte Carlo: -Inf
Mostrar código
import numpy as npfrom scipy.stats import norm# Valor exato de P(Z > 4.5)valor_exato = np.log(norm.sf(4.5)) # sf is the survival function, equivalent to (1 - cdf)print(f"Valor exato (log(P(Z > 4.5))): {valor_exato}")
Valor exato (log(P(Z > 4.5))): -12.592419735713081
Mostrar código
# Simulação Monte Carlon =100000z = np.random.normal(0, 1, n)# Estimativa Monte Carlo de P(Z > 4.5)p_estimada = np.mean(z >4.5)print(f"Estimativa Monte Carlo de P(Z > 4.5): {p_estimada}")
Estimativa Monte Carlo de P(Z > 4.5): 0.0
Mostrar código
# Logaritmo da estimativa Monte Carlolog_p_estimada = np.log(p_estimada)print(f"Logaritmo da estimativa Monte Carlo: {log_p_estimada}")
Logaritmo da estimativa Monte Carlo: -inf
O método de Monte Carlo exige uma grande quantidade de amostras para fornecer uma estimativa precisa devido à raridade do evento . A abordagem pode se tornar ineficiente para eventos raros.
13.2 Amostragem por Importância
A Amostragem por Importância é uma técnica que nos permite simular valores a partir de uma densidade auxiliar .
A ideia chave é que, se tem densidade , a esperança pode ser reescrita como:
em que tem densidade . Isso vale desde que possua suporte tão ou mais amplo que a região de integração. Assim, podemos estimar usando valores simulados de independentemente pela fórmula:
Note que os pesos ajustam a importância de cada amostra, tornando a simulação mais eficiente.
13.2.1 Revistando o Exemplo 1 via Amostragem por Importância
Para melhorar a eficiência no Exemplo 1, vamos agora usar Amostragem por Importância. Em vez de simular diretamente de , simulamos de uma distribuição exponencial truncada a partir de 4.5. A densidade de importância é:
O estimador de Monte Carlo ponderado é, portanto, onde é a densidade da normal . Aqui está o código equivalente em Python no formato solicitado:
n <-100# Gerar n valores da distribuição exponencial truncaday <-rexp(n) +4.5# Estimativa por importânciaestimativa_importancia <-mean(dnorm(y) /exp(-(y -4.5)))cat("Estimativa por amostragem por importância:", estimativa_importancia, "\n")
Estimativa por amostragem por importância: 3.723979e-06
Mostrar código
# Logaritmo da estimativa por importâncialog_estimativa_importancia <-log(estimativa_importancia)cat("Logaritmo da estimativa por amostragem por importância:", log_estimativa_importancia, "\n")
Logaritmo da estimativa por amostragem por importância: -12.50072
Mostrar código
import numpy as npfrom scipy.stats import expon, normn =100# Gerar n valores da distribuição exponencial truncaday = expon.rvs(scale=1, size=n) +4.5# Estimativa por importânciaestimativa_importancia = np.mean(norm.pdf(y) / np.exp(-(y -4.5)))print(f"Estimativa por amostragem por importância: {estimativa_importancia}")
Estimativa por amostragem por importância: 3.329630733431657e-06
Mostrar código
# Logaritmo da estimativa por importâncialog_estimativa_importancia = np.log(estimativa_importancia)print(f"Logaritmo da estimativa por amostragem por importância: {log_estimativa_importancia}")
Logaritmo da estimativa por amostragem por importância: -12.612649150982133
Com essa técnica, concentramos as simulações na região relevante, melhorando a eficiência da estimativa para eventos raros.
13.3 Exemplo 2: Estimativa de com Amostragem por Importância
Agora, vamos estimar onde . Sabemos que o valor exato desta integral é .
# Valor exato da integralreal <-sqrt(pi) /2cat("Valor exato:", real, "\n")
Valor exato: 0.8862269
Mostrar código
# Número de amostrasn <-10000# Geração de amostras da distribuição exponencialx <-rexp(n, 1)# Estimativa Monte Carlo para E[sqrt(X)]estimativa_mc <-mean(sqrt(x))cat("Estimativa Monte Carlo de E[sqrt(X)]:", estimativa_mc, "\n")
Estimativa Monte Carlo de E[sqrt(X)]: 0.8842487
Mostrar código
# Variância da estimativavariancia_mc <-var(sqrt(x))cat("Variância da estimativa:", variancia_mc, "\n")
Variância da estimativa: 0.2075346
Mostrar código
import numpy as npfrom scipy.stats import expon# Valor exato da integralreal = np.sqrt(np.pi) /2print(f"Valor exato: {real}")
Valor exato: 0.8862269254527579
Mostrar código
# Número de amostrasn =10000# Geração de amostras da distribuição exponencialx = expon.rvs(scale=1, size=n)# Estimativa Monte Carlo para E[sqrt(X)]estimativa_mc = np.mean(np.sqrt(x))print(f"Estimativa Monte Carlo de E[sqrt(X)]: {estimativa_mc}")
Estimativa Monte Carlo de E[sqrt(X)]: 0.8832009971066371
Mostrar código
# Variância da estimativavariancia_mc = np.var(np.sqrt(x), ddof=1)print(f"Variância da estimativa: {variancia_mc}")
Variância da estimativa: 0.213930257711554
13.3.2 Aproximação via Amostragem por Importância
Agora, vamos usar a Amostragem por Importância com duas distribuições diferentes para melhorar a eficiência.
# Gerando amostras de uma distribuição normal absolutaz <-abs(rnorm(n))# Função de densidade combinada g(x)g <-function(x) {return(dnorm(x) +dnorm(-x))}# Estimativa por amostragem por importânciaestimativa_importancia <-mean((sqrt(z)) *dexp(z, 1) /g(z))cat("Estimativa por amostragem por importância:", estimativa_importancia, "\n")
Estimativa por amostragem por importância: 1.038467
Mostrar código
# Variância da estimativa por amostragem por importânciavariancia_importancia <-var((sqrt(z)) *dexp(z, 1) /g(z))cat("Variância da estimativa por amostragem por importância:", variancia_importancia, "\n")
Variância da estimativa por amostragem por importância: 367.4869
Mostrar código
import numpy as npfrom scipy.stats import norm, expon# Definir o tamanho da amostran =10000# Altere conforme necessário# Gerando amostras de uma distribuição normal absolutaz = np.abs(np.random.normal(size=n))# Função de densidade combinada g(x)def g(x):return norm.pdf(x) + norm.pdf(-x)# Estimativa por amostragem por importânciaestimativa_importancia = np.mean((np.sqrt(z)) * expon.pdf(z, scale=1) / g(z))print("Estimativa por amostragem por importância:", estimativa_importancia)
Estimativa por amostragem por importância: 0.8269444372337743
Mostrar código
# Variância da estimativa por amostragem por importânciavariancia_importancia = np.var((np.sqrt(z)) * expon.pdf(z, scale=1) / g(z))print("Variância da estimativa por amostragem por importância:", variancia_importancia)
Variância da estimativa por amostragem por importância: 3.3092709373223057
# Gerando amostras de uma distribuição Cauchy absolutaz <-abs(rcauchy(n))# Função de densidade combinada g2(x) para a Cauchyg2 <-function(x) {return(dcauchy(x) +dcauchy(-x))}# Estimativa por amostragem por importância usando Cauchyestimativa_importancia_cauchy <-mean((sqrt(z)) *dexp(z, 1) /g2(z))cat("Estimativa por amostragem por importância (Cauchy):", estimativa_importancia_cauchy, "\n")
Estimativa por amostragem por importância (Cauchy): 0.885894
Mostrar código
# Variância da estimativa por amostragem por importância usando Cauchyvariancia_importancia_cauchy <-var((sqrt(z)) *dexp(z, 1) /g2(z))cat("Variância da estimativa por amostragem por importância (Cauchy):", variancia_importancia_cauchy, "\n")
Variância da estimativa por amostragem por importância (Cauchy): 0.1985572
Mostrar código
import numpy as npfrom scipy.stats import cauchy, expon# Gerando amostras de uma distribuição Cauchy absolutaz = np.abs(cauchy.rvs(size=n))# Função de densidade combinada g2(x) para a Cauchydef g2(x):return cauchy.pdf(x) + cauchy.pdf(-x)# Estimativa por amostragem por importância usando Cauchyestimativa_importancia_cauchy = np.mean(np.sqrt(z) * expon.pdf(z, scale=1) / g2(z))print(f"Estimativa por amostragem por importância (Cauchy): {estimativa_importancia_cauchy}")
Estimativa por amostragem por importância (Cauchy): 0.8853104584819294
Mostrar código
# Variância da estimativa por amostragem por importância usando Cauchyvariancia_importancia_cauchy = np.var(np.sqrt(z) * expon.pdf(z, scale=1) / g2(z), ddof=1)print(f"Variância da estimativa por amostragem por importância (Cauchy): {variancia_importancia_cauchy}")
Variância da estimativa por amostragem por importância (Cauchy): 0.19450904194031554
Podemos visualizar as funções de densidade e as funções de importância e para entender melhor a escolha das distribuições de importância.
Esses gráficos mostram como as diferentes escolhas de distribuições de importância afetam a função ponderada, ajudando a reduzir a variância do estimador.
13.4 Exercícios
Exercício 1. Usando a Amostragem por Importância, estime a probabilidade de que uma variável aleatória seja maior que 5.0. Compare os resultados obtidos com a amostragem direta usando Monte Carlo simples e discuta a eficiência da Amostragem por Importância em relação ao método direto.
Exercício 2. Estime o valor da integral utilizando a Amostragem por Importância com duas distribuições de importância diferentes. Justifique a escolha das distribuições e compare a eficiência de cada uma.
Exercício 3. Utilize a Amostragem por Importância para estimar , onde . Escolha uma densidade auxiliar apropriada para melhorar a eficiência da estimativa e justifique sua escolha. Compare os resultados com a aproximação via Monte Carlo simples.