반응형

Intro


정규분포는 종모양을 띄는 분포로, 가장 익숙한 개념입니다. 이번 글에서는 정규분포와 정규성 검정에 대해서 정리하겠습니다.

정규분포


정규분포 (normal distribution, gaussian distribution)는 평균($\mu$)과 표준편차($\sigma$)에 의해 모양이 결정되는 데이터 분포입니다.

따라서 확률 변수 $X$가 정규분포를 따르고 평균과 표준편차를 알 수 있으면, 각 $x$값이 발견될 확률을 아래의 식으로 구할 수 있습니다.

$$\frac{1}{\sqrt{2\pi\sigma}}e^{-\frac{(x-\mu)^2}{2\sigma^2}}$$

$\mu=0, \sigma=1$인 특수한 경우의 정규분포를 표준 정규분포라고 합니다.

표준 정규분포를 따르지 않는 정규분포와 다른 분포들도 분포를 이루는 각 값에서 평균을 빼고, 표준편차로 나눔으로써 $\mu=0, \sigma=1$인 상태로 변환할 수 있습니다.

이런 과정을 표준화(standardization)이라고 합니다.

이때 표준화된 분포의 각 값을 z-score라고 합니다.

$$z=\frac{x-\mu}{\sigma}$$

표준화는 분포의 모양을 바꾸지 않는 변환이기 때문에, 아래와 같은 목적으로 사용될 수 있습니다.

두 분포의 모양 비교
데이터 전처리 (scaling)
정규성 검정

정규성 검정


정규성 검정(normality test)은 주어진 분포가 정규분포를 따르는지 확인하기 위한 방법입니다. 이는 가설 검정 기법인 t-test, ANOVA가 검정하려는 데이터의 분포가 정규성을 갖는다는 가정하에 사용되기 때문에, 해당 방법들을 적용할 수 있는지 여부를 알기 위해서 사용됩니다.

정규성 검정을위한 첫번째 방법으로, Q-Qplot(Quantile-Quantile plot)이 있습니다. Q-Qplot은 두 분포가 얼마나 유사한지를 보여주는 일반적인 graphical method입니다.

이때 정규성검정을 하고자 하는 분포를 표준화한 뒤, 표준 정규분포와의 Q-Qplot을 그리면, 해당 분포가 정규분포를 갖는지 알 수 있습니다.

예시를 통해 확인해보겠습니다.

[code download]

# 표준정규분포의 Q-Q plot
std_normal = np.random.normal(loc=0, scale=1, size=20000) # 표준정규분포에서 데이터 샘플링, loc=평균, scale=편차

f, ax = plt.subplots(1,2, figsize=(10,5))
f.subplots_adjust(right=1)

sns.histplot(std_normal, ax=ax[0]) # 샘플링한 데이터의 분포
ax[0].set_title("Data distribution")
ax[0].set_xlabel("sample value")

stats.probplot(std_normal, dist="norm", plot=ax[1]) # Q-Q plot

plt.show()
f.savefig(f"{save_path}/qq_normal.png")

표준 정규분포에서 추출한 데이터의 분포와 그것의 Q-Qplot을 그리는 코드입니다. 결과는 아래와 같습니다.

2번째 그림의 빨간 선이 데이터가 완벽한 표준 정규분포를 가질 때의 값이고, 비교하고자 하는 분포의 데이터는 파란 점으로 표현되어 있습니다. 당연하게도 둘은 거의 일치하는 것을 알 수 있습니다.

이번에는 실제 세계의 데이터가 정규분포를 갖는지 확인해보겠습니다. [data download]

# AT&T회사의 일별 주가변동 정보의 Q-Qplot
sp500_px_df = pd.read_csv('data/sp500_data.csv') # S&P500에 있는 회사의 일별 주식 등락 정보
sp500_px_df.rename(columns={'Unnamed: 0': 'Dates'},inplace=True)

atnt = 'T'    # 회사 AT&T

times = list(range(300))
poisson = stats.poisson.pmf(times,mu=20)

f, ax = plt.subplots(1,2, figsize=(10,5))
f.subplots_adjust(right=1)

sns.histplot(sp500_px_df[atnt], ax=ax[0])
ax[0].set_title("Data distribution")
ax[0].set_xlabel("fluctuation")

stats.probplot(sp500_px_df[atnt], dist="norm", plot=ax[1])

plt.show()
f.savefig(f"{save_path}/qq_atnt.png")

위와 같이, 데이터가 중앙에 많이 몰려있고, 평균에서 멀어질수록 급격하게 데이터 수가 감소하는 분포를 Q-Qplot을 통해 보면, 양 끝에서 차이가 커짐을 알 수 있습니다. 따라서 이 데이터는 정규분포를 같는다고 보기 어렵겠네요.

정규성을 검정할 수 있는 다른 방법은 통계적 가설 검정을 이용한 방법이 있습니다.

이 방법은 우선 아래와 같이 가설을 설정합니다.

귀무가설(null hypothesis,$H_0$): *"주어진 데이터는 정규분포를 따른다"*

대립 가설(alternative hypothesis, $H_1$): *"주어진 데이터는 정규분포를 따르지 않는다"*

그다음 두 가설을 검정하기 위한 다양한 방법을 적용한 뒤, 검정 결과 p-value가 특정값보다 크면 귀무가설을 기각하지 않고 정규성을 갖는다고 보는 겁니다.

이런 통계적 가설 검정 방법은 여러 개가 있는데, 대표적으로 D'Agostino's K-squared test, Shapiro–Wilk test 등이 있습니다.

마무리


이번에는 정규분포와 정규성 검정에 대해서 정리해봤습니다!

이번 글을 쓰면서 matplotlib의 구조에 대해서 깊게 알게 되어 기쁘네요!

읽어주셔서 감사합니다~ 좋은 하루 보내세요!

 

References

선형대수와 통계학으로 배우는 머신러닝 with 파이썬

Wikipedia-Normality test

반응형

+ Recent posts