Моделирование распределения выборки не приводит к нормальному

Я пытался смоделировать «распределение выборки пропорций выборки» с помощью Python. Я пробовал использовать переменную Бернулли, как в примере здесь

Суть в том, что из большого количества жевательных резинок у нас есть желтые шары с истинной пропорцией 0,6. Если мы возьмем образцы (некоторого размера, скажем, 10), возьмем среднее значение и построим график, мы должны получить нормальное распределение.

Я пытался сделать это на питоне, но всегда получаю равномерное распределение (или плоские посередине). Я не могу понять, что мне не хватает.

Программа:

from SDSP import create_bernoulli_population, get_frequency_df
from random import shuffle, choices
from bi_to_nor_demo import get_metrics, bare_minimal_plot
import matplotlib.pyplot as plt


N = 10000  # 10000 balls
p = 0.6    # probability of yellow ball is 0.6, and others (1-0.6)=>0.4
n_pickups = 1000       # sample size
n_experiments = 100  # I dont know what this is called 


# generate population
population = create_bernoulli_population(N,p)
theor_df = get_frequency_df(population)
theor_df

# choose sample, take mean and add to X_mean_list. Do this for n_experiments times
X_hat = []
X_mean_list = []
for each_experiment in range(n_experiments):
    X_hat = choices(population, k=n_pickups)  # this method is with replacement
    shuffle(population)
    X_mean = sum(X_hat)/len(X_hat)
    X_mean_list.append(X_mean)

# plot X_mean_list as bar graph
stats_df = get_frequency_df(X_mean_list)
fig, ax = plt.subplots(1,1, figsize=(5,5))
X = stats_df['x'].tolist()
P = stats_df['p(x)'].tolist()    
ax.bar(X, P, color="C0") 

plt.show()

Зависимые функции:
bi_to_nor_demo
SDSP

Вывод:
 введите описание изображения здесь

