for textmining

딥러닝 학습 기술들

|

이번 글은 딥러닝 관련 다양한 학습기술들을 살펴보고자 합니다. 이번 글은 미국 스탠포드 대학의 CS231n과 역시 같은 대학의 CS224d 강좌를 정리했음을 먼저 밝힙니다. 따로 정리할 예정인 배치정규화(batch-regularization)를 제외하고 전반적인 내용을 요약하였습니다. 그럼 시작하겠습니다.

딥러닝 학습의 일반적 절차

딥러닝의 일반적 절차는 다음과 같습니다.

  1. 적절한 네트워크 선택

    1) 구조(structure) : Single words vs Bag of Words, etc.

    2) 비선형성(nonlinearity) 획득 방법 : ReLu vs tanh, etc.

  2. 그래디언트 체크 : 네트워크를 구축했는데 그래디언트 계산이 혹시 잘못될 염려가 있으므로 잘됐는지 체크해봅니다

  3. 학습 파라메터 초기화 : 초기화 방법에도 여러가지가 있으므로 적절히 선택합니다

  4. 학습 파라메터 최적화 : Stochastic Gradient vs Adam, etc.

  5. 과적합 방지 : dropout vs regularize, etc.

비선형성 획득 : 활성함수

뉴럴네트워크의 개별 뉴런에 들어오는 입력신호의 총합을 출력신호로 변환하는 함수를 활성화함수(activation function)라고 합니다. 활성화함수 유무는 초창기 모델인 퍼셉트론(perceptron)과 뉴럴네트워크의 유일한 차이점이기도 하죠. 활성화함수는 대개 비선형함수(non-linear function)를 씁니다. 활성화함수로 왜 선형함수를 쓰면 안되는 걸까요? ‘밑바닥부터 시작하는 딥러닝’의 한 글귀를 인용해보겠습니다.

선형함수인 $h(x)=cx$를 활성화함수로 사용한 3층 네트워크를 떠올려 보세요. 이를 식으로 나타내면 $y(x)=h(h(h(x)))$가 됩니다. 이는 실은 $y(x)=ax$와 똑같은 식입니다. $a=c^3$이라고만 하면 끝이죠. 즉, 은닉층이 없는 네트워크로 표현할 수 있습니다. 뉴럴네트워크에서 층을 쌓는 혜택을 얻고 싶다면 활성화함수로는 반드시 비선형 함수를 사용해야 합니다.

그러면 뉴럴네트워크 활성화함수 몇 가지 살펴보겠습니다.

시그모이드

로지스틱 함수로도 불립니다. 원래 수식 및 미분식은 아래와 같습니다.

시그모이드 함수의 범위는 $[0,1]$이고요, 그래프의 모양은 아래와 같습니다.

시그모이드 함수를 1차 미분한 그래프는 아래와 같습니다.

시그모이드 함수는 개별 뉴런이 내뱉어 주는 값을 S자 커브 형태로 자연스럽게 활성화를 해주기 때문에 예전부터 인기가 좀 있었습니다. 다만 입력값이 -5보다 작거나 5보다 클 경우에는 그래디언트 값이 지나치게 작아지고(=이렇게 되면 학습이 잘 안되죠), exp 연산이 다소 무겁다(=학습이 느려지죠)는 단점이 있습니다.

아울러 $σ(x)$의 범위는 $[0,1]$로서 모두 0 이상의 값을 지닌다는 문제가 있습니다. 이게 단점이 되는 이유는 바로 학습 속도와 관련이 있는데요. 예컨대 아래와 같은 뉴런이 있고 활성화함수 $f$가 시그모이드라고 가정해봅시다.

$x_0$, $x_1$, $x_2$는 모두 0 이상의 값을 갖습니다. 이들은 직전 층에서 시그모이드 함수에 의해 그 값이 양수로 활성화됐기 때문입니다. 여기에서 역전파시 최종 Loss에서 출발해 시그모이드 적용 직전의 $w_ix_i+b$ 각각에 들어오는 그래디언트를 $δ$라고 두겠습니다. 그렇다면 $w_i$의 그래디언트는 아래와 같습니다.

