실습_4. 추론 및 가설검정

Updated:

이항분포

이산형 확률분포 중 하나인 이항분포를 따르는 확률질량함수와 누적분포함수를 확인해보고 샘플을 뽑아보겠습니다.

  • 문제

Q1. 확률질량함수 성공의 횟수를 확률변수 X 로 두고, X~ Bin(n,p) 에 대한 분포를 그려보겠습니다.

1) n을 10개, p 를 0.3 개로 두고, sp.stats.binom 을 사용하여 stat_bin 에 저장해보겠습니다.

n, p = 10,  0.3
stat_bin = sp.stats.binom(n, p)

2) 이에 대한 확률질량함수를 그려보면

x_axis = np.arange(n + 1) 
plt.bar(x_axis, stat_bin.pmf(x_axis))

1의 확률을 0.3 으로 해뒀기 때문에 1이 3번 나오는 것이 그래프에서 가장 높은 질량을 차지하고 있는 것을 확인할 수 있습니다.

Q2. 누적분포함수 이항분포에 대한 누적분포함수를 그려보겠습니다. 위에서 코드만 pmf 를 cdf 로 바꿔주면 됩니다.

x_axis = np.arange(n + 1) 
plt.bar(x_axis, stat_bin.cdf(x_axis))

Q3. 랜덤표본 추출 X는 성공의 횟수이므로, x = 0,1,…,n이 될 수 있습니다. 위에서 pmf 를 그려보았던 10번 시도하고 성공의 확률이 p=0.3을 따르는, 즉 X~bin(10,3) 인 분포를 50번 반복하여 성공의 횟수에 대한 랜덤표본을 확인해보고 이에 대한 표본평균을 계산해보겠습니다.

1) 반복값의 동일함을 위한 seed 설정

np.random.seed(seed = 0) Copy seed는 랜덤으로 표본추출 등을 할 때 재현성을 갖추기 위해 설정합니다.

2) 랜덤표본 추출 표본을 추출하여 random_bin 에 저장해 확인해보겠습니다.

random_bin = np.random.binomial(n = 10,p=0.3, size = 50)

여기서 n을 1으로 주면, 베르누이 분포를 따르는 표본을 추출할 수 있습니다.

3) 평균계산 앞 시간에서 배운 평균을 계산해 bin_mean 에 저장해보겠습니다.

bin_mean = np.mean(random_bin)

10번의 시도에 따른 성공의 확률을 0.3 으로 줬으니까, 평균도 3과 매우 가까운 것을 확인하실 수 있습니다.

코드

from elice_utils import EliceUtils
import numpy as np 
import matplotlib.pyplot as plt
import scipy as sp
from scipy import stats
elice_utils = EliceUtils()    

# Q1. 이항분포pmf 그리기 
# 이항분포 생성
n, p = 10,  0.3
stat_bin = sp.stats.binom(n, p)

# 그리기
fig, ax = plt.subplots()
## pmf를 만드는 코드를 작성해 주세요
x_axis = np.arange(n + 1) 
plt.bar(x_axis, stat_bin.pmf(x_axis))


##
plt.show()
fig.savefig("pmf_plot.png")
elice_utils.send_image("pmf_plot.png")

# Q2. 이항분포cdf 그리기 
## cdf 만드는 코드를 작성해 주세요
x_axis = np.arange(n + 1) 
plt.bar(x_axis, stat_bin.cdf(x_axis))


##
plt.show()
fig.savefig("cdf_plot.png")
elice_utils.send_image("cdf_plot.png")


# Q3. 랜덤표본 추출
## seed 설정 seed = 0 
np.random.seed(seed = 0)

## 랜덤 샘플 추출
random_bin = np.random.binomial(n = 10,p=0.3, size = 50)
print(random_bin)
## 평균계산
bin_mean = np.mean(random_bin)
print(bin_mean)

초기하분포

불량을 잡아내는데 유용하게 쓰이는 이산형 분포인 초기하분포의 확률질량함수를 확인해보겠습니다.

  • 문제

공장에서 A공정에서는 모니터를 30개씩 생산하고 있습니다. 이 공정의 불량률을 검사하는데 양품이 25개, 불량품이 5개인 공정에서 10개의 모니터를 추출해 불량품인지 확인 해보겠습니다.

Q1. 확률질량함수

