Always awake,

카이제곱 분포 모양 확인하기 본문

통계

카이제곱 분포 모양 확인하기

호재 P.B 2020. 8. 30. 01:11

 

"본 포스팅은 카이제곱 분포의 모양을 개념적으로 확인하기 위한 포스팅입니다"

 

학부 때 통계 강의에서 이산확률 분포, 연속형 확률 분포를 배우며 아무렇지 않게 넘어갔던 분포의 모양에 갑자기 궁금해졌습니다.

 

특히, 일반적인 지수 분포, 정규분포 등은 수식을 통해서 모양을 이해할 수 있었지만 카이제곱 분포, F 분포 등은 추상적으로 분포의 모양을 이해했었습니다.

 

카이제곱 분포의 정의

i.i.d 한 (identically independent distributed) 한 k개의 표준 정규분포의 확률 변수를 제곱한 후 모두 더한 것은 자유도가 k인 카이제곱분포를 따른다.

모양은 아래와 같습니다.

 

<자유도(k)에 따른 카이제곱 분포의 모양>

 

출처 : http://blog.naver.com/PostView.nhn?blogId=mykepzzang&logNo=220852102307

 

 

카이제곱 분포 확률 계산? (표준정규분포 기반)

$Z \sim Norm(0,1)$인 표준 정규분포를 따른다고 하였을 때

 

$Z^2 \sim chisquare(1)$ : $Z^2$는 자유도가 1인 카이제곱 분포를 따릅니다.

 

자유도가 1인 카이제곱 분포의 확률변수가 1일 때의 확률은 $Z^2 = 1$이므로 $Z = ± 1$인 경우입니다.

(정규분포의 확률 변수 값이 +1, -1 일때의 확률을 더한 것과 같습니다)

 

즉, $Pr(Z=+1) + Pr(Z=-1)$이 됩니다.

 

카이제곱 분포 모양 추론 (확률변수 별 확률 계산)

카이제곱 분포의 각 확률변수 별 확률 값을 계산하여 분포의 모양을 추론하려 하였으나(표준 정규분포 확률변수로부터) 

자유도가 높아지면 카이제곱분포의 확률 변수에 대응하는 각 표준정규분포의 확률변수 값의 조합이 너무 많아서

이 방법으로는 할 수 없겠다고 판단하였습니다 ㅜ

 

ex) 자유도가 2인 카이제곱 분포 → 확률변수 = 1일 때 확률

 

  • i.i.d한 2개의 카이제곱 분포(자유도가 1인)의 확률변수가 각각 0.1, 0.9일 때도 가능하고, 0.2, 0.8일 때도 가능하고, 0.3, 0.7 일 때도 가능하고.... (무한한 경우의 수가 가능)
  • 실수집합이므로 무한이 많은 경우의 수가 있다
  • 이를 다 계산하는 것은 무리라고 생각하였습니다.

 

카이제곱 분포 모양 추론 (랜덤 확률변수 추출 후 빈도 기반 역추론)

그래서 생각한 방법은 

분포에서 랜덤 확률 변수를 추출하여 역으로 시뮬레이션 하는 방법입니다.

 

  • i.i.d 한 k개의 표준 정규분포에서 각각 10000개 정도씩 확률변수를 추출한다.
  • 그리고 추출된 각 확률변수를 제곱하여 더하면 자유도가 k인 카이제곱 분포의 랜덤 변수가 10000개가 생길 것이다.
  • 10000개의 랜덤 변수로 히스토그램을 그리면 자유도가 k인 카이제곱분포의 모양을 모양을 추론할 수 있을 것이다.

<카이제곱 분포 모양 확인 계획>

이것을 python으로 구현해보려고 합니다.

그렇다면 코드 작성 시 구체적으로 고려할 사항이 무엇이 있을지 생각해보았습니다.

 

  • 각 표준정규분포는 서로 i.i.d 해야 한다
    • → python의 표준정규분포에서 랜덤 확률 변수 추출 시 random_state 값을 다르게 설정하면 될 것 같다.
  • 표준 정규 분포의 값을 제곱하여 합한 것이 카이제곱 분포이다
    • → 각 시행(같은 no)에서 나온 확률변수의 값을 제곱하여 더해주면 된다.

