preprocessing

인공신경망 이해하기 (4) 디테일

지금까지의 글에서는 머신러닝의 기초와 신경망의 구조 및 학습에 대해서 다루어보았다. 그러나 중간중간추후에 기회가 된다면 자세히 다루겠다고 미뤄둔 내용들이 있다.

(1) 선형 분류기
(2) 퍼셉트론과 신경망
(3) 학습에는 왕도가 없다

이번 글에서는 지금까지 다룬 뼈대에 살점을 붙여보려고 한다. 자주 등장하는 개념을 위주로 정리해보려 했다. 여기서부터는 신경망을 포함한 머신러닝 학습의 디테일이다.

 

  1. 정규화
    1. Ridge regularization
    2. Lasso regularization
    3. Elastic Net regularization
    4. Dropout
    5. DropConnect
  2. 수치적 최적화
    1. 일반 경사하강법
    2. 모멘텀 경사하강법
    3. 적응형 학습률 방법
  3. 데이터 전처리
    1. 센터링과 스케일링
    2. minmax 표준화
    3. 주성분 분석 (PCA)

 

정규화

정규화의 개념과 학습에서의 역할에 대해서는 이 글에서 언급했었다 ((1) 선형 분류기정규화 손실 추가하기). 간단히 다시 정리하자면, 분류기가 데이터에서 분류문제와 상관이 없는 노이즈까지 학습하지 않도록 제약을 두는 것을 말한다.

정규화 방법들의 디테일에 대해서 살펴보기 전에 가중치 행렬과 편향 벡터를 다시 들여다보자. 다음은 신경망의 한 층만을 식으로 나타낸 것이다. 선형 분류기의 판별함수와도 같은 식이다.

스케치

스케치 재활용 장난아니다..는 생각은 접어두고, 이 식 XW + b은 다음과 같이 더욱 간단히 줄일 수 있다. 두 식의 계산 결과는 완전 동일하다.

스케치

 

무슨 짓을 한걸까? feature 행렬 X의 열에 1열벡터를 추가해주었고 가중치 행렬 W와 편향 벡터 b를 합쳐서 하나의 큰 가중치 행렬로 만들었다. 이처럼 feature 행렬의 마지막 열에 1벡터를 추가해서 가중치와 편향을 하나의 벡터로 나타내는 기술을 “feature 행렬을 증강시킨다 (feature matrix augmentation; design matrix augmentation)”고 한다.

표기 및 구현상의 편의성을 이유로 실제 알고리즘을 코딩할 때는 증강된 버전을 많이 사용한다. 이제부터 말하는 가중치 행렬 W는 모두 증강된 가중치 행렬이다. , 가중치 w_{ij} 뿐만 아니라 편향 정보 b_k도 포함하고 있는 행렬이다. 편의상 편향 정보도 $w_{ij}$라고 호칭하겠다.

스케치

이제 우리의 가중치 행렬은 이렇게 생겼다.

 

Ridge 정규화 (L2 정규화)

이미 선형 분류기를 구현하는 과정에서 차례 다룬적이 있는 Ridge 정규화법 가중치 행렬 W 모든 성분 w_{ij} 제곱합 R(W) = \sum_{\forall (i, j)} w_{ij}^2 제약하는 정규화법이다. 제곱값(2차항) 제약하기 때문에 L2 정규화라고도 부른다.

스케치

Ridge 정규화된 가중치행렬은 전체적으로 고르고 작은 값을 선호하게 된다. 튀는 값이 있거나 전체적으로 가중치의 크기가 커지면 정규화 손실 R(W)의 값이 커진다.

 

Lasso 정규화 (L1 정규화)

가중치의 제곱합 \sum_{\forall (i,j)} w_{ij}^2 제약하는 Ridge 정규화와 달리 Lasso 정규화 가중치의 절대값의 R(W) = \sum_{\forall (i,j)} |w_{ij}| 제약한다. 1차항인 절대값항을 제약하기 때문에 L1 정규화라고도 널리 불린다.

Lasso 정규화된 가중치행렬은 중요한 feature에 연결된 가중치값을 제외하고는 작은 가중치값을 가지도록 제약하는 경향이 있다. 그래서 Lasso 정규화 강도를 점차 늘리면 가중치값이 분류 문제 해결에 중요한 feature 순서대로 0 되는 을 확인할 수 있다. 이를 그래프로 나타내면 다음과 같다.

output_7_0

feature에 대응하는 가중치값이 0으로 수렴하는 속도를 보여주는 이 플롯을 Lasso path라고 한다. 선형 분류기나 회귀분석에서는 Lasso path를 사용해서 feature 중요도를 판단하기도 한다. 더 천천히 0이 되는 가중치의 feature일수록 더 중요한 feature인 것이다. 그림의 경우는 X_4가 가장 중요한 feature라고 판단할 수 있다.

 

Elastic Net 정규화

1차항(Lasso) 2차항(Ridge) 모두 사용해서 정규화를 수도 있다.

R(W) = \alpha \sum_{\forall (i,j)} w_{ij}^2 + (1-\alpha) \sum_{\forall{(i,j)}} |w_{ij}|

