앞서 설명한 RNN은 성능이 좋지 못하다.(ㅠㅠ 도대체 언제 좋은거 만들건데요) 그 원인은 대개 장기 의존 관계, 즉 긴 시계열의 패턴을 파악 및 학습하기 어렵다는 것이다. 따라서 앞서 설명한 RNN은 가장 기초적인 RNN의 개념 정도로만 이해하고 실제로 쓰이는 계층은 주로 LSTM과 GRU이다. 이 LSTM과 GRU는 기존의 RNN에 게이트라는 구조가 더해져 있어 시계열 데이터의 장기 의존 관계를 학습할 수 있다. 게이트가 무엇이고 어떤 구조이길래 장기 의존 관계를 학습할 수 있게 되었는지 LSTM을 통해 살펴보도록 하자.

 

 

 

기존 RNN의 문제점

LSTM을 설명하기 앞서, 기존 RNN이 데이터의 장기 의존 관계를 학습하기 어려운 이유에 대해 자세히 설명하도록 하겠다. 기존의 RNN이 장기 의존 관계를 학습하기 어려운 이유는 BPTT에서 기울기 소실 혹은 기울기 폭발이 일어나기 때문이다. 앞서 BPTT에서 설명했다시피, BPTT는 시간 크기가 커질수록 기울기가 불안정하다. 이와 관련해서 RNNLM을 활용한 하나의 예시를 들도록 하겠다.

 

철수는 교실 책상에 앉아 있다. 영희는 교실로 들어갔다. 영희는 ___에게 인사를 했다.

 

여기서 ___에 들어갈 말은 무엇일까? 이것을 알기 위해서는 사람이나 RNN이나 똑같다. 우리는 영희가 '철수'에게 인사를 한다는 것을 문맥의 흐름으로 유추할 수 있다. 그렇기 위해서는 철수가 교실에 있다는 정보를 기억해야한다. RNN도 동일하다. 영희가 '철수'에게 인사를 한다는 것을 앞서 학습했던 문장을 기억하여 예측할 수 있다. 이런 정보를 RNN 계층은 은닉 상태에 인코딩해 보관해둔다.

 

그렇다면 이 예제에서 RNNLM은 어떻게 학습을 할까? 정답으로 '철수'가 주어졌을 때 RNNLM은 그 시점(정답이 주어진 시점)으로부터 과거 방향으로 기울기를 전달하게 된다.

 

Tom을 철수라고 생각해 이해하자.

 

RNN 계층은 과거 방향으로 의미 있는 기울기를 전달함으로써 시간 방향의 의존 관계를 학습할 수 있다. 하지만 기울기 소실, 혹은 폭발이 일어난다면 유의미한 기울기가 전달되지 못하고 그 결과 가중치 매개변수가 제대로 갱신되지 않아 학습이 잘 되지 않는다. 그렇다면 기존 RNN 계층에서 왜 기울기 소실 혹은 폭발이 일어나는 것일까?

 

 

기울기 소실 및 폭발 원인

1. 활성화 함수 (tanh)

기존 RNN의 활성화 함수로는 tanh함수를 주로 사용하는데, 이는 모든 신경망의 기울기 소실 이유와 동일한 양상을 띠게 된다. tanh함수를 역전파시키면 층이 깊어질수록 기울기값이 점점 작아지는 문제가 발생하게 되기 때문이다.

 

 

2.MatMul(행렬 곱) 노드

기존 RNN의 역전파 시 기울기는 MatMul 노드에 의해서도 변화하게 된다. (여기서는 기울기 폭발을 생각하기 위해 tanh함수의 역전파는 무시하도록 한다.) 기울기는 MatMul 노드를 지나가는 횟수에 비례해 폭발적으로 증가 혹은 감소하게 된다. MatMul 노드의 값이 1 이상인 경우는 층이 깊어질수록 곱해지면서 기울기 폭발이 일어나고, 1 이하인 경우는 층이 깊어질수록 기울기 감소가 일어나게 된다. 지금 설명은 MatMul 노드가 스칼라값이지만 행렬일 경우에는 행렬의 특잇값(데이터가 얼마나 퍼져 있는지를 나타냄)이 척도가되어 특잇값의 최댓값이 1보다 크면 지수적으로 증가하고, 1보다 작으면 지수적으로 감소할 가능성이 높다고 예측한다.

 

 

