딥러닝/혁펜하임의 Easy! 딥러닝

[Chapter 8] 왜 RNN보다 트랜스포머가 더 좋다는 걸까?

꾸준함. 2025. 2. 12. 23:04

1. 연속적인 데이터와 토크나이징 (Tokenizing)

  • 연속적인 데이터는 우리 일상 속에서 흔히 볼 수 있으며 이러한 데이터를 처리하는 예시는 다음과 같음
    • 검색창의 자동 완성 기능: 사용자가 `엔비디아`라고 입력할 경우 자동 완성 AI는 이 연속된 글자 입력을 바탕으로 `엔비디아 주식`, `엔비디아 그래픽 카드` 등과 같이 가능한 검색어의 뒷부분을 예측
    • 주가 예측: 과거부터 현재까지의 주가, 거래량, 경제 지표 등의 연속적인 데이터를 분석하여 미래의 주가 움직임을 예측
    • 동영상에서의 동작 인식: 체조 선수의 연기를 다음 동영상에서 연속된 프레임을 분석하여 선수의 동작을 인식하고, 해당 난이도와 완성도를 바탕으로 점수 예측

 

  • 이러한 연속적인 데이터를 효과적으로 처리하기 위해 개발된 것이 바로 RNN (Recurrent Neural Network)
  • RNN은 이전 정보를 기억하고 활용하여 시간의 흐름이나 순서가 중요한 데이터를 다룸
  • RNN으로 연속적인 데이터를 처리하기 위해서는 먼저 데이터를 적절한 단위로 나누는 과정이 필요
    • 해당 과정을 토크나이징 (Tokenizing)이라고 하며, 나눠진 각 단위를 토큰 (Token)이라고 부름
    • 글자 단위로 나누거나 띄어쓰기 단위로 나눌 수 있지만, 최근에는 주로 Sub-Word 단위의 토크나이징을 사용

 

  • Sub-Word 단위의 토크나이징은 단어를 더 작게 나누어, 모델이 새로운 단어나 복합어의 의미를 유추할 수 있게 해 줌
    • ex) `Pretrained`라는 단어가 학습 데이터에는 없지만 테스트 데이터에 있다고 가정했을 때 띄어쓰기 단위로 토크나이징을 했다면 AI는 해당 단어의 뜻을 전혀 알 수 없을 것
    • 하지만 Sub-Word 단위로 나누는 토크나이저를 사용했을 경우 해당 단어를 `Pre`, `train`, `ed`와 같이 나눌 것이고 만약 모델이 `Preview`, `training`, 그리고 `Weighted` 등의 단어를 통해 `Pre`, `train`, `ed`, 각각의 의미를 학습했을 ㄱ여우 이들을 조합하여 `사전 학습된`이라는 의미를 유추 가능

 

  • 토크나이징 후에는 각 토큰을 숫자로 변환해야 하며 이때 주로 사용되는 방법이 One-Hot Encoding
    • 이 과정에서 각 토큰은 고유한 인덱스를 부여받음
    • ex) 토크나이저의 어휘 사전이 {`저는`: 0, `강사`: 1, `입니다`: 2, `당신을`: 3, `사랑`: 4, `합니다`: 5}라고 가정했을 때 각 토큰은 다음과 같이 One-Hot 벡터로 표현되며 One-Hot 벡터의 길이는 토크나이저가 가진 전체 토큰의 개수와 같음
      • `저는`: [1, 0, 0, 0, 0, 0]
      • `강사`: [0, 1, 0, 0, 0, 0]
      • `입니다`: [0, 0, 1, 0, 0, 0]
      • `당신을`: [0, 0, 0, 1, 0, 0]
      • `사랑`: [0, 0, 0, 0, 1, 0]
      • `합니다`: [0, 0, 0, 0, 0, 1]
    • 위 대응 관계는 문장 내 단어의 순서와는 무관함
      • `저는 강사입니다`: [[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0]]
      • `당신을 사랑합니다`: [[0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]]
    • 이렇게 인코딩 된 데이터는 순차적으로 RNN에 입력됨

 

2. RNN의 동작 방식

  • RNN은 `되풀이되는`, `반복되는`이라는 뜻의 `Recurrent`에서 그 이름이 유래됨
  • RNN은 입력 토큰을 순서대로 받아들이며, 각 단계마다 이전 은닉 상태를 활용해 현재 시점의 은닉 상태를 업데이트
  • RNN은 각 토큰을 One-Hot Encoding 한 후 순차적으로 처리하는 방식을 사용하며 과정은 다음과 같음

 

https://medium.com/@serbanliviu/the-intuition-behind-recurrent-neural-networks-6fce753fe9f0
https://medium.com/@serbanliviu/the-intuition-behind-recurrent-neural-networks-6fce753fe9f0



  •  

https://www.genspark.ai/
https://www.genspark.ai/
https://www.genspark.ai/

 

  • 여기서 주목할 점은 W_xh, W_hh, W_hy, b_h, 그리고 b_y가 모든 시점에서 동일하게 사용된다는 것
    • RNN이 모든 시점에서 같은 규칙을 적용한다는 것을 의미

 

https://www.genspark.ai/

 

  • 출력(y_t)은 반드시 매 시점마다 얻어야 하는 것은 아님
    • 네트워크 설계에 따라 원하는 시점에서만 출력층을 연결할 수 있음
    • 더불어, 출력의 활성화 함수는 문제의 유형에 따라 달라지며 회귀 문제에서는 활성화 함수 없이 그대로 사용하고, 분류 문제에서는 Softmax를 사용

 

https://www.genspark.ai/

 

RNN의 이러한 구조는 다음과 같이 두 가지 중요한 이점을 제공합니다.

  • 이전 정보의 유지: RNN은 이전 시점의 정보를 현재 시점으로 전달하기 때문에 연속적인 데이터의 맥락을 이해하고 처리 가능
  • 가변적 입력 처리: RNN은 동일한 레이어를 반복적으로 사용하기 때문에 다양한 길이의 입력을 자연스럽게 처리 가능
    • 입력 시퀀스의 길이에 따라 짧은 문장은 적은 횟수로, 긴 문장은 더 많은 횟수로 동일한 레이어를 통과시키기만 하면 됨
    • 이 과정에서 모든 토큰은 동일한 웨이트 행렬을 통과하게 되므로, 특정 시점에 대응하는 웨이트만 집중적으로 학습되는 학습 불균형 문제가 발생하지 않음

 

