Advanced Machine Learning 11 - RNNs (2) & Transformer (1)
Before starting
“Class” 카테고리에 있는 포스팅들은 실제로 수업에서 배운 내용을 정리하려는 목적으로 작성되었다. 이 글은 그 중 Advanced Machine Learning 과목의 수업을 다룬다.
Vanilla RNN
저번 글에서 다룬 RNN의 구조는 아래 사진과 같다.
즉, 하나의 Hidden State가 모델 내부적으로 공유되며, 매 Step마다 이 Hidden State가 업데이트되며 Sequential Memory 역할을 수행한다. 또한 이 동작은 매 Step마다 진행되므로 입력값이 가변적이어도 처리가 가능하다.
Backpropagation Through Time
그렇다면 RNN에서 Loss는 어떻게 계산될까? 매 Step마다 출력값이 존재하는 상황을 가정해보면, 각각의 출력값마다 얼마나 잘 예측했는지를 계산할 수 있다. 그리고 Hidden State는 매 Step마다 계속 업데이트가 되기 때문에, $t$번째 Step에서의 출력값 $y_t$의 Loss에는 $t$ 이전의 모든 Step에서의 Loss가 전부 어느 정도 반영되어야 한다.
즉, 위의 그림처럼 모든 경로에 대해 전부 Backpropagation이 수행되어야 한다. 이러한 방식을 Backpropagation Through Time, 즉 BPTT라고 부른다.
\[L=\sum_{t=1}^{T}L_t=\sum_{t=1}^{T}l(f_W(h_{t-1},x_t),x_{t+1})\]수식으로 나타내면 위와 같다. 여기서 $h_{t-1}$이 사실상 $t=1\ldots t$의 모든 Step이 다 반영되어 있으니 위의 식이 BPTT를 나타낸다고 보면 된다.
Vanishing Gradient
Vanilla RNN은 BPTT를 사용해서 학습을 시키면 된다는 것을 알았다. 그런데 이 방식에는 치명적인 문제점이 존재한다.
위 사진과 같이, MLP에서 사용하던 Backpropagation 및 Chain Rule을 적용하면 $\dfrac{\partial h_t}{\partial h_{t-1}}$을 반복적으로 계산해야 한다.
\[\begin{aligned} \dfrac{\partial h_t}{\partial h_{t-1}} &= \dfrac{\partial \tanh(W_{hh}h_{t-1}+W_{hx}x_t)}{\partial h_{t-1}} \\ &= (1-\tanh(W_{hh}h_{t-1}+W_{hx}x_t)^2)\times W_{hh} \end{aligned}\]그런데 이 값을 계산해보면 위와 같이 나온다. 위의 결과값에서 $W_{hh}$가 반복적으로 곱해진다는 점이 중요하다. $W_{hh}$는 모든 Hidden State의 공유 파라미터이므로, 모든 Step에서 전부 동일한 값을 가진다. Chain Rule을 통해 Gradient를 계산하면 이 값이 계속 곱해지기 때문에, $W_{hh}$의 크기에 따라 반드시 Exploding Gradients 혹은 Vanishing Gradients 중 하나의 문제가 발생하게 된다.
그나마 $W_{hh}$가 너무 커서 Exploding Gradient 문제가 발생할 경우엔 Gradient Clipping을 통해 강제로 크기를 줄여서 학습을 진행할 수 있다. 문제가 되는 것은 $W_{hh}$가 너무 작아서 발생하는 Vanishing Gradient인데, 이쪽은 강제로 크기를 늘려봤자 결국 Gradient가 소실되는 것을 원천적으로 막을 수는 없기 때문이다.
이러한 Vanishing Gradient 문제 때문에 Vanilla RNN은 실제로는 Long-term Dependency를 잘 반영하지 못하는 모델이다. $W_{hh}$가 많이 곱해질수록 Gradient가 소실된다는 이야기는, 곧 멀리 있는 데이터를 잘 기억하지 못한다는 의미와 동일하기 때문이다. 이는 Sequential Data를 다루기 위한 모델로써는 치명적인 문제점이라 Activation function을 ReLU를 비롯한 다른 것으로 교체하거나, 혹은 초기 Weights를 적절한 값으로 변경하거나 하는 식으로 이를 해결하기 위한 연구가 이루어졌었다.
그러나 Vanishing Gradient가 발생하는 근본적인 원인은 Chain Rule에서 일어나기 때문에 위의 마이너한 변경들로는 이 현상을 방지할 수 없었다. 그렇기 때문에 모델 구조 자체를 변경해야 하는 결론에 이르렀고, 이 때문에 고안된 모델이 LSTM과 GRU이다.
Long Short-Term Memory
Long Short-Term Memory, 즉 LSTM은 Hidden State 외에도 Cell State라는 또 하나의 상태를 만들어 이 둘을 같이 관리한다.
LSTM의 구조는 위 사진과 같다. 여기서 $\sigma$는 Sigmoid 함수를 뜻하며, $[0,1]$로 스케일링되는 특성을 활용해 데이터를 통과시킬 비율을 Sigmoid로 계산한다.
먼저 좌측의 $f_t$는 Forget Gate라고 부른다. 이는 $x_t$와 $h_{t-1}$로부터 Cell State를 남길 비율을 결정한다. 또한 가운데 영역은 Input Gate $i_t$라고 부르며, 역시 $x_t$와 $h_{t-1}$로부터 얻은 이번 Step의 정보를 얼마나 많이 Cell State에 넘겨줄지를 결정한다. 우측의 $o_t$는 Output Gate라고 부르는데, 위의 두 Gate를 거쳐 얻은 이번 Step의 Cell State를 Hidden State에 얼마나 반영할지를 결정한다.
\[\begin{aligned} f_t&=\sigma(W_f[h_{t-1},x_t]+b_f) \\ i_t&=\sigma(W_i[h_{t-1},x_t]+b_i) \\ \tilde{C_t}&=\tanh(W_C\cdot[h_{t-1},x_t]+b_C) \\ C_t&=f_t\ast C_{t-1}+i_t\ast\tilde{C_t} \\ o_t&=\sigma(W_o\cdot[h_{t-1},x_t]+b_o) \\ h_t&=o_t\ast\tanh(C_t) \end{aligned}\]LSTM에서 일어나는 일을 수식 및 그림으로 정리하면 각각 위와 같다.
그러면 LSTM은 Gradient가 어떻게 흐르기에 Vanilla RNN에서의 Vanishing Gradient 문제를 해결할 수 있을까? 위의 LSTM에서 발생하는 각 수식들 중, 우리가 중요하게 봐야할 것은 Cell State를 업데이트하는 $C_t=f_t\ast C_{t-1}+i_t\ast\tilde{C_t}$ 부분이다.
\[\dfrac{\partial C_t}{\partial C_{t-1}}=C_{t-1}\sigma^{\prime}(\cdot)W_f\ast o_{t-1}\tanh^{\prime}(C_{t-1})+\tilde{C_t}\sigma^{\prime}(\cdot)W_i\ast o_{t-1}\tanh^{\prime}(C_{t-1})+f_t\]Vanilla RNN과 비슷하게, 이 부분을 Backpropagation으로 계산하게 되면 $\dfrac{\partial C_t}{\partial C_{t-1}}$을 계산해야 하는데, 이는 위와 같이 전개할 수 있다. Vanilla RNN과 다르게, Gradient에 덧셈이 포함되어 있음을 알 수 있는데, 이 덧셈으로 인해 위의 계산이 여러번 수행되어도 Gradient가 0으로 수렴하는 현상을 막아주는 것이다.
Gated Recurrent Unit
Gated Recurrent Unit, 즉 GRU는 LSTM의 구조를 단순하게 변형시킨 모델이다. 결과적으로 Vanilla RNN의 Vanishing Gradient 문제를 해결한다는 점은 같지만, LSTM보다 상대적으로 가볍다. 여기서는 GRU에 대해 간단하게만 알아보자.
GRU의 구조는 위와 같다. LSTM과는 다르게 Cell State가 다시 사라져있다는 것을 알 수 있는데, 실제로 GRU에서는 Hidden State 하나만 관리한다. 또한 Gate의 개수도 2개로 줄어있는데, 이들을 각각 Update Gate $z_t$, Reset Gate $r_t$라고 부른다.
Update Gate $z_t$는 이번 Step의 Input Data의 비중을 결정하는 Gate이다. 그리고 Reset Gate $r_t$는 이번 단계의 New Hidden State Content $\tilde{h_t}$에 이전 Step에서 온 Data를 얼마나 반영할 것인지를 결정하는 Gate이다.
여기서 New Hidden State Content라는 말이 나오는데, 이는 Hidden State를 그대로 사용하지 않고 Reset Gate에 의해 정해진 비율과 이번 Step의 입력값 $x_t$를 가지고 새로 계산해서 구한다. 그리고 이 New Hidden State Content와 이전 Step의 Hidden State를 Update Gate에서 정해진 비율대로 결합하여 Hidden State를 업데이트한다.
\[\begin{aligned} z_t&=\sigma(W_z\cdot[h_{t-1},x_t]) \\ r_t&=\sigma(W_r\cdot[h_{t-1},x_t]) \\ \tilde{h_t}&=\tanh(W\cdot[r_t\ast h_{t-1},x_t]) \\ h_t&=(1-z_t)\ast h_{t-1}+z_t\ast\tilde{h_t} \end{aligned}\]GRU에서 일어나는 전체 과정을 수식으로 표현하면 위와 같다.
Limitations of RNNs
현재 주로 쓰이는 모델인 Transformer는 RNN 계열의 모델이 가지고 있는 치명적인 한계를 극복하기 위해 고안되었다. 먼저 RNN 계열의 모델이 갖는 문제점을 알아보자.
먼저 RNN 계열 모델에서는 항상 Sequential하게 동작한다. Sequential Data를 다루는데 Sequential 동작을 하는게 무슨 문제냐고 할 수 있지만, 위의 특성으로 인해 입력과 출력을 전부 알고 있는 학습 상황에서조차 Sequential하게 동작해야만 해서 학습 속도가 매우 느리다. 이는 곧 큰 데이터셋을 가지고 학습시키기 어렵다는 의미이다.
또한 LSTM과 GRU 등의 변형 RNN 모델 연구로 인해 RNN 계열에서도 Hidden State를 잘 살리고 최대한 오래 보존시킬 방법은 생겼으나, 여전히 Hidden State는 Step-by-Step 형태로만 구축이 된다는 점이다. 이 역시 첫 번째 문제점과 마찬가지로 Parallel Computing을 상당히 제약하는 단점이다.
이러한 문제점들로 인해 과감하게 RNN을 포기하고 Attention 기반의 방법론이 연구되었고, 그 중 하나가 Transformer이다.