1) 양품이 25개, 불량품이 5개인 공정에서 10개의 모니터를 추출해 불량품인지 확인하여 stat_hyp 에 저장해보겠습니다.

[M, n, N] = [30, 5, 10]
stat_hyp = sp.stats.hypergeom(M, n, N)

2) 위의 pmf로 확률질량함수를 확인해보겠습니다.

x_axis = np.arange(n+1)
plt.bar(x_axis, stat_hyp.pmf(x_axis))

각각의 확률은 발견할 불량품의 개수입니다. 10개를 검사했을 때 2개의 불량품을 발견할 확률이 가장 큰 걸 확인할 수 있습니다.

Q2. 누적분포함수

pmf를 cdf로 변경만 해주면 누적분포함수를 확인할 수 있습니다.

x_axis = np.arange(n+1)
plt.bar(x_axis, stat_hyp.cdf(x_axis))

Q3. 샘플링 X는 성공의 횟수이므로, x = 0,1,…,n이 될 수 있습니다. 위에서 pmf 를 그려보았던 양품이 25개, 불량품이 5개인 공정에서 10개의 모니터를 추출해 불량품인지 확인하는 과정을 50번 반복하여 샘플링 결과 양품의 개수에 대한 랜덤표본을 확인해보고 이에 대한 표본평균을 계산해보겠습니다.

1) 반복값의 동일함을 위한 seed 설정

np.random.seed(seed = 0)

seed는 랜덤으로 표본추출 등을 할 때 재현성을 갖추기 위해 설정합니다.

2) 샘플 추출 샘플을 추출하여 random_hyp 에 저장해 확인해보겠습니다.

random_hyp = np.random.hypergeometric(ngood = 5, nbad= 25, nsample=10, size = 50)

ngood 에 우리가 관심이 있는 불량품의 개수를 넣어야 합니다. 영어가 bad이라고 해서 불량품의 개수를 bad 에 넣으면 반대의 결과가 나옵니다.

3) 평균계산 앞 시간에서 배운 평균을 계산해 hyp_mean 에 저장해보겠습니다.

hyp_mean = np.mean(random_hyp)

평균이 2와 가까운 것을 확인하실 수 있습니다. 10개를 검사했을 때 2개정도의 불량품을 찾아낼 수 있습니다.

코드

from elice_utils import EliceUtils
import numpy as np 
import matplotlib.pyplot as plt
import scipy as sp
from scipy import stats
elice_utils = EliceUtils() 

# 초기하분포
[M, n, N] = [30, 5, 10]
stat_hyp = sp.stats.hypergeom(M, n, N)

# 그리기
fig, ax = plt.subplots()
## pmf를 만드는 코드를 작성해 주세요
x_axis = np.arange(n+1)
plt.bar(x_axis, stat_hyp.pmf(x_axis))


##
plt.show()
fig.savefig("pmf_plot.png")
elice_utils.send_image("pmf_plot.png")

# Q2. 초기하분포 cdf 그리기 
## cdf 만드는 코드를 작성해 주세요
x_axis = np.arange(n+1)
plt.bar(x_axis, stat_hyp.cdf(x_axis))

##
plt.show()
fig.savefig("cdf_plot.png")
elice_utils.send_image("cdf_plot.png")

# Q3. 랜덤표본 추출
## seed 설정 seed = 0 
np.random.seed(seed = 0)

## 랜덤 샘플 추출
random_hyp = np.random.hypergeometric(ngood = 5, nbad= 25, nsample=10, size = 50)
print(random_hyp)
## 평균계산
hyp_mean = np.mean(random_hyp)
print(hyp_mean)

균일분포

일정한 구간에서 임의로 선택된 수에 대한 확률분포이며 연속형 분포인 균일분포의 확률밀도함수를 확인해보겠습니다.

  • 문제

0부터 1까지의 구간을 따르는 균일분포 X~uni(0,1) 에 대하여 알아보겠습니다.

Q1. 확률밀도함수 1) 0부터 1까지의 구간에 속하는 값을 가질 수 있고 그 확률이 균일한 확률밀도함수를 확인하여 stat_uni 에 저장해보겠습니다.

stat_uni = sp.stats.uniform()

2) 위의 pdf로 확률밀도함수를 확인해보겠습니다.

