딥러닝

Transformers & Self-Attention 아주아주 구체적인 수식과 맥락정리 [CS224N Lecture 7 정리]

uchanee 2026. 1. 3. 21:41

 

1) 지금까지의 NLP 전략 되돌아보기: “BiLSTM + (필요하면) Attention”

2014~2017 전후로, “너무 fancy한 거 없이 잘 풀기”의 표준 레시피는 대충 이랬다.

  • 입력 문장을 **BiLSTM(양방향)**으로 인코딩해서 문맥화
  • 출력(번역/요약/생성)이 필요하면 UniLSTM 디코더로 한 토큰씩 생성
  • 그리고 Attention으로 디코더가 인코더의 정보를 필요할 때마다 “다시 조회”
    → **고정 길이 벡터로 압축해야 하는 병목(bottleneck)**을 피하려고

이 전략은 “잘 먹혔고”, 실제로 많은 태스크에서 SOTA였다.

 

그런데 오늘 강의의 포인트는 명확하다:

“문제는 같은데, recurrence(LSTM)를 빼고 새 빌딩블록으로 바꿔보자.”


2) RNN의 한계 2가지: (1) 먼 거리 상호작용이 비싸다 (2) 병렬화가 안 된다

2.1 Linear Interaction Distance 문제

RNN은 시간축으로 한 칸씩 진행하면서 hidden을 갱신한다. 그래서

  • 가까운 단어(예: “tasty pizza”)는 자연스럽게 잘 연결됨
  • 하지만 멀리 떨어진 의존성(주어-동사, 수식 관계 등)은 학습이 어려워짐

예시처럼

the chef … (긴 수식절) … was …

에서 “chef ↔ was”는 강하게 연결되어야 하는데, RNN에서는 그 정보가 가려면 중간 단어 수만큼 step을 거쳐야 한다.
결국 “멀수록 어려움”이 구조적으로 박혀있다.

 

2.2 time index 의존 → 병렬화 불가 문제

RNN의 더 치명적인 약점은 이거다.

  • ht를 계산하려면 ht이 필요
  • 즉 길이 nn이면 O(n)개의 순차 연산이 강제됨
  • GPU는 병렬 연산에 강한데, RNN은 “앞이 끝나야 뒤를 함”

그래서 길이가 길어질수록 훈련/추론이 비효율적이다.

 

(강의의 핵심 대답)
“Attention은 linear interaction(장거리 연결) 문제는 줄여주지만, recurrence 자체가 남아 있으면 병렬화 문제는 해결 못 한다.”

 


3) Recurrence 대신 Attention: “문장 안에서 단어들이 서로를 직접 본다”

그럼 질문은 이렇게 바뀐다.

“RNN을 없애고, Attention만으로 문장 표현을 만들면?”

Attention을 쓰면 직관적으로 이런 장점이 생긴다.

  • 각 토큰 임베딩은 동시에 만들 수 있음 (병렬)
  • Attention은 “전체 시퀀스”에 대해 한 번에 계산 가능 (병렬)
  • 멀리 떨어진 단어도 거리 상관 없이 한 번에 직접 참조 가능

즉 attention은
(a) 장거리 상호작용 문제 + (b) 비병렬성 문제를 같이 해결하는 방향으로 보인다.

 


4) Attention을 제일 잘 이해하는 비유: “Key-Value 저장소의 fuzzy lookup”

강의에서 정말 중요한 관점:

딕셔너리 lookup (hard)

  • query가 특정 key에 딱 맞으면 value를 가져옴

Attention lookup (soft / fuzzy)

    • query가 모든 key와 유사도를 계산
    • softmax로 “가중치(확률)”를 만들고
    • value들을 가중합(weighted sum)해서 결과를 만듦

 

  •  

이 관점 하나만 잡으면, self-attention 수식이 그냥 “조회 시스템”으로 보이기 시작한다.


5) Self-Attention 수식: Q/K/V로 “조회”를 구현한다

문장 길이 , 임베딩 차원 d. 각 토큰 임베딩을 xi∈Rd라고 하자.

5.1 Q, K, V 만들기 (선형변환)

  • Q(Query): “나는 무엇이 필요하지?”(질문)
  • K(Key): “나는 어떤 특징을 갖고 있지?”(색인)
  • V(Value): “실제로 전달할 정보”(내용)

5.2 유사도(점수) 계산 → softmax로 가중치

5.3 출력은 value의 가중합

해석(진짜 중요)
토큰 ii는 문장 전체의 토큰 j들을 “얼마나 참고할지” αij로 정하고, 그만큼 정보를 섞어서 새 표현 oi를 만든다.

 


6) 그런데 self-attention만으로는 LSTM 대체가 안 된다: “필수 보완 3가지”

강의에서 “barriers & solutions”로 딱 정리해주는 파트가 있다.

 


핵심은 이 3개를 해결해야 self-attention이 “빌딩블록”이 된다는 것.


(1) 순서 정보가 없다 → Positional Encoding 필요

Self-attention은 기본적으로 “집합(set)”처럼 동작할 수 있다.
즉 단어 multiset이 같으면 순서가 달라도 비슷한 결과를 낼 수 있는 위험이 생김.

그래서 입력에 위치 정보 pi를 더한다.

    • Sinusoidal(positional signal): sin/cos로 위치를 표현 (고정)
    • Learned positional embedding: 위치 벡터를 학습 (실전에서 흔함)

 

(2) 비선형성이 약하다 → Position-wise FFN(MLP) 필요

Self-attention의 본질은 “가중평균”이라, 그 자체만 반복하면 표현력이 부족해질 수 있다.

그래서 각 토큰 위치마다 동일한 MLP를 붙입니다(완전 병렬 가능).