여기서 \alpha [0, 1] 구간 내의 값으로 1차항 제약과 2차항 제약 사이의 밸런스를 조정하는 역할을 한다. \alpha=0 때는 Lasso 정규화와 동일해진다 (2차항 정규화항이 0 되어 사라진다). 반대로 \alpha=1 때는 Ridge 정규화와 동일해진다 (1차항 정규화항이 0 된다).

 

그래서 써야하나요

셋 중 무슨 정규화를 사용할지 고민이라면 그냥 Ridge를 쓰면 된다. 튀는 값을 불호하는 Ridge의 특성상 덜 공격적인 가중치값을 얻을 수 있다.

신경망 모형의 경우엔 주로 Ridge 정규화와 함께 아래에서 설명할 Dropout 기법을 사용해서 정규화한다.

 

Dropout

지금껏 설명한 다른 정규화법과 달리 Dropout은 신경망 기반 모형에 특화된 정규화 방법이다. Dropout의 직관은 이렇다: 각각의 뉴런은 매 학습에서 p의 확률로 활성화될 수도 있고 그렇지 않을 수도 있다.

스케치

이렇게 학습시킨 신경망의 분류결과는 마치 비슷하지만 서로다른 여러개의 신경망 모형들의 분류 결과를 평균내는 과 유사한 형태가 된다. 신경망 여러개의 결과가 평균내졌기 때문에 일반적이지 않은 분류 결과를 제거하는 정규화의 효과를 가진다.

Dropout을 사용하면 학습 과정에서 각 뉴런의 활성화 확률이 p이므로 활성화 기댓값은 E(a) = p \times f(XW) + (1-p)\times0 = p \times f(XW)이다. 즉, Dropout을 사용하지 않았을 때의 활성화함수값 f(XW)에 비해 크기가 p의 비율로 작아진다.

Test set에서 성능평가를 할 때에는 모든 뉴런이 활성화된 상태에서 분류를 하므로 활성화함수값을 학습할 때와 같은 크기로 조정해줘야 한다. 성능평가시의 활성화함수값에 \times p를 해주면 학습시의 활성화함수값과 같은 크기로 조정된다.

Test set에서 성능평가시에 활성화함수값의 크기를 조정해줘야하는 귀찮음때문에 새로운 방법이 고안되었다. 새로운 방법에서는 활성화함수값의 크기를 학습시에 \div p로 조정해준다. 이렇게 하면 학습시 활성화함수의 기댓값은 E(a) = \{p \times f(XW) + (1-p)\times0\} \div p = f(XW)가 되므로, 성능평가시에는 별도의 활성화함수값 조정을 해주지 않아도 된다.

이 방식을 inverted Dropout이라고 하며, 일반적으로 dropout을 사용했다고 하면 열에 아홉은 inverted dropout을 사용했다는 말이다. inverted가 아닌 dropout은 잘 사용하지 않는다.

 

DropConnect

Dropout 유사한 방법으로 DropConnect라는 방법이 있다. epoch마다 랜덤하게 뉴런의 출력 죽여버리는 Dropout 달리 DropConnect epoch마다 뉴런의 입력 랜덤하게 죽인다.

스케치

DropConnect 사용하면 특정 뉴런을 완전히 죽이지는 않고 일부 연결만 죽일 수도 있다. 따라서 DropConnect Dropout 포함하는, 더 일반적인 개념이라 있겠다.

 

 

수치적 최적화

수치적 최적화 역시 처음 선형 분류기를 학습시킬 때 언급했었다. 수치적 최적화는 손실함수값 L을 최소로 만드는 가중치값 W를 찾기 위해 사용됐었다. 지금까지는 경사하강법(또는 SGD)을 사용해서 수치적 최적화를 진행했었다.

 

일반 경사하강법

일반 경사하강법은 그라디언트의 반대 방향으로 가중치를 움직이며 최적의 가중치값을 찾는 방법이다.

W_{new} = W_{old} - \eta \frac{\partial L}{\partial W}

계산 시간과 메모리를 절약하기 위해서 확률적 경사하강법(SGD)를 사용할 수도 있었다. 매 학습에서 가중치 하나만으로 그라디언트를 계산하는 SGD는 아래와 같이 표현된다.

W_{new} = W_{old} - \eta \frac{\partial L}{\partial w_{ij}}

일반 경사하강법은 손실함수의 최저점 주변에서 가중치 값이 진동하는 특징이 있다.

 

모멘텀 경사하강법

모멘텀 경사하강법은 물리학적인 관점에서 경사하강법을 재해석한 방법이다.

손실함수 모양의 곡선에 공을 굴러 떨어뜨린다고 생각해보자. 공의 위치에너지와 운동에너지를 생각해볼 수 있다. 모멘텀 경사하강법에서는 그라디언트를 공의 위치에너지라고 생각한다. 최초의 운동에너지는 0이라고 본다.

  1. 위치에너지(= \frac{\partial L}{\partial W_{old}}) 운동에너지 v 변환된다.
    • v_{new} = \mu \times v_{old} - \eta \frac{\partial L}{\partial W_{old}}
    • 여기서 새로운 하이퍼 파라미터 \mu이 등장한다. m모멘텀이라고 부른다. 실제로는 마찰계수와 비슷한 역할을 한다 (업데이트 전의 속도 v_{old}를 감소시킨다).
  2. 1.에서 업데이트된 운동에너지만큼 가중치가 움직인다.
    • W_{new} = W_{old} + v_{new}
  3. 손실 함수가 수렴할 때까지 반복한다.

 

