Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Como gerar uma distribuição U(0, alfa) a partir de uma distribuição U(0, 1)?

0 votos
14 visitas
perguntada Nov 6 em Ciência da Computação por bonfim_tiago (6 pontos)  

Exercício 2.19 do livro "Monte Carlo Simulation" de Robert and Casella, Página 65

Compartilhe

1 Resposta

0 votos
respondida Nov 6 por bonfim_tiago (6 pontos)  

Boa noite pessoal,

O referido exercício propõe um algoritmo que consiste na geração de amostras provenientes de uma distribuição U(0, 1) seguidamente de um teste para avaliar se a amostra é superior a um parâmetro de controle alfa.

A partir disso, questiona-se se a distribuição resultante, limitada superiormente ao valor de alfa, seria equivalente a uma distribuição U(0, alfa). Na verdade, o livro nos pede somente para comparar as duas distribuições.

Por fim, o livro pede que seja analisado o comportamento dessas funções próximo aos valores de 0 e 1 especificamente.

O código elaborado para resolução do problema proposto é bastante simples, na verdade. Ao invés de pegar poucas sequências e analisar seus comportamentos, acredito que seja mais frutífero rodar logo 1.000 simulações e depois plottar um diagrama de dispersão dos desvios das médias de ambas as distribuições em função do parâmetro de controle alfa. Segue abaixo o código desenvolvido para essa tarefa:

import random
import numpy as np
import matplotlib.pyplot as plt

error_vector = list()

# A thousand iterations seems fine for this MC simulation,
# since we're interested on the convergence of uniform distributions
for i in range(1000):
    alfa = random.uniform(0, 1)

    uniform_sample_alfa_limit = list()
    uniform_sample_standard = list()

    while True:
        # distribution of the algorithm proposed on the book
        a_alfa = random.uniform(0, 1)
        # Uniform distribution on interval (0, alfa)
        a_standard = random.uniform(0, alfa)

        # Check the stop condition of the algorithm under evaluation
        if a_alfa < alfa:
            uniform_sample_alfa_limit.append(a_alfa)
            uniform_sample_standard.append(alfa * a_standard)
        else:
            break

    # if the vector is not empty, lets calculate the mean error between both distributions
    if len(uniform_sample_alfa_limit):
        iteration_mean_error = np.abs((np.mean(uniform_sample_alfa_limit) - np.mean(uniform_sample_standard)) /
                                      np.mean(uniform_sample_alfa_limit)) * 100

        # Relative errors can be too large for very small numbers. Lets filter this data so we can see what's happening
        if iteration_mean_error <= 100:
            error_vector.append((alfa, iteration_mean_error))

# Lets plot all the points on a scatter graph
graph_x_vector = list()
graph_y_vector = list()

for error in error_vector:
    graph_x_vector.append(error[0])
    graph_y_vector.append(error[1])

plt.scatter(graph_x_vector, graph_y_vector, color='b')
plt.show()

A seguir, apresenta-se o gráfico resultante do código em apreço para avaliação do exercício proposto.

A imagem será apresentada aqui.

Como pode ser observado, pequenos valores de alfa vão sempre produzir grandes erros entre as duas distribuições. Isso acontece por conta do reduzido número de pontos que foram possíveis de serem gerados até que uma amostra aleatória fosse superior ao próprio parâmetro alfa.

Por outro lado, a medida em que a variável de controle alfa vai crescendo, cada vez mais próximo da unidade, os desvios vão se reduzindo por conta do maior número de pontos que é possível gerar antes que a condição de parada do exercício seja violada. Assim, conseguimos gerar uma sequência que vai, cada vez mais, se aproximando da distribuição U(0, alfa)

Agora, analisar esse gráfico de dispersão não é uma tarefa trivial em decorrência do grande número de pontos contidos aí. Por conta disso, vamos avançar um pouquinho mais e obter uma curva polinomial de terceiro grau que minimiza os erros quadráticos médios para todos os mil pontos apresentados. Depois, vamos apresentar essa curva e verificar se o comportamento observado é mais claro nela.

O trecho de código gerado para tal função segue apresentado abaixo:

# The scatter diagram is not very clear... lets make a regression of the curve
z = np.polyfit(graph_x_vector, graph_y_vector, 3)

# a convenient way to deal with a polynomial functions based on its parameters
p = np.poly1d(z)

poly_x = list()
poly_y = list()

for i in range(11):
    poly_x.append(0.1 * i)
    poly_y.append(p(0.1 * i))

plt.scatter(poly_x, poly_y, color='b')
plt.title("Third degree regression of the scatter graph points")
plt.xlabel("Alfa Parameter")
plt.ylabel("Relative Error on the averages of both distributions")
plt.show()

Com gráfico resultante apresentado abaixo:

A imagem será apresentada aqui.

E, finalmente, conseguimos observar de forma bastante clara o comportamento da distribuição gerada pelo algoritmo proposto no livro, isto é, uma U(0, 1) que para de amostrar quando o ponto gerado é superior ao valor da variável de controle alfa, em relação a uma distribuição U(0, alfa).

Para pontos muito próximos de zero, obtemos um erro expressivo tendo em vista o pequeno número de amostras que foi possível obter com o algoritmo. Por outro lado, na medida em que alfa se aproxima da unidade, ambas distribuições começam, ao menos em termos de média, a se assemelhar.

até a próxima!

...