기울기 폭발에 대한 대책으로는 기울기 클리핑(gradient clipping)을 사용한다. 기울기 클리핑의 식은 다음과 같다.

 

기울기 클리핑

 

신경망에서 사용되는 모든 매개변수에 대한 기울기를 하나로 처리한다고 가정(모든 매개변수에 대한 기울기의 합)하고, 이를 g라고 표현했다. 이때 ||g||이 문턱값을 초과하면 두번째 줄의 수식과 같이 기울기를 수정하는 것을 기울기 클리핑이라고 하며 이는 기울기 폭발을 효과적으로 잘 대처한다.

 

 

 

 

LSTM

기존 RNN 계층의 기울기 소실 문제를 해결하기 위한 게이트를 추가한 것이 바로 LSTM이다. LSTM은 기울기 소실이 일어나기 매우 어려운 구조로 되어있기 때문에 대부분의 시계열 데이터 처리의 가장 기본으로 LSTM을 주로 사용한다.

 

σ 는 Sigmoid 함수를 의미한다.

 

기억 셀(memory cell)

LSTM은 은닉 벡터인 h뿐만 아니라 c라는 경로도 있다. c를 기억 셀(memory cell)이라 하며, LSTM 전용의 기억 메커니즘이다. 기억 셀의 특징은 은닉 벡터인 h와 다르게 데이터를 LSTM 계층 내에서만 주고받고 다른 계층으로는 출력하지 않는다는 것이다. ct는 시각 과거부터 시각 t까지에 필요한 모든 정보가 저장되어 있다. ct는 은닉 상태 ht의 계산에 사용되기 때문에(ht=tanh(ct)) 은닉 상태와 기억 셀의 원소 수는 동일하다.

 

 

LSTM을 구성하는 다양한 게이트들을 설명하기에 앞서 게이트의 정의에 대해 설명하도록 하겠다. 게이트는 데이터의 흐름을 제어하는 역할을 한다. LSTM에 사용하는 게이트는 열기, 닫기 뿐만 아니라 어느 정도의 데이터를 흘려 보낼지에 대한 제어도 할 수 있다. 이것 역시 데이터로부터 자동으로 학습되는 정보이다. 게이트는 게이트의 열림 상태를 제어하기 위해 전용 가중치 매개변수를 이용하며, 이 가중치 매개변수는 학습 데이터로부터 갱신된다. 게이트의 열림 상태를 제어하는 것을 학습하는데 사용되는 함수는 Sigmoid 함수이다.

 

 

 

output 게이트

ouput 게이트

 

output 게이트는 ht(=tanh(ct))의 각 원소에 대해 그것이 다음 시각의 은닉 상태에 얼마나 중요한가를 조정한다. 즉, 데이터를 얼마나 흘려보낼지를 결정하는 게이트이다. output 게이트의 열림 상태는(몇 %를 흘려보낼까) 입력 xt와 이전 상태 ht-1로부터 구한다.

 

output 게이트 수식

 

이 output 게이트 식과 tanh(c)의 원소별 곱(아마다르 곱)은 h로 출력된다.

 

 

 

 

 

forget 게이트

 

forget 게이트는 기억셀이 불필요한 기억을 잊도록 돕는 게이트이다.

 

 

 

 

 

새로운 기억 셀

 

forget 게이트를 거치면서 이전 시각의 기억 셀로부터 잊어야 할 기억이 삭제된 후, 새로 기억해야 할 정보를 기억셀에 추가해야 한다. 이를 위해 우리는 tanh 노드를 추가한다. tanh 노드가 계산한 결과가 이전 시각의 기억 셀(ct-1)에 더해진다. 이는 기억 셀에 새로운 정보를 추가하는 것으로, 여기서 사용되는 tanh는 게이트가 아니다. tanh를 사용하는 목적은 기억 셀에 새로운 정보를 추가하는 것이 목적이다. 따라서 새로운 기억셀에 대한 식은 다음과 같다.

 

 