Nesterov 모멘텀 경사하강법

Nesterov는 모멘텀 경사하강법에 대한 좀 특이한(?) 개선법을 내놓았다.

을 이미 관측한 시점에서 가속도와 속도를 계산하면, 과거의 속도를 이용해서 미래의 공의 위치를 결정하는 것이므로 진짜 현실세계에서 떨어지고 있는 공의 물리적 성질과는 약간의 차이가 있을 것이다. 따라서 굴러가는을 더 현실에 가깝게 물리학적으로 모델링하려면 앞으로 공이 움직일 위치(W_{ahead}) 속도(\frac{\partial L}{\partial w_{ahead}})를 예측해서 공의 위치(가중치값 업데이트 W_{new})를 결정해야 한다.

Nesterov의 모멘텀 경사하강법은 이렇게 진행된다.

  1. 가까운 미래의 공의 위치 W_{ahead} 예측한다.
    • W_{ahead} = W_{old} + (m \times v)
  2. 가까운 미래의 위치 W_{ahead}에서의 그라디언트( 위치에너지; \frac{\partial L}{\partial W_{ahead}}) 계산한다.
  3. 위치에너지 \frac{\partial L}{\partial W_{ahead}} 운동에너지 v 변환시킨다.
    • v_{new} = \mu \times v_{old} - \eta \frac{\partial L}{\partial W_{ahead}}
  4. 운동에너지만큼 가중치를 움직인다.
    • W_{new} = W_{old} + v_{new}

모멘텀 경사하강법들은 일반 경사하강법에 비해 훨씬 빠른 속도로 손실함수의 최저점에 도달한다. 하지만관성때문에 손실함수의 최저점이 되는 값을 지나쳐버렸다가 되돌아오는(“overthrow”되는) 성질이 있다.

 

적응형 학습률(adaptive learning rate) 방법

모멘텀 경사하강법이 경사를 타고 내려오는 속도를 변형시켜 개선시켰다면, 적응형 학습률 방법은 학습 도중에 학습률 \eta를 변형시켜서 개선시킨다 – 그래서 이름이 적응형 학습률(adaptive learning rate)이다.

적응형 학습률 방법은 매 학습에서의 그라디언트 정보를 캐시(cache)라는 변수에 차곡차곡 “기억”해둔다. 그리고 캐시를 이용해서 학습률 \eta를 조정해 나간다. 학습이 진행되어 그라디언트가 작아져도 학습 속도가 느려지지 않도록 조정해주며 가중치를 fine-tuning하는 데에 도움이 된다.

Adagrad라고 이름붙은 방법은 다음과 같이 학습률 \eta를 조정한다.

  1. 그라디언트를 이용해서 캐시를 업데이트한다.
    • cache_{new} = cache_{old} + (\frac{\partial L}{\partial w_{old}})^2
  2. 학습률 \eta 조정(업데이트)한다.
    • \eta_{new} = \frac{\eta_{old}}{\sqrt{cache_{new}}}
  3. 가중치 W 업데이트한다.
    • W_{new} = W_{old} - \eta_{new} \frac{\partial L}{\partial W}

제프리 힌튼이 제시한 RMSProp이라는 방법에서는 캐시가 시간이 지남에 따라 정보를 조금씩잊어버린다”.

  1. 그라디언트를 이용해서 캐시를 업데이트한다. , 캐시는 이전 정보의 일부를 잊어버린다. decay rate \gamma만큼의 정보만 기억한다.
    • cache_{new} = \gamma \times cache_{old} + (1 - \gamma) \times (\frac{\partial L}{\partial w_{old}})^2
  2. 학습률 \eta 조정(업데이트)한다.
    • \eta_{new} = \frac{\eta_{old}}{\sqrt{cache_{new}}}
  3. 가중치 W 업데이트한다.
    • W_{new} = W_{old} - \eta_{new} \frac{\partial L}{\partial W}

 

실제 학습 시 각 방법의 움직임 특징을 보이기 위해서 움짤을 만들어봤다.

ezgif-5-72ec1ba217

이 애니메이션도 유명하다 (출처).

 

 

데이터 전처리

분류기에 학습을 시키기 전에 입력 데이터를 학습에 알맞게 변형시키는 과정을 일컬어 전처리(preprocessing)라 부른다. 전처리는 주로 학습 데이터의 본질만을 남겨두고, 학습에 방해가 되는 요소를 제거하는 역할을 한다.

예를 들어 붓꽃 분류 문제에서, 꽃받침 길이는 cm 단위로 측정되어 있는데 꽃받침 너비는 mm 단위로 측정되었다면 어땠을까? mm 단위로 측정된 값들이 대체로 cm 단위로 측정된 값보다 큰 수치로 기록되어 있을 것이고 이는 가중치의 업데이트에 좋지 않은 영향을 미칠 것이다.