앞서 말씀드렸듯 $x_0​$, $x_1​$, $x_2​$는 모두 0 이상이기 때문에 $δ​$가 양수라면 Loss에 대한 $w_0, w_1, w_2​$ 각각의 그래디언트가 모두 양수, 반대라면 모두 음수 값이 될 것입니다. 따라서 데이터 $x​$와 파라메터 $w​$를 2차원 벡터로 가정해 본다면 $w​$의 그래디언트는 2사분면과 4사분면 쪽 방향이 될 수는 없습니다.

결과적으로 $w$ 학습시 아래 그림처럼 허용되는 방향에 제약이 가해져(요소값이 모두 양수인’ 1사분면과’ 모두 음수인 ‘3사분면’ 쪽 방향만 선택 가능) 학습속도가 늦거나 수렴이 어렵게 됩니다. 이 문제는 함수값이 0에 대해 대칭(zero-centered)인 하이퍼볼릭탄젠트 같은 함수를 쓰면 극복할 수 있다고 합니다.

하이퍼볼릭탄젠트

하이퍼볼릭탄젠트는 시그모이드 함수의 크기와 위치를 조절(rescale and shift)한 함수입니다. 시그모이드 함수와의 관계식과 미분식은 각각 아래와 같습니다.

하이퍼볼릭탄젠트의 범위는 $[-1,1]$입니다. 그래프의 모양은 시그모이드 함수와는 달리 0을 기준으로 대칭인 점을 확인할 수 있습니다. 이 때문에 하이퍼볼릭탄젠트는 시그모이드를 활성화함수로 썼을 때보다 학습 수렴 속도가 빠르다고 합니다.

하이퍼볼릭탄젠트를 1차 미분한 그래프는 아래와 같습니다. 시그모이드함수와 마찬가지로 $x$가 -5보다 작거나 5보다 크면 그래디언트가 0으로 작아지는 점을 볼 수 있습니다. 이것이 하이퍼볼릭탄젠트의 단점입니다.

Rectified Linear Unit (ReLU)

ReLU는 아래와 같이 정의됩니다.

그래프의 모양은 아래와 같습니다. $x$가 양수이기만 하면 그래디언트가 1로 일정하므로 그래디언트가 죽는 현상을 피할 수 있고, 미분하기도 편리해 계산복잡성이 낮습니다. 실제로 시그모이드나 하이퍼볼릭탄젠트 함수 대비 학습수렴 속도가 6배나 빠르다고 합니다.

다만 위 그림에서 확인할 수 있듯 0을 기준으로 대칭인 모양은 아닙니다. 아울러 $x$가 음수이면 그래디언트가 무조건 0이 된다는 단점이 있습니다. 이를 극복하기 위해 Leaky ReLU가 고안되었습니다.

Leaky ReLU

Leaky ReLU의 식은 아래와 같습니다.

그래프의 모양은 다음과 같습니다. $x$가 음수일 때 그래디언트가 0.01이라는 점을 제외하고는 ReLU와 같은 특성을 지닙니다.

Exponential Linear Units (ELU)

ELU는 ReLU의 특성을 공유하고요, 그래디언트가 죽지 않는다는 장점이 있다고 합니다. 다음 수식과 같습니다.

Maxout Neurons

MN은 다음과 같습니다. 연결된 두 개의 뉴런 값 중 큰 값을 취해 비선형성을 확보합니다. 다만 활성화함수를 적용하기 위해 필요한 연산량이 많다는 단점이 있습니다.

학습 파라메터 초기화

각 층의 가중치(weights)와 편향(bias) 등 학습 파라메터는 초기값 설정이 매우 중요하다고 합니다. 뉴럴네트워크가 풀려는 문제 자체가 non-convex optimization이기 때문에 시작점에 따라 최적지점을 찾지 못하게 될 수도 있습니다.

또한 학습 파라메터의 초기값을 적절하게 설정할 경우 그래디언트 조절에도 유의미한 효과를 낸다고 합니다. 이와 관련해 시그모이드 함수의 1차 미분 그래프를 다시 보도록 하겠습니다.

