신경망(Neural Network)뿐 아니라 대부분 모델에서 학습을 수행하기 전에 데이터 값의 범위를 정규화(Normalization), 표준화(Standardization) 하는 것은 매우 중요합니다.

이러한 처리 방법을 사용해서 값의 범위를 비슷하게 만들거나 평균이 1인 정규 분포 형태로 만들어주는 것은 학습 시에 큰 도움이 됩니다.

하지만 현실 데이터에선 값의 범위가 균형적(balanced)이거나 정규분포 형태를 거의 보기 어렵고, 주로 꼬리가 치우친(Skewed or unbalanced) 형태를 띄고 있는데요. Skewed Data는 모델 입력으로 사용하기 전, 전처리 과정(Preprocessing or Engineering)에서 어떤 처리 방법을 사용할지 한번쯤은 고민하게 만드는 골치아픈 데이터입니다.

출처: 위키백과

이때, 기본적으로 세 가지 방법을 후보로 생각해볼 수 있습니다.

  1. Min-Max Scaler; 정규화
  2. Standard Mean/Std Scaler; 표준화
  3. Apply Log-function; 로그화

이 방법들을 통해 성능을 많이 향상시킬 수 있는데, 이뿐 아니라 Gaussian Rank 방법을 추가로 고려해볼 수 있습니다.

Gaussian Rank 방법은 Numeric Feature Distribution을 Normal Distribution으로 변형시켜줍니다.

  1. -1 ~ 1 사이의 값(clipped value)을 순서(sorted)매깁니다.
  2. 순서 값에 오차역함수(inverse error function)을 적용하여 마치 Normal Distribution처럼 만듭니다.

오차역함수(inverse error function)

Gaussian Rank 방법은 Porto Seguro's Safe Driver Prediction(캐글 대회, 아래 URL 참고) 1등 솔루션 인터뷰를 보면,
Min-Max Scaler나 Standard mean/std Scaler보다 더 좋은 성능으로 가장 좋았다고 나와있습니다.

 

Porto Seguro’s Safe Driver Prediction | Kaggle

 

www.kaggle.com

 

총 세 가지 구현 방법을 찾게되었는데, 아래 세 개 코드를 참고하시길 바랍니다.

  1. NumPy 구현 - 1 (Github 참조) : https://github.com/affjljoo3581/Job-Recommend-Competition
  2. NumPy 구현 - 2 (Kaggle 참조) : https://www.kaggle.com/tottenham/10-fold-simple-dnn-with-rank-gauss
  3. sklearn - QuantileTransformer 활용 (Kaggle 참조)
    https://www.kaggle.com/kushal1506/moa-pytorch-0-01859-rankgauss-pca-nn

< 공통 사용 모듈 Import >

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from scipy.special import erfinv
from sklearn.preprocessing import QuantileTransformer

np.random.seed(42)

먼저, 예제로 사용할 더미 데이터를 생성합니다.

# 데이터 생성
X = (np.random.randn(200, 1) * 5 + 10) ** 2
df = pd.DataFrame(X)
df.head()

 

1. NumPy 구현 - 1

Gaussian Rank 적용

epsilon = 1e-4
noise_scale = 0.001

gaussian_noise = np.random.normal(0, 1, df[df.columns[0]].shape)
transformed_data = df[df.columns[0]] + noise_scale * df[df.columns[0]].max() * gaussian_noise

data_rank = np.argsort(np.argsort(transformed_data))
data_rank = 2 * data_rank / data_rank.max() - 1

clipped_data_rank = np.clip(data_rank, -1 + epsilon, 1 - epsilon)
# 오차역함수 적용
transformed_data = erfinv(clipped_data_rank)

결과 확인

plt.figure(figsize = (10, 5))

plt.subplot(1, 2, 1)
plt.hist(df[df.columns[0]])
plt.title('Before')

plt.subplot(1, 2, 2)
plt.hist(transformed_data)
plt.title('After Gaussian Rank')

plt.tight_layout()
plt.show()