3. 다음 토큰 예측 (Next Token Prediction)

RNN의 학습 원리와 구조적 한계를 이해하기 위해, 자동 완성 AI를 예로 들어 설명해 보겠습니다.

자동 완성 AI는 사용자의 입력에 따라 적절히 단어를 완성시키며 `Hello`를 예로 들면 다음과 같이 동작합니다.

  • `H` 입력 시 `ello`를 제안하여 `Hello` 완성
  • `He` 입력 시 `llo`를 제안하여 `Hello` 완성
  • `Hel` 입력 시 `lo`를 제안하여 `Hello` 완성
  • `Hell` 입력 시 `o`를 제안하여 `Hello` 완성

 

위 예시를 RNN으로 구현하는 방법으로는 아래 사진과 같이 글자 단위 토크나이저를 사용하여 `Hell`을 입력으로, `ello`를 각 시점의 레이블로 삼고 학습하는 모델을 고려할 수 있습니다.

  • 시퀀스 `Hell`을 입력으로 받아, 각 시점마다 바로 다음 글자를 예측하도록 학습

 

https://www.slideserve.com/leane/generating-text-with-recurrent-neural-networks

 

그렇다면 RNN이 입력 시퀀스 `Hell`을 학습했다면, 자동 완성을 위해서는 항상 네 글자를 모두 입력해야 하는 걸까요?

  • 학습 시에는 `Hell`을 입력하여 각 시점의 다음 글자인 `ello`를 예측하도록 하지만 테스트 시에는 다양한 길이의 입력에 유연하게 대응 가능
  • 테스트 시에는 RNN이 예측한 출력을 다음 입력으로 사용하는 방식을 취하며 이는 실제 자동 완성 기능에 적합함
  • ex) `H`만 입력하는 경우
    • 잘 학습된 RNN이라면 `e`를 출력
    • 출력된 `e`를 다음 입력으로 사용
    • `e`와 이전 시점의 정보 `H`를 바탕으로 `l`을 예측
    • 예측된 `l`을 다시 입력으로 사용하여 다음 `l`을 예측
    • 마지막으로, `l`을 입력으로 사용하여 `o`를 예측
    • 결과적으로 `H` 하나만 입력해도 `ello` 전체를 얻을 수 있음

 

  • 이러한 유연성 덕분에 RNN이 충분히 잘 학습되었다는 전제하에 다양한 길이의 입력에 대응할 수 있는 효과적인 자동 완성 AI로 활용될 수 있음

 

앞서 거론한 학습 방식을 다음 토큰 예측 (Next Token Prediction)이라고 합니다.

  • 각 시점에서 바로 다음에 올 토큰을 예측하는 것이 해당 방식의 핵심
  • Next Token Prediction은 ChatGPT와 같은 LLM의 기본 학습 방식이며 이 방법으로 모델은 먼저 언어의 패턴과 구조를 학습
  • 각 시점에서 다음에 올 가장 적절한 글자나 단어를 전체 어휘 중에서 선택해야 하기 때문에 Next Token Prediction은 본질적으로 다중 분류 문제
  • 따라서 출력층에는 Softmax 함수를 사용하고, Loss 함수로는 Cross-Entropy를 사용하며 전체 Loss는 각 시점의 Cross-Entropy Loss의 평균으로 계산

 

4. RNN의 구조적 한계

RNN의 이러한 구조는 강력하지만, 동시에 두 가지 주요한 한계를 지니고 있습니다.

  • 멀수록 잊혀진다: Loss와 멀리 있는 토큰의 정보가 그래디언트에 미치는 영향력이 매우 작아짐
  • 갈수록 뭉개진다: Forward Propagation 과정에서 발생하는 문제로 시점을 거치면서 초기 시점의 입력에 대한 정보가 점점 뭉개지는 현상

 

4.1 멀수록 잊혀진다

  • RNN에서는 시퀀스의 길이가 길어질수록 초기 입력 토큰들이 마지막 시점의 Loss에 대한 그래디언트에 미치는 영향력이 급격히 감소
    • Back Propagation 과정에서 여러 항을 더할 때, 시퀀스를 거슬로 올라갈수록 항의 크기가 점점 작아지기 때문

 

https://www.genspark.ai/
https://www.genspark.ai/
https://www.genspark.ai/
https://www.genspark.ai/

 

정리

  • 위 수식에서 볼 수 있듯이, 최종 Loss가 t = 5에서 계산되더라도 처음 입력된 'H'에 의해 전달되는 그래디언트는 여러 단계의 미분값 곱에 의해 지수적으로 축소됨
  • 이로 인해 RNN은 길이가 긴 시퀀스에서 초기 입력 정보를 잊어버리기 쉬우며, 이는 '멀수록 잊혀진다'라는 표현으로 요약할 수 있음
  • 이와 같은 기울기 소실 문제는 LSTM (Long Short Term Memory), GRU (Gated Recurrent Unit) 등과 같은 구조가 제안된 배경 중 하나로, 이들 구조는 장기 의존성 문제를 부분적으로 해결하기 위해 설계됨
    • 전통적인 기울기 소실 문제는 신경망의 깊이가 깊어질수록 입력층에 가까운 파라미터들에 대한 그래디언트 크기가 현저히 작아져 학습이 제대로 이루어지지 않는 현상
    • RNN은 각 시점의 Loss를 모두 고려하기 때문에 특정 파라미터에 대한 전체 그래디언트의 크기는 일반적으로 작지 않음
    • RNN의 실제 문제는 그래디언트를 구성하는 요소가 각 시점 입력의 가중합으로 표현되며, 이때 각 항의 크기가 불균형하다는 점, 멀리 있는 시점에 대한 항은 상대적으로 작으므로, 그 정보가 효과적으로 반영되지 않음
    • RNN에서 나타나는 현상을 정확히 표현하자면 '그래디언트가 각 입력 시점에 대해 불균형적 가중합으로 구해지는 문제'라고 할 수 있음

 