Обновление: Я даже попробовал равномерное распределение, как показано ниже, но получил аналогичный результат. Не сходится к нормальному :(. (Используя функцию ниже вместо create_bernoulli_population)

def create_uniform_population(N, Y=[]):
    """
    Given the total size of population N, 
    this function generates list of those outcomes uniformly distributed
    population list
    N - Population size, eg N=10000
    p - probability of interested outcome  
    Returns the outcomes spread out in population as a list
    """
    uniform_p = 1/len(Y)
    print(uniform_p)
    total_pops = []
    for i in range(0,len(Y)):
        each_o = [i]*(int(uniform_p*N))
        total_pops += each_o
    shuffle(total_pops)    
    return total_pops

person Parthiban Rajendran    schedule 07.08.2018    source источник


Ответы (3)


не могли бы вы поделиться своими настройками matplotlib? Я думаю, что у вас есть усеченный график, вы правы в том, что выборочное распределение выборочной доли на бернулли должно нормально распределяться вокруг ожидаемого значения совокупности ...

возможно, используя что-то как:

plt.tight_layout()

чтобы проверить, нет ли проблем с графиком

person Daniel Vieira    schedule 07.08.2018
comment
Я проверил, что усечения нет. Также пробовал plt.tight_layout (), но тот же результат - person Parthiban Rajendran; 07.08.2018
comment
ты классный Даниэль. Возможно, одним из виновников была ширина, уменьшившая визуализацию графа лучше. Также возникла проблема с расчетом. скоро обновлю. - person Parthiban Rajendran; 07.08.2018
comment
@PaariVendhan, с удовольствием! Рад, что вы смогли решить свою проблему, удачи вам в симуляциях! - person Daniel Vieira; 09.08.2018

def plotHist(nr, N, n_):
    ''' plots the RVs'''
    x = np.zeros((N))
    sp = f.add_subplot(3, 2, n_ )

    for i in range(N):    
        for j in range(nr):
            x[i] += np.random.binomial(10, 0.6)/10 
        x[i] *= 1/nr
    plt.hist(x, 100, normed=True, color='#348ABD', label=" %d RVs"%(nr));
    plt.setp(sp.get_yticklabels(), visible=False)


N = 1000000   # number of samples taken
nr = ([1, 2, 4, 8, 16, 32])

for i in range(np.size(nr)):
    plotHist(nr[i], N, i+1)

Выше приведен пример кода, основанный на общем блоге, который я написал на CLT: https://rajeshrinet.github.io/blog/2014/central-limit-theorem/

По сути, я генерирую несколько случайных чисел (nr) из распределения в диапазоне (0,1) и суммирую их. Затем я вижу, как они сходятся, когда я увеличиваю количество случайных чисел.

Вот снимок экрана с кодом и результатом.

person Rajesh    schedule 07.08.2018
comment
ваш np.random.binomial всегда будет возвращать случайное значение из биномиального распределения? Биномиальное распределение всегда сходится к нормальному. В моем случае я пытаюсь использовать распределение Бернулли и униформу. Не могли бы вы проверить мой код, если мне что-то не хватает? - person Parthiban Rajendran; 07.08.2018
comment
Извините за неправильный вопрос! Я не переделывал упражнение для бинома при n = 1, которым является Бернулли. У вас длинный код! Я постараюсь найти время, чтобы разобраться в этом. - person Rajesh; 07.08.2018
comment
Кроме того, указанное выше можно изменить, заменив x[i] += np.random.binomial(10, 0.6)/10 на x[i] += np.random.binomial(1, 0.6). Тогда это Бернулли. Вы можете видеть, что он все еще имеет тенденцию к гауссову. Я также отправил вам снимок экрана по электронной почте. - person Rajesh; 07.08.2018
comment
Я очень ценю то, что ответил на мой запрос и помог мне здесь. с нетерпением жду отзывов. Я также пробовал запустить ваш код с n = 1 в random.binomial и получил ненормальное распределение как здесь - person Parthiban Rajendran; 07.08.2018
comment
странно, я получаю только один график (вместе с предупреждением) и ненормальное распределение как здесь снова - person Parthiban Rajendran; 07.08.2018
comment
да, я видел твое изображение, так что удивляюсь, что у меня другое. также требуется очень много времени для выполнения для 1000000 - person Parthiban Rajendran; 07.08.2018
comment
Я решил проблему с предупреждением и одним графиком, теперь он выглядит так, как вы показали, я продолжаю изучать, как это может быть связано. пожалуйста, вернитесь, как только у вас будет время взглянуть на мой код. - person Parthiban Rajendran; 07.08.2018
comment
Исследование и попытка сопоставить ваш код с моей логикой помогли найти виновника, теперь графики намного лучше, без особых отклонений от моей логики. Я отправлю обновленный код, пожалуйста, проверьте, все ли в порядке. - person Parthiban Rajendran; 07.08.2018

Решение.
Думаю, я пришел к решению. Путем реверс-инжиниринга подхода Раджеша и подсказки Даниэля, может ли график быть проблемой, наконец, я понял виновника: ширина гистограммы по умолчанию, равная 0,8, слишком велика, чтобы мой график отображался как сплющенный сверху. Ниже приведен измененный код и вывод.

from SDSP import create_bernoulli_population, get_frequency_df
from random import shuffle, choices
from bi_to_nor_demo import get_metrics, bare_minimal_plot
import matplotlib.pyplot as plt

N = 10000  # 10000 balls
p = 0.6    # probability of yellow ball is 0.6, and others (1-0.6)=>0.4
n_pickups = 10       # sample size
n_experiments = 2000  # I dont know what this is called 


# THEORETICAL PDF
# generate population and calculate theoretical bernoulli pdf
population = create_bernoulli_population(N,p)
theor_df = get_frequency_df(population)


# STATISTICAL PDF
# choose sample, take mean and add to X_mean_list. Do this for n_experiments times. 
X_hat = []
X_mean_list = []
for each_experiment in range(n_experiments):
    X_hat = choices(population, k=n_pickups)  # choose, say 10 samples from population (with replacement)
    X_mean = sum(X_hat)/len(X_hat)
    X_mean_list.append(X_mean)
stats_df = get_frequency_df(X_mean_list)


# plot both theoretical and statistical outcomes
fig, (ax1,ax2) = plt.subplots(2,1, figsize=(5,10))
from SDSP import plot_pdf
mu,var,sigma = get_metrics(theor_df)
plot_pdf(theor_df, ax1, mu, sigma, p, title='True Population Parameters')
mu,var,sigma = get_metrics(stats_df)
plot_pdf(stats_df, ax2, mu, sigma, p=mu, bar_width=round(0.5/n_pickups,3),title='Sampling Distribution of\n a Sample Proportion')
plt.tight_layout()
plt.show()

Вывод:
output_solved

person Parthiban Rajendran    schedule 07.08.2018