x_axis = np.linspace(0, 1, 100)
plt.bar(x_axis, stat_uni.pdf(x_axis))

0과 1 사이의 구간에 속하는 값을 가질 확률이 동일한 분포이므로 직사각형의 형태가 나옵니다.

Q2. 누적분포함수 확률밀도함수의 pmf를 cdf로 변경만 해주면 누적분포함수를 확인할 수 있습니다.

x_axis = np.linspace(0, 1, 100)
plt.bar(x_axis, stat_uni.cdf(x_axis))

+np.linspace(0, 1, 100) 는 0부터 1까지의 구간에서 100개의 숫자를 동일한 크기만큼 뽑아주는 함수입니다.

Q3. 샘플링 0부터 1까지의 구간을 따르는 균일분포 X~uni(0,1) 에 대한 랜덤표본을 확인해보고 이에 대한 표본평균을 계산해보겠습니다.

1) 반복값의 동일함을 위한 seed 설정

np.random.seed(seed = 0)

seed는 랜덤으로 표본추출 등을 할 때 재현성을 갖추기 위해 설정합니다.

2) 샘플 추출 샘플을 100개 추출하여 random_uni 에 저장해 확인해보겠습니다.

random_uni = np.random.uniform(0,1,100)

0부터 1까지의 구간에서 100개의 샘플을 추출합니다.

3) 평균계산 앞 시간에서 배운 평균을 계산해 uni_mean 에 저장해보겠습니다.

uni_mean = np.mean(random_uni)

평균이 0.5와 매우 가까운 것을 확인하실 수 있습니다.

코드

from elice_utils import EliceUtils
import numpy as np 
import matplotlib.pyplot as plt
import scipy as sp
from scipy import stats
elice_utils = EliceUtils() 

# 균일분포
stat_uni = sp.stats.uniform()

# 그리기
fig, ax = plt.subplots()
## pdf를 만드는 코드를 작성해 주세요
x_axis = np.linspace(0, 1, 100)
plt.bar(x_axis, stat_uni.pdf(x_axis))


##
plt.show()
fig.savefig("pdf_plot.png")
elice_utils.send_image("pdf_plot.png")

# Q2. 균일분포 cdf 그리기 
## cdf 만드는 코드를 작성해 주세요
x_axis = np.linspace(0, 1, 100)
plt.bar(x_axis, stat_uni.cdf(x_axis))

##
plt.show()
fig.savefig("cdf_plot.png")
elice_utils.send_image("cdf_plot.png")

# Q3. 균일분포 샘플링
## seed 설정
np.random.seed(seed = 0)

## 샘플 추출
random_uni = np.random.uniform(0,1,100)
print(random_uni)

## 평균 계산
uni_mean = np.mean(random_uni)
print(uni_mean)

정규분포

종 모양의 확률밀도함수를 갖는 분포로 여러 종류의 자료를 설명하는데 좋은 분포이며 연속형 분포인 정규분포의 확률밀도함수를 확인해보겠습니다.

  • 문제

mu 가 0 이고 sigma 가 1인 정규분포인 표준정규분포 X~N(0, 1) 에 대하여 알아보겠습니다.

Q1. 확률밀도함수 1) mu 가 0 이고 sigma 가 1인 표준정규분포의 확률밀도함수를 확인하여 stat_nor 에 저장해보겠습니다.

stat_nor = sp.stats.norm(0,1)

2) 위의 pdf로 확률밀도함수를 확인해보겠습니다.

x_axis = np.linspace(-3, 3, 100)
plt.bar(x_axis, stat_nor.pdf(x_axis))

평소에 많이 보시던 종형의 분포 형태가 나옵니다.

Q2. 누적분포함수 확률밀도함수의 pmf를 cdf로 변경만 해주면 누적분포함수를 확인할 수 있습니다.

x_axis = np.linspace(-3, 3, 100)
plt.bar(x_axis, stat_nor.cdf(x_axis))

+np.linspace(-3, 3, 100) 는 -3부터 3까지의 구간에서 100개의 숫자를 동일한 크기만큼 뽑아주는 함수입니다. 표준정규분포의 그래프를 많이 보셨던 형태와 유사하게 하기 위해 임의로 -3,3 을 설정했습니다.

Q3. 샘플링 표준정규분포 X~N(0,1) 에 대한 랜덤표본을 확인해보고 이에 대한 표본평균을 계산해보겠습니다.