4.2 갈수록 뭉개진다

RNN의 두 번째 주요 한계점은 Forward Propagation 과정에서 발생하며 시점을 거치면서 초기 시점의 입력에 대한 정보가 점점 뭉개지는 현상을 볼 수 있습니다.

이 현상을 이해하기 위해 RNN의 작동 방식을 복습하면, 각 시점에서 RNN은 이전 시점의 h_(t - 1)과 현재 입력 x_t를 결합하여 새로운 h_t를 만들며 이 과정에서 tanh 함수가 사용됩니다.

그런데, tanh 함수의 특성상 입력값을 항상 -1과 1 사이의 값으로 변환하므로 두 가지 효과를 가집니다.

  • 정보의 정제: 반복된 비선형 변환을 통해 입력 데이터의 특징이 정제될 수 있음
  • 정보의 압축: 입력 데이터의 특징이 정제되는 동시에 출력값이 -1과 1 사이로 압축되면서 입력값들의 세부적인 차이가 줄어들게 됨, 특히 큰 절댓값을 가진 입력들은 tanh 함수의 평탄한 부분으로 인해 그 차이가 크게 감소함

 

결과적으로, 시퀀스의 후반부로 갈수록 이전 입력들의 세부적인 정보가 점차 압축되어 구별하기 어려워지며 이는 RNN의 현재 h에는 이전의 모든 입력 정보가 담겨있긴 하지만, 최근 입력의 정보는 상대적으로 또렷하게 담겨 있는 반면 오래된 입력의 정보일수록 점점 더 뭉개져 담기게 된다는 것을 의미합니다.

정리하면 RNN이 최근의 정보는 또렷하게 기억하는 반면, 오래된 정보일수록 세부적인 내용을 구분하기 어려워지는 경향이 있음을 의미합니다.

  • ex) "딥러닝 책을 여러 해에 걸쳐 열심히 연구하고 고민하여 밤낮으로 노력하여 마침내 쓰다."라는 문장에서 마지막 단어인 "쓰다"의 의미를 정확히 파악하기 위해서는 문장의 맨 앞에 있는 "책을"이라는 정보가 필요하지만 RNN이 이와 같은 긴 문장을 처리하면서 초반의 정보가 뭉개지므로 "쓰다"라는 단어를 처리할 때 "책을 쓰다"인지 "돈을 쓰다"인지 구분하기 어려움

 

이러한 RNN의 두 가지 주요 한계점은 특히 긴 시퀀스를 다루는 작업에서 큰 문제가 됩니다.

 

5. RNN의 여러 가지 유형

RNN은 다양한 형태로 구성될 수 있으며, 입력과 출력의 시점 수에 따라 여러 유형으로 나눌 수 있습니다.

 

5.1 One to Many 방식

  • 하나의 입력 시점과 여러 개의 출력시점을 가짐
  • ex) 이미지 캡셔닝을 예로 들 수 있으며 피아노를 치는 사람의 사진이 단일 입력 주어졌을 때 모델은 "A man is playing the piano"와 같이 이미지를 설명하는 문장을 생성
    • 이 과정에서 모델은 이미지의 주요 특징을 파악하고 이를 바탕으로 순차적으로 단어를 생성하여 전체 문장을 만들어냄

 

5.2 Many to One 방식

  • 여러 개의 입력 시점과 하나의 출력 시점을 가짐
  • ex) 긍정 혹은 부정으로 이진 분류하는 감정 분석이 대표적인 예이며 "이 영화는 정말 훌륭했습니다. 강력히 추천합니다!"라는 영화 리뷰가 입력으로 주어졌을 때 모델은 이를 분석하여 0.98과 같은 높은 긍정 지수를 출력할 수 있음
    • 이 과정에서 모델은 전체적인 맥락과 감정을 이해하고, 이를 단일값으로 요약함

 

5.3 Many to Many 방식

  • 여러 개의 입력 시점과 여러 개의 출력 시점을 가짐
  • 기계 번역이 대표적인 예이며 "저는 강사입니다"라는 한국어 문장이 입력으로 주어졌을 때 모델은 이를 분석하여 "I am an instructor"라는 영어 문장을 출력
    • 이 과정에서 모델은 입력 문장의 각 단어와 전체적인 의미를 이해하고, 이를 바탕으로 Target 언어의 문법과 어휘를 고려하여 번역문 생성

 

https://scientistcafe.com/ids/recurrent-neural-network

 

6. Seq2seq 개념 및 문제점

  • 번역기는 주로 "Many to Many" 방식의 특별한 구조인 Seq2seq (Sequence-to-Sequence) 모델을 사용하며 해당 모델은 시퀀스를 입력받아 다른 시퀀스를 출력하는 구조
  • Seq2seq 모델에서는 <sos>와 <eos>라는 특별한 토큰이 사용됨
    • <sos>는 'Start of Sequence'를 의미하며 디코더에게 번역 시작을 알리는 신호로 사용됨
    • <eos>는 'End of Sequence'를 의미하며 모델이 번역을 언제 멈춰야 할지 학습할 수 있게 함
    • <eos> 없이는 모델이 언제 멈춰야 할지 몰라 무한히 단어를 생성할 수 있으므로 가변 길이의 출력을 다루는데 필수적
    • 해당 토큰들은 문장의 시작과 끝을 표시하며, 다른 단어들과 마찬가지로 One-Hot Encoding 방식으로 벡터화

 

  • Seq2seq 모델에서는 인코더와 디코더, 두 부분으로 구성됨
    • 각 부분은 서로 다른 RNN으로 이루어져 있으며, 각각 고유한 W_x, W_h, W_y 파라미터 세트를 가지고 학습됨
    • 단, 각 부분 내에서는 모든 시점에서 파라미터가 공유됨

 