보통 2-layer MLP(중간 hidden 하나) 형태로 쓴다.

 


(3) 미래를 보면 치팅이다 → Causal Masking 필요

언어모델/디코더는 yt를 만들 때 을 보면 안 된다.

그래서 score 행렬에서 미래 방향을 막는다.

    • j>ieij=−∞
    • softmax 후 αij=0이 되어 미래를 못 봄

 

정리: Positional encoding + FFN + (디코더면) Masking
이게 “최소 self-attention 블록”의 필수 요소.

 


7) Self-Attention을 GPU-friendly하게: 행렬로 한 방에 계산

토큰을 행렬로 쌓아

라고 두면,

여기서 핵심은 QK⊤N×N 행렬이라는 점.
즉 모든 토큰쌍의 관계를 한 번에 계산할 수 있고, GPU 병렬화가 잘 된다.

 


8) Multi-Head Attention: “관계를 한 종류만 보지 말자”

이제 self-attention을 “여러 개(head)”로 병렬로 돌린다.

 


직관은 간단하다

어떤 head는 주어-동사를 보고,
어떤 head는 수식 관계를 보고,
어떤 head는 엔티티 연결을 보는 식으로 “관점 분업”을 하게 만들자.

각 head ℓ\ell마다 다른 투영을 가진다.

그리고

“그냥 W를 여러 번 복사해 학습하는 거냐?”

아니고, head마다 다른 WQ,WK,WV를 학습한다고 보면 된다.
다만 보통 dk=d/h처럼 head 차원을 쪼개서 총 파라미터 규모를 비슷하게 유지한다.(구현은 한 번에 곱하고 reshape).

 


9) Scaled Dot-Product Attention: 왜 sqrt(로 나누나?

점곱 q⊤k는 차원이 커질수록 값의 스케일이 커지기 쉽고,
softmax 입력이 너무 커지면 분포가 너무 뾰족해져 gradient가 약해질 수 있다.

그래서

로 스케일링해서 학습을 안정화한다.

 


10) Transformer를 “Transformer답게” 만드는 디테일: Add & Norm

트랜스포머 다이어그램에 항상 붙는 그거:

(1) Residual connection

입력을 출력에 더해주는 skip connection.

    • gradient가 identity 경로로 잘 흐름
    • 깊게 쌓아도 학습이 쉬워짐(ResNet 철학)

 

(2) LayerNorm

각 토큰 벡터 x∈Rd에 대해 (토큰 단위로)

중요 포인트:

    • 문장 전체가 아니라 “토큰 벡터 하나” 기준
    • 배치 간 통계 공유도 안 함 (BatchNorm과 대비)

11) Transformer 구조 정리: Decoder / Encoder / Encoder-Decoder

 

 

11.1 Transformer Decoder (언어모델)

블록 1개는 보통:

  1. Masked Multi-Head Self-Attention
  2. Add & Norm
  3. FFN(MLP)
  4. Add & Norm

이 블록을 여러 층 쌓고, 마지막에 다음 토큰 분포를 예측한다.

 

11.2 Transformer Encoder

Decoder와 거의 같은데,

    • 마스킹이 없다(양방향 문맥)
    • 입력을 “이해/인코딩”하는 용도

11.3 Encoder–Decoder Transformer (원 논문 번역 구조)

Decoder에 cross-attention이 추가된다.

  • Query: 디코더 쪽
  • Key/Value: 인코더 출력 쪽

즉 “번역문 생성하는 현재 토큰”이 “원문 전체 표현”을 조회하면서 생성하는 구조.

 


12) Transformer가 세상을 먹은 이유: 성능 + 병렬화 + 스케일

강의가 강조하는 진짜 포인트는 이거다.

    • RNN은 병렬화가 안 돼서 큰 데이터/큰 모델로 가기 힘듦
    • Transformer는 attention/FFN이 병렬화가 잘 돼서 학습이 매우 효율적
    • 그래서 “더 큰 모델 + 더 큰 데이터”를 돌릴 수 있었고,
    • 그 위에서 pretraining 혁명이 폭발적으로 진행됨

13) 단점/연구 이슈: O(n²) 비용과 긴 문맥

Self-attention은 토큰쌍을 다 보니까 score가 N×N
즉 비용이 O(n²)로 커진다..

 

  • 짧은 문장(예: 30토큰)이면 괜찮지만
  • 긴 문서(수만 토큰)로 가면 계산/메모리가 급격히 커짐

그래서 efficient attention(희소화, 저랭크 근사 등) 연구가 많고, 강의에서도 대표 예시를 언급한다.

 

또 흥미로운 관찰도 있다.

    • 모델이 커질수록 attention보다 FFN 쪽이 연산 비중이 더 커지는 경향이 언급됨
      → “그럼 attention O(n²)를 줄이는 게 절대선인가?”는 열려 있는 문제로 남아 있다.

 

마지막으로 “수많은 변형이 나왔지만, 원본 Transformer가 여전히 강하다 / 수정이 항상 이득을 주진 않는다”는 메시지도 후반부에 등장한다.


마무리

    1. RNN은 장거리 의존성이 어렵고, 무엇보다 병렬화가 안 됨
    2. Attention은 토큰 간 관계를 한 번에 계산해 장거리 연결 + 병렬화에 유리
    3. Attention은 “Key-Value 저장소의 soft lookup”으로 이해하면 쉽다
    4. Self-attention은 QK⊤→softmax→VQK^\top \to \text{softmax} \to V 흐름
    5. LSTM 대체를 위해 positional encoding / FFN / masking이 필수
    6. Transformer는 MHA + Add&Norm + FFN을 쌓은 표준 구조, 단 O(n²) 한계가 있다