RNN의 문제점
RNN은 과거 입력들이 계속 연결된 구조이기에,
역전파 과정에서 gradient가 계속 곱해지면서 weight가 1보다 작으면 gradient가 점점 작아져 사라지고(vanishing),
1보다 크면 gradient가 점점 커져서 폭발하게 된다(exploding).
이러한 문제는 RNN이 장기 의존성을 학습하는 데 큰 방해가 된다.
그나마 exploding 문제는 gradient clipping을 하면 되지만, vanishing gradient 문제는 RNN의 구조를 바꿔야 할 필요가 있다.
그래서 나타난 것이 LSTM이다.
LSTM(Long Short Term Memory)
기울기 소실/폭발 문제를 해결하기 위해 등장한 구조로,
핵심 아이디어는 '정보를 장기적으로 유지할 수 있는 cell state'와 'cell state를 조절 가능한 gate'를 도입한 것이다.
그리고 게이트의 종류는 세 가지가 있는데,
forget gate : 과거의 정보 중 어느 것을 잊을지
input gate : 현재 입력에서 어떤 정보를 저장할지
output gate : 최종적으로 출력할 hidden state를 조절
각 gate는 sigmoid 또는 tanh 활성화 함수를 사용해 정보를 선택하거나 통제한다.
LSTM의 구조에 의해 LSTM은 중요한 정보는 저장하고 불필요한 정보는 잊는 선택적 기억이 가능해진다. 또한 gradient 흐름이 끊기지 않게 된다.
LSTM의 장점
정보 보존이 쉽다.
하지만 주의할 점
기울기 소실/폭발 문제를 완벽히 해결한 것은 아니다. 다만 구조적으로 더 효율적인 gradient flow를 제공하는 것이다.
비슷한 다른 RNN 구조들도 있다.
GRU
LSTM보다 구조가 단순하고 gate 수가 적어 계산량이 줄고 속도가 빠르다.
peephole connections, bidirectional RNN, stacked RNN 등.. 다른 것들도 있긴 하다
요약해보자면,
RNN은 유연한 구조를 가질 수 있지만 성능이 낮다.
LSTM/GRU는 additive gate 구조로 gradient 흐름을 개선한다.
exploding 문제는 gradient clipping으로, vanishing 문제는 additive gate 연산으로 개선할 수 있다.
Seq2Seq
이 모델의 목적은, seq를 입력받아 또 다른 seq를 출력하는 것이다. 변역이나.. 이미지 캡셔닝이나.. 등등!
Encoder
입력 seq를 받아서 하나의 고정된 context vector로 압축하여 저장한다.
Decoder
위의 context vector를 바탕으로 출력 seq를 한 토큰씩 생성한다. 일반적으로 autoregressive 형식을 사용한다.
Seq2Seq with RNN
인코더 부분을, 입력 seq를 RNN에 넣어 마지막 hidden state를 context vector로 취하는 형식으로.
디코더 부분은, 위 context vector를 초기 hidden state로 사용하여 RNN을 통해 출력 seq를 한 토큰씩 생성
보통 학습 시에는 디코더의 입력으로 이전 출력이 아닌 GT를 사용하여 안정적으로 학습한다. teacher forcing 기법이다.
추론 시에는 디코더의 입력으로 이전 모델이 예측한 값을 사용한다.
이때의 문제점은, 입력 seq 길이가 긴 경우, context vector 하나로 모든 정보가 요약되기 어렵기에 정보 손실 가능성이 큰 것이다.
따라서 이를 해결할 아이디어는, 디코더의 각 출력 시점마다 새로운 context vector를 사용하는 것이다.
즉, 하나의 context vector를 고정시키는 것이 아니라 동적으로 context vector를 생성한다는 것이다.
이것이 Attention mechanism으로 이어진다.
Attention
Attention이 도입된 Seq2Seq에서는, 디코더의 각 time step에서 hidden states 전체를 동적으로 주목한다.
각 time step 마다 context vector가 달라지기에 더 풍부한 정보를 활용할 수 있다. 또한 입력 Seq이 길어져도 필요한 정보를 선택해서 볼 수 있다.
그럼 각 time step에서 context vector를 어떻게 생성하는지 보자.
일단 인코더는 각 입력 단어에 대해 hidden state를 생성할 것이다.
그리고 디코더는 현재 시점 t에서 다음 출력을 만드려 한다. 인코더의 각 hidden state와 현재 decoder 상태 st를 비교한다.
그리고 둘 사이 유사도를 계산해 얼마나 중요한지 판단한다. 이를 softmax로 정규화하여 attention weight를 얻는다.
유사도가 높을수록 중요한 것이니, 이 attention weight를 hidden state와 곱하는 가중치로 사용할 수 있을 것이다.
따라서 attention weights와 encoder hidden states를 weighted sum을 하여 context vector를 생성하는 것이다.
디코더의 가장 첫 부분에서는 인코더의 hidden state를 활용하였는데,
그 이후, 디코더 s2에서는 인코더 hidden state + 디코더 s1 를 활용해서 새로운 context vector를 생성한다.
이렇게 attention을 사용하면 병목현상이 사라지고 매 time step마다 input의 어떤 다른 부분을 볼 건지를 변경할 수 있다.
Image captioning + spatial features
입력 : 이미지, 출력 : 이미지 설명 문장
CNN의 feature map을 공간적으로 분해해서 각각을 입력 단어처럼 간주한다.
RNN decoder가 문장을 생성한다. 이렇게 하면 이미지 내 어떤 부분을 보고 해당 단어를 만들었는지 알 수 있다.
하지만 여기서도 context vector에 대한 병목현상이 발생한다. 만약 생성해야 할 출력이 엄청나게 길면 어떡할 것인가..
Image captioning with RNNs + Attention
일반적으로 이미지 캡셔닝에서는 CNN으로 이미지를 feature vec으로 변환 후, 이를 RNN의 입력으로 사용한다.
이후 attention을 적용하면, 각 time step에서 어떤 이미지 위치에 집중할지 attention weight를 계산해준다.
그래서 여기서도 attention을 위해 Alignment Scores를 도입했다.
이는 encoder(CNN) output인 z와 decoder의 초기 hidden state인 h0 사이 유사도를 계산한 결과이다.
그리고 이 alignment score에 softmax를 입혀 attention matrix를 구해낸다.
그리고 그 attention matrix를 z와 weighted sum해서 context vector를 구할 수 있다.
이렇게 하면 위와 마찬가지로, 각 time step에서 input img의 다른 부분을 보는 context vector를 생성할 수 있다.
이런 단계를 거치게 된다.
항상 context vector를 만들 때에는 a와 z(features)의 weighted sum으로 구하는 것이다.
다만 c1, c2, c3... 얘네가 달라지게 되는 이유는 a가 매번 변하기 때문이다.
위 사진을 보면, a를 구할 때 alignment scores가 필요한데, 이는 매번 z와 이전h를 weighted sum하여 만들어진다.
이 과정을 반복하며 autoregressive하게 decoder는 다음 단어를 생성한다. (물론 학습 과정에서는 GT 단어로 학습!)
이렇게 이미지의 다양한 부분에 집중할 수 있게 해주는 attention은 기존 방식보다 유연하고 성능이 좋으며, 긴 시퀀스나 복잡한 이미지에 대해 유리하다.
Temperature
Softmax에 Temperature를 도입해 분포의 sharpness를 조절할 수 있다.
T<1이면 , softmax(z/T)의 값이 몇 배가 되면서 특정 값만 강조되게 된다.
하지만 T>1이면, 분포가 거의 모든 값이 비슷하게 변화된다.
특히 dor-product attention에서는 입력 차원이 커지면 분산이 커져 numerical instability가 발생 가능하기에, 이를 막기 위해 root(dk)로 나누는 방법을 사용한다.
General Attention Layer
기본 구조 : Query q, Key k, Value v
alignment score : q * k^t
Attention weight : softmax(alignment score)
Output : sigma(alpha * v)
핵심 개념은, '내가 지금 집중해야 할 Value는 무엇인가?'를 Query와 Key간의 유사도를 통해 판단한다는 것이다.
그림을 보면, 일단 key랑 value를 x와 weight의 곱으로 구한다.
이후 q와 k의 곱으로 alignment를 구하고, 이를 softmax 시켜 attention score를 구한다.
attention score와 v의 곱, 즉 v 중 집중해야 할 곳을 찾는 과정을 거쳐 output을 낸다.
Self-Attention
위 general attention에서는 q는 디코더의 현재 hidden state, k&v는 인코더의 hidden state 전체로 봤었는데,
self attention에서는 q/k/v가 모두 입력 자체이다.
예를 들어 general attention은, "나는 학교에 간다"와 "I go to school"에서 '나'와 'I'의 관계를 보는 것이라면,
self attention은 "나는 어제 고기를 먹었다. 그것은 맛있었다."에서 '고기'와 '그것'의 관계를 보는 것이다.
그럼 이제 self attention이 왜 도입됐는지 알 수 있다.
general attention만으로는 decoder가 encoder를 참고하는, 두 개의 seq가 있는 경우만 쓸 수 있다. 예를 들어 번역 같은.
그치만 self attention으로 보고 싶은 건, 문장 내의 관계이다. 뭐 대명사가 뭘 지칭하는 건지.. 이런.
Positional Encoding
근데 얘네는 RNN처럼 순차적으로 입력한 것도 아니고, 병렬적으로 바로 넣은 것이기에 순서 정보를 파악하기가 어렵다.
하지만 seq data는 순서가 중요하기에, 위치 정보를 따로 제공해주려 한다.
짝수 index는 sin을, 홀수 index는 cos을 사용해서 식을 세울 수 있다.
이 방식을 쓰면 절대 위치 뿐만 아니라 상대 위치 정보까지 제공할 수 있다.
또한 정해진 수학적 함수이기에 굳이 학습을 하지 않아도 일반화가 잘 된다.
Masked self-attention
self attention을 할 때, 두 가지 경우가 있다.
하나는 단어 간 관계를 계산할 때, 즉 it이 앞의 무엇을 가르키는가를 볼 때.. 그럴 때는 미래 단어도 포함해서 보는 것이 유리한데,
만약 문장 생성을 할 때 쓰인다면, 미래 정보를 포함하면 안된다.
근데.. 어차피 self-attention은 자기 자신을 입력으로 받는 건데 미래정보를 포함하는지 아닌지 그걸 따질 수가 있나? 싶은데,
Transformer의 구조를 다시 잘 살펴보면,
encoder에서는 입력 문장을 self-attention으로 인코딩하고,
decoder에서는 지금까지 생성한 단어들을 self-attention으로 처리하고 encoder와 cross attention을 해서 다음 단어를 예측하기 위해 자기 자신을 입력으로 받는 self-attention이 필요한데, 여기서 치팅이 발생한다는 것이다.
self-attention에서는 입력만 보지만, 디코더에서는 그 입력이 곧 정답 문장이라는 것이다.
그래서!! 미래 토큰을 보지 못하게 인위적으로 마스킹하는 것이다.
그래서 인코더에서와 en-decoder cross attention에서는 마스킹이 필요하지 않다.
디코더에서만 필요한 것.
Multi-head self-attention
다양한 관점에서 정보를 병렬적으로 바라보기 위한 것이다.
self attention만으로는 하나의 의미 공간에서만의 관계를 계산한다.
뭐.. 문법적인 관계만 본다든가, 의미적인 관계만 본다든가 하는.
근데 문장에는 다양한 종류의 관계가 있는데, 이걸 다 표현하고 싶어서 멀티헤드어텐션을 쓰는 것이다.
그럼 근데 파라미터 개수나 연산량이 너무 많아지는 거 아냐?! 할 수도 있지만,
계산해보면 #parameters나 FLOPs는 SA나 MHSA나 똑같다.
Normalization in Transformer
BatchNorm : 배치 단위 정규화 -> 배치 사이즈 1일 때 불안정
LayerNorm : 개별 샘플의 feature 단위 정규화 -> Transformer에서 주로 사용
Transformer Encoder
PE + MHSelf-attention + LayerNorm + MLP
Transformer Decoder
PE + Masked MHSA + LayerNorm + MLP + MHA
MHA : 각 head마다 고유한 Q, K, V
GQA : 그룹별로 Q가 다르고 K, V는 공유
MQA : 모든 head가 같은 K, V 공유
'AI > 딥러닝' 카테고리의 다른 글
Pruning and Quantization (4) | 2025.06.19 |
---|---|
CNN applications and RNN (1) | 2025.06.18 |
CNN (4) | 2025.06.18 |
Numerical Stability, Optimization (1) | 2025.04.24 |
Regularization (1) | 2025.04.24 |