https://medium.com/@infin94/understanding-the-seq2seq-model-what-you-should-know-before-understanding-transformers-e5891bcd57ec

 

위 그림과 같이 인코더의 마지막 은닉 벡터가 디코더로 전달되어 두 부분을 연결합니다.

  • 은닉 벡터를 Context Vector라고 부르는데 입력 문장의 전체 맥락 정보를 담고 있기 때문
  • Context Vector는 인코더가 입력 시퀀스의 정보를 압축한 것으로, 디코더가 번역문을 생성할 때 참조하는 핵심 정보
  • 디코더는 이 Context Vector를 기반으로 번역을 수행하며 <sos> 토큰으로 시작해 다음 토큰을 순차적으로 예측하는 방식으로 번역문을 생성
  • 이 과정은 앞서 다룬 "다음 토큰 예측" 방식과 유사하기 때문에 Seq2seq의 디코더를 Next Token Predictor라고 부를 수 있음

 

Seq2seq 모델은 학습 시와 테스트 시와 다르게 동작하며 이는 앞서 설명한 자동 완성 AI의 동작 방식과 유사합니다.

  • 학습 과정: 학습 시에는 Teacher Forcing이라는 기법을 사용하며 해당 방법에서는 디코더에 전체 정답 문장을 한 번에 입력으로 제공
    • Teacher Forcing이라고 부르는 이유는 마치 선생님이 학생에게 정답을 알려주는 것처럼 모델에게 정확한 이전 단어를 제공
    • 이에 따라 모델이 올바른 맥락에서 학습할 수 있게 해 주며, 학습 속도를 높이는 장점이 있음

 

  • 추론 과정: 실제 사용 시에는 인코더가 입력 문장으로부터 Context Vector를 생성하고, 디코더는 이를 바탕으로 <sos> 토큰부터 시작하여 하나씩 토큰 생성
    • 추론 시에는 Teacher Forcing을 사용하지 않고 생성된 각 토큰을 다음 토큰 예측을 위한 입력으로 사용

 

6.1 Seq2seq의 문제점

  • 순차적으로 토큰을 생성하는 방식을 가지므로 초기에 잘못된 예측 발생 시 이후의 모든 예측에 영향을 미칠 수 있음
    • Seq2seq 뿐만 아니라 대부분의 순차적 생성 모델이 가지고 있는 공통적인 문제

 

  • Seq2Seq은 두 개의 RNN을 연결한 구조이므로, RNN의 주요 한계점도 그대로 가지고 있음
    • "멀수록 잊혀지는" 문제로 인해 디코더에서 Loss와 멀리 있는 입력 토큰이 그래디언트에 미치는 영향력이 작아지며 특히 인코더의 파라미터들은 디코더의 첫 입력보다도 더 멀리 위치하여 학습이 더욱 어려움
    • "정보가 뭉개지는" 문제도 가지고 있어 Context Vector에 문장의 정보를 효과적으로 담아야 하는데, 이 과정에서 문제가 발생함
      • "I have to know why"라는 문장에서 Context Vector에는 "why"라는 정보가 가장 뚜렷하게 담기고 "I"의 정보는 가장 뭉개져 담기게 됨
      • 위와 같은 한계로 인해 Seq2seq 모델은 번역 시 입력 문장의 마지막 단어에 과도하게 의존하게 됨
      • ex) "저는 강사입니다"를 번역할 때, "I"를 출력할 때는 "저는"에, "instructor"를 출력할 때는 "강사"에 주목해야 하지만 실제로는 "입니다"의 정보가 가장 뚜렷하게 담긴 Context Vector를 사용하게 됨에 따라 사람의 번역 방식과 거리가 멀어짐

 

위와 같은 한계를 극복하기 위해 새로운 접근 방식이 필요했고, 여기서 Attention 메커니즘이 등장하게 됩니다.

 

7. Attention: 시점마다 다른 Context Vector의 사용

Attention은 RNN 구조의 한계를 극복하는 데 큰 역할을 한 혁신적인 방법이며 Attention의 발전 과정은 자연어 처리 기술에 큰 변화를 가져왔습니다.

  • 초기에는 RNN 구조에 Attention 개념을 도입하여 성능을 크게 향상함
  • 이후 "Attention is all you need"라는 논문의 제목에서 알 수 있듯이 트랜스포머는 여기서 한 걸음 더 나아가 RNN 구조를 완전히 탈피하고 Attention의 사용을 극대화함
  • 이로 인해 자연어 처리 분야는 비약적인 성능 발전을 이루게 되었고, 복잡한 언어 처리 작업에서 놀라운 성과를 거두며 현대 자연어 처리 기술의 기반을 마련함

 

책에서 제시하는 Attention 메커니즘은 Luong Attention의 핵심 아이디어를 바탕으로 하되, 설명의 편의와 이해의 용이성을 위해 일부 단순화된 형태로 표현되어 있습니다.

 

Attention이 기존의 방식과 가장 크게 다른 점은 Context Vector가 출력 시점마다 달라진다는 것입니다.

  • 기존의 Seq2seq 모델에서는 컨텍스트 벡터 c가 모든 시점에서 동일 (모든 c가 마지막 인코더의 마지막 은닉 벡터와 동일)
  • 반면, Attention 메커니즘은 매 시점마다 다른 Context Vector를 생성
  • 이렇게 시점마다 다르게 생성된 Context Vector는 각 시점의 출력을 계산할 때 사용되며 구체적인 계산 과정은 다음과 같음

 

https://www.genspark.ai/
https://www.genspark.ai/

 

정리하면 Attention 메커니즘에서는 각 시점의 Context Vector가 추가로 출력 계산에 관여하며 이렇게 각 시점마다 다른 Context Vector를 사용함으로써 Attention 메커니즘은 디코더가 출력을 생성할 때 입력 시퀀스의 정보를 더 유연하게 활용할 수 있게 합니다.

 

7.1 Attention: Context Vector 만들기