Gaussian Rank - 1

2. NumPy 구현 - 2

함수 정의

def rank_gauss(x):
    N = x.shape[0]
    temp = x.argsort()
    
    rank_x = temp.argsort() / N
    rank_x -= rank_x.mean()
    rank_x *= 2
    
    efi_x = erfinv(rank_x)
    efi_x -= efi_x.mean()
    return efi_x
    
transformed_data = rank_gauss(df[df.columns[0]])

결과 확인

Gaussian Rank - 2

3. sklearn QuantileTransformer 활용

transformer = QuantileTransformer(n_quantiles=100,random_state=0, output_distribution="normal")
transformer.fit(X)

transfored_data = transformer.transform(X)

결과 확인

Gaussian Rank - 3

 

립시츠 함수를 다루는 이유는 아래 BatchNormalization 내용을 다룬 논문 때문입니다.

How Does Batch Normalization Help Optimization?

기존 BN 논문에서는 'BN은 Internal Covariance(내부 공변량 변화, 가끔 가다보면 내부 공선성이라고 표현하기도 하더라, 여기서는 더 많이 사용되는 내부 공변량 변화를 사용하겠습니다)을 해결하기 때문에 잘된다.'라고 주장합니다. 위 논문은 이에 반례를 제공하고, 한 단계 나아가 BN이 왜 잘되는지 수학적으로 증명하고 있으니 이를 조금씩 살펴보겠습니다.
(논문 소개와 립시츠 함수에 관한 글)

이번 글에서 소개할 논문

Internal Covariance

먼저 내부 공변량 변화를 쉽게 설명하자면, 우리가 흔히 사용하는 hidden layer는 당연하게도 input을 받아들이고 output을 내보냅니다. 또, 이렇게 도출된 output은 다음 단계에서 hidden layer의 input으로 활용되죠. 문제는 여기에 있습니다. 이전 층의 불규칙한 output으로 인해 다음 층의 input distribution이 급격히 변화하고, 이러한 문제가 최종적으로 학습에 큰 영향을 끼치게되어 좋지 않은 성능을 가져다 주는 문제입니다.

즉, 사공이 많으면 배가 산으로 가듯이 기존 입력값의 분포가 여러 가지 모양을 가지게 되니 해결하고자 하는 데이터의 분포를 학습할 수도 없고, 모델 입장에서는 혼란을 가지게 되어 우리에게 안좋은 성능을 가져다줍니다. 하지만 BN은 충분히 다양한 모델 구조에서도 자신의 성능을 증명했듯이, 이러한 문제를 해결할 수 있다고 합니다. BN은 다양한 장점을 가지고 있지만 그 중, 규제화(Regularizer) 기능을 이용하면, 이러한 문제가 해결되어 좋은 성능을 가지게 해준다고 합니다. 마치, hidden layer의 출력값에 표준화를 적용해준다는 것과 비슷합니다.

그림: BatchNormalization Paper, Algorithm1

신경망의 입력으로 사용할 데이터에 표준화를 적용하는 것과 그렇지 않은 것의 성능 차이는 여러 가지 데이터셋에서도 확인해 볼 수 있습니다. 이를 알면 위에서 말한 장점처럼 수학적으로 자세히 증명하지 않아도, BN이 좋은 성능을 이끌어내고 있다고 느낌적으로 생각해볼 수 있습니다.

 

Lipschitz Function

(위키 백과) 립시츠 함수는 두 점 사이의 거리를 일정 비 이상으로 증가시키지 않는 함수이다.
검색해보면 흔히 볼 수 있는 수식은 아래와 같다.

$$\left| f(x) - f(y)\over x - y\right| <= K$$

립시츠 조건이 성립하면 균등연속함수(역은 필수는 아님)이므로 해당 범위에서 미분이 가능하며, 미분 계수는 정해진 K 값을 넘을 수 없게 됩니다. 즉, 쉽게 해석해보면 립시츠 함수일때 기울기가 K를 넘지 않으므로 gradient exploding과 같은 문제를 예방할 수 있습니다. 이 점만 기억하면 논문의 주장을 충분히 이해할 수 있습니다.

 

