본문 바로가기
수학의 재미/확률분포

정균분포 난수를 만들어 주세요 #6 : random.normal

by hustler78 2022. 6. 17.
728x90
반응형

이번글은 

2022.06.15 - [수학의 재미/확률분포] - 정균분포 난수를 만들어 주세요 #5 : Marsaglia-Bray method

 

정균분포 난수를 만들어 주세요 #5 : Marsaglia-Bray method

이번 글은 2022.06.15 - [수학의 재미/확률분포] - 정균분포 난수를 만들어 주세요 #4 : Box-Muller 방법 정균분포 난수를 만들어 주세요 #4 : Box-Muller 방법 이번 글은 2022.06.14 - [수학의 재미/확률분포] -..

sine-qua-none.tistory.com

에서 이어집니다.

 

저번글에서 5회에 걸쳐 정규분포를 따르는 random number를 만드는 방법에 대해서 다뤘습니다.

 

방법1 중심극한 정리를 이용하여, uniform random number의 표본평균 구하기  [여기]
방법2 Normal cumulative distribution function 을 이용하기 [여기]에서 [여기]까지
방법3 Box Muller 방법으로 정규분포 난수 2개를 한방에 구하기 [여기]

이 방법들에 덧붙여 python에서 제공하는 정규분포 난수가 있습니다. 바로

numpy.random.normal

입니다.

 

 

np.random.normal(loc=0.0, scale=1.0, size=None)

이렇게 평균(loc)과 표준편차(scale)을 size를 입력받아 정규분포 난수 배열을 생성해주는 함수입니다. code 예제를 보겠습니다.

이 예제는 python의 numpy tutorial 에서 가지고 왔습니다.

 

import math
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

def Introduce_Python_normal_random():
    mu, sigma = 0, 0.1  # mean and standard deviation
    s = np.random.normal(mu, sigma, 1000)
    count, bins, ignored = plt.hist(s, 30, density=True)
    # plt.plot(bins, 1 / (sigma * np.sqrt(2 * np.pi)) *
    #          np.exp(- (bins - mu) ** 2 / (2 * sigma ** 2)),
    #          linewidth=2, color='r')
    plt.plot(bins, norm.pdf(bins,mu,sigma))

    plt.show()
    
if __name__ == '__main__':
    Introduce_Python_normal_random()

 

간략하게 보면,

    s = np.random.normal(mu, sigma, 1000)​

 

$\mu=0 , \sigma=0.1$인 정규분포 난수를 1000개 발생시켜

 

    count, bins, ignored = plt.hist(s, 30, density=True)

bins=30인, 즉 계급의 계수가 30개인 histogram을 그리는데 밀도 함수 형식으로 그립니다(density=True) 이렇게 히스토그램의 전체 면적이 1이 되도록 그려야, 정규분포의 확률 밀도 함수와 비교가 가능하겠죠.

 

    # plt.plot(bins, 1 / (sigma * np.sqrt(2 * np.pi)) *
    #          np.exp(- (bins - mu) ** 2 / (2 * sigma ** 2)),
    #          linewidth=2, color='r')
    plt.plot(bins, norm.pdf(bins,mu,sigma))

정규분포의 pdf 함수를 그립니다. $x$ 는 bins 이고, 평균과 분산은 각각 mu, sigma입니다.

 

결과를 볼까요?

난수 1000개를 히스토그램으로 세운 것과 이론적인 확률 밀도 함수가 잘 매치되는 모습입니다. 

 

난수의 개수를 대폭 늘리고, 계급 구간을 더 잘게 쪼개는 어떨까요?

 

import math
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

def Introduce_Python_normal_random():
    mu, sigma = 0, 0.1  # mean and standard deviation
    s = np.random.normal(mu, sigma, 100000)
    count, bins, ignored = plt.hist(s, 100, density=True, label='normal random histogram')
    # plt.plot(bins, 1 / (sigma * np.sqrt(2 * np.pi)) *
    #          np.exp(- (bins - mu) ** 2 / (2 * sigma ** 2)),
    #          linewidth=2, color='r')
    plt.plot(bins, norm.pdf(bins,mu,sigma), linewidth=2, color='r', label='pdf of normal')
    plt.legend()
    plt.show()

if __name__ == '__main__':
    Introduce_Python_normal_random()

 

더욱더 완벽한 모습이 나옵니다. 이 정도면 지금까지 봤던 정규분포 난수 생성법 다 필요 없이 python 제공 함수를 써도 될 것 같습니다.

728x90
반응형

댓글