Transfomer (Advanced)

김동준·2025년 9월 16일

LLM

목록 보기
6/50

“Attention Is All You Need” 논문 상세 해설

핵심 포인트
구글이 2017년에 발표한 “Attention Is All You Need” 논문은 RNN 계열을 완전히 대체할 수 있는 병렬 처리 기반 시퀀스 모델을 제시하며, 이후 모든 NLP·AI 연구의 패러다임을 바꿨습니다. 이 해설에서는 논문의 주요 구성 요소를 코드 구현 관점과 수식, 직관적 설명 세 가지 측면에서 자세히 unpack 합니다.


1. 전체 아키텍처 개요

논문은 인코더(6개 레이어)–디코더(6개 레이어) 구조를 제안합니다.

  • 각 레이어는 Ordered:
    1) Multi-Head Self-Attention
    2) Add & Layer Normalization
    3) Position-wise Feed-Forward Network
    4) Add & Layer Normalization
  • 디코더 레이어는 위 순서 중 1) 대신 Masked Multi-Head Self-Attention을 사용하고, 3) 앞에 Encoder–Decoder Attention을 추가합니다[1].
# 의사 코드(pseudocode)
for layer in 1..6:
    x = LayerNorm(x + MultiHeadSelfAttention(x))
    x = LayerNorm(x + FeedForward(x))
encoder_output = x

for layer in 1..6:
    y = LayerNorm(y + MaskedMultiHeadSelfAttention(y))
    y = LayerNorm(y + MultiHeadAttention(y, encoder_output))
    y = LayerNorm(y + FeedForward(y))
decoder_output = y

2. Positional Encoding

  • 이유: Transformer는 RNN처럼 순차 처리하지 않으므로 각 토큰의 순서 정보를 별도로 주입해야 합니다.
  • 수식:
    PE(pos,2i)=sin(pos100002i/dmodel),PE(pos,2i+1)=cos(pos100002i/dmodel)PE_{(pos,2i)} = \sin\Bigl(\frac{pos}{10000^{2i/d_{model}}}\Bigr),\quad PE_{(pos,2i+1)} = \cos\Bigl(\frac{pos}{10000^{2i/d_{model}}}\Bigr)
  • 구현 포인트:
    • posi에 따라 미리 계산한 [seq_len×dmodel][seq\_len\times d_{model}] 행렬을 임베딩에 더해줌.
    • 파이토치 예시:
      pe = torch.zeros(max_len, d_model)
      position = torch.arange(0, max_len).unsqueeze(1)
      div_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model))
      pe[:, 0::2] = torch.sin(position * div_term)
      pe[:, 1::2] = torch.cos(position * div_term)
      embeddings = token_embeddings + pe[:seq_len]

3. Scaled Dot-Product Attention

  • 쿼리, 키, 값 변환:
    Q=XWQ,K=XWK,V=XWVQ = XW^Q,\quad K = XW^K,\quad V = XW^V
  • 어텐션 공식:
    Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q,K,V) = \text{softmax}\Bigl(\frac{QK^T}{\sqrt{d_k}}\Bigr)V
    • dk\sqrt{d_k} 스케일링은 큰 내적값으로 인한 softmax 기울기 소실을 방지.
scores = torch.matmul(Q, K.transpose(-2,-1)) / math.sqrt(d_k)
weights = torch.softmax(scores, dim=-1)
output = torch.matmul(weights, V)

4. Multi-Head Attention

  • 이유: 하나의 어텐션으로는 다양한 의미 관계 포착에 한계가 있어, 여러 개의 헤드를 병렬 수행
  • 수식:
    headi=Attention(QWiQ,KWiK,VWiV),MultiHead=Concat(head1,,headh)WO\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V),\quad \text{MultiHead} = \text{Concat}(\text{head}_1,\dots,\text{head}_h)W^O
heads = []
for i in range(num_heads):
    Qi = Q @ W_Q[i]
    Ki = K @ W_K[i]
    Vi = V @ W_V[i]
    head = scaled_dot_product_attention(Qi, Ki, Vi)
    heads.append(head)
multi_head = torch.cat(heads, dim=-1) @ W_O

5. Feed-Forward Network (FFN)

  • 구조: 각 위치별로 동일한 두 개의 선형 변환 + ReLU
  • 수식:
    FFN(x)=max(0,xW1+b1)W2+b2\text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2
def feed_forward(x):
    return self.linear2(F.relu(self.linear1(x)))

6. Residual Connection & Layer Normalization

  • 잔차 연결(Residual): 각 서브레이어 입력을 그대로 더해 그레디언트 통로 확보
  • LayerNorm: 각 레이어마다 정규화 수행해 학습 안정화
x = LayerNorm(x + sublayer(x))

7. Masked Attention (디코더용)

  • 목적: 디코더가 다음 단어를 미리 보지 않도록 마스킹
  • 구현: 어텐션 스코어 행렬의 미래 위치에 -inf를 더해 softmax가 0을 출력하도록 처리
mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1).bool()
scores = scores.masked_fill(mask, float('-inf'))

8. 학습 및 성능

  • 최적화: Adam, 학습률 워밍업 + 선형 감소
  • 효과:
    • 번역 태스크(WMT 2014 En→De)에서 기존 BLEU 28.4 → 41.0
    • 병렬 처리로 학습 속도 5~10배 이상 향상
    • 긴 시퀀스 처리 시 RNN 대비 명확한 성능 우위

9. 실무 구현 팁

  1. 모듈화: MultiHeadAttention, PositionwiseFFN, PositionalEncoding, TransformerEncoderLayer, TransformerDecoderLayer 등 클래스로 분리
  2. GPU 배치 처리를 위한 마스킹 및 패딩 처리
  3. 학습률 스케줄러: LambdaLR로 워밍업(warmup_steps) 적용
  4. 배치 내 문장 길이 불균형: 효율적 패딩/마스킹으로 계산 낭비 최소화

결론:
“Attention Is All You Need” 논문은 병렬성과 유연성, 성능을 모두 잡은 모델로, 이후 GPT·BERT·T5 등 전 세계 AI 커뮤니티가 활용하는 Transformer 패밀리의 출발점입니다. 주니어 개발자라면 위 구성 요소를 하나씩 코드로 직접 구현해 보고, 작은 번역기나 요약기 프로젝트를 통해 학습 흐름을 몸으로 익히길 추천합니다.

출처
[1] <지식 사전> 트랜스포머(Transformer)가 뭔데? AI 혁명의 핵심 ... https://blog.kakaocloud.com/91

profile
Story Engineer

0개의 댓글