전처리 과정에서는 이처럼 단위 차이에 의한 영향, 최대최소값의 차이에 의한 영향, 평균값의 차이에 의한 영향, 분포도 차이에 의한 영향 등 데이터의 본질과는 무관한 영향을 제거한다.

전처리시 주의해야할 점은 전처리 통계량(데이터 평균, 데이터 분산, eigenvalue, eigenvector, …)은 모두 training set에서만 계산되어야 한다는 것이다. 이에 대해서는 ‘(3) 학습에는 왕도가 없다‘ 에서 다루었다.

 

센터링(centering) 스케일링(scaling)

가장 간편하고 보편적인 전처리는 데이터를 평균 0, 분산 1을 따르도록 변형시키는 것이다. 이 중 평균을 0으로 만드는 과정을 센터링(centering)이라고 하고 분산을 1로 만드는 과정을 스케일링(scaling)이라고 한다.

굳이 하나를 고른다면 스케일링보다는 센터링이 훨씬 중요하다고 한다.

 

Minmax 표준화

데이터의 분포를 유지한 채로 모든 관측값이 일정 구간 (주로 [0, 1]) 사이에 존재하도록 변형하고 싶다면 minmax 표준화를 사용할 수 있다.

X_{normalized} = \frac{X - \min(X)}{\max(X) - \min(X)}

변형한 데이터는 모두 [0, 1] 사이의 값을 갖게 된다. 이 방법은 데이터를 센터링하지는 않기 때문에 신경망에 사용하기엔 부적합할 수 있다.

 

주성분 분석 (Principal Component Analysis; PCA)

주성분 분석은 상관관계가 존재할 수도 있는 데이터셋을 서로 독립인 성분(주성분)의 데이터셋으로 분리해주는 테크닉이다.

PCA 데이터의 공분산 행렬(covariance matrix) \Sigma 특이값 분해(singular-value decomposition; SVD)시키는 과정과 동일하다. 혹은 데이터의 상관 행렬(correlation matrix) R 고유값 분해(eigen-value decomposition)시키는 과정과 동일하다.

상관관계가 존재하는 데이터 X PCA를 통해서 세 행렬의 곱으로 분해할 수 있다.

X = Z_s D^{1/2} U^T, 따라서 Z_s = XUD^{-1/2}

여기서 Z_s 평균이 0이고 분산이 1이며 모든 차원이 서로 독립(full-rank) 데이터이다. D Z 차원의 분산의 행렬이다. 동시에 X eigenvalue 대각성분으로 가지는 대각행렬이기도 하다. U 회전행렬이다. 동시에 X eigenvector matrix이기도 하다.

스케치

이를 기하적으로 해석해보면 이렇다: 모든 차원이 서로 독립이고 표준화된 데이터 Z_s 차원간 상관관계가 존재하는 데이터 X U만큼 회전시키고 D^{-1/2} 표준화시켜서 얻을 있다. 과정에서 얻은 Z_1, Z_2 또는 Z_{s_1}, Z_{s_2} 주성분(principal component; PC)라고 부른다.

데이터를 센터링, 스케일링하는 대신 PCA PC를 사용해도 된다. 한 차원의 PC만으로도 대부분의 데이터 분산을 설명할 수 있다면 아예 데이터의 차원을 축소해도 된다. 그림의 경우 Z_1만으로도 대부분의 데이터 분산을 설명할 수 있으므로 Z_2 차원을 버리고 1차원으로 데이터를 축소시켜도 된다.

주저리 주저리 설명하긴 했지만 신경망 모형에서는 주로 PCA보다 센터링 + 스케일링을 선호한다고 한다.

 

여기까지 Batch Normalization 하나만 빼고 대강의 살은 붙였다.

다음 글에서는 신경망에 적용시킬 수 있는 특수한 층(layer) 구조에 대해서 다뤄보겠다. 이 내용을 다루면서 Batch Normalization도 다룰 생각이다.

 

 

참고

  • 이 글은 CS231n 강의록을 매우 많이 참고했다. 원 강의록을 읽어보시기를 강하게 추천드린다.
  • Adaptive learning rate method 내용은 이 페이지도 참고했다.
  • 첫 번째 수치적 최적화 비교 GIF를 만드는 과정에서 최적화할 함수 모양을 설정할 때 이 페이지를 참고했다.
  • 두 번째 수치적 최적화 비교 GIF는 CS231n에서 가져왔으나 원 출처가 따로 있다.
  • PCA 내용은 “Analyzing Multivariate Data” (Lattin et al., 2002)를 참고했다.

인공신경망 이해하기 (3) 학습에는 왕도가 없다

지금까지 선형 분류기를 통해 머신러닝의 기초를 짚어보았다. , 일부 특수한 비선형 문제를 해결하기 위해 사용되는 커널 트릭을 아주 간단히 다루었으며 신경망 기초 이론을 이야기하면서 2층 신경망을 직접 구현해서 대부분의 비선형 문제를 해결할 수 있다는 것을 보였다.

(1) 선형 분류기
(2) 퍼셉트론과 신경망