g는 새로운 기억으로 이전 시각의 기억 셀인 ct-1에 더해진다.

 

 

 

 

input 게이트

 

input 게이트는 새로운 기억인 g에 추가하는 게이트로, g의 각 원소가 새로 추가되는 정보로써의 가치가 얼만큼인지를 판단한다. 새 정보를 무비판적으로 수용하는 것이 아니라, 적절히 선택하는 것이 이 게이트의 역할이다.

 

 

 

결론적으로 LSTM은 기존의 RNN과 달리 기억 셀이라는 것이 존재하고 이 기억 셀을 잘 활용하기 위해 output, forget, input 게이트가 사용된다. 이 기억 셀은 역전파시 +와 x노드만을 지나고, +노드는 역전파시 상류에서 전해지는 기울기를 그대로 흘리기 때문에 기울기 소실이 발생하지 않으며 기억 셀에서 사용되는 x노드는 행렬 곱이 아닌 원소별 곱이기 때문에 매번 새로운 게이트 값을 이용하므로 곱셈 효과가 누적되지 않아 기울기 소실이 발생하지 않는다.

 

LSTM의 x노드는 forget 게이트가 제어하며, forget 게이트가 잊어야 한다고 판단한 기억 셀의 원소에 대해서는 기울기값이 작아지고 잊지 말아야 한다고 판단한 기억 셀의 원소에 대해서는 기울기 소실 없이 그대로 전파된다.

 

LSTM에 사용되는 게이트들의 식을 보면 다음과 같이 4개의 가중치(또는 편향)를 하나로 모을 수 있고, 원래 별개로 4번의 계산을 수행해야 했던 것이 단 1회의 계산만으로 동일한 결과를 얻을 수 있게 된다.

 

 

 

 

 

 


 

 

 

 

 

 

추가적으로 RNN의 개선방안에 대해 간략하게 이야기하고 넘어가겠다.

RNN도 여타 신경망과 같이 overfitting의 문제가 발생한다. 이를 해결하기 위해서는 훈련 데이터의 양 늘리기와 모델의 복잡도 줄이기, 정규화, 드롭아웃(drop out)이 있다. 이 중에서 드롭아웃에 대해 살펴보면, RNN에서는 dropout 계층을 어디에 삽입해야할까? 정답은 상하 방향으로 삽입하는 방법이다.

 

dropout 계층 사용의 좋은 예

 

이렇게 상하 방향으로 드롭아웃을 삽입하는 이유는 드롭아웃을 시계열 방향으로 삽입하면 학습 시 시간이 흐를수록 드롭아웃에 의한 노이즈가 축적되어 정보가 사라질 수 있기 때문이다. 상하 방향으로 드롭아웃을 삽입하면 시간 방향(좌우 방향)에 영향을 주지 않는다.

 

하지만 의지의 인간은 기존의 드롭아웃 말고 새로운 드롭아웃을 만들어 시간 방향에도 드롭 아웃을 사용할 수 있게 했는데 자세한 내용은 여기를 참고하길 바란다.

 

 

 


 

 

 

 

또한 가중치 공유는 RNN의 성능을 높이는데 큰 도움을 준다. Embedding 계층의 가중치와 Affine 계층의 가중치를 연결하는 방법인 가중치 공유는 두 계층의 가중치를 공유함으로써 학습하는 매개변수 수가 크게 줄어드는 동시에 정확도도 향상된다.

 

 

이로써 LSTM에 대한 설명은 끝이 났다. 필자가 처음에 LSTM을 공부할 땐 제대로 이해가 안갔는데 3번 정도 읽으니 이해가 갔다.(ㅠㅠ) 모두들 힘내봅시다!

+ Recent posts