입력값 $x$에 가중치 $w$를 곱하고 편향 $b$를 더한 식을 $t$라고 둡시다. 여기에서 $w$가 100, $b$가 50이라면 $x$가 0.01로 매우 작더라도 $t$는 51이 됩니다. 역전파시 시그모이드 함수를 통과시키면 $σ’(51)$가 반환이 될텐데요, 위 그래프를 보시다시피 $t$가 5만 넘어도 $σ’(t)$는 0에 수렴하기 때문에 그래디언트가 죽어버리는 결과를 초래하게 됩니다. 그래디언트가 지나치게 작아지기 때문에 이후 학습이 사실상 불가능해지는 것이지요.

이와 별개로 뉴럴네트워크 입력층의 가중치 $W$를 모두 0으로 초기화한다면 어떻게 될까요? 순전파 때는 $W$가 0이기 때문에 두번째 층의 뉴런에 모두 같은 값이 전달됩니다. 미분의 연쇄법칙(chain-rule)을 떠올려보면 두번째 층의 모든 뉴런에 같은 값이 입력된다는 것은 역전파 때 두번째 층의 가중치가 모두 똑같이 갱신된다는 말이 됩니다. 다시 말해 뉴런이 100개가 됐든 1000개가 됐든 거의 같은 값을 출력하게 돼 네트워크의 표현력을 제한하게 된다는 얘기입니다.

따라서 학습파라메터의 초기값을 잘 설정해주어야 합니다. 이와 관련해 다양한 파라메터 초기화 방법론이 제시되었습니다. 일부를 소개하면 다음과 같습니다. 여기에서 $n_{in}$은 직전 레이어의 차원수, $n_{out}$은 다음 레이어의 차원수입니다. 아래 초기화식은 각 층의 가중치 $W$에 관한 식이고요, 은닉층과 출력층의 편향 $b$는 대개 0으로 설정한다고 합니다.

LeCun Initialization (Xavier Initialization)

Glorot Initialization

He Initialization

학습 파라메터 최적화 (1)

학습 파라메터 최적화 기법으로 널리 쓰이는 그래디언트 디센트(Gradient Descent)는 기본적으로 아래와 같은 구조를 지닙니다. 여기에서 $θ$는 갱신 대상 학습 파라메터, $dL/dθ$는 Loss에 대한 $θ$의 그래디언트, $η$는 학습률(leaning rate)을 의미합니다. 즉 아래 식은 Loss에 대한 $θ$의 그래디언트 반대 방향으로 $η$만큼 조금씩 $θ$를 업데이트하라는 뜻입니다.

그래디언트 디센트 방법론에도 여러 변형이 존재합니다. 세 가지 살펴보겠습니다. 아래 제시된 코드는 파이썬 기준입니다.

Batch Gradient Descent

이 방법은 전체 학습데이터 Loss에 대한 각 파라메터의 그래디언트를 한꺼번에 구한 뒤 1 epoch동안 모든 파라메터 업데이트를 단 한번 수행하는 방식입니다. 매우 느리고 메모리 요구량이 많다는 단점이 있지만 최적해를 찾을 수 있다는 장점이 있다고 합니다. (It’s guaranteed to converge to the global minimum for convex error surfaces and to a local minimum for non-convex surfaces)

for i in range(nb_epochs):
    params_grad = evaluate_gradient(loss_function, data, params)
    params = params - learning_rate * params_grad

Stochastic Gradient Descent

학습데이터의 순서를 랜덤으로 섞은 뒤 개별 레코드(위 코드에서 example) 단위로 Loss와 그래디언트를 구한 뒤 학습 파라메터를 조금씩 업데이트하는 방식입니다. 1 epoch동안 학습데이터 개수만큼의 업데이트가 수행됩니다. BGD보다 훨씬 빠르면서도 수렴 결과가 BGD와 일치(학습률을 줄였을 때)한다고 합니다.