이번 글에서는 신경망(을 포함한 머신러닝 모델)을 학습시키고 성능을 평가할 때 주의해야 할 점들에 대해 포괄적으로 다뤄보고자 한다.

 

  1. Train set / test set
    1. Label skew 주의하기
  2. 하이퍼 파라미터 결정하기
    1. 결정해야 하는 하이퍼 파라미터
      1. 학습률 (learning rate)
      2. 정규화 강도 (regularization strength)
      3. ..
    2.  좋은 하이퍼파라미터 값 찾기
  3. 모형을 학습시키기 전에
    1. 초기 가중치, 편향 설정
    2. 데이터 전처리
    3. 초기 그라디언트 체크
    4. 초기 손실함수 체크
    5. 의도적 과적화
  4. 모형을 학습시키는 중에
    1. 손실함수 모니터링
    2. training set acc. vs. test set acc.
  5. 구현

 

Training set / Test set

앞서 과적화(overfitting) 현상에 대해 짧게 언급한 적이 있다. 모형이 데이터를 지나치게 학습한 나머지, 실제 카테고리 분류와는 관련이 없는 노이즈까지 학습해버리는 현상을 말한다.

사람 사진을 보고 남자인지, 여자인지, 혹은 둘 다 아닌지 성별을 구별해주는 모형을 학습시킨다고 해보자. 그런데 하필, 학습에 사용한 데이터에서 남자 사진은 모두 배경에 의자가 함께 찍혀있었다고 가정해보자.

제대로 학습된 모형이라면 이목구비의 생김새, 배치, 머리카락의 모양, 길이 등을 학습해서 성별을 구별할 것이다. 그러나 과적화된 모형은 배경에 의자가 있는지(카테고리 구분과 관련 없는 노이즈)를 보고 성별을 구별한다.

이러한 오버피팅 문제를 해결하기 위해서 정규화 손실항 R(W) 손실함수 L 추가한다는 것을 이야기했었다. , 정규화의 세기는 정규화 강도 (regularization strength) \lambda 사용해서 조절한다는 것도 이미 이야기한 있다.

여기서 의문이 생긴다. 정규화를 했어도 오버피팅이 일어날 있다. 오버피팅이 일어나지 않았는지 어떻게 확신할 있을까? 다른 말로 풀어보면 이렇다: 학습시킨 분류기가 학습에 사용한 데이터 외에 다른 데이터에도 일반적으로 동작한다는 것을 어떻게 확인할 있을까?

답은 간단하다. 직접 테스트를 해보는 수밖에 없다. 그리고 테스트를 하기 위해 우리는 가지고 있는 모든 데이터 중 일부만을 학습에 사용해야 한다. 전체 데이터를 두 조각으로 쪼개어 한 조각은 테스트 용으로 남겨둬야 한다는 말이다.

e18489e185b3e1848fe185a6e1848ee185b512.png

쪼갠 데이터 중 학습에 사용하는 데이터셋을 training set, 학습에는 사용하지 않고 테스트시에만 사용하는 데이터셋을 test set이라고 한다. 데이터를 쪼개는 비율은 정해져 있지는 않지만 일반적으로 train:test = 4:1, 7:3, 9:1 등을 많이 사용한다.

 

카테고리가 치우치지 않도록 쪼개야 한다

데이터를 쪼개는 과정에서 카테고리(라벨) 데이터셋의 카테고리가 종류로 치우칠 있다. 예를 들어,  붓꽃 데이터를 training set test set으로 쪼개는 과정에서 training set에는 setosa 종과 versicolor 종의 데이터만, test set에는 verginica 종의 데이터만 포함될 있다. 이런 경우 training set, test set 모두 데이터가 불완전하므로 제대로 학습 테스트를 수가 없다.

따라서 항상 train/test 데이터셋 쪼개기를 수행할 때에는 카테고리가 한 쪽으로 치우지지 않도록 조심을 기해야 한다.

가장 간편하면서도 많이 사용하는 방법은 전체 데이터를 랜덤 셔플한 다음 train/test set 쪼개는 이다.

e18489e185b3e1848fe185a6e1848ee185b513.png

(그럴 일은 많지 않겠지만) 극히 낮은 확률로 랜덤 셔플한 후 쪼개었음에도 카테고리가 치우칠 수 있다. 이런 상황을 방지하기 위해 아예 층화 추출(stratified sampling)을 해도 된다. 층화추출법은 전체 데이터에서 각 카테고리의 비율을 유지하며 샘플링하는 기법이다. 그러나 오히려 층화추출에 의해 test set의 카테고리가 치우치는 경우가 있어서 그냥 랜덤 셔플 후 샘플링 방법을 사용하는 것이 다수이다.

e18489e185b3e1848fe185a6e1848ee185b514.png

Train set은 최종 테스트(모형 성능평가)를 위해 가만히 남겨두고, training set만 가지고 놀도록 하자. 이제 학습에 사용할 데이터셋은 준비가 됐다.

 

하이퍼 파라미터 결정

결정해야 하는 하이퍼 파라미터

하이퍼 파라미터(hyper-parameter)는 머신러닝에서 분류기 등 모형의 학습 양상을 결정하는 중요한 수치이다. 분류기를 학습하는 과정에서 업데이트되는 파라미터(parameter; 우리가 다루었던 가중치 W와 편향b이 여기에 속한다)와 달리, 하이퍼 파라미터는 분류기를 학습하기 전에 결정되고, 학습 과정에서는 일반적으로 업데이트되지 않는다그래서 hyper라고 부른다.

