Как построить кривую нормального распределения вместе с центральной предельной теоремой - PullRequest
2 голосов
/ 11 марта 2019

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

Ниже приведена реализация, которую я пробовал.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import math

# 1000 simulations of die roll
n = 10000

avg = []
for i in range(1,n):#roll dice 10 times for n times
    a = np.random.randint(1,7,10)#roll dice 10 times from 1 to 6 & capturing each event
    avg.append(np.average(a))#find average of those 10 times each time

plt.hist(avg[0:])

zscore = stats.zscore(avg[0:])

mu, sigma = np.mean(avg), np.std(avg)
s = np.random.normal(mu, sigma, 10000)

# Create the bins and histogram
count, bins, ignored = plt.hist(s, 20, normed=True)

# Plot the distribution curve
plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2)))

Я получаю приведенный ниже график,

enter image description here

Внизу вы можете увидеть нормальную кривую красного цвета.

Может кто-нибудь сказать мне, почему кривая не подходит?

Ответы [ 4 ]

1 голос
/ 11 марта 2019
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import math

# 1000 simulations of die roll
n = 10000

avg = []
for i in range(1,n):#roll dice 10 times for n times
    a = np.random.randint(1,7,10)#roll dice 10 times from 1 to 6 & capturing each event
    avg.append(np.average(a))#find average of those 10 times each time

plt.hist(avg[0:],20,normed=True)

zscore = stats.zscore(avg[0:])

mu, sigma = np.mean(avg), np.std(avg)
s = np.random.normal(mu, sigma, 10000)

# Create the bins and histogram
count, bins, ignored = plt.hist(s, 20, normed=True)

# Plot the distribution curve
plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2)))

Я только что уменьшил гистограмму среднего списка.

График: -

enter image description here

1 голос
/ 11 марта 2019

У тебя почти было это! Сначала убедитесь, что вы строите две гистограммы на одной и той же оси:

plt.hist(avg[0:])

и

plt.hist(s, 20, normed=True)

Чтобы вы могли построить нормальную плотность по гистограмме, вы правильно нормализовали второй график с аргументом normed=True. Однако вы также забыли нормализовать первую гистограмму (plt.hist(avg[0:]), normed=True).

Я бы также порекомендовал, поскольку, поскольку вы уже импортировали scipy.stats, вы также можете использовать обычный дистрибутив, который входит в этот модуль, вместо того, чтобы самостоятельно кодировать pdf.

Собрав все это вместе, мы получим:

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats

# 1000 simulations of die roll
n = 10000

avg = []
for i in range(1,n):
    a = np.random.randint(1,7,10)
    avg.append(np.average(a))

# CHANGED: normalise this histogram too
plt.hist(avg[0:], 20, normed=True)

zscore = stats.zscore(avg[0:])

mu, sigma = np.mean(avg), np.std(avg)
s = np.random.normal(mu, sigma, 10000)

# Create the bins and histogram
count, bins, ignored = plt.hist(s, 20, normed=True)

# Use scipy.stats implementation of the normal pdf
# Plot the distribution curve
x = np.linspace(1.5, 5.5, num=100)
plt.plot(x, stats.norm.pdf(x, mu, sigma))

Что дало мне следующий сюжет:

enter image description here

Редактировать

В комментариях вы спрашивали:

  1. Как я выбрал 1,5 и 5,5 в np.linspace
  2. Можно ли построить нормальное ядро ​​на ненормированной гистограмме?

По адресу q1. Сначала я выбрал 1,5 и 5,5 на глаз. После построения гистограммы я увидел, что ячейки гистограммы выглядят в диапазоне от 1,5 до 5,5, так что это диапазон, на котором мы хотели бы построить нормальное распределение.

Более программный способ выбора этого диапазона был бы:

x = np.linspace(bins.min(), bins.max(), num=100)

Что касается вопроса 2. Да, мы можем достичь того, что вы хотите. Однако вы должны знать, что мы больше не будем строить функцию плотности вероятности .

После удаления аргумента normed=True при построении гистограммы:

x = np.linspace(bins.min(), bins.max(), num=100)

# Find pdf of normal kernel at mu
max_density = stats.norm.pdf(mu, mu, sigma)
# Calculate how to scale pdf
scale = count.max() / max_density

plt.plot(x, scale * stats.norm.pdf(x, mu, sigma))

Это дало мне следующий сюжет: enter image description here

0 голосов
/ 04 апреля 2019

Бросок игральных костей - это случай равномерного распределения.Вероятность появления любого числа от 1 до 6 составляет 1/6.Таким образом, среднее значение и стандартное отклонение задаются как

enter image description here

Теперь CLT говорит, что для достаточно большого значения n, равного 10 в коде,PDF среднего значения n бросков приблизится к нормальному распределению со средним 3,5 и стандартным отклонением 1,7078 / sqrt (10)

n_bins=50
pdf_from_hist, bin_edges=np.histogram(np.array(avg), bins=n_bins, density=True)
bin_mid_pts= np.add(bin_edges[:-1], bin_edges[1:])*0.5
assert(len(list(pdf_from_hist))  == len(list(bin_mid_pts)))
expected_std=1.7078/math.sqrt(10)
expected_mean=3.5
pk_s=[]
qk_s=[]
for i in range(n_bins):
    p=stat.norm.pdf(bin_mid_pts[i], expected_mean, expected_std) 
    q=pdf_from_hist[i]
    if q <= 1.0e-5:
        continue
    pk_s.append(p)
    qk_s.append(q)
#compute the kl divergence
kl_div=stat.entropy(pk_s, qk_s)
print('the pdf of the mean of the 10 throws differ from the corresponding normal dist with a kl divergence of %r' % kl_div)
0 голосов
/ 11 марта 2019

логика кажется правильной.

проблема заключается в отображении данных.

попробуйте нормализовать первую гистограмму с помощью normed=true и иметь одинаковые бины для обеих гистограмм.как 20 бункеров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...