Attention 메커니즘에서 Context Vector를 만드는 과정을 이해하기 위해서는 먼저 인코더의 은닉 벡터를 바라보는 관점의 전환이 필요합니다.

편의상 '저는' (x_1), '강사' (x_2), '입니다' (x_3)가 인코더에 들어왔고 은닉 벡터가 3개 (h_1, h_2, h_3)가 있다고 가정하겠습니다.

  • 기존 RNN에서는 h_3을 x_1, x_2, x_3의 정보를 모두 담은 '문장 벡터'로 해석
  • 그러나 Attention에서는 각 은닉 벡터의 본분을 '개별 단어를 잘 표현하는 것'으로 봄
  • 이러한 새로운 시각에서 h_1, h_2, h_3는 각각 '저는', '강사', '입니다'를 벡터 공간에서 표현하는 워드 임베딩 벡터 (Word Embedding Vector)로 볼 수 있음
    • 워드 임베딩 벡터는 각 단어의 의미와 특성을 고차원의 벡터 공간에 embed, 즉 '박아 넣는' 역할을 하는 벡터
    • h_1의 본분은 '저는'을, h_2의 본분은 '강사'를, h_3의 본분은 '입니다'를 벡터 공간에 잘 표현하는 것이며 이는 각 은닉 벡터가 해당 단어의 의미와 특성을 잘 포착해야 한다는 것을 의미
    • 앞서 h_3에는 분명 x_1, x_2, x_3가 모두 담겨있다고 언급했기 때문에 '입니다'만을 표현하는 벡터라는 것이 잘 이해가 되지 않을 수 있으나 이는 '입니다'를 임베딩할 때 '저는'과 '강사'의 정보도 참고했다는 것으로 이해 가능
    • 정리하면 h_3는 '입니다'라는 단어의 의미를 중심으로 하되, 이전 단어들의 문맥을 고려하여 더 풍부하고 정확한 표현을 하는 임베딩 벡터라고 볼 수 있음

 

위와 같은 관점으로 보더라도 기존 방식처럼 c_4 = h_3로 설정하는 것은 입력 문장에서 '입니다'만을 고려하는 것과 같음을 알 수 있으며 이는 여전히 전체 문장의 의미를 파악하는 데 부족하여 학습에 어려움이 따를 것이라고 직관적으로 예상할 수 있습니다.

  • 따라서 모든 단어의 의미를 담기 위해 h_1 + h_2 + h_3와 같이 모든 워드 임베딩 벡터를 더하는 방법을 고려
  • 문장 내 각 단어의 중요도가 다르기 때문에 단순히 더할 경우 어떤 단어를 더 주목해야 할지 알 수가 없음
  • 이에 따라 단순히 더하는 것이 아닌 가중합을 사용
    • c_4 = w_1 * h_1 + w_2 * h_2 + w_3 * h_3
    • 새로운 파라미터 w_1, w_2, w_3 또한 학습 가능함

 

그러나 '가중합'을 사용하는 방법에도 문제가 있습니다.

아래 그림을 예시로 들면 네 번째 출력 시점에서 'instructor'를 출력하기 위해서는 '강사'에 대한 가중치인 w_2가 커야 합니다.

하지만 '저는 딥러닝 강사입니다'와 같이 문장이 길어질 경우 '강사'의 위치가 바뀌고, c_4 = w_1 * h_1 + w_2 * h_2 + w_3 * h_3 + w_4 * h_4와 같이 가중치의 개수도 늘어나며 두 가지 문제를 야기합니다.

  • 학습 기회의 불균형: 긴 문장에서만 나타나는 가중치는 학습 기회가 적어짐
  • 학습 방향의 비일관성: '강사'의 위치가 바뀜에 따라 어떤 가중치를 높여야 할지가 달라짐
  • 이러한 불일치는 모델이 어떤 토큰을 중요하게 여겨야 할지 혼란에 빠지게 하며, 효과적인 학습이 이루어지기 어려워짐

 

혁펜하임님의 ALL DEEP DIVE 강의 내용 중 일부

 

7.1.1 가중합 문제 해결

앞서 설명한 '가중합'의 문제를 해결하기 위해서는 가중치를 고정된 파라미터가 아닌 각 단어의 함수로 만들어야 합니다.

  • 이렇게 하면 단순히 '두 번째 단어를 더 중요하게 봐라'가 아닌 "'강사'라는 단어를 더 주목해라"라는 방식으로 학습 가능
  • ex) '저는 딥러닝 강사입니다'라는 문장에서도 'instructor'를 출력하기 위해 세 번째 시점의 '강사'라는 단어가 중요하다는 것을 자연스럽게 학습시킬 수 있음

 

또한, 각 출력 시점마다 다른 Context Vector를 생성하기 위해서는 현재의 출력 시점 정보가 필요합니다.

  • 해당 정보가 없을 경우 모든 시점에서 동일한 Context Vector를 사용하게 되어 Attention의 장점을 살릴 수 없음
  • 이를 위해 디코더의 현재 은닉 상태 s를 활용하며 s는 각 시점의 출력 단어 정보를 담고 있는 워드 임베딩 벡터
  • ex) s_1은 '<sos>', s_2는 'I',..., s_5는 'instructor'의 정보를 담고 있으며 이 s를 이용함으로써 각 출력 시점에서 입력 문장의 어떤 부분에 주목해야 할지를 결정할 수 있게 됨
    • 이를 반영하여 네 번째 시점의 Context Vector를 c_4 = f(s_4, h_1)*h_1 + f(s_4, h_2) * h_2 + f(s_4, h_3) * h_3와 같이 표현할 수 있음
    • f(s_4, h_i)는 현재 시점의 임베딩 벡터 s_4와 각 입력 단어의 임베딩 벡터 h_i 사이의 '주목도'를 나타내는 함수
    • Luong Attention에서는 위 함수를 내적 (Dot Product)으로 정의하며 두 벡터의 내적을 <, >로 표기했을 경우 위 식을 c_4 = <s_4, h_1> * h_1 + <s_4, h_2> * h_2 + <s_4, h_3> * h_3로 표현할 수 있음
    • 이렇게 정의했을 경우 현재 시점이 'an'일 때, 입력 문장 중 어떤 단어를 주목하면 'instructor'를 출력할 수 있을지를 AI가 스스로 학습을 통해 깨닫게 됨
    • ex) 네 번째 시점에 대해서는 '강사'에 해당하는 <s_4, h_2> 값을 키우는 방향으로 학습이 이뤄지게 됨

 

