DevOps··2분 읽기·0

5. 조립: 토큰이 쌓이고 레이어가 깊어지는 과정

어텐션과 FFN을 조립하는 과정

글꼴

3편에서 어텐션을, 4편에서 FFN을 각각 "OOM" 하나로 이해했다. 부품의 동작 원리는 파악했다. 이번 편에서는 이 부품들을 조립한다. 토큰이 5개로 늘어나고, 레이어가 36개 쌓이면 어떤 일이 벌어지는가?


어텐션과 FFN — 하나의 레이어를 이루는 두 부품

이 둘은 하나의 레이어 안에서 순서대로 실행된다.

┌──────────────────────────────────────────────────┐
│                   하나의 레이어                      │
│                                                    │
│  ┌──────────────┐         ┌──────────────┐        │
│  │   어텐션       │   →    │     FFN      │        │
│  │              │         │              │        │
│  │ ● 토큰 간 연산  │         │ ● 토큰별 독립   │        │
│  │ ● "누가 누구와  │         │ ● "이게 무슨    │        │
│  │   관련있나"    │         │   의미인가"    │        │
│  │ ● 관계 파악    │         │ ● 의미 변환    │        │
│  └──────────────┘         └──────────────┘        │
│                                                    │
│  인풋: 벡터(2048)          인풋: 벡터(2048)          │
│  아웃풋: 벡터(2048)         아웃풋: 벡터(2048)         │
│                                                    │
│  각 부품 전후에 LayerNorm + 잔차 연결 적용 (4편)       │
└──────────────────────────────────────────────────┘

어텐션은 "killer"가 "OOM"과 관련 있다는 관계를 파악한다. 가로 연결이다. FFN은 관계가 파악된 벡터를 "메모리 부족 상황"이라는 의미로 변환한다. 세로 깊이다. 인풋/아웃풋 차원이 항상 동일(2048)이니까 이 레이어를 몇 개든 쌓을 수 있다.


5개 토큰이 36개 레이어를 동시에 통과한다

"OOM killer가 nginx를" = 5개 토큰. 이 5개가 한꺼번에 레이어 1에 들어가고, 레이어 1의 출력이 레이어 2에 들어가고... 레이어 36까지 통과한다.

임베딩 벡터 5개 (각 토큰의 개별 의미만, 문맥 없음)


┌─ 레이어 1 ───────────────────────────────────┐
│  어텐션: 5개 토큰이 동시에 서로 참조             │  문법 구조 파악
│  FFN: 각 벡터를 독립적으로 의미 변환               │
│  (LayerNorm + 잔차연결 포함)                     │
└───────────────────────────────────────────────┘
    │  벡터 5개 (1차 문맥 반영)

┌─ 레이어 2 ───────────────────────────────────┐
│  어텐션: 이미 1차 문맥이 담긴 벡터들 사이에서       │  의미 부여
│          더 깊은 관계를 계산                       │
│  FFN → (LayerNorm + 잔차연결)                    │
└───────────────────────────────────────────────┘
    │  벡터 5개 (2차 문맥 반영)
    ▼  ...36개 레이어...
┌─ 레이어 36 ──────────────────────────────────┐
│  어텐션 → FFN                                    │  고차 추론
└───────────────────────────────────────────────┘


최종 벡터 5개 (각 2048차원, 풍부한 문맥)

모든 레이어가 동일한 구조이지만, 각 레이어의 W는 전부 다른 파라미터다. 사람이 설계한 게 아니라 학습 결과로 역할이 분화된다. 앞쪽이 문법, 뒤쪽이 의미와 추론.

레이어 수도 모델마다 다르다. 3B는 약 36개, 7B는 약 32개, 14B는 약 48개. 더 많은 레이어는 더 깊은 추론을 의미한다.


인과적 마스킹 — 동시에 넣어도 미래를 못 본다

그런데 5개를 "동시에" 넣으면, 뒤에 있는 토큰의 정보가 앞 토큰에 새어 들어가지 않을까?

그렇게 되면 안 된다. LLM의 학습 목표는 "다음 토큰 예측"이다. 미래를 볼 수 있으면 답을 보고 시험 치는 것과 같다. 이걸 보장하는 게 인과적 마스킹이다.

어텐션 계산 시 각 토큰이 볼 수 있는 범위:
 
Q ↓ \ K →    OOM    killer    가    nginx    를
─────────   ─────  ──────  ─────  ─────  ─────
OOM         ○       ✕       ✕       ✕      ✕
killer      ○       ○       ✕       ✕      ✕
가          ○       ○       ○       ✕      ✕
nginx       ○       ○       ○       ○      ✕
를          ○       ○       ○       ○      ○
 
○ = 참조 가능    ✕ = 마스킹 (-∞ → softmax 후 0)
→ 하삼각(lower triangular) 행렬.

✕ 위치에 -∞를 넣으면 softmax를 거친 후 주목도가 0이 된다. 미래 토큰의 V는 가중합에 반영되지 않는다.

이 마스크 덕분에 "OOM"의 어텐션 결과는 뒤에 killer가 있든 없든 동일하다. 5개를 동시에 넣어도 1개씩 순차적으로 넣은 것과 같은 결과가 보장된다. GPU가 5개를 병렬로 한 번에 처리할 수 있는 이유이기도 하다.


벡터에서 토큰으로 — 출력 행렬

36개 레이어를 통과한 최종 벡터 5개가 나왔다. 다음 토큰을 예측하려면 이 벡터를 토큰으로 바꿔야 한다.

최종 벡터 (마지막 토큰 "를" 위치, 2048차원)

    ▼  × 출력 행렬 (2048 × 151,936)


151,936개의 점수 (어휘 전체에 하나씩)

    ▼  softmax


확률 분포:
  "종료시켰다"   23%  ◀── 가장 높음
  "메모리"       15%
  "해당"          8%
  "OOM"           6%
  ...
  나머지 15만개  각 0.001% 미만

왜 "마지막 토큰 위치"의 벡터만 사용하는가? 인과적 마스킹 덕분에 마지막 토큰의 벡터에 이전 모든 토큰의 정보가 누적되어 있다. 이 벡터 하나가 문장 전체의 문맥을 담고 있다.

출력 행렬과의 행렬곱으로 점수를 구하고, softmax로 확률로 바꾸고, 그중에서 하나를 고른다. 벡터 공간에서 "가장 가까운 토큰"을 찾는 게 아니라, 행렬곱으로 점수를 직접 계산하는 거다.


1편의 "한 문장의 여행"이 여기서 완성된다

"OOM killer가 nginx를"
 
  ① 토크나이저: 텍스트 → 정수 5개                    (2편)
  ② 임베딩: 정수 → 벡터 5개 (개별 의미만)             (2편)
  ③ 5개를 한꺼번에 36개 레이어에 통과:                 (이번 편)
     레이어마다 어텐션(인과적 마스킹) → FFN → 잔차연결
  ④ 마지막 토큰("를") 위치의 최종 벡터 → 출력 행렬      (이번 편)
  → "종료시켰다" 선택
  → 이후 토큰 생성은? → 6편

그런데 "종료시켰다"가 선택된 후에는 어떻게 될까? 이제 6개 토큰이다. 앞의 5개는 이미 처리가 끝났는데, 또 6개를 통째로 36개 레이어에 넣어야 할까? 다음 편에서 이 낭비를 없애는 방법을 다룬다.

이 글이 어떠셨나요?

이 글이 도움이 되셨나요?
공유:

관련 포스트

뉴스레터 구독

새 글이 올라오면 이메일로 알려드려요.

댓글

댓글을 불러오는 중...