이 두 가지를 고려하여 python의 scipy 패키지를 이용하여 코드를 작성해보았습니다.

 


코드 작성

패키지 importing

  • scipy의 stats 모듈 : 통계 관련 함수가 있다. 여기서 정규분포 클래스를 사용합니다.
from scipy import stats as st
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import random

 

변수 초기화

  • k_list : 확인하고자 하는 카이제곱 분포의 자유도 (1~9)
  • random_state_list : 정규분포에서 랜덤 확률변수 추출 시 각 정규분포마다 사용될 random seed 값의 후보
  • chi_dict 
    • key : 자유도(k)
    • value : k개의 정규분포 랜덤 샘플 값, 제곱하여 더한 카이제곱 값이 담긴 Data frame (아래의 temp_df)
  • rv : 정규분포 클래스 
  • chi_df : chi_dict의 각 자유도별 카이제곱 값이 담긴 Data frame
# degree of freedom for testing 
k_list = [i for i in range(1, 10)]

# candidates of random state for i.i.d condition to each Normal Distribution sample
random_state_list = [i for i in range(1000)]

# key : degree of freedom, value : dataframe for 10000 sizes (columns = index column for each normal distribution sample set + chi square sample column )
chi_dict = {}
rv = st.norm(0,1)

# dataframe for chi sampled (each degree of freedom)
chi_df = pd.DataFrame()

 

카이제곱 분포 랜덤 확률 변수 생성

i.i.d 한 k개의 정규분포에서 10000개씩 랜덤 확률 변수를 생성 후 각각 제곱한 값을 더하여 카이제곱 랜덤 확률 변수를 생성합니다.

 

for k in k_list:
    # value for chi_dict
    temp_df = pd.DataFrame()
    
    
    # sampling for each norm distribution(k replication)(i.i.d) 
    for i in range(1, k+1):
        rand_state = random.choice(random_state_list)
        random_state_list.remove(rand_state)
        temp_df['%d norm sampled' % i] = rv.rvs(size = 10000, random_state = rand_state)
    
    chi_val_colname = 'chi dof_{}_sampled'.format('0' + str(k) if k < 10 else k) 
    temp_df[chi_val_colname] = temp_df[['%d norm sampled' % i for i in range(1, k+1)]].apply(np.square).sum(axis = 1)
    
    chi_dict[k] = temp_df
    
    chi_df[chi_val_colname] = temp_df[chi_val_colname]

데이터의 생김새를 예시로 보면 다음과 같습니다.

 

  • chi_dict[3] : k = 3인 카이제곱 분포 sample
    • i.i.d 한 정규분포 k개(3개)에서 10000개씩 샘플링
    • 제곱을 취한 후 합하여 chi dof_03_sampled 열 생성

 

  • chi_df : 자유도(k)별로 생성된 카이제곱 sample
    • k별로 chi_dict의 value 중 마지막 열(카이제곱 sample)을 합친 Data frame

 

카이제곱 분포 sample 분포 확인(Histogram)

이제 chi_df에서 자유도 별로 샘플링 된 값들을 히스토그램을 그려 분포의 모양을 확인해보겠습니다.

col_num = 3
row_num = (len(chi_df.columns) // col_num) + 1

fig, ax = plt.subplots(row_num, col_num , figsize = (col_num * 10, row_num * 5 ), sharey = True)

for idx, c in enumerate(chi_df.columns):

    chi_df[c].hist(ax = ax.ravel()[idx], bins = 300)
    ax.ravel()[idx].set_title(c[4:10], fontsize = 15)
    
fig.suptitle('chi square histogram by degree of freedom(1~9)', fontsize= 20)

<자유도(1~9)에 따른 카이제곱 분포 히스토그램>

이론과 어느정도 일치하는 것을 볼 수 있습니다.

 


마치며

피드백은 언제나 환영입니다~

 

 

글이 도움이 되셨다면 아래 클릭 한번 부탁드립니다 :)

반응형

'통계' 카테고리의 다른 글

신뢰성 분석  (1) 2021.10.11
로지스틱 회귀(Logistic Regression)  (3) 2021.10.10
공분산과 상관계수  (11) 2020.09.20
주성분 분석(PCA)의 개념적 이해  (0) 2020.09.01
최대 우도 추정법(Maximum Likelihood Estimation)  (5) 2020.09.01