BatchNormalization은 내부 공변량 변화랑 정말 관계가 있을까?

위에서 설명했듯이 BN은 내부 공변량 변화 문제를 해결한다고 했습니다. 이를 반증하기 위해 논문에서는 한 가지 실험을 수행합니다.

기존처럼 BN을 쓴 것과 여기에 Noise를 추가한 경우를 실험합니다. 노이즈를 추가하는 이유는 일부러 내부 공변량 변화를 발생시키기 위함입니다. 빨간색 분포를 보면 Layer를 거칠수록 파란색, 주황색 분포보다 더욱 불안정함을 알 수 있습니다. 하지만 성능을 확인해보면 내부 공변량 변화 존재 유무를 떠나서 거의 비슷하거나 또는 Noise를 추가한 모델이 더 좋은 성능을 보여주고 있다는 것을 볼 수 있습니다.

여기서 바로 BN이 주고 있는 성능 향상의 원인이 내부 공변량 변화에 크게 치우쳐져 있지 않음을 알 수 있습니다.

심지어 BN을 쓴다고 해서 내부 공변량 변화가 해결되지 않고, 완전히 심각한 문제를 일으키는 경우도 있습니다.

 

BatchNormalization은 그럼 무슨 역할을 하고 있을까?

이후에도 논문에서는 BN이 내부 공변량 변화와 약한 관계를 가지고 있음을 실험적으로 증명합니다. 그럼에도 불구하고 BN을 사용하면 성능 향상이 일어날 뿐더러 training 과정이 BN을 사용하지 않은 경우보다 더욱 stable함을 보여주고 있다는 것이죠.

왜 잘될까요? 논문에서는 BN을 optimization 관점으로 바라보아야 한다고 주장합니다. 일반적으로 신경망이 가지는 land-scape는 non-convex하고, unstable하기 때문에 loss function을 최적화하는데 문제점을 가지고 있습니다. 따라서 이 논문은 "BN이 내부 공변량 변화를 해결한다기 보다는 이러한 문제점을 해결해주고 있는 것이 아닐까?" 라고 생각합니다.

그럼 이 논문에서 BN을 통해 밝힌 것은 다음과 같습니다.

  1. optimization problem의 landscape를 더욱 smooth하게 만들어줍니다.
  2. Loss function이 립시츠해져서 loss의 gradient가 더욱 smooth해집니다. 이러한 결과는 향후 학습에서 gradient가 더욱 reliable해지고, predictive하게 만든다고 합니다.
  3. predictive가 어느정도 보완되기 때문에 gradient based optimization problem에서도 다음 스텝을 밟는데 있어 어느정도 위험을 배제할 수 있다.

2번 실험에 관한 내용은 다음 figure에서 확인할 수 있습니다.

 

자세한 수학적 증명은 논문을 통해 확인하시길 바라고, 그 중 하나를 보자면,,

아래 그림에서 오른쪽의 $\gamma^2 \over \sigma^2$가 립시츠 함수에서 상수 역할을 하기때문에 왼쪽 항의 Loss function에서 발생하는 gradient가 smooth 될 수 있다고 합니다.

 

Reference

www.slideshare.net/HoseongLee6/how-does-batch-normalization-help-optimization-paper-review

ko.wikipedia.org/wiki/립시츠_연속_함수

www.youtube.com/watch?v=hiN0IMM50FM&list=PLWKf9beHi3TgstcIn8K6dI_85_ppAxzB8&index=34

https://hwiyong.tistory.com/27

 

posterior과 bayesian

논문을 읽다보면 확률 모델에 대한 이야기가 많이 나옵니다. 사실상 이해를 못한 채 넘어가는 부분이 많은데, 검색을 통해서 공부하고 또 공부한 내용을 한번 적어보도록 하겠습니다. 대표적으�

hwiyong.tistory.com


위 글에서 사전확률과 사후확률을 충분히 설명했습니다.