for i in range(nb_epochs):
    np.random.shuffle(data)
    for example in data:
    	params_grad = evaluate_gradient(loss_function, example, params)
    	params = params - learning_rate * params_grad

Mini-batch Gradient Descent

이 방식은 개별 레코드가 아니라 batch_size(아래 코드에서 50) 단위로 학습한다는 점을 제외하고는 SGD와 같습니다. SGD에 비해 안정적으로 학습하는 경향이 있다고 합니다. 게다가 데이터가 배치 단위로 들어가게 되면 사실상 행렬 연산이 되기 때문에 시중에 공개돼 있는 강력한 라이브러리를 사용할 수 있다는 장점 또한 있습니다.

for i in range(nb_epochs):
    np.random.shuffle(data)
    for batch in get_batches(data, batch_size=50):
    	params_grad = evaluate_gradient(loss_function, batch, params)
    	params = params - learning_rate * params_grad

학습 파라메터 최적화 (2)

그래디언트 디센트 계열 외에 다양한 최적화 기법을 소개합니다. 최근 각광받고 있는 기법들입니다.

Momentum

모멘텀은 운동량을 뜻하는 단어로 물리 현상과 관계가 있습니다. 예컨대 아래 그림처럼 공이 한번 움직이기 시작하면 기울기 방향으로 힘을 받아 가속하게 되죠. 모멘텀 기법은 바로 이 점에 착안했습니다.

모멘텀 기법은 수식으로는 다음과 같이 쓸 수 있습니다. 여기에서 $μv$는 물체가 아무런 힘을 받지 않을 때 서서히 하강시키는 역할을 합니다($μ$는 0.9 등의 값으로 설정합니다). 물리에서는 지면 마찰이나 공기 저항에 해당합니다. 나머지는 그래디언트 디센트 기법과 동일합니다.

모멘텀 기법의 최적화 효과를 직관적으로 나타낸 그림은 아래와 같습니다. 하단 좌측 그림을 보시면 현재의 그래디언트가 모멘텀과 같은 방향이라면 업데이트가 더 크게 이뤄지게 됩니다. 하단 우측 그림에서 최적화 지점이 원 내부 중앙이라고 했을 때 모멘텀 기법이 조금 더 효율적인 업데이트 경로를 거치고 있는 점을 확인할 수 있습니다.

코드로는 아래와 같습니다. 여기에서 $μ$는 사용자가 지정하는 하이퍼파라메터입니다.

param_grad = evaluate_gradient(loss_function, data, params)
v = mu * v - learning_rate * param_grad
param = v + param

Nesterov Accelerated Gradient

이 기법은 모멘텀 기법을 업그레이드한 버전입니다. 현재 학습 파라메터(붉은색 원 : 아래 코드에서 $params$)를 직전까지 축적된 그래디언트 방향(녹색선)으로 이동시킵니다. 이 벡터($params_{ahead}$)를 기준으로 그래디언트(붉은색 선 : $params_grad_{ahead}$)를 계산합니다. 실제 업데이트는 둘을 모두 반영해 이뤄집니다.

모멘텀과의 차이 : 모멘텀은 현재 점(붉은색 원)에서 그래디언트를 구합니다. NAG는 녹색선과 빨간선이 이루는 꼭지점에서 그래디언트를 구합니다.

이 기법을 코드로 나타내면 아래와 같습니다. 여기에서도 $μ$는 역시 사용자가 지정하는 하이퍼파라메터입니다.

params_ahead = params + mu * v
params_grad_ahead = evaluate_gradient(loss_function, data, params_ahead)
v = mu * v - learning_rate * params_grad_ahead
params = v + params

AdaGrad

학습률 감소와 연관된 기법입니다. AdaGrad는 각각의 학습 파라메터에 맞춤형으로 학습률을 조정하면서 학습을 진행합니다. 수식은 아래와 같습니다. 여기에서 $⊙$는 행렬의 원소별 곱셈을 의미합니다. 식을 보시면 학습 파라메터의 원소 가운데 많이 움직인(크게 갱신된) 원소는 학습률이 낮아지게 돼 있습니다. 다시 말해 학습률이 학습 파라메터의 원소마다 다르게 적용된다는 뜻입니다.