1) 반복값의 동일함을 위한 seed 설정

np.random.seed(seed = 0)

seed는 랜덤으로 표본추출 등을 할 때 재현성을 갖추기 위해 설정합니다.

2) 샘플 추출 샘플을 100개 추출하여 random_nor 에 저장해 확인해보겠습니다.

random_nor = np.random.normal(0,1,100)

표준정규분포에서 100개의 샘플을 추출합니다.

표준정규분포이므로 np.random.normal(0,1,100) 대신np.random.standard_normal(100)을 사용해도 같은 기능을 합니다. 3) 평균계산 앞 시간에서 배운 평균을 계산해 nor_mean 에 저장해보겠습니다.

nor_mean = np.mean(random_nor)

평균이 0과 매우 가까운 것을 확인하실 수 있습니다.

코드

from elice_utils import EliceUtils
import numpy as np 
import matplotlib.pyplot as plt
import scipy as sp
from scipy import stats
elice_utils = EliceUtils() 

# 정규분포
stat_nor = sp.stats.norm(0,1)

# Q1. 정규분포 pdf 그리기
fig, ax = plt.subplots()
## pdf를 만드는 코드를 작성해 주세요
x_axis = np.linspace(-3, 3, 100)
plt.bar(x_axis, stat_nor.pdf(x_axis))


##
plt.show()
fig.savefig("pdf_plot.png")
elice_utils.send_image("pdf_plot.png")

# Q2. 정규분포 cdf 그리기 
## cdf 만드는 코드를 작성해 주세요
x_axis = np.linspace(-3, 3, 100)
plt.bar(x_axis, stat_nor.cdf(x_axis))


##
plt.show()
fig.savefig("cdf_plot.png")
elice_utils.send_image("cdf_plot.png")

# Q3. 정규분포 샘플링
## seed 설정
np.random.seed(seed = 0)

## 샘플 추출
random_nor = np.random.normal(0,1,100)
print(random_nor) 

## 평균 계산
nor_mean = np.mean(random_nor)
print(nor_mean)

이항 검정

이항 검정에 대한 가설을 설정하고, 검정을 해보겠습니다. 후라이드 치킨 종류를 선호하는 후라이드 파(0)와 양념 치킨 종류를 선호하는 양념파(1)가 있습니다. 이 치킨 선호 유형을 베르누이 확률분포로 결정되는 값이라고 가정하겠습니다. 새로 출시한 치킨을 선호하는 비율은 양념파와 후라이드파가 같다고 가정하므로 베르누이 확률분포의 모수는 0.5 입니다.

새로 출시한 치킨을 선호하는 사람 50명 중 30명이 양념파였을 때, “새로 출시된 치킨을 선호하는 사람은 양념파이다” 라고 주장할 수 있을까요? 이를 표본을 추출하여 유의수준 0.05를 기준으로 확인해보겠습니다.

귀무가설 : “새로 출시한 치킨을 선호하는 사람은 치킨 선호 유형과 연관이 없다 : p= 0.5” vs. 대립가설 : “새로 출시한 치킨을 선호하는 사람은 치킨 선호 유형과 연관이 있다 : p != 0.5”

  • 문제

1) 추출한 표본 값의 동일함을 위한 seed 설정

np.random.seed(seed = 0)

seed는 랜덤으로 표본추출 등을 할 때 재현성을 갖추기 위해 설정합니다.

2) 표본 추출

귀무가설의 모수 p = 0.5 를 갖고 베르누이 분포를 따르므로 n = 1으로 두어 이를 따르는 표본을 10개 추출하여 random_ber 에 저장해 확인해보겠습니다.

random_ber = np.random.binomial(n = 1,p=0.5, size = 50)

그리고 추출한 표본 중 0이 아닌 개수, 여기서는 1의 개수를 뽑아 n_ber 에 저장해보겠습니다.

여기서 np.count_nonzero() 함수는 0이 아닌 값의 개수를 세어 주는 함수입니다. 베르누이 분포는 0 또는 1의 값만 나오므로 1의 값이 몇 개인지 세어줍니다.

n_ber = np.count_nonzero(random_ber)

1의 값은 30개입니다. 그렇다면 p = 0.6 일까요? 이를 검정해보겠습니다.