사전확률은 내가 알고있는 지식으로부터 얻어진 특정 사건의 확률

사후확률은 특정 사건이 일어났을 때, 어떤 원인때문이다 라고 생각되는 확률입니다.

 

베이즈 정리의 대표적인 수식은 다음과 같습니다.

 위 수식은 두 가지 사건이 존재할때 성립하고, 그보다 더 많은 사건이 존재할 때는 다음과 같이 표현할 수 있습니다.

간단한 예를 들어서 베이즈 정리를 사용해보겠습니다.

우리는 지금 세 개의 상자를 가지고 있고, 각 상자는 흰돌과 검은돌을 아래 표처럼 가지고 있습니다.

상자 흰돌의 개수 검은돌의 개수
A 3 6
B 1 9
C 3 3

위 표를 통해 알 수 있는 것은 세 개의 상자 중 하나를 선택하는 확률이 1/3 이라는 것과 상자에서 검은돌과 흰돌이 뽑힐 확률을 알 수 있습니다.

예를 들어 A 상자에서 흰돌을 뽑을 확률은 3/9입니다. 또, 이를 P(흰돌|A) 이라고 표현할 수 있습니다.
위에서 알 수 있는 강조된 확률은 정확히 사전확률에 해당합니다.

그래서 우리가 알고 싶은 것은 '흰돌을 뽑았는데, 이 흰돌이 A 상자로부터 나올 확률은 무엇인가?' 입니다.
이 확률은 굉장히 알기 어렵습니다. 하지만 우리가 알고있는 사전확률과 베이즈 정리을 사용하면 구할 수 있을 것입니다.
위 문제는 다음과 같이 표현합니다. P(A|흰돌)

베이즈 정리를 사용하면 다음 수식으로 P(A|흰돌)를 구할 수 있습니다.

직접 확률을 대입해보면 다음과 같습니다.

 

가장 기본적이며 쉬운 연속분포의 하나이다.(물론 이산도 정의하면 이산균등분포가 가능)

연속분포이기 때문에 확률도 면적으로 구하게 된다. 



출처 : https://ko.wikipedia.org/wiki/연속균등분포


균등분포는 확률분포가 취하는 모든 구간에서 일정한 확률을 가지는 분포이다. 

ex) 주사위




< PDF >



< 기댓값과 분산 > 




지수분포란, 

사건이 서로 독립적일 때, 일정 시간동안 발생하는 사건의 횟수가 푸아송 분포를 따른다면, 다음 사건이 일어날 때까지 대기 시간은 지수분포를 따른다

 

다시 말해서, 포아송분포는 단위시간동안 발생하는 사건의 횟수에 대해 관심이 있다고 할 수 있고,

지수분포는 어떤 사건이 발생하기까지의 시간에 대해 관심이 있는 것입니다. 

 

지수분포는 감마분포의 특수한 형태이기도 하다. 

감마분포의 모수 중 a가 1이되면 지수분포의 모양이 되게 된다. 

지수분포는 기하분포와 함께 무기억성을 가지고 있는 분포이다.

(그림 감마분포와 지수분포의 관계식)

이 외에도 여러가지 관련된 것이 많습니다. 

지수분포를 확장하면 감마분포가 되기도 하죠. 

지수분포는 아래 분포그림과 같이 점점 확률이 줄어드는 사건에 쓸 수 있습니다. 예를 들어,

사람의 수명과 죽음에 대한 사건

전자제품 수명과 남은 사용기간에 대한 사건 등


< PDF >

 

< 기댓값과 분산 >

 

Reference 

https://math7.tistory.com/51

 

'# 기타 공부한 것들 > math' 카테고리의 다른 글

Bayes 정리: 간단 예제로 이해하기  (0) 2020.06.01
균등분포(균일분포, Uniform dist)  (0) 2019.02.26
다항분포(multinomial distribution)  (0) 2019.02.14
음이항 분포  (0) 2019.02.01
기하 분포  (1) 2019.01.30