이를 코드로 나타면 아래와 같습니다. 아래 코드에서 eps는 분모가 너무 0에 가깝지 않도록 안정화하는 역할을 합니다. 보통 $10^{-4}$에서 $10^{-8}$의 값을 쓴다고 합니다.

params_grad = evaluate_gradient(loss_function, data, params)
h = h + params_grad**2
params = params - learning_rate / (np.sqrt(h) + eps) * params_grad

RMSProp

AdaGrad는 학습률 $η$를, 과거의 기울기를 제곱한 값을 계속 더해나간 $h$로 나눠줍니다. 학습을 진행할 수록 $η$가 지속적으로 작아진다는 뜻입니다. 계속 학습하면 $η$가 0이 돼서 학습이 불가능해지는 시점이 옵니다. RMSProp은 이를 개선하기 위한 기법입니다. 즉 과거의 모든 기울기를 다 더해 균일하게 반영하는 것이 아니라, 먼 과거의 기울기는 서서히 잊고 새로운 기울기 정보를 크게 반영하기 위해 $h$를 계산할 때 지수이동평균(Exponential Moving Average)을 적용합니다.

코드는 아래와 같습니다. 여기에서 decay_rate는 사용자 지정 하이퍼파라메터이고 보통 $[0.9, 0.99, 0.999]$ 가운데 하나를 쓴다고 합니다.

params_grad = evaluate_gradient(loss_function, data, params)
h = decay_rate * h + (1 - decay_rate) * params_grad**2
params = params - learning_rate / (np.sqrt(h) + eps) * params_grad

Adam

모멘텀은 공이 구르듯 하는 물리 법칙에 착안해 만들어진 기법입니다. AdaGrad과 RMSProp은 학습 파라메터의 개별 원소마다 학습률을 달리 적용합니다. 두 기법을 합친 것이 바로 Adam입니다. 퍼포먼스가 좋아서 최근 많은 관심을 받고 있는 기법인데요. 코드는 다음과 같습니다.

params_grad = evaluate_gradient(loss_function, data, params)
m = beta1 * m + (1 - beta1) * params_grad
v = beta2 * v + (1 - beta2) * params_grad**2
params = params - learining_rate * m / (np.sqrt(v) + eps)

여기에서 $beta_1$, $beta_2$, $eps$는 사용자가 지정하는 하이퍼파라메터입니다. 논문에 따르면 각각 0.9, 0.999, $10^{-8}$이 좋다고 합니다.

각 기법 비교

너무나도 유명한 그림이라 설명은 생략하겠습니다. 저 역시 정리 용도로 올려 둡니다.

과적합 방지

과적합(overfitting)이란 모델이 학습데이터에만 지나치게 적응해서 일반화 성능이 떨어지는 경우를 말합니다. 기계학습은 범용 성능을 지향하기 때문에 학습데이터 외에 처음 보는 데이터가 주어지더라도 올바르게 판단할 수 있는 능력을 가져야 합니다. 뉴럴네트워크 학습시 과적합을 방지하는 몇 가지 기법에 대해 살펴보도록 하겠습니다.

모델 크기 줄이기

가장 간단한 방법입니다. 레이어나 뉴런 등 학습해야할 파라메터의 개수를 줄여서 과적합을 방지합니다.

early stopping

학습을 일찍 중단하는 방식으로 과적합을 방지합니다.

가중치 감소

과적합은 학습 파라메터의 값이 커서 발생하는 경우가 많다고 합니다. 가중치 감소(weight decay)는 이를 방지하기 위해 학습 파라메터의 값이 크면 그에 상응하는 큰 패널티를 부여하는 기법입니다.

1) L2 Regularization : 가장 일반적인 regulization 기법입니다. 기존 손실함수($L_{old}$)에 모든 학습파라메터의 제곱을 더한 식을 새로운 손실함수로 씁니다. 아래 식과 같습니다. 여기에서 $1/2$이 붙은 것은 미분 편의성을 고려한 것이고, $λ$는 패널티의 세기를 결정하는 사용자 지정 하이퍼파라메터입니다. 이 기법은 큰 값이 많이 존재하는 가중치에 제약을 주고, 가중치 값을 가능한 널리 퍼지도록 하는 효과를 냅니다.