실제로는 가중합을 하기 전에 각 단어에 대한 가중치인 <s_4, h_1>, <s_4, h_2>, <s_4, h_3>를 0과 1 사이의 값으로 표현하고, 그 합이 1이 되도록 만들기 위해 Softmax 함수를 적용합니다.

정리하면 Softmax 함수를 통과한 가중치로 가중합 하여 Context Vector를 만들며 이는 다음과 같은 이유에서 중요합니다.

  • 크기 규제: Softmax를 적용함으로써 특정 단어의 가중치가 지나치게 커지는 것을 방지하여 모델이 한 단어에만 과도하게 집중하는 것을 막아줌
  • 양수 보장: '주목도'는 개념적으로 '얼마나 중요한가'를 나타내므로, 음수가 되면 해석하기 어려움
  • 분포로 해석: 가중치의 합이 1이 되므로, 각 단어에 대한 주목도를 분포로 해석할 수 있고 이는 모델의 결정을 이해하고 해석하는데 도움이 됨

 

https://medium.com/@infin94/understanding-the-seq2seq-model-what-you-should-know-before-understanding-transformers-e5891bcd57ec

 

이러한 방식으로 Attention 메커니즘은 각 출력 시점에서 입력 문장의 어떤 부분에 주목해야 할지를 효과적으로 학습할 수 있게 합니다.

 

7.2 Attention의 학습 원리와 해석

  • Attention 메커니즘은 현재 시점의 Context Vector를 만들 때 어떤 단어에 더 주목하고, 어떤 단어는 덜 고려해야 할지를 학습
  • 이때, Attention의 가중치를 구하는 방법으로 내적을 사용하는 이유는 내적이 두 벡터의 '닮은 정도'를 나타내는 좋은 척도이기 때문
    • ex) 디코더의 현재 시점의 워드 임베딩 벡터 s_4와 인코더의 워드 임베딩 벡터들인 h_1, h_2, h_3가 벡터 공간에 존재할 때, 네 번째 시점에서 h_2가 중요하다면 <s_4, h_2>와 같이 커지도록 학습이 이루어지며 이는 s_4와 h_2를 벡터 공간상에서 서로 가까워지게 만드는 과정

 

  • 주목할 점은 가중치 값 자체를 직접 학습하는 것이 아니라, 벡터들을 '어디에 위치시킬지'를 학습한다는 것
    • 디코더에서 s_4를 만들거나 인코더에서 h_2를 만들 때, 입력 토큰에 웨이트 행렬을 곱하여 만듦
    • 따라서 이 웨이트 행렬을 학습한다는 것은 곧 입력 토큰 벡터 (One-Hot 벡터)를 벡터 공간의 어느 위치로 이동시키는 것이 좋을지를 결정하는 것과 같음
    • ex) 네 번째 시점에서 'instructor'를 출력해야 한다면, 모델은 s_4와 '강사'를 임베딩한 벡터가 서로 가까운 곳에 위치하도록 파라미터를 업데이트시킬 것이며 이렇게 함으로써 'instructor'를 출력할 때 '강사'라는 단어에 더 주목하게 됨
    • 흥미로운 사실은 디코더가 Next Token Predictor로 작동하기 때문에 실제로 가까워지도록 학습되는 것은 'instructor'와 '강사'가 아닌, 'an'과 '강사'라는 점
      • 앞선 예제에서 s_4와 h_2가 서로 가깝게 되도록 학습될 것이라고 예상했고 여기서 s_4는 'an'을 임베딩하는 벡터이고, h_2는 '강사'를 임베딩하는 벡터이므로 이러한 현상이 발생
      • 결과적으로 'an' 다음에 오기에 적합한 영어 단어에 대응하는 한글 단어들이 'an' 벡터와 가까워지게 됨

 

  • Transformer 모델에서 Attention 메커니즘은 입력 토큰들 사이의 상관관계를 효율적으로 학습하기 위한 핵심 구성 요소이며 Attention 메커니즘을 이해하려면 Query 벡터, Key 벡터, 그리고 Value 벡터가 각각 어떤 역할을 수행하는지 살펴보는 것이 중요
    • Query 벡터: 한 문장에서 특정 단어가 문맥상 다른 단어와 어떻게 관계 맺고 있는지를 찾으려 할 때, 그 “기준이 되는 단어”의 내적 표현
    • Key 벡터: Query 벡터가 “누구에게 주목해야 하는가?”를 묻는 역할을 한다면, Key 벡터는 “나는 이런 정보를 가지고 있어요!”라고 알려주는 역할
    • Value 벡터:  Query 벡터와 Key 벡터를 통해 “누구에게 주목할지”를 정했으면, 그 토큰들에게서 가져올 정보를 최종적으로 모아서 새로운 표현으로 만드는 역할을 담당
    • 위 세 벡터는 서로 내적 연산과 Softmax를 거쳐 Attention 가중치를 생성하고, 이 가중치로 Value 벡터들을 가중 합하여 최종 문맥 벡터를 산출함
      • 이 과정을 통해 모델은 입력 토큰들 간의 중요한 연관관계를 학습하고, 특정 토큰이 필요로 하는 문맥 정보를 동적으로 조정하여 더 풍부한 표현을 만들어 냄

 

https://pub.towardsai.net/self-attention-in-transformers-computation-logic-and-implementation-ae5072b60abc

 

7.3 RNN + Attention의 두 가지 문제점