본격적으로 모형을 학습하기 전 우리가 정해야 하는 하이퍼 파라미터는 이런 것들이 있다.

학습률 (learning rate; \eta)

가장 먼저 살펴볼 하이퍼 파라미터는 학습률 \eta이다. 이녀석은 가중치를 업데이트할 때 등장했었다.

W_{new} = W_{old} - \eta \frac{\partial L}{\partial W}

b_{new} = b_{old} - \eta \frac{\partial L}{\partial b}

학습률 \eta의 값을 크게 설정할수록 한 번의 업데이트에서 가중치값이 변화하는 폭이 커진다 (학습 속도가 빨라진다). 반대로 \eta의 값을 작게 설정할수록 가중치값의 변화폭이 작아진다.

빨리 학습한다는 것이 듣기에는 좋아보이지만 경사하강법의 원리를 생각한다면 마냥 좋은건 아니다. \eta가 너무 크면 경사를 올바르게 타고 내려가지 못해서 이상한 값으로 가중치 W가 수렴해버릴 수 있기 때문이다.

그럼 아예 학습률을 아주 작게 설정해버리면? 학습에 너무 많은 시간이 걸려서 효율이 떨어진다. 가중치 W가 덜 좋은 값(non-optimum)으로 수렴해버리는 경우도 있다.

e18489e185b3e1848fe185a6e1848ee185b515.png

따라서 적절한 학습률을 설정하는 것이 모형 가중치의 수렴과 학습 효율에 중요하다고 하겠다.

신경망의 경우엔 처음에는 큰 학습률을 사용했다가, 일정 정도 이상 학습을 한 이후에는 학습률을 작게 조정하는 경우도 있다. 이러한 기술을 학습률 분해(learning rate decay)라고 한다. 가장 많이 사용하는 학습률 분해 테크닉은 다음과 같다.

\eta = \gamma^t \eta_0

여기서 \eta_0 초기에 설정한 학습률이고, \gamma [0, 1] 사이의 , t 학습 기간이다. 방법을 사용하면 일정 학습 기간 t마다 \gamma 비율로 초기 학습률이 점점분해되어작아진다. 일정 학습 기간마다 같은 비율로 학습률을 분해시킨다고 해서 방법을 step decay라고 하고 \gamma 분해율(decay rate)이라 부른다.

학습률을 분해시킬 때는 분해율 \gamma 분해기간 t 추가로 결정해줘야 한다. 다시말해 \gamma, t 하이퍼파라미터이다.

정규화 강도 (regularization strength; \lambda)

정규화의 세기를 정해주는 정규화 강도 \lambda도 하이퍼 파라미터다.

정규화 강도를 너무 세게 하면 데이터로부터 오는 손실이 무시될 수 있다 (데이터로부터 거의 학습을 하지 않는 underfitting 현상이 발생한다). 반대로 정규화 강도를 너무 약하게 하면 데이터의 노이즈까지 학습하는 오버피팅이 발생할 수 있다.

Dropout이라는, 신경망 모형에서 자주 사용하는 정규화 방법에선 뉴런이 특정 확률(p)로 활성화될 수도 있고 안 될 수도 있다. 이 때 뉴런이 활성화될 확률 p도 학습 전 결정해야하는 하이퍼 파라미터이다. Dropout에 대해서는 다른 글에서 자세히 살펴보기로 한다.

외의 하이퍼 파라미터

  • RNN에서 뉴런의 unfold 횟수
  • CNN에서 filter 크기 stride
  • 경사하강법 외의 다른 최적화 방법에 필요한 하이퍼파라미터

등등이 많지만 주로 초기 학습률 \eta_0, 학습률 분해율 \gamma 분해기간 t, 정규화 강도 \lambda 모형의 성능과 수렴에 중요한 영향을 미치기에 글에서는 자세히 다루지 않겠다.

 

좋은 하이퍼파라미터 찾기

validation set 만들기

결정해야하는 하이퍼 파라미터의 종류를 알았으니 이젠 그 값을 결정할 차례다. 어떤 값이 좋은 값인지는 어떻게 알 수 있을까? 다른 방법이 없다. 테스트를 해봐야 한다.

이 때 주의해야 할 것은 test set으로는 하이퍼 파라미터 테스트를 하면 안된다는 것이다. Test set으로 테스트한 하이퍼 파라미터를 사용하겠다는 것은 모형의 학습에 test set을 사용하겠다는 것과 같은 말이다. (Test set은 최종 모형의 성능 평가를 할 때, 딱 한 번만 사용해야 한다!)

e18489e185b3e1848fe185a6e1848ee185b516.png

대신 training set을 다시 한번 쪼개어 하이퍼 파라미터 테스트용 데이터셋을 만들기로 한다. training set을 쪼개어 만든 하이퍼 파라미터 테스트용 데이터셋을 우리는 validation set이라고 부른다. 만든 validation set에 다양한 하이퍼 파라미터 세팅을 시험해보면서 우수한 성능을 내는 값을 선택하면 된다.

Cross-validation (CV)

데이터를 여러개의 fold 나눈 다음 validation set 만드는 방법도 있다.

