while (1): study();

Ch6. 게이트가 추가된 RNN 본문

독서

Ch6. 게이트가 추가된 RNN

전국민실업화 2021. 7. 29. 21:25
728x90

 이번 장에서는 Vanilla RNN에서 개선된 버전인 LSTM을 구현하여 본격적인 RNN LM을 구축합니다. 기존의 Vanilla RNN은 다음과 같이 계산됩니다.

$$h_{t} = tanh(h_{t-1}W_{h} + x_{t}W_{x} + b)$$

 이 때 $W_{h}$와 $W_{X}$는 계층 내에서 같은 가중치이므로, 타임스탭이 길어질 때마다 매번 같은(정확히는 비슷한) 행렬이 입력에 곱해지게 됩니다. 행렬의 최대 특잇값이 1보다 크다면 출력은 지수적으로 증가하고, 1보다 작으면 지수적으로 감소합니다. 따라서 역전파 과정에서 커지거나 작아진 가중치가 곱해지면 기울기도 그에 따라서 폭발하거나 소실될 가능성이 증가합니다.

 또한 하이퍼볼릭 탄젠트 함수의 도함수가 0부터 1사이의 값을 가질 수 있기 때문에, 역전파 과정에서 그 도함수인 $1 - tanh(x)^{2}$이 지속적으로 곱해지면 역시 기울기가 소실할 가능성이 커집니다.

 

Gradient Clipping

기울기가 너무 커지는 것을 방지하기 위해서 Gradient Clipping을 사용할 수 있습니다. 이는 기울기의 놈이 일정치 이상으로 증가하면 크기를 감소시키는 방식입니다.

$$if ||\hat{g}|| \geq:$$

$$\hat{g} = {threshold \over ||\hat{g}||}\hat{g}$$

일반적으로는 L2놈을 많이 사용하는 듯 합니다.

 

LSTM

 LSTM(Long Short-Term Memory)는 기울기 소실에 조금 더 잘 대응할 수 있습니다. 

 기존의 RNN 구조가 단순히 가중치의 행렬곱으로 계산했다면, LSTM은 내부적으로 아다마르 곱(Hadamard product)을 수행합니다. 이는 흔히 말하는 원소별(element-wise) 곱입니다. Cell state는 전체 기억을 담당하는데, 여기에 가해지는 연산은 아다마르 곱과 덧셈 뿐인 것을 확인할 수 있습니다. 결과적으로 행렬곱이 지속적으로 반복되어 발생하는 기울기 소실 현상에 대응할 수 있게 됩니다. 수식으로는 다음과 같습니다.

 게이트에는 시그모이드 활성화 함수가 적용되어, 0과 1 사이 수치를 반환하고 출력의 강도를 조절하는 역할을 합니다. forget gate는 입력을 받아 이전 타임스탭의 cell state에 곱해져 필요없는 기억을 잊어버립니다. input gate는 기억할만한 정보를 걸러내어 cell state에 싣는 역할을 하고, output gate는 최종 hidden state가 나가기 전 중요한 정보만을 내보내도록 합니다.

 교재에서는 드랍아웃과 Weight Tying을 이용하여 정규화하고 있기 때문에, 저도 여기까지 구현한 후 실험해보도록 하겠습니다. 총 3층의 LSTM 계층을 스택했으며, 학습률을 20으로 주고, BPTT 블록은 10 단위로 잘랐습니다. PTB 데이터셋에서 3000개의 샘플만을 사용했고, 검증용 데이터셋은 20%인 600개를 사용하여 평가했습니다. 최대 기울기 놈은 1로 클리핑하였습니다. 또한 초반의 불안정한 학습경향 때문에 SGD 옵티마이저를 사용했습니다

 학습이 잘 진행되는 것을 알 수 있습니다.

 

Gate Tying

 가만보니 forget gate와 input gate가 유사한 역할을 하는 듯 합니다. forget gate는 입력을 받아서 중요하지 않은 정보를 잊어버리고, input gate는 중요한 정보를 선별합니다. 따라서 만약 두 게이트를 하나로 통합시키고, 망각하는 게이트의 경우에는 1 - input gate와 같이 사용하면 비슷한 결과를 도출하면서, 연산량을 줄일 수 있지 않을까요?

이번엔 에포크를 50회로 주되, 5회 동안 성능이 개선되지 않으면 조기종료시켰습니다.

Simple LSTM

 일반적인 구현으로는 최저 검증 PPL은 1182 정도이고, 23.66초가 걸렸습니다.

Gate Tying

 forget gate와 input gate를 묶은 경우, 최저 검증 ppl은 1200 정도였습니다. 실험을 여러번 해보았으나, 1182보다 낮은 수치는 잘 나오지 않았습니다. 아무래도 두 게이트를 묶을 시 표현력이 어느정도 제한되는 것은 맞는 것 같습니다만, "거의" 비슷한 결과가 나오는 것을 확인할 수 있습니다.

 또한 훈련 시간이 23.66초에서 19.53초로 약 17% 정도 줄어들었습니다. 파라미터 개수도 줄었을 것을 감안하면 꽤 효율이 좋다고 이야기할 수 있겠습니다.

 

 Gate Tying 모델에서 조금 더 성능을 쥐어짜내기 위해서 변형 드롭아웃(Variational Dropout)을 추가하고, 파라미터를 조금 조정했습니다. (변형 드롭아웃은 LSTM 계층의 시간축 출력에 마스크를 씌우는 것입니다) 우선 훈련 데이터를 5000개로 조금 더 주었습니다. 또한 일반화성능을 높이기 위해 미니배치 사이즈를 32로 낮추어 업데이트 횟수를 늘렸고, 드랍아웃 확률을 0.5, 변형 드롭아웃 확률은 0.3으로 주었습니다. 최대 기울기 놈은 0.5로 주었고, 조기종료 에포크도 10회로 크게 주었습니다.

  추가적으로 최고 검증점수를 갱신하지 못하면 학습률을 4분의 1로 낮추어, 최적점에 최대한 수렴할 수 있도록 했습니다.

 OOV 문제 때문에 과적합이 잡히지는 않았지만, 그래도 성능이 훨씬 더 개선된 것을 확인할 수 있습니다. 모든 코퍼스를 활용할 경우 꽤 낮은 점수를 확인할 수 있을 것으로 예상됩니다만, 컴퓨팅 자원의 한계상.. 시간이 허락하면 진행하도록 하겠습니다.


추가

 교재에서 제시한 테스트 셋에 대한 최소 PPL이 75.76인데, Gate Tying모델을 같은 세팅으로 맞추어 (정확히는 드롭아웃 확률을 0.4, 변형 드롭아웃 확률을 0..2로 주어) 학습시켜보았습니다.

 약 33에포크 정도에서 검증 데이터에 대해 130 정도 PPL이 나왔는데, 코랩 서버가 다운되어버려서.. 테스트 세트에 대해서는 실험해보지는 못했습니다. 허나 그렇다고 해도 130과 75의 간극은 상당하므로, 아마 게이트를 적게 사용함에 따라서 모델의 표현력이 과하게 제한되어버린듯 합니다. 아무래도 기존 LSTM이 확실히 더 잘 작동하네요.

728x90

'독서' 카테고리의 다른 글

Ch8. 어텐션  (0) 2021.08.01
Ch7. RNN을 사용한 문장 생성  (0) 2021.07.31
Ch5. 순환 신경망(RNN)  (0) 2021.07.28
Ch4. Word2Vec 속도 개선  (0) 2021.07.27
Ch3. Word2Vec  (0) 2021.07.26
Comments