Attention 메커님즘의 도입은 RNN을 기반으로 한 Seq2seq 구조의 성능을 비약적으로 향상시켰지만 해당 방식에도 여전히 두 가지 개선 포인트가 남아있었습니다.

  • `멀수록 잊혀진다`는 RNN의 근본적인 문제가 디코더 부분에서 여전히 존재한다는 점과
  • 의미를 제대로 담지 못한 워드 임베딩 벡터에 Attention을 적용한다는 것

 

7.3.1 디코더의 `멀수록 잊혀진다` 문제

  • Loss와 시간적으로 멀리 떨어진 디코더의 입력 토큰은 해당 시점의 Loss의 그래디언트에 미치는 영향력이 여전히 작음
    • 다만, Attention의 도입으로 인코더 부분에서는 해당 문제가 상당 부분 완화됨

 

https://www.genspark.ai/
https://www.genspark.ai/

 

https://www.genspark.ai/

 

내용을 정리하면 다음과 같습니다.

  • 인코더의 경우 모든 은닉 상태에 대해 가중치 기반의 접근을 가능하게 하여, 원래 RNN의 순차적 제약 없이 먼 시점의 정보까지 효과적으로 활용하지만
  • 디코더는 여전히 순차적 특성 (즉, 오래된 토큰이 잊혀짐)에 의존하므로, `멀수록 잊혀진다`는 문제가 완전히 해결되지 않음

 

7.3.2 의미를 제대로 담지 못한 워드 임베딩 벡터에 Attention을 적용하는 문제

  • 기본 Seq2seq 구조는 단어의 의미를 효과적으로 임베딩하는 데 한계 존재
    • 정확한 번역을 위해서는 단어가 사용된 맥락을 정확히 파악해야지만 RNN 구조에서는 이러한 맥락 정보를 완벽히 포착하기 어려움 
    • ex) `쓰다`는 문맥에 따라 여러 가지 의미를 가질 수 있음
      • "돈을 쓰다" -> `spend`
      • "글을 쓰다" -> `write`
      • "모자를 쓰다" -> `put on` 혹은 `wear`
      • "맛이 쓰다" -> `bitter`
    • `쓰다`가 문장의 일곱 번째 토큰으로 입력되고, `돈을`이 첫 번째 토큰으로 입력되었다고 가정했을 때 이상적으로 h_7이 `소비하다`라는 의미를 정확히 담아야하지만 RNN의 특성상 x_1의 정보가 일곱 번째 시점까지 가면서 뭉개져 온전히 전달되기 어려움
      • 결과적으로 `쓰다`라는 단어가 일곱 번째 시점까지 잘 전달되지 않아 h_7은 `쓰다`의 정확한 의미를 제대로 파악하지 못할 가능성이 높음
      • 따라서 Attention 메커니즘을 통해 Context Vector를 만들 때 h_7에 높은 가중치를 부여핟러ㅏ도, 이를 `spend`로 정확히 번역하기 어려움

 

정리하면 Attention 메커니즘의 접근 방식이 매우 훌륭함에도 불구하고, 애초에 워드 임베딩 벡터가 단어의 의미를 제대로 담지 못하면 전체적인 학습 과정에 어려움이 따를 수 있음을 시사합니다.

 

7.3.3 불완전한 해결책: Bidirectional RNN

위에 거론된 문제를 해결하기 위해 입력 시퀀스를 양방향으로 처리하여 각 단어의 앞뒤 문맥을 모두 고려하는 Bidirectional RNN이 제안되었지만 여전히 한계가 존재했습니다.

  • 양방향으로 정보를 처리하지만, 여전히 RNN의 기본 구조를 사용하기 때문에 거리가 먼 토큰의 정보를 효과적으로 활용하는 데 한계 존재
  • 시점을 이동하며 입력 토큰의 정보를 하나씩 담는 방식은 불가피하게 거리에 영향을 받을 수 없어, 역방향으로 처리할 때도 멀리 있는 토큰의 정보를 온전히 반영하기 어려움
    • ex) "The musician draws, with his soulful melodies and heartfelt lyrics, a large crowd of fans"라는 문장이 주어졌을 때 `draws`의 정확한 의미를 파악하기 위해서는 문장의 끝부분에 있는 `crowd`란느 단어를 고려해야 함
    • 이를 위해 Bidirectional RNN을 사용하더라도 이렇게 멀리 떨어진 정보를 효과적으로 활용하는 것은 여전히 어려운 과제

 

8. 트랜스포머의 Self-Attention

앞서 거론한 문제들은 결국 모두 RNN의 구조적 한계에서 비롯됩니다.

트랜스포머는 이러한 한계를 극복하기 위해 RNN 구조를 완전히 탈피하고, Self-Attention이라는 혁신적인 메커니즘을 도입했으며 이를 통해 문장 내 모든 단어 간의 관계를 직접적으로 고려할 수 있게 되었습니다.

  • 놀랍게도 Self-Attention은 RNN의 핵심이라고 할 수 있는 `시점을 이동하며 이전 정보를 담는 연결`을 완전히 끊어냄으로써 RNN의 두 가지 주요 문제를 동시에 해결함
  • RNN에서 거리에 따른 문제가 발생하는 근본적인 이유는 시점을 이동하며 W_h와 같은 웨이트 행렬이 게속해서 곱해지는 구조이기 때문인데 트랜스포머는 이러한 연결을 모두 끊어내어, 각 워드 임베딩 벡터가 초기에는 다른 토큰을 참조하지 않고 독립적으로 생성되도록 함
  • ex) `돈을 쓰다`라는 문장에서 `쓰다`에 해당하는 임베딩 벡터는 처음에는 오직 `쓰다`라는 토큰만을 고려하여 생성됨
  • 다만, 이렇게 연결을 끊음에 따라 각 토큰의 위치 정보도 함께 소실되는데 트랜스포머는 해당 문제를 해결하기 위해 위치 인코딩 (Position Encoding)이라는 기법을 사용하여 각 토큰의 임베딩 벡터에 해당 토큰의 위치 정보를 추가함에 따라 모델이 토큰의 순서를 인식할 수 있게 해줌

 