e18489e185b3e1848fe185a6e1848ee185b517.png

방법을 k-fold cross-validation이라고 한다. 주로 3 또는 5-fold CV 많이 사용한다.

Random search

Validation set에 시험해볼 하이퍼 파라미터 값은 어떻게 정할까? 정답: 무작위로 정한다. 그렇다고 완전 무작위로 하지는 않고 보통 다음과 같은 가이드라인을 따른다.

  1. 처음에는 큰 범위에서 무작위로 선택한다.
  2. 짧게 (1~3회 정도) 학습시킨다. 여기서 학습한다함은 가중치를 업데이트시킨다는 것이다.
  3. 좋은 성능을 내는 범위로 범위의 크기를 좀 줄여서 무작위로 선택한다.
  4. 길게 (5~10 정도) 학습시킨다.
  5. 범위를 조금 더 줄여서 무작위로 선택한다.
  6. 더욱 길게 학습시킨다.

이렇게 큰 범위에서 점점 좁은 범위로 하이퍼 파라미터 값을 선택해 나가면서 좋은 값을 fine-tuning할 수 있다. 최종적인 후보 값을 선택한 후에는 손실함수값이 수렴할 때까지 끝까지 학습을 시킨다.

 

모형을 학습시키기 전에

모형을 학습시키는 코드를 짜기 전에 고려해야 하는 문제가 몇 가지 있다. 첫째는 학습을 시작하기 전 모형을 구성하는 파라미터(W, b ) 등의 초기 값들을 어떻게 설정할 것인지에 대한 문제이고, 둘째는 모형이 올바르게 구현되었는지를 확인하는 문제이다..

 

초기 가중치 W 설정

학습 이전 초기 가중치는 평균이 0인 임의의 작은 수로 설정하는 것이 보편적이다.

W = np.random.randn((D, K)) * .01

그런데 뉴런에 입력되는 데이터의 feature 차원에 따라 판별함수값 s = XW + b = \sum w_ix_i + b_i 크기가 제각기 달라지므로, 판별함수값의 크기가 표준편차 1 갖도록 feature 차원수 n으로 표준화를 해준다.

W = np.random.randn(n) * .01 / np.sqrt(n)

ReLU 활성화 함수로 갖는 신경망층의 경우 \div \sqrt{n/2} 표준화해주면 된다고 증명돼있다.

W = np.random.randn(n) * .01 / np.sqrt(n/2.)

요즘은 batch normalization(BatchNorm; BN)이라는 방식을 사용하는 것이 거의 필수가 되었다. BatchNorm 대해서는 나중에 기회가 되면 다루기로 한다. 간단하게 정리해보자면

  • BN layer라는 표준화층을 모든 뉴런의 판별함수와 활성화함수 사이에 추가한다.
  • 표준화 과정에 사용되는 파라미터도 수치적 최적화(경사하강법 등) 과정에서 업데이트되도록 한다.
  • 시간이 지남에 따라 은닉층의 출력이 특정 방향으로 shift되는 것을 막을 수 있다.

 

초기 편향 b 설정

초기 편향은 간단히 영벡터로 설정해준다.

b = np.random.zeros((1, K))

 

입력 데이터 표준화

분류기에 입력시킬 데이터(train set, test set, validation set 모두) 또한 전처리(preprocessing) 해주어야 한다. 평균이 0, 표준편차가 1 되도록 모든 관찰값을 정규화해준다.

x_mean = np.sum(x, axis=0) / x.shape[0]   # 표본평균

x_std = np.std(x, axis=0)              # 표본표준편차

x_normalized = (x - x_mean) / x_std

주의할 점은 표본평균과 표본표준편차를 계산할 test set, validation set 사용하면 안된다 것이다. 표본평균/표준편차는 training set으로만 계산해야한다. Training set에서 계산한 값들로 validation set, test set표준화해주면 된다.

 

초기 손실함수값 체크

손실함수에서는 두 가지 사항을 확인해야한다.

  • nan이 아닌 값을 반환하는가
  • 예상되는 값과 비슷한 값을 반환하는가

구현한 손실함수가 학습 이전에 nan을 반환하거나 예상되는 값과 다른 값을 반환한다면 구현한 코드에 문제가 있을 가능성이 크다.

 

초기 그라디언트 체크

분석적으로 계산한(역전파로 계산한) 그라디언트가 수치적으로 계산한 그라디언트와 일치하는지 체크한다. 수치적으로 그라디언트는 미분의 정의(f^\prime (x) = \lim_{h \to 0} \frac{f(x+h) - f(x-h)}{2h}) 사용해서 계산할 있다.

분석적 그라디언트가 수치적 그라디언트와 일치하는지의 여부는 아래 에러함수의 값으로 판단한다.

\frac{|f^\prime_N - f^\prime_A|}{\max(|f^\prime_N|, |f^\prime_A|)}