2) L1 Regulazation : 기존 손실함수에 학습파라메터의 절대값을 더해 적용합니다. 이 기법은 학습파라메터를 sparse하게(거의 0에 가깝게) 만드는 특성이 있습니다.

**3) L1 + L2 **: 물론 두 기법을 동시에 사용할 수도 있습니다.

Dropout

드롭아웃은 일부 뉴런을 꺼서 학습하는 방법입니다. 일종의 앙상블(ensemble) 효과를 낸다고 합니다. 학습시에는 삭제할 뉴런을 무작위로 끄고, 테스트할 때 모든 뉴런을 씁니다.

기타 학습 기법들

기타 기법들을 소개합니다.

학습률 감소

학습률(learining rate)은 아래 그림처럼 학습 과정에 중요한 역할을 차지합니다. 지나치게 크면 발산하여 올바른 학습을 할 수 없고, 작으면 학습시간이 너무 길어집니다.

학습 시작부터 종료시까지 학습률을 고정한 채로 학습을 시킬 수도 있지만 학습이 거듭될 수록 해당 모델이 최적 지점에 수렴하게 될 것이므로 막바지에는 학습률을 작게 해 파라메터를 미세 조정하는 것이 좋을 것입니다. 학습률 감소 기법은 이 때문에 제안됐는데요, 각각 아래와 같습니다. 여기에서 $η$는 학습률, $t$는 스텝 수이며 $k$는 사용자가 지정하는 하이퍼파라메터입니다.

step decay : 스텝마다 일정한 양만큼 학습률을 줄이는 기법입니다. 5epoch마다 반으로 줄이거나 20epoch마다 1/10씩 줄이는 방법이 많이 쓰이지만, 데이터나 네트워크 구조에 따라 일률적으로 적용하기는 어렵습니다.

exponential decay : $η=η_0e^{-kt}$

$1/t$ decay : $η=η_0/(1+kt)$

하이퍼파라메터 최적화

하이퍼파라메터는 사용자가 지정해줘야 하는 값으로 어떤 값이 최적인지는 미리 알기 어렵습니다. 데이터나 모델 구조마다 달라지기도 하고요. 최적의 하이퍼파라메터를 찾기 위한 일반적인 절차는 아래와 같습니다.

  • 1단계 : 하이퍼파라메터 값의 범위를 설정한다
  • 2단계 : 설정된 범위에서 하이퍼파라메터의 값을 무작위로 추출한다
  • 3단계 : 샘플링한 하이퍼파라메터 값을 사용해 학습하고, 검증 데이터로 정확도를 평가한다 (단, 에폭은 작게 설정)
  • 2단계와 3단계를 반복하고, 그 결과를 보고 하이퍼파라메터 탐색 범위를 좁힌다

Multi-Task Learning

Multi-Task Learing이란 여러 학습 과제를 동시에 해결하는 기계학습의 한 종류입니다. 예컨대 같은 학습말뭉치로 개체명인식(Named Entity Recognition)품사분류(Part-Of-Speech Tagging)를 동시에 수행하는 뉴럴네트워크를 만들 수 있습니다. 아래 그림을 먼저 볼까요?

위 그림의 두 네트워크는 마지막에 붙어있는 소프트맥스 계층(Softmax layer)만 제외하면 완전히 동일합니다. 다만 $S_1$의 소프트맥스 확률값은 NER, $S_2$는 포스태깅 과제를 수행하면서 나오는 스코어라는 점에 유의할 필요가 있습니다. 위와 같은 Multi-Task Learining 네트워크에서는 아래 수식처럼 역전파시 $S_1$의 그래디언트와 $S_2$의 그래디언트가 동일한 네트워크에 함께 전달되면서 학습이 이뤄지게 됩니다.

Comments