이렇게 독립적으로 생성된 초기 임베딩 벡터는 문백 정보를 담을 수 없기 때문에 트랜스포머는 워드 임베딩 벡터를 점진적으로 쇄신해 나가는 방식을 채택합니다.

  • 이를 위해 도입된 핵심 메커니즘이 바로 Self-Attention이며 Self-Attention은 인코더와 디코더 각각이 자신이 가진 임베딩 벡터들에 대해 Attention을 수행하는 과정을 지칭
  • ex) `저는 강사입니다`라는 문장이 주어졌을 때 최초 임베딩된 h_1, h_2, h_3는 각 토큰만을 보고 임베딩한 벡터이며 Self-Attention을 수행하여 새로운 임베딩 벡터 h_new를 얻음
    • 예를 들어 h2_new는 <h_2, h_1> * h_1 + <h_2, h_2> * h_2 + <h_2, h_3> * h_3와 같이 계산됨
    • 이 과정에서 h_2는 Query 벡터가 되어 `강사`를 잘 임베딩하기 위해 주변 단어에 query 즉, `질문`을 함
    • 주변 단어인 h_1, h_2, h_3는 Key 벡터이자 Value 벡터가 되어, 어떤 단어에 주목할지 가중치를 결정하고 해당 가중치를 바탕으로 Value Vector 간의 가중합을 구함으로써 `강사`라는 토큰의 워드 임베딩 벡터를 주변 단어를 고려하여 쇄신함
    • 위 과정은 문장의 맥락을 파악하여 해당 단어의 의미를 더 정확하게 이해하는 것과 같음
    • 또한, RNN과 달리 모든 위치의 단어들을 동시에 처리할 수 있어 병렬 연산이 가능하며, 거리에 관계없이 모든 단어 간의 관계를 직접적으로 고려할 수 있음

 

https://alvinntnu.github.io/NTNU_ENC2045_LECTURES/nlp/dl-attention-transformer-intuition.html

 

  • 디코더 역시 Self-Attention을 수행하는데 인코더와 달리 학습 시와 테스트 시의 동작 방식이 다름
    • 디코더는 학습 시에는 Teacher Forcing 방식을 사용하며 이는 정답 문장을 입력으로 제공하는 방식이므로 네 번째 시점의 워드 임베딩 벡터를 구할 때 미래 시점인 다섯 번째 시점의 임베딩 벡터 s_5도 활용할 수 있음
    • 반면, 테스트 시에는 이전 토큰의 출력만을 활용할 수 있기 때문에 네 번째 시점에서는 네 번째 시점까지의 정보만을 사용할 수 있음

 

  • 위와 같은 차이를 모델에 반영하지 않을 경우 테스트 시 성능이 크게 저하될 수 있으며 이유는 다음과 같음
    • 학습 시: 모델이 `다음 토큰은 무엇일까?`를 예측하는 것을 학습 시 `근데 다음 토큰의 임베딩 벡터는 s_5야`라는 정보를 받기 때문에 모델은 s_5에 과도하게 의존하도록 학습될 수 있음
    • 테스트 시: 모델은 다서 번째 토큰의 정보를 모르는 상태에서 s4_new를 생성해야하는데 학습 시 크게 의존했던 s_5 정보가 없어 성능이 급격하게 떨어짐
    • 이러한 불일치를 해결하기 위해 디코더의 Self-Attention에서는 `마스킹` 기법을 사용하며 해당 기법을 적용하면 s4_new는 <s_4, s_1> * s_1 + <s_4, s_2> * s_2 + <s_4, s_3> * s_3 + <s_4, s_4> * s_4와 같이 계산하여 학습 시에 미래 시점을 참조하지 못하도록 강제함
      • 이렇게 미래 시점의 정보를 사용하지 않도록 미래 시점에 해당하는 가중치를 0으로 만드는 방식의 Self-Attention을 Masked Self-Attention이라고 함

 

https://pytorch.org/blog/interactive-chat-gen-model/

 

실제 트랜스포머 모델에서는 임베딩 벡터의 쇄신은 한 번으로 끝나지 않고 여러 인코더 레이어와 디코더 레이어를 거치면서 임베딩 벡터를 지속적으로 업데이트합니다.

특히, 디코더에서는 각 레이어마다 Self-Attention을 수행한 뒤 Context Vector도 갱신합니다.

  • ex) 네 번째 시점에서 Context Vector는 c4_new = <s4_new, h1_new> * h1_new + <s4_new, h2_new> * h2_new + <s4_new, h3_new> * h3_new와 같이 계산됨
  • 여기서 Query 벡터인 s4_new는 디코더의 각 레이어마다 갱신되는 임베딩 벡터를 사용하며
  • h1_new, h2_new, h3_new는 인코더 레이어를 모두 통과한 최종 임베딩 벡터를 사용
  • 이렇게 디코더의 Query 벡터와 인코더의 Key, Value 벡터를 사용하여 Context Vector를 생성하는 과정을 Encoder-Decoder Attention이라고 부름

 

https://jalammar.github.io/illustrated-transformer/

 

정리하면, 트랜스포머는 RNN의 주요 한계점들을 다음과 같이 해결했습니다.

  • `갈수록 뭉개지는` 현상으로 인해 디코더가 입력 문장의 마지막 단어에만 집중하는 문제는 Encoder-Decoder Attention으로 완화
  • `멀수록 잊혀지는` 현상으로 인한 디코더 파라미터 학습의 어려움은 디코더의 Self-Attention으로 해결
  • `의미를 제대로 담지 못한 워드 임베딩 벡터에 Attention`하는 문제는 인코더의 Self-Attention으로 개선

 

위와 같은 혁신적인 구조 덕분에 트랜스포머는 긴 문장을 처리할 때도 우수한 성능을 보이며, 병렬 처리가 가능해 학습 속도도 크게 향상했고 트랜스포머의 등장은 자연어 처리 분야에 혁명을 일으켰으며, 그 영량력은 AI 산업 전반으로 확산되었습니다.

 

참고

혁펜하임의 Easy! 딥러닝

반응형