여기서 f^\prime_N, f^\prime_A는 각각 수치적 그라디언트, 분석적 그라디언트이다. 그라디언트의 크기에 대한 상대적인 오류 비율이라는 의미에서 이 에러함수를 relative error라고 칭한다.

  • Relative error 값이 1e-7 이하이면 아무 문제 없다.
  • 1e-4 정도의 에러는 문제가 있을 수도 있다. ReLU처럼 미분불가능한 구간이 있는 경우엔 이정도 오류는 괜찮다. 미분불가능한 구간이 없는 경우엔 문제가 있는 에러 크기이다.
  • 1e-4 이상의 에러는 문제가 있다. 분석적 그라디언트를 잘못 계산했을 수 있다.

 

의도적 과적화

Training set에서 작은 크기의 샘플을 추출한 다음 이걸 모형에 학습시켜서 의도적으로 과적화를 유도한다. 의도적으로 과적화시켰음에도 100%에 가까운 accuracy를 얻을 수 없다면 이 모형으로는 해당 분류 문제를 해결할 수 없다. 즉 분류기 설계가 잘못됐거나 분리가 불가능한 데이터이다.

모든 사항을 확인했다면 이제 모형을 학습시키면 된다.

 

모형을 학습시키는 도중에

모형을 학습시키는 중에도 모형이 데이터를 잘 학습하고 있는지 체크할 필요가 있다. 머신러닝 모형의 학습양상은 손실함수값의 수렴과 test set에서의 accuracy를 확인함으로써 파악할 수 있다.

 

손실함수 모니터링

가중치 W와 손실함수 L는 머신러닝 모형의 내부를 보여주는 창이다. 특히나 손실함수는 은닉층 학습양상이 직관적이지 않은(블랙박스) 신경망 기반 모형의 학습양상을 파악하는 데에 큰 도움이 된다.

스케치

매 학습단계(epoch)에서의 손실함수값을 통해서 우리는

  • 학습률이 적절히 잘 설정되었는지
  • 학습이 잘 되었는지, 되다 만 것은 아닌지

등을 판단할 수 있다.

(1) 학습률이 너무 경우 손실함수 L 최적의 값이 아닌 값으로 수렴할 있다. 경우 학습률 \eta 작게 설정해야 한다.

(2) 학습률이 너무 작은 경우 손실함수 $\latex L$이 수렴하는 데에 훨씬 오랜 epoch가 필요하다. 컴퓨팅 파워와 시간이 충분하다면 epoch를 늘려보자. 그렇지 않다면 \eta 값을 조금 더 크게 설정해보는 것도 방법이다.

 

Test set accuracy 모니터링

학습단계에서 training set에서의 accuracy test set에서의 accuracy 비교하면

  • 오버피팅이 되었는지 (정규화 강도를 조절해야 하는지)
  • 언더피팅이 되었는지 (학습이 덜 되었는지, 분류기가 너무 단순하지는 않은지)

등을 판단할 수 있다.

e18489e185b3e1848fe185a6e1848ee185b519-e1524062685380.png

(1) test acc train acc 비해 너무 낮다면 오버피팅의 가능성이 크다. 경우에는 정규화 강도 \lambda 값을 키워볼 필요가 있다.

(2) test acc train acc와 거의 같다면 언더피팅을 의심해볼 수 있다. 이 경우 손실함수가 잘 수렴했는지, sub-optimal 값으로 수렴한 것은 아닌지 살펴보아야 한다. 손실함수에 문제가 없음에도 이런 현상이 나타났다면 모형이 해당 분류문제를 해결하기엔 너무 단순한 것일 수 있다. 파라미터 갯수를 늘려서 새로 모형을 만들어보자. 신경망의 경우 뉴런 수를 늘리거나 은닉층을 하나 추가해서 파라미터 갯수를 늘릴 수 있다. 물론, 그냥 문제가 쉬워서 test set에서도 성능이 좋게 나오는 걸수도 있다. 이 경우엔 두 accuracy 모두 1에 가깝게 나올 것이다.

 

구현

사실 이전 글에서 구현했던 분류기에는 지금까지 다뤘던 내용이 상당히 이미 코드에 포함되어 있다. 여기서는 나선형 데이터를 분류하는 2-layer NN을 구현하는 과정에서 초기 가중치 설정과 train/test set 분리, test set accuracy 모니터링을 추가로 코드로 구현해보았다.

왼쪽열 그래프들은 붓꽃 분류문제에서의 accuracy, 손실함수값이고 오른쪽 그래프들은 나선형 데이터 분류문제에서의 acc와 손실함수값이다. training set만으로 학습을 마친 뒤 decision hyperplane을 training set과 test set에 각각 덧씌워 그려보았다.

 

여기까지 살펴 보았듯이 머신러닝 모형을 학습시키는 데에는 왕도가 없다. 파라미터 초기화를 잘 해주고 세심히 하이퍼 파라미터를 조정한 다음 학습 과정을 유심히 지켜보며 문제가 생기지는 않는지 계속 모형을 관찰하며 어루만져 주어야 한다.

이제야 제대로 된 학습과 테스트까지 다루었다다음 글에서는 지금껏 자세히 다루지 않았던 내용들(경사하강법 이회의 수치적 최적화 방법, Ridge 외의 정규화 방법 등)을 차례차례 다뤄보고자 한다.

 

참고

  • 이 글은 CS231n 강의록을 매우 많이 참고했다. 원 강의록을 읽어보시기를 강하게 추천드린다.
  • 코드는 이 노트북에 있다.