3) 이항 검정 2)에서 추출한 표본을 가지고 이항검정을 해 binom_test 에 저장해보겠습니다.

binom_test = sp.stats.binom_test(n_ber, 50)

결과값인 유의확률이 0.05 보다 매우 크므로 귀무가설을 기각할 수 없습니다. 그러므로 새로 출시된 치킨을 선호하는 것은 후라이드파와 양념파에 상관이 없습니다. 즉, “새로 출시된 치킨을 선호하는 사람은 양념파이다” 라고 주장할 수 없습니다.

#

import numpy as np 
import scipy as sp
from scipy import stats

# 이항 검정
## 1) seed 설정 seed = 0
np.random.seed(seed = 0)

## 2) 샘플 추출
random_ber = np.random.binomial(n = 1,p=0.5, size = 50)
print(random_ber)

n_ber = np.count_nonzero(random_ber)
print(n_ber)

## 3) 가설 검정
binom_test = sp.stats.binom_test(n_ber, 50)
print(binom_test)

모평균 가설검정

모평균 가설검정에 대한 가설을 설정하고, 검정을 해보겠습니다. 표준편차의 값을 알고 있는 정규분포의 표본에 대한 기댓값을 검정하는 방법이다. 단일 표본 z- 검정이라고도 하는데, 따로 함수ztest가 준비되어 있지 않으므로 직접 ztest 를 만들어보겠습니다.

“고양이”를 주인공으로 동영상을 촬영하여 올렸을 때, 한 달 동안 구독자 수를 100명 으로 늘릴 수 있다고 합니다. 이 때, 표준편차는 5임을 알고 있다고 가정합니다. 10명을 대상으로 고양이 주인공 동영상의 한 달 구독자 수를 조사하였더니, 평균이 “103.69” 이었다고 합니다.

고양이 주인공 동영상의 구독자 수의 모평균을 mu라고 하자. 위의 주장은 mu = 100 이므로 가설은 귀무가설 : “ mu = 100” vs. 대립가설 : “ mu != 100”

  • 문제 1) 추출한 표본 값의 동일함을 위한 seed 설정
np.random.seed(seed = 0)

seed는 랜덤으로 표본추출 등을 할 때 재현성을 갖추기 위해 설정합니다.

2) 표본 추출

귀무가설의 모수 mu = 100, sigma = 5 를 갖고 정규분포를 따르는 표본을 10개 표본을 추출하여 random_nor 에 저장해 확인해보겠습니다.

random_nor = np.random.normal(100,5,10)

추출한 표본으로 평균을 계산해 nor_mean 에 저장해보겠습니다.

nor_mean = np.mean(random_nor)

이를 확인해보니, 103.69가 나왔습니다. 그렇다면 대립가설인 mu != 100 이 맞을까요?

3) 모평균 가설 검정 함수 정의

def ztest(stat, mu, sigma):
    z = (stat.mean() - mu) / (sigma*np.sqrt(len(stat)))
    return (2 * (1-sp.stats.norm.cdf(z)))

4) 모평균 가설 검정 2)에서 추출한 표본을 가지고 모평균 가설 검정을 해 mu_test 에 저장해보겠습니다.

mu_test = ztest(random_nor, 100, 10)

결과값인 유의확률이 0.05 보다 크므로 귀무가설을 기각할 수 없습니다. 하지만, 이는 표본의 크기가 매우 작으므로 이러한 결과가 나왔을 수도 있습니다. 표본의 크기를 1000으로 높여서 다시 한 번 검정해보고 이에 대한 결과를 확인해보세요!

코드

import numpy as np 
import scipy as sp
from scipy import stats

# 모평균 가설검정
## 1) seed 설정 seed = 0
np.random.seed(seed = 0)

## 2) 샘플 추출
random_nor = np.random.normal(100,5,10)
print(random_nor)

# 평균 계산
nor_mean = np.mean(random_nor)
print(nor_mean)

## 3) 모평균 가설 검정 함수 정의
def ztest(stat, mu, sigma):
    z = (stat.mean() - mu) / (sigma*np.sqrt(len(stat)))
    return (2 * (1-sp.stats.norm.cdf(z)))

## 4) 모평균 가설 검정
mu_test = ztest(random_nor, 100, 10)
print(mu_test)

Leave a comment