1. 자연어 처리 기초
1.1 학습 목표
1.1.1 GPT-3 등장
하나의 모델로 다양한 업무를 하려는 흐름
Pretrain → Transfer
Few-shot / Zero-shot
RNN/LSTM의 한계를 Attention 으로 해결
1.1.3 NLP의 핵심 난제
순서가 의미를 바꿈
단어 하나 변화가 의미 및 라벨을 뒤집음 (ex: “안”)
토큰화와 OOV(사전에 없는 단어)가 실무 난이도를 크게 좌우
1.1.4 기초 수식
언어 모델 확률(체인 룰)
내적 = 유사도
softmax가 확률이 되는 이유
1.2 GPT-3
1.2.1 GPT-3 방향성
Task마다 모델을 새로 만들고 라벨을 많이 모아 학습하는 방식은 비용이 큼
큰 모델을 미리 학습(Pretrain)해두고, 적은 예시(Few-shot) 또는 예시 없이(Zero-shot) 다양한 Task를 수행하게 하려는 방향
1.2.2 GPT-3 핵심 동기
Transformer가 번역에서 성공 → “Transformer 구조로 더 잘할 수 없을까?”
Task 및 Domain이 바뀌면 성능이 떨어지는 문제
다양한 데이터로 미리 학습하면 새로운 Task 적응이 쉬워진다로 개념 발전
Attention
Positional Encoding
1.3.1 Self-Attention
문장 안의 각 토큰이 문장 내 다른 토큰들을 참고해서 자기 표현을 업데이트
토큰 i의 새 표현 = (토큰 1을 보는 비율)*v1
+ (토큰 2를 보는 비율)*v2
+ ...
+ (토큰 n을 보는 비율)*vn
1.3.2 Positional Encoding
Transformer는 구조적으로 순서 정보가 자동으로 들어가지 않음
토큰 위치 정보를 숫자 벡터로 추가해서 순서를 인지하게 만들어야 함
1.4 데이터 관점 비교
1.4.1 Tabular vs Vision vs NLP
구분 Tabular(테이블) Vision(이미지) NLP(자연어) 핵심 구조 피처(열) 기반 픽셀 로컬리티 (근처가 중요) 토큰 순서/의존성 (멀리도 중요) 위치 변화 영향 보통 “열 의미 고정” 이동해도 비슷(완전 불변은 아니지만 CNN이 강함) 위치 바뀌면 의미 크게 변함 작은 변화의 영향 열 하나 변화는 보통 점진적 픽셀 1개 변화는 대체로 영향 작음(일반적) 단어 1개(“안”)가 라벨 뒤집기도 대표 모델 가정 독립/약한 상관 가정이 쉬움 locality, (translation) equivariance long-range dependency, order-sensitive
1.5 토큰화
1.5.1 토큰화란
문장을 모델이 먹을 수 있는 단위로 쪼개고 각 조각을 숫자로 바꾸는 과정
1.5.2 토큰화 단위
Character
예: 나는 → [나, 는]
장점: OOV 거의 없음
단점: 길이 폭증, 의미 단위가 약함
Space
예: I love apples → [I, love, apples]
장점: 단순함
단점: “tokenization!” vs “tokenization” 같은 변형에 취약, 한국어는 공백이 의미 단위와 안 맞는 경우가 많음
Punctuation
구두점 기준 분리
장점: 일부 개선
단점: 근본 해결은 아님
Subword
예: unbelievable → [un, believe, able]
OOV를 크게 줄이면서 길이 폭증도 완화
대표: GPT 계열(BPE), BERT 계열(WordPiece)
1.6 언어 모델
1.6.1 문장 확률
체인 룰(Chain Rule)로 분해
문장을 단어들의 나열로 보면 길이 (T)인 문장은 다음처럼 표현 가능
( W 1 , W 2 , … , W T ) (W_1, W_2, \ldots, W_T) ( W 1 , W 2 , … , W T )
문장 전체 결합확률은 체인 룰로 다음처럼 분해
P ( W 1 , W 2 , … , W T ) = ∏ t = 1 T P ( W t ∣ W < t ) P(W_1, W_2, \ldots, W_T) = \prod_{t=1}^{T} P(W_t \mid W_{<t}) P ( W 1 , W 2 , … , W T ) = t = 1 ∏ T P ( W t ∣ W < t )
여기서 (W_{<t})는 “(t)번째 단어 이전까지의 모든 단어들”을 의미
P ( W 1 ) P(W_1) P ( W 1 ) : 첫 단어가 나올 확률
P ( W 2 ∣ W 1 ) P(W_2 \mid W_1) P ( W 2 ∣ W 1 ) : 첫 단어가 주어졌을 때 두 번째 단어 확률
P ( W 3 ∣ W 1 , W 2 ) P(W_3 \mid W_1, W_2) P ( W 3 ∣ W 1 , W 2 ) : 앞의 두 단어가 주어졌을 때 세 번째 단어 확률
P ( W T ∣ W 1 , … , W T − 1 ) P(W_T \mid W_1, \ldots, W_{T-1}) P ( W T ∣ W 1 , … , W T − 1 ) : 이전 단어들이 주어졌을 때 마지막 단어 확률
언어 모델은 한 문장을 한 번에 통째로 외우는 게 아님
즉, “지금까지 단어들이 주어졌을 때 다음 단어 확률”을 반복적으로 예측하고 그 확률들을 곱해서 문장 전체 확률을 구성
1.7 평가 지표
왜 번역/생성은 “정답률(Accuracy)”로 끝나지 않나
번역/요약/생성 태스크는 정답이 한 가지로 고정되지 않음
같은 의미라도 표현이 여러 가지가 가능하므로, “정확히 일치”만 보는 정답률로는 평가가 어려움
따라서 BLEU/ROUGE 같은 자동 평가 지표가 등장
1.7.1 핵심 지표 정리
BLEU
핵심: n-gram precision(겹치는 조각 비율) + brevity penalty(짧은 번역 패널티)
장점: 자동 평가 가능
한계: 의미가 같아도 표현이 다르면 낮게 나올 수 있음
ROUGE
요약에서 많이 사용
성격: recall에 가까움(참고 요약의 내용이 얼마나 포함됐나)
대표: ROUGE-N, ROUGE-L
METEOR
정렬(alignment) 관점이 강하고, 어간(stemming), 동의어 등을 고려(세부는 설정/버전에 따라 차이)
Human Evaluation
여전히 중요
기준 예시: Adequacy(의미), Fluency(자연스러움)
pairwise 비교(둘 중 더 좋은 것 선택)가 안정적
1.8 트랜스포머 이전: RNN/LSTM 인코더-디코더(Seq2Seq)
“문맥(context)을 하나로 요약하고 싶다” → 인코더-디코더 구조가 자연스럽게 등장
1.8.1 RNN 구조(시간축으로 펼침)
x1 -> [RNN] -> h1
-> (다음으로 전달)
x2 -> [RNN] -> h2
x3 -> [RNN] -> h3
...
(x_t): t번째 입력(토큰 임베딩)
(h_t): t번째 은닉 상태(문맥 누적 정보)
1.8.2 인코더-디코더(번역) 개념
(Encoder) 한국어 토큰들 -> h1,h2,...,hT -> (context 요약)
(Decoder) context + 이전 출력 -> 다음 단어 생성 -> ...
인코더: 입력 문장을 읽고 표현을 만듦
디코더: 인코더 요약(context) + 이전 출력 토큰을 바탕으로 다음 토큰 생성
1.8.3 한계가 생기는 이유
정보 병목(Bottleneck) : 긴 문장을 하나의 context 벡터로 압축 → 앞부분 정보 손실
순차 처리의 한계 : 병렬화가 어려움
장기 의존성 문제 : 멀리 떨어진 정보 연결이 어렵고 학습이 불안정(대표: vanishing gradient)
1.9 Attention
1.9.1 디코더-인코더 Attention 직관(Seq2Seq Attention)
디코더가 출력 토큰 하나(시점 (j))를 만들 때,
인코더의 모든 상태 ((h_1, \ldots, h_T)) 중 어디를 얼마나 참고할지(가중치) 를 계산한다.
(1) 유사도 점수(score) 계산
score j , i = s i m i l a r i t y ( s j , h i ) \text{score}_{j,i} = \mathrm{similarity}(\mathbf{s}_j, \mathbf{h}_i) score j , i = s i m i l a r i t y ( s j , h i )
(2) softmax로 가중치(attention weight) 만들기
α j , i = exp ( score ∗ j , i ) ∑ ∗ k = 1 T exp ( score j , k ) \alpha_{j,i} = \frac{\exp(\text{score}*{j,i})} {\sum*{k=1}^{T}\exp(\text{score}_{j,k})} α j , i = ∑ ∗ k = 1 T exp ( score j , k ) exp ( score ∗ j , i )
(3) 가중합으로 컨텍스트 벡터(context vector) 만들기
c ∗ j = ∑ ∗ i = 1 T α j , i , h i \mathbf{c}*j = \sum*{i=1}^{T} \alpha_{j,i},\mathbf{h}_i c ∗ j = ∑ ∗ i = 1 T α j , i , h i
기호 의미
s j \mathbf{s}_j s j : 디코더의 (j)번째 상태(hidden state)
h i \mathbf{h}_i h i : 인코더의 (i)번째 상태(hidden state)
α j , i \alpha_{j,i} α j , i : (j)번째 출력 생성 시 (i)번째 입력을 얼마나 참고할지 나타내는 가중치
∑ i = 1 T α j , i = 1 \sum_{i=1}^{T}\alpha_{j,i} = 1 ∑ i = 1 T α j , i = 1
c j \mathbf{c}_j c j : 디코더 (j)시점의 컨텍스트 벡터(입력 정보를 정렬+요약해서 제공)
1.9.2 전사본 표현 교정(중요)
핵심 흐름은 동일: 유사도 점수 → softmax → 가중합
다만 실제 구현은 여러 변형이 존재한다.
(1) 전통 Seq2Seq Attention의 대표 변형
s i m i l a r i t y ( s j , h i ) = s j ⊤ h i \mathrm{similarity}(\mathbf{s}_j, \mathbf{h}_i) = \mathbf{s}_j^{\top}\mathbf{h}_i s i m i l a r i t y ( s j , h i ) = s j ⊤ h i
Additive(Bahdanau, MLP 기반)
s i m i l a r i t y ( s j , h i ) = v ⊤ tanh ( W s s j + W h h i ) \mathrm{similarity}(\mathbf{s}_j, \mathbf{h}_i) = \mathbf{v}^{\top}\tanh(W_s\mathbf{s}_j + W_h\mathbf{h}_i) s i m i l a r i t y ( s j , h i ) = v ⊤ tanh ( W s s j + W h h i )
(2) 트랜스포머 Attention과의 연결
트랜스포머는 같은 아이디어를 (Q, K, V)로 재구성해 효율적으로 만든 형태다.
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K ⊤ d k ) V \mathrm{Attention}(Q, K, V) = \mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V A t t e n t i o n ( Q , K , V ) = s o f t m a x ( d k Q K ⊤ ) V
1.10 선형대수 기초
수식을 봤을 때 “아 유사도구나 / 아 확률로 바꾸는구나”를 즉시 캐치하기
1.10.1 벡터/행렬/전치(Transpose)
h ∈ R d × 1 \mathbf{h} \in \mathbb{R}^{d \times 1} h ∈ R d × 1
h ⊤ ∈ R 1 × d \mathbf{h}^{\top} \in \mathbb{R}^{1 \times d} h ⊤ ∈ R 1 × d
h ⊤ g ∈ R \mathbf{h}^{\top}\mathbf{g} \in \mathbb{R} h ⊤ g ∈ R
1.10.2 내적이 왜 “유사도” 느낌인가?
(1) 코사인 유사도에 내적이 포함됨
cos ( θ ) = a ⊤ b ∥ a ∥ , ∥ b ∥ \cos(\theta) = \frac{\mathbf{a}^{\top}\mathbf{b}}{\lVert \mathbf{a}\rVert,\lVert \mathbf{b}\rVert} cos ( θ ) = ∥ a ∥ , ∥ b ∥ a ⊤ b
방향이 비슷할수록 값이 커짐
정규화하면 내적이 곧 “방향 유사도”처럼 동작
(2) 거리(distance) 전개에도 내적이 등장
∥ x − y ∥ 2 = x ⊤ x − 2 x ⊤ y + y ⊤ y \lVert \mathbf{x}-\mathbf{y}\rVert^{2} = \mathbf{x}^{\top}\mathbf{x} - 2\mathbf{x}^{\top}\mathbf{y} + \mathbf{y}^{\top}\mathbf{y} ∥ x − y ∥ 2 = x ⊤ x − 2 x ⊤ y + y ⊤ y
x ⊤ y \mathbf{x}^{\top}\mathbf{y} x ⊤ y 가 커질수록(더 비슷할수록) 거리는 작아지는 구조
그래서 내적은 “유사도”로 자주 쓰인다
1.10.3 softmax가 왜 “확률”이 되나?
s o f t m a x ( z i ) = e z i ∑ k e z k \mathrm{softmax}(z_i) = \frac{e^{z_i}}{\sum_{k} e^{z_k}} s o f t m a x ( z i ) = ∑ k e z k e z i
항상 0보다 큼
전체 합이 1
미분이 깔끔해 학습에 유리
✅ 실무 팁(수치 안정성)
s o f t m a x ( z ) ∗ i = e z i − max ( z ) ∑ ∗ k e z k − max ( z ) \mathrm{softmax}(\mathbf{z})*i = \frac{e^{z_i - \max(\mathbf{z})}}{\sum*{k} e^{z_k - \max(\mathbf{z})}} s o f t m a x ( z ) ∗ i = ∑ ∗ k e z k − m a x ( z ) e z i − m a x ( z )
overflow 방지를 위해 보통 (\max(\mathbf{z}))를 빼고 계산
정규화 구조 때문에 결과 확률은 동일하게 유지된다
1.11 트랜스포머로 돌아오기: 왜 GPT/BERT가 여기서 나왔나?
트랜스포머는 RNN의 순차 처리를 버리고, Attention으로 문장 내 관계를 한 번에 계산할 수 있게 만든 구조
1.11.1 트랜스포머 Attention 블록(자체완결)
입력 X (토큰 임베딩 + 포지션) [n x d]
Q = XWq
K = XWk
V = XWv
A = softmax( QK^T / sqrt(dk) ) [n x n] // 토큰-토큰 관계표
출력 = A V [n x d]
(A): 토큰-토큰 관계(어느 토큰이 어느 토큰을 얼마나 참고하는지)
1.11.2 Multi-Head가 왜 필요?
한 번의 관계표만으로는 관계의 종류를 다양하게 담기 어려움
여러 헤드가 서로 다른 관점(문법/의미/지시어/장거리 의존 등)으로 관계를 학습
1.12 GPT vs BERT: 같은 트랜스포머지만 목표가 다르다
모델 구조 학습 목표 강점 GPT 계열 Decoder-only 다음 토큰 예측(Autoregressive) 생성, 프롬프트 기반 적응(Few/Zero-shot) BERT 계열 Encoder-only 마스크 채우기(Masked LM) 분류/추출(QA span 등)에서 강함
1.12.1 전사본 표현 교정(중요)
트랜스포머도 임베딩 레이어(토큰 ID → 벡터)는 반드시 존재
다만 word2vec처럼 임베딩을 따로 만들고 고정하기보다,
모델 학습 과정에서 임베딩까지 end-to-end로 같이 최적화하는 경우가 일반적
→ “임베딩을 따로 튜닝하는 비중이 줄었다”로 이해하면 자연스럽다
아래는 네가 준 내용을 강의 흐름 그대로 유지하면서, Velog에서 수식이 절대 안 깨지게 $$ ... $$로 통일하고, ASCII/표/shape 추적/핵심 교정 까지 “교재” 톤으로 완성한 최종본이야.
(원문에 있던 [ ] 수식 표기, 괄호/슬래시/루트 표기 흔들림, 인덱스 표기 혼동을 전부 정리했어.)
1.1 트랜스포머는 “인코더-디코더” 구조
입력 문장(소스)을 Encoder 가 이해(표현 벡터로 변환)
출력 문장(타겟)을 Decoder 가 생성(한 토큰씩)
슬라이드의 큰 흐름은 다음처럼 잡으면 된다.
Input (token + position)
-> Encoder blocks (self-attention + FFN)
-> Decoder blocks (masked self-attention + cross-attention + FFN)
-> Linear + Softmax
-> Output tokens
1.2 트랜스포머가 RNN보다 유리했던 이유
병렬 처리 가능 : 토큰을 순차적으로 처리하지 않고, 한 번에 행렬 연산으로 처리
번역 태스크에서 성능(BLEU)과 효율이 강점으로 제시됨
이후 BERT/GPT가 트랜스포머 블록을 채택 하면서 “사전학습 → 적응”의 표준이 됨
2) Positional Encoding
2.1 왜 필요한가?
RNN은 입력이 x1 → x2 → x3 ... 순서대로 들어오므로 순서 정보가 구조에 내장
트랜스포머는 병렬 처리로 토큰을 동시에 다루므로, 그냥 두면 토큰의 위치를 모름
그래서 토큰 임베딩에 위치 정보를 더해 순서를 주입한다
입력 단계(개념)
token ids -> Embedding(d_model)
-> + PositionalEncoding(d_model)
-> Encoder/Decoder blocks
2.2 “그럼 위치를 숫자로 주면 되지 않나?”가 왜 위험한가
(A) 그냥 0,1,2,3… 더하기
값 스케일이 커지며 학습 안정성 (초기 분포, 스케일)이 흔들릴 수 있음
(B) 0~1 정규화 (예: 0, 0.33, 0.66, 1)
문장 길이가 바뀌면 같은 “2번째 토큰”도 값이 바뀜
→ 같은 위치가 일관된 의미를 갖기 어려움
(C) 원-핫/이진 벡터
길이에 무관하게 같은 위치에 같은 벡터를 할당 가능
하지만 위치 간 상대 거리/기하학적 관계 를 표현하기가 까다로움(왜곡 가능)
2.3 Sinusoidal Positional Encoding (원 논문 정석)
짝수 차원에는 sin, 홀수 차원에는 cos를 번갈아 사용
P E ( p o s , 2 i ) = sin ( p o s 1000 0 2 i d m o d e l ) PE(pos, 2i) = \sin\left(\frac{pos}{10000^{\frac{2i}{d_{model}}}}\right) P E ( p o s , 2 i ) = sin ( 1 0 0 0 0 d m o d e l 2 i p o s )
P E ( p o s , 2 i + 1 ) = cos ( p o s 1000 0 2 i d m o d e l ) PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{\frac{2i}{d_{model}}}}\right) P E ( p o s , 2 i + 1 ) = cos ( 1 0 0 0 0 d m o d e l 2 i p o s )
직관(강의 흐름 정리)
sin/cos 범위는 대략 ([-1, 1]) → 스케일 폭주 방지
차원마다 주파수가 달라서 짧은/긴 거리 관계를 다양한 해상도로 표현
“위치 변화가 벡터를 회전시키는 것처럼” 이해해도 직관적으로 도움이 됨
2.4 (실전) Positional Encoding 구현 예시 (이해용)
import numpy as np
def positional_encoding ( max_len: int , d_model: int ) - > np. ndarray:
pos = np. arange( max_len) [ : , None ]
i = np. arange( d_model) [ None , : ]
angle_rates = 1 / ( 10000 ** ( 2 * ( i // 2 ) / d_model) )
angles = pos * angle_rates
pe = np. zeros_like( angles)
pe[ : , 0 : : 2 ] = np. sin( angles[ : , 0 : : 2 ] )
pe[ : , 1 : : 2 ] = np. cos( angles[ : , 1 : : 2 ] )
return pe
3) Self-Attention / Scaled Dot-Product Attention
3.1 Q, K, V를 한 문장으로
Query(Q) : “지금 내가 무엇을 찾고 싶은가?”
Key(K) : “각 토큰이 어떤 특징을 갖고 있어 매칭 기준이 되는가?”
Value(V) : “매칭되면 실제로 가져올 정보(내용)는 무엇인가?”
요약하면, 관계의 기준(Q/K)과 실제 내용(V)을 분리하면 표현력이 좋아진다 는 흐름이다.
3.2 수식(정석)
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K ⊤ d k ) V \mathrm{Attention}(Q, K, V) = \mathrm{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V A t t e n t i o n ( Q , K , V ) = s o f t m a x ( d k Q K ⊤ ) V
“Scaled(/sqrt(d_k))”의 의미 (중요)
내적 (QK^\top)는 차원 (d_k)가 커질수록 값의 분산이 커지기 쉬움
그대로 softmax에 넣으면 값이 과도하게 커져 softmax가 포화(거의 0/1) → 학습 불안정
그래서 (\sqrt{d_k})로 나눠 스케일을 안정화한다
3.3 차원(shape) 추적 (구현 실수 방지 핵심)
시퀀스 길이 (L), 모델 차원 (d_{model}), 헤드 차원 (d_k, d_v)
항목 shape 입력 (X) ((L, d_{model})) (W^Q, W^K) ((d_{model}, d_k)) (W^V) ((d_{model}, d_v)) (Q=XW^Q) ((L, d_k)) (K=XW^K) ((L, d_k)) (V=XW^V) ((L, d_v)) (QK^\top) ((L, L)) (\mathrm{softmax}(QK^\top/\sqrt{d_k})) ((L, L)) 출력 ((\cdot)V) ((L, d_v))
강의의 “(3×4)·(4×2)=(3×2)” 감각은 맞지만, 실제로는 X와 W의 shape를 일관되게 유지 하는 게 핵심이다.
4) Masked Self-Attention (왜 디코더에서만 마스크?)
4.1 이유: 생성(Autoregressive)은 “미래 토큰”을 보면 안 됨
디코더는 다음 단어를 예측해야 함
예: I love you에서 love를 예측할 때, 미래 토큰 you를 보면 치팅
그래서 디코더 self-attention에는 look-ahead mask(상삼각 마스크) 를 적용한다
마스크 직관
허용: 과거/현재
금지: 미래
t=2일 때 볼 수 있는 범위: [1..2]
4.2 구현 관점(핵심)
마스크로 가려지는 위치의 score에 매우 작은 값을 더함(실제로는 (-\infty)에 가까운 값)
softmax를 거치면 해당 확률이 거의 0이 되어 영향이 사라짐
5) Multi-Head Attention (왜 헤드를 여러 개 쓰나?)
5.1 직관(강의 흐름)
어떤 헤드는 주어-동사 관계를 강하게 보고
어떤 헤드는 지시어/대명사 관계를 보고
어떤 헤드는 구문 패턴 을 본다
→ 한 가지 attention만으로 모든 관계를 잡기 어렵기 때문에 여러 관점(헤드) 으로 본다
5.2 수식(정석)
h e a d i = A t t e n t i o n ( Q W i Q , ; K W i K , ; V W i V ) \mathrm{head}_i = \mathrm{Attention}(QW_i^Q,; KW_i^K,; VW_i^V) h e a d i = A t t e n t i o n ( Q W i Q , ; K W i K , ; V W i V )
M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , … , h e a d h ) W O \mathrm{MultiHead}(Q, K, V) = \mathrm{Concat}(\mathrm{head}_1, \ldots, \mathrm{head}_h)W^O M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , … , h e a d h ) W O
5.3 차원 설계 (Residual을 위한 “차원 맞추기”)
residual add를 하려면 입력/출력 차원이 같아야 함
보통 (d_{model})을 헤드 수 (h)로 나눔
d k = d v = d m o d e l h d_k = d_v = \frac{d_{model}}{h} d k = d v = h d m o d e l
각 헤드 출력 concat → 다시 ((L, d_{model}))로 돌아와 residual add 가능
6) Skip Connection + Layer Normalization (Add & Norm)
슬라이드에서도 “성능 향상: Skip / LayerNorm”을 따로 강조한다.
6.1 Residual(Skip) Connection
목적: 깊은 네트워크에서 그라디언트 흐름 개선 + 학습 안정화
y = x + S u b L a y e r ( x ) y = x + \mathrm{SubLayer}(x) y = x + S u b L a y e r ( x )
6.2 LayerNorm (BatchNorm과 차이)
BatchNorm: 배치 통계에 의존 → 배치 작으면 불안정
LayerNorm: 토큰(샘플) 내부 feature 차원 기준 정규화 → 배치 크기에 덜 민감
방법 평균/분산을 어디서 계산? NLP에서 선호 BatchNorm 배치 차원 배치 작아지면 불리 LayerNorm feature((d_{model})) 차원 트랜스포머 표준
7) Encoder/Decoder 블록 전체 흐름 한 장 요약
7.1 Encoder (한 층)
X
-> Multi-Head Self-Attention
-> Add & Norm (Residual + LayerNorm)
-> Feed Forward
-> Add & Norm
7.2 Decoder (한 층)
Y (shifted right)
-> Masked Multi-Head Self-Attention
-> Add & Norm
-> Encoder-Decoder Attention (Q: decoder, K/V: encoder)
-> Add & Norm
-> Feed Forward
-> Add & Norm
8) (다음 챕터 대비) GPT vs BERT에서 어디가 달라지나?
BERT : Encoder-only (양방향 문맥 이해)
GPT : Decoder-only (masked self-attention 기반, 다음 토큰 생성)
따라서 이번 파트의 “Positional Encoding, (Masked) Multi-Head Attention, LayerNorm, Residual”은 그대로 GPT/BERT 이해의 기반이 된다.
아래는 네 원문을 강의 흐름 그대로 유지하면서, Velog에서 수식이 깨지지 않도록 전부 $$ ... $$로 통일 하고, 표/ASCII/shape 추적/단계별 정리 까지 “교재” 톤으로 완성한 최종본이야. 그대로 복붙하면 돼.
0) 이 강의에서 얻어야 하는 것 (학습 목표)
왜 비전에서 트랜스포머를 쓰려 했는지
ViT 핵심 아이디어 : 이미지를 토큰 시퀀스 로 바꿔 Transformer Encoder에 넣기
DETR 핵심 아이디어 : Detection을 집합(set) 예측 으로 바꾸고 NMS 제거
두 모델 모두에서 Positional Encoding/Embedding이 왜 필수인지
면접/실무에서 말할 수 있게: 장점·단점·언제 쓰는지
1) 도입: “NLP에서 되면 CV에서도 되지 않을까?” + CNN의 Inductive Bias
1.1 CNN이 강한 이유(Inductive Bias)
CNN은 이미지에 맞는 “가정”이 구조적으로 들어가 있어서, 비교적 적은 데이터에서도 잘 학습되는 경향이 있습니다.
가정 1: 지역성(Locality)
가까운 픽셀들이 의미를 만든다 → 작은 커널로도 잘 배움
가정 2: 가중치 공유(Weight Sharing)
같은 패턴(엣지 등)은 위치가 달라도 같은 필터로 잡힌다
가정 3: Translation Equivariance
물체가 이동하면 feature map도 같이 이동
(완전한 invariance는 pooling/구조 설계로 얻는 경우가 많음)
1.2 CNN의 취약점(강의 예시를 정확히 정리)
강의의 “눈/코/입 위치가 이상해도 얼굴로 인식” 요지는 다음처럼 정리하면 더 정확합니다.
CNN은 국소 패턴 은 매우 잘 잡지만,
전역 관계(눈-코-입의 상대 위치) 를 “자동으로 강제”하진 않음
따라서 데이터/학습 조건에 따라 부분만 맞으면 전체를 맞다고 착각 하는 문제가 생길 수 있음
핵심 문장: 이미지를 패치로 쪼개서, 각 패치를 토큰처럼 만들어 Transformer Encoder에 입력한다.
2.1 ViT 전체 흐름 (Step-by-step)
Step 1) Patchify: 이미지를 P×P 패치로 쪼갠다
X ∈ R H × W × C X \in \mathbb{R}^{H \times W \times C} X ∈ R H × W × C
패치 크기: (P \times P)
패치 개수:
N = H P ⋅ W P N = \frac{H}{P}\cdot \frac{W}{P} N = P H ⋅ P W
x p , i ∈ R P 2 ⋅ C x_{p,i} \in \mathbb{R}^{P^2\cdot C} x p , i ∈ R P 2 ⋅ C
✅ shape 추적(예시)
이미지: (224\times224\times3)
패치: (16\times16)
패치 개수: (N=(224/16)^2=14^2=196)
패치 벡터 차원: (16^2\cdot3=768)
Step 2) Linear Projection: 패치를 D차원 토큰으로 바꾼다
z i = x p , i W E + b , z i ∈ R D z_i = x_{p,i}W_E + b,\quad z_i \in \mathbb{R}^{D} z i = x p , i W E + b , z i ∈ R D
W E ∈ R ( P 2 C ) × D W_E \in \mathbb{R}^{(P^2C)\times D} W E ∈ R ( P 2 C ) × D
Step 3) [CLS] 토큰 붙이기 + Positional Embedding 더하기
Z 0 = [ z cls ; ; z 1 ; ; … ; ; z N ] Z_0 = [z_{\text{cls}};; z_1;; \dots;; z_N] Z 0 = [ z cls ; ; z 1 ; ; … ; ; z N ]
위치 정보를 잃기 때문에 Positional Embedding 을 더함:
Z = Z 0 + E pos Z = Z_0 + E_{\text{pos}} Z = Z 0 + E pos
여기서
E pos ∈ R ( N + 1 ) × D E_{\text{pos}} \in \mathbb{R}^{(N+1)\times D} E pos ∈ R ( N + 1 ) × D
표준 Encoder 블록(MHSA + FFN + Residual + LayerNorm)을 (L)번 반복
Step 5) MLP Head로 분류
마지막 층 출력에서 [CLS] 위치 벡터 를 뽑아 분류:
y ^ = M L P ( Z cls ( L ) ) \hat{y} = \mathrm{MLP}(Z^{(L)}_{\text{cls}}) y ^ = M L P ( Z cls ( L ) )
2.2 (중요) ViT는 왜 큰 데이터가 필요했나?
강의의 “그냥 쓰면 훈련이 잘 안 된다”는 말을 원인-결과 로 정확히 정리하면:
CNN은 이미지에 맞는 inductive bias(지역성/공유/계층)가 있어서
상대적으로 적은 데이터 에서도 안정적으로 학습되는 편
초기 ViT는 그 bias가 약해서
“무슨 패턴을 우선 배워야 하는지”를 데이터에서 더 많이 배워야 했음
그래서 논문에서 대규모 데이터로 pretrain 후 fine-tune 을 강조(JFT-300M 등)
2.3 ViT 시각화 결과(강의 포인트 3가지)
Embedding filter가 low-level 패턴을 학습
CNN 1층이 엣지/텍스처를 배우듯, ViT 초기 층에서도 유사 패턴이 나타남
Positional embedding 이후 공간 구조가 드러남
위치 정보가 들어가면서 “가까운 패치끼리 비슷하게 보는 경향” 같은 구조가 관찰
Layer가 깊어질수록 attention distance가 커짐
초기층은 근처 패치, 후반층은 먼 패치까지 보며
CNN의 receptive field가 넓어지는 느낌과 유사한 현상
2.4 ViT 한 장 요약(면접용)
한 줄: “이미지를 패치 토큰 시퀀스로 바꿔 Transformer Encoder로 분류한다.”
장점: 전역 관계를 MHSA로 직접 모델링
단점(초기 ViT 관점): CNN bias가 약해 큰 데이터/사전학습 의존도가 큼
3) DETR — “Detection을 Set Prediction으로 바꿔 NMS 제거”
강의에서 “DETI”처럼 들린 건 DETR 이 맞습니다.
(End-to-End Object Detection with Transformers, ECCV 2020)
3.1 기존 Detection의 골칫거리: 후보 박스가 많아 NMS 필요
앵커/후보가 많아 같은 물체에 박스가 여러 개 겹쳐 나옴
그래서 후처리로 NMS(Non-Maximum Suppression) 로 중복 제거
3.2 DETR의 핵심 아이디어 (Step-by-step)
Step 1) Backbone(CNN)으로 feature map 추출
ViT처럼 처음부터 패치 토큰화하는 게 아니라,
CNN으로 feature map을 뽑고 Transformer에 입력
예:
F ∈ R H ′ × W ′ × C ′ F \in \mathbb{R}^{H' \times W' \times C'} F ∈ R H ′ × W ′ × C ′
Step 2) feature map을 시퀀스로 펼치고(Flatten), 2D Positional Encoding 추가
L = H ′ ⋅ W ′ L = H'\cdot W' L = H ′ ⋅ W ′
X ∈ R L × C ′ X \in \mathbb{R}^{L \times C'} X ∈ R L × C ′
2D 위치 정보를 유지하기 위해 positional encoding을 더함:
X ← X + E pos X \leftarrow X + E_{\text{pos}} X ← X + E pos
Encoder가 이미지 전체 정보를 통합한 표현을 만든다
Step 4) Decoder에 “Object Queries”를 넣는다 (DETR 감성 핵심)
고정 개수 (N_q)개의 학습 가능한 query 벡터
Q ∈ R N q × d m o d e l Q \in \mathbb{R}^{N_q \times d_{model}} Q ∈ R N q × d m o d e l
각 query가 “하나의 물체 슬롯”처럼 동작하도록 학습된다
Step 5) 각 query 출력에서 (클래스, 박스) 예측
각 query마다 출력:
class logits: (K) classes + no-object
box: ((c_x, c_y, w, h)) (보통 정규화)
3.3 no-object 클래스는 왜 필요?
고정 개수 query를 쓰면, 이미지에 물체가 2개여도 query는 예를 들어 100개일 수 있습니다.
남는 query들은 “아무 물체도 담당하지 않음”이어야 함
그래서 no-object 클래스 가 필요하다
3.4 NMS를 없애는 핵심 장치: Bipartite Matching + Hungarian Algorithm
핵심 목표
“각 GT(정답 물체)에 예측 query를 1개씩만 매칭하자.”
→ 그러면 같은 물체를 여러 query가 중복 예측하는 학습이 줄어듦 → NMS 의존이 감소
Step-by-step
예측 (Nq)개와 GT (N {gt})개의 비용(cost) 행렬 구성
비용 합이 최소가 되는 1:1 매칭 을 찾음 (Hungarian Algorithm)
그 매칭 결과로 loss를 계산하고 학습
3.5 DETR Loss를 “직관”으로 이해하기
보통 손실은 다음 두 덩어리로 이해하면 충분합니다.
헝가리안 매칭은 “loss를 최소화하는 1:1 매칭을 고르는 과정 ”으로 이해하면 정확합니다.
4) ViT vs DETR vs CNN 한 번에 정리
구분 CNN(전통) ViT DETR 입력 표현 픽셀→컨볼루션 패치→토큰 시퀀스 CNN feature map→시퀀스 핵심 강점 적은 데이터에도 강함(bias) 전역 관계 모델링이 깔끔 NMS 제거 , end-to-end set prediction포지션 처리 구조적으로 내재(공간) pos embedding 필수 2D pos encoding 필수 주 용도 분류/검출/세그 전반 분류(원형) 오브젝트 디텍션
0) 이 파트 한 줄 목표
시계열 예측은 입력 길이 (L)이 매우 길어지기 쉬워서 Self-Attention 비용이 ( O ( (O( ( O ( L 2 L^2 L 2 ) ) )) ) ) 로 폭증한다.
Informer(AAAI 2021) 는 이를 줄이기 위해 중요한 Query만 골라 계산하는 ProbSparse Attention 으로 효율을 높여 Long Sequence Forecasting 을 가능하게 하려는 모델이다.
1) 용어/발화 오류 교정 (강의 이해 필수)
강의에서 들린 표현 올바른 표현 설명 “트리플 AI” AAAI 인공지능 분야 주요 학회 (AAAI Conference) “리스트 / NS팀” LSTM 시계열에서 전통적으로 많이 쓰던 RNN 계열 “인포멀/인포먼트” Informer Long sequence time-series forecasting 모델 “커다리티/쿼드리티” Quadratic complexity 길이 (L)에서 비용이 (O(L^2))로 증가 “프로보스/프로모션 어텐션” ProbSparse Attention 활성 Query만 골라 attention 계산 “확인 페이스” Hugging Face 모델/코드 공유 플랫폼 “기타에서 다운” GitHub에서 다운 코드 저장소
✅ 중요한 정정 1 — 샘플링 예시 숫자
강의에서 “30초 + 100kHz → 3000개 입력”이라고 했다면 수치가 어긋나 있어요.
100kHz = 초당 100,000 샘플
30초면:
L = 30 × 100 , 000 = 3 , 000 , 000 L = 30 \times 100{,}000 = 3{,}000{,}000 L = 3 0 × 1 0 0 , 0 0 0 = 3 , 0 0 0 , 0 0 0
즉 3,000,000개 가 맞습니다.
“3000개”라는 발화는 실제 의도가 100Hz(초당 100샘플) 정도였을 가능성이 큽니다.
Step 1) 시계열은 입력 길이 (L)이 매우 길어지기 쉽다
자연어 문장은 보통 수십~수백 토큰
센서/로그/계측 데이터는 초당 샘플이 누적되어 수천~수백만 포인트 까지 늘어남
Step 2) Self-Attention은 (L\times L) 어텐션 행렬이 생긴다
기본 self-attention은 다음을 계산한다.
A = s o f t m a x ( Q K ⊤ d k ) A = \mathrm{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right) A = s o f t m a x ( d k Q K ⊤ )
여기서 (A)의 shape는:
A ∈ R L × L A \in \mathbb{R}^{L \times L} A ∈ R L × L
Step 3) 그래서 계산/메모리가 (O(L^2))로 증가한다
예를 들어 (L=3000)이면,
L 2 = 3000 × 3000 = 9 , 000 , 000 L^2 = 3000 \times 3000 = 9{,}000{,}000 L 2 = 3 0 0 0 × 3 0 0 0 = 9 , 0 0 0 , 0 0 0
어텐션 행렬만 900만 원소 가 된다.
여기에 레이어 수, 헤드 수, 배치 크기 까지 곱해지면 시계열에서는 큰 부담이 된다.
강의의 직관은 다음으로 요약할 수 있다.
3.1 Lazy Query vs Active Query
Lazy Query : 모든 Key에 대한 attention 분포가 거의 균등(평평)
→ 계산해도 얻는 정보가 적다
Active Query : 특정 Key에 attention이 강하게 몰림
→ 중요한 상호작용이므로 계산 가치가 크다
Lazy: [0.02 0.02 0.02 0.02 ...] (거의 균등)
Active: [0.60 0.20 0.10 0.05 ...] (특정 키에 집중)
4) ProbSparse Attention: “Active Query만 뽑아서 계산”
4.1 핵심 아이디어
전체 Query 중에서 상위 (u)개(활성 Query) 만 골라 attention을 계산
나머지는 근사/생략하여 비용을 줄인다
강의에서 “Top 6 query” 같은 표현은 보통 다음을 의미한다.
전체 Query 중 상위 (u) 개만 attention 계산
(u)는 고정 숫자일 수도 있고, 길이 (L)에 따라 정해질 수도 있음(설계/실험에 따라)
강의에서 “uniform(1/Lk)처럼 만들도록 loss를 준다”처럼 들렸다면 오해가 생길 수 있어요.
이 파트는 보통 아래 흐름으로 이해하는 게 자연스럽습니다.
어떤 Query의 attention 분포가 uniform에 가까우면 (lazy) 정보량이 적다
uniform에서 멀수록 (active) 특정 Key에 집중하므로 중요하다
따라서 uniform에서 많이 벗어난 Query 를 골라 계산한다
즉 결론은:
“uniform처럼 만들자”가 아니라
“uniform에서 많이 벗어난(active) Query를 골라 계산하자” 가 핵심입니다.
시계열 예측에서는 디코더 입력을 다음처럼 구성하는 방식이 흔합니다.
5.2 전체 흐름(그림)
flowchart LR
A[Past series X_enc] --> Enc[Encoder]
B[Known tail tokens] --> DecIn[Decoder input]
C[Future placeholders (zeros/mask)] --> DecIn
Enc --> Dec[Decoder]
DecIn --> Dec
Dec --> Yhat[Forecast Y_hat]
Ytrue[Ground truth future] --> Loss
Yhat --> Loss
5.3 학습은 어떻게 진행되나?
디코더 출력 (\hat{Y})를 실제 미래 (Y)와 비교해 loss(MSE 등)를 최소화하도록 학습
예:
L = 1 T ∑ t = 1 T ( Y t − Y ^ t ) 2 \mathcal{L} = \frac{1}{T}\sum_{t=1}^{T} (Y_t - \hat{Y}_t)^2 L = T 1 t = 1 ∑ T ( Y t − Y ^ t ) 2
핵심은 “긴 시퀀스를 다 보는 대신, 계산할 attention을 줄여 효율을 확보”하는 방향입니다.
6) 차원(shape) 추적 (구현 시 실수 방지)
시퀀스 길이 (L), 모델 차원 (d_{model}), 헤드 차원 (d_k)
항목 shape 입력 (X) ((L, d_{model})) (Q, K, V) ((L, d_k)), ((L, d_k)), ((L, d_v)) ( Q K ⊤ ) (QK^\top) ( Q K ⊤ ) ((L, L)) ( A = s o f t m a x ( Q K ⊤ / d k ) ) (A=\mathrm{softmax}(QK^\top/\sqrt{d_k})) ( A = s o f t m a x ( Q K ⊤ / d k ) ) ((L, L)) 출력 (AV) ((L, d_v))
Informer는 여기서 모든 Query에 대해 ( L × L ) (L\times L) ( L × L ) 계산을 하지 않도록 줄이는 게 핵심이다.
5 BERT & GPT
5.1 이 교재 사용법
[타임라인 ↔ 슬라이드] 로 “지금 강의가 어느 페이지인지” 먼저 잡습니다.
각 파트는 아래 순서로 공부하면 가장 안정적으로 이해가 됩니다.
정확 용어/정의(발화 오류 교정 포함)
핵심 직관(그림/표로 요약)
수식(슬라이드/논문식 형태로 정확 표기 + 의미 해설)
면접/실무 답변 템플릿(15초 요약)
5.2 강의 음성 TXT ↔ 슬라이드 싱크 맵 (PDF 페이지 기준)
음성(대략) PDF 페이지 주제 싱크 포인트(음성 키워드) 00:02–02:51 p2–p4 왜 BERT/GPT가 중요해졌나 “레이블 만들기 어렵다”, “자연어는 데이터는 많다” 02:51–07:22 p3–p4 레이블링 난이도/데이터 특성 비교 번역/요약 “정답 정의가 애매”, “투표/다수결” 07:22–14:44 p5–p6 (CV 예시로) 프리트레인–파인튜닝 / 트랜스퍼러닝 “로우레벨/하이레벨”, “파라미터 고정(Freeze)” 15:38–18:19 p7 few-shot / zero-shot 직관 “서포트셋/쿼리셋”, “유사도 기반” 18:34–24:01 p8–p10 용어가 엄밀하지 않다 + 도메인/러닝 패러다임 정의 “도메인=joint distribution”, “소스/타겟” 24:29–34:20 p11–p19 GPT-1 “Generative Pre-Training”, “2-stage”, “L1/L2/L3” 35:14–50:18 p20–p35 BERT “bi-directional”, “MLM + NSP”, “segment embedding” 50:18–58:56 p36–p44 GPT-2 “WebText”, “BPE”, “zero-shot” 58:56–01:05:03 p45–p49 GPT-3 + 요약 “few-shot”, “gradient update 없이”, “정리 표”
5.3 강의에서 자주 헷갈린 용어/표현 정정 표
음성에서 들리는 표현 정식 용어 한 줄 정의 “버터” BERT Encoder 기반 + MLM(마스크 토큰 복원) 중심 사전학습“지피티” GPT Decoder 기반 + Causal LM(다음 토큰 예측) 중심“언슈퍼바이즈 프리트레이닝” Self-supervised pretraining 레이블 없이 예측 과제(MLM/다음토큰) 로 학습 “트랜스포머 러닝” (문맥상) Transfer learning 소스에서 학습한 표현/가중치를 타겟 태스크로 전이 “어블레이션” Ablation study 요소를 제거/변형하며 성능 기여도를 확인 “바이디렉셔널” Bidirectional (BERT) 좌/우 문맥을 함께 보며 표현학습 “레프트-투-라이트” Causal / Autoregressive (GPT) 과거 토큰만 보고 다음 토큰을 예측(미래는 마스킹)
5.4 Part A. 왜 BERT/GPT가 폭발했나 (p2–p4)
5.4.1 강의 핵심 논리 (Step-by-step)
Step 1) NLP는 입력 데이터 (X)가 매우 많다
웹/문서/댓글/로그 등 텍스트는 무한히 쌓인다 (강의 요지)
Step 2) 하지만 레이블 (Y)를 만들기 어렵다
번역/요약/NLI 등은
“정답의 정의” 자체가 애매하거나
사람마다 기준이 달라 합의(투표/다수결/가이드라인) 가 필요
Step 3) 결론: “레이블 없이도 학습되는 과제”로 먼저 크게 학습한다
Self-supervised (자기지도) 과제(MLM/다음토큰예측)로 표현을 먼저 학습
이후 필요한 태스크에 소량 레이블로 적응(파인튜닝/프롬프트)
5.4.2 (p4) “NLP vs Bio/CV”가 말하는 진짜 포인트
항목 Bio/CV(예: MRI 세그멘테이션) NLP(예: 요약/의미/추론) 입력 데이터 (X) 상대적으로 적음(수집 비용 큼) 매우 많음 레이블 (Y) 전문가가 만들면 “정답 정의가 비교적 명확” “정답 정의 자체가 애매”한 경우 많음 병목 데이터 수집/품질 레이블링 + 정답 정의 자연스러운 전략 전이학습/파인튜닝 대규모 사전학습 → 범용 표현 → 적응
5.5 Part B. Pretrain → Finetune / Transfer / Few-shot·Zero-shot (p5–p10)
5.5.1 (p5) CV 예시로 이해하는 “프리트레인–파인튜닝”
강의의 “로우레벨/하이레벨 필터”를 NLP로 대응하면:
로우레벨 : 기본 문법/표현/일반 문맥 패턴(범용)
하이레벨 : 특정 태스크(감성/QA/NER/분류)에 맞는 결정 경계(특화)
파라미터 고정(Freeze) 직관
[Pretrained Backbone]
Layer1 (freeze) <- 범용 패턴
Layer2 (freeze)
Layer3 (train) <- 타겟 태스크에 맞게 조정
Head (train) <- 태스크 출력층
실무 팁: 데이터가 적을수록 “하단 레이어 freeze + 상단만 학습”이 안정적인 출발점입니다.
5.5.2 (p6) Transfer learning vs Finetuning 정리
용어 실무적으로 가장 정확한 정의 강의 예시 연결 Pretraining 대규모 데이터로 범용 표현 학습(대개 자기지도) 웹 텍스트로 LM 학습 Finetuning 타겟 태스크 데이터로 추가 학습(파라미터 업데이트) “영-한 번역 데이터로 맞춘다” Transfer learning 소스에서 학습한 표현/가중치를 타겟에 전이하는 전체 전략 “영-일로 먼저 배우고 영-한으로”
5.5.3 (p7) Few-shot / One-shot / Zero-shot (NLP 프롬프트로 정확 대응)
정의(시험/면접)
Zero-shot : 예시 0개
One-shot : 예시 1개
Few-shot : 예시 (k)개
NLP 구현(강의 “번역 원샷”을 정확 프롬프트로)
[예시(1-shot)]
한국어: 나는 배고프다
영어: I am hungry
[문제]
한국어: 오늘 날씨가 좋다
영어:
핵심:
파라미터 업데이트(gradient update) 없이
프롬프트(지시 + 예시 + 질의)만으로 조건부 생성 을 수행
5.5.4 (p8–p10) Domain/러닝 패러다임 혼동 방지(필수 2개)
(1) Domain이란?
도메인 (D)는 보통 데이터가 생성/샘플링되는 분포(환경) 를 의미합니다.
(2) Transfer vs (In-context) Zero/Few-shot을 가르는 가장 쉬운 기준
Transfer(파인튜닝 포함) : 타겟 데이터로 파라미터 업데이트 있음
Zero/Few-shot(in-context) : 프롬프트에 예시가 있을 뿐 파라미터 업데이트 없음
5.6 Part C. GPT-1 (p11–p19) — Generative Pre-Training + Fine-tuning
5.6.1 (p11) GPT-1 큰 그림
GPT = Generative Pre-Training
철학: (1) LM으로 먼저 크게 학습 → (2) 태스크별로 약간만 맞춤
flowchart LR
A[Large unlabeled text] --> B[Stage 1: LM Pretraining]
B --> C[Transformer Decoder (shared)]
D[Labeled dataset per task] --> E[Stage 2: Supervised fine-tuning]
C --> E
E --> F[Downstream performance]
5.6.2 (p14) Stage 1: Causal Language Modeling 수식(정확 표기)
토큰 시퀀스를 (U=(u_1,\dots,u_n))라 할 때, GPT의 언어모델은 과거 토큰만 조건으로 다음 토큰을 예측합니다.
(1) 최대화 관점(로그우도)
[
\max{\theta}\ \sum {i=1}^{n}\log P(ui \mid u {<i};\theta)
]
(2) 손실(최소화) 관점(음의 로그우도)
[
L_{\text{LM}}(\theta)
-\sum{i=1}^{n}\log P(u_i \mid u {<i};\theta)
]
강의의 “레프트-투-라이트(미래 못 봄)”는 (u_{<i})만 쓰는 조건부 확률을 뜻합니다.
5.6.3 (p15) Stage 2: Supervised Fine-tuning + LM 보조항
타겟 태스크 데이터 (C)가 ((x,y)) 쌍의 집합일 때:
(1) 태스크 손실(예: 분류)
[
L_{\text{task}}(\theta)
-\sum_{(x,y)\in C}\log P(y\mid x;\theta)
]
(2) 최종 손실(슬라이드의 (\lambda) 결합을 “손실 형태로” 정확히)
[
L(\theta)
L_{\text{task}}(\theta)
\lambda\ L_{\text{LM}}(\theta)
]
(\lambda)가 작은 이유(강의 의도):
태스크 성능에 집중 하되
LM 일반성(표현)을 조금 유지해 과적합 완화 에 도움
5.6.4 (p16) “입력 구조만 바꾸면 다양한 태스크에 적용”의 의미
모델(디코더 트랜스포머)은 그대로 두고, 태스크 입력을 텍스트 시퀀스로 ‘포맷팅’ 합니다.
태스크 입력 포맷(예시) 출력/판정 문장 분류 [BOS] textclass 문장쌍(NLI/유사도) [BOS] premise [SEP] hypothesisentail/neutral/contradict QA(간단형) [BOS] question [SEP] contextanswer span / 생성 다지선다 각 옵션별 [BOS] question [SEP] option_i 점수화 argmax option
5.6.5 (p17–p19) Ablation 요지(강의 포인트 유지)
프리트레인(LM) + 파인튜닝 조합이 성능에 기여
모델 깊이/규모 증가가 성능을 밀어올림
LSTM 대비 Transformer가 여러 태스크에서 더 강한 경향
5.7 Part D. BERT (p20–p35) — Bidirectional Encoder + MLM(+NSP)
5.7.1 (p21–p23) GPT vs BERT 구조 차이(핵심 1줄)
GPT : Decoder + Causal(미래 마스킹) → 생성에 유리
BERT : Encoder + Bidirectional(좌/우 문맥) → 이해/표현학습에 유리
GPT (Causal):
t3는 (t1,t2)만 봄, (t4,t5)는 마스킹
BERT (Bidirectional):
t3는 (t1,t2,t4,t5) 모두 볼 수 있음
(단, MLM에서는 일부 토큰이 [MASK]로 가려짐)
5.7.2 (p24–p26) Pretrain 1: Masked Language Model(MLM)
목적
입력 토큰 일부를 가리고, 가려진 토큰을 맞추며 양방향 문맥 표현 을 학습합니다.
마스크 위치 집합을 (M)이라 할 때:
[
L_{\text{MLM}}(\theta)
-\sum{i\in M}\log P(x_i \mid x {\backslash M};\theta)
]
80/10/10 규칙(강의 싱크 강함)
마스크 후보로 뽑힌 토큰(보통 전체의 15% 내외)에 대해:
80% → [MASK]로 치환
10% → 랜덤 토큰으로 치환
10% → 원래 토큰 유지
이유
파인튜닝/추론에서는 [MASK]가 없을 수 있으므로
[MASK]에만 과적응하는 것을 방지
5.7.3 (p27) Pretrain 2: Next Sentence Prediction(NSP)
두 문장 A, B가 주어졌을 때:
IsNext : 실제 코퍼스에서 A 다음에 B가 이어짐
NotNext : B를 다른 문서/문맥에서 랜덤 샘플
목표는:
[
L_{\text{NSP}}(\theta)
-\sum \log P(\text{label} \mid A,B;\theta)
]
강의 기준에서는 NSP를 핵심 구성으로 설명하므로 그대로 따라가면 됩니다.
5.7.4 (p28) BERT 입력 임베딩 3종 합(시험 단골)
토큰 위치 (i)에서 최종 입력 임베딩:
[
\mathbf{e}_i
\mathbf{e}^{token}_i
\mathbf{e}^{pos}_i
\mathbf{e}^{segment}_i
]
(\mathbf{e}^{token}): 토큰 의미(서브워드)
(\mathbf{e}^{pos}): 위치 정보
(\mathbf{e}^{segment}): 문장 A/B 구분(문장쌍 입력)
5.7.5 (p29) Fine-tuning 패턴 2가지(문장 단위 vs 토큰 단위)
(1) Sequence-level(문장/문장쌍 분류)
[CLS] 출력 벡터 (\mathbf{h}_{CLS}) → 분류기 → label
[
\hat{y}=\text{softmax}(W\mathbf{h}_{CLS}+b)
]
(2) Token-level / Span-level
NER: 각 토큰 벡터 (\mathbf{h}_i)에 분류기
SQuAD(QA): start/end 위치 예측
SQuAD 스팬 점수화(강의의 dot product를 수식으로 정리)
[
\text{score}{start}(i)=\mathbf{h} i^\top \mathbf{s},\quad
\text{score}{end}(i)=\mathbf{h} i^\top \mathbf{e}
][
P(start=i)=\text{softmax}(\text{score}*{start}),\quad
P(end=i)=\text{softmax}(\text{score}*{end})
]
5.7.6 (p30–p33) 벤치마크가 의미하는 것(강의 흐름 유지)
슬라이드 벤치마크 태스크 타입 잘하면 좋아지는 능력 p30 GLUE 문장/문장쌍 분류 묶음 범용 문맥 이해(일반화) p31 SQuAD 지문 기반 QA(스팬) 정보 위치 찾기 + 토큰 이해 p32 SWAG 상식 기반 이어쓰기(다지선다) 문장 흐름/상식 추론 p33 CoNLL NER 토큰 태깅 개체 인식(사람/장소/기관 등)
5.7.7 (p34–p35) Ablation 해석(강의 요지 그대로)
당시 설정에서는 MLM/NSP가 성능에 기여
특히 MLM이 “문맥 표현”을 강하게 밀어줌
5.8 Part E. GPT-2 (p36–p44) — 더 큰 데이터 + BPE + Zero-shot
5.8.1 (p36–p38) GPT-2가 강조한 3가지
더 큰 데이터(WebText 등)로 LM 학습
스케일(모델/데이터) 증가
파인튜닝 없이도(혹은 최소화) zero-shot 성능 을 보여줄 수 있다
5.8.2 (p39–p43) BPE(Byte Pair Encoding) — 완전 정리
왜 필요한가?
단어 단위 토크나이징은 OOV(사전에 없는 단어)가 빈번
서브워드(BPE/WordPiece 등)를 쓰면 “처음 보는 단어”도 분해/조합 가능
BPE 알고리즘(정확 Step-by-step)
초기 vocabulary를 문자(또는 바이트) 단위로 시작
말뭉치에서 가장 빈번한 연속 pair 를 찾음
그 pair를 merge하여 하나의 토큰 으로 추가
목표 vocab 크기까지 반복
강의의 “트위터 이모지” 맥락은, byte-level 계열 토크나이징이 특수문자/이모지 처리에 유리하다는 직관으로 이해하면 됩니다.
5.8.3 (p36–p44) Zero-shot 프롬프트화(강의 요지)
분류 문제도 “라벨을 출력 토큰으로 생성”하는 형태로 바꿔서 수행 가능
즉, 헤드(softmax classifier)를 학습하지 않고 프롬프트로 태스크를 기술
5.9 Part F. GPT-3 (p45–p49) — 스케일 + In-context learning
5.9.1 (p45) GPT-3 핵심 메시지(강의 표현 그대로)
GPT-2 철학을 확장: 더 큰 모델 + 더 큰 데이터 → 더 강한 일반화
프롬프트에 예시를 넣어 zero/one/few-shot 수행
중요한 포인트: gradient update 없이 (학습 없이) 추론에서 해결
5.9.2 In-context learning 흐름(도식)
flowchart LR
A[Instruction: task description] --> M[Pretrained GPT]
B[Examples: (x1->y1)...(xk->yk)] --> M
C[Query: x?] --> M
M --> D[Generated answer y?]
5.9.3 (p49) 강의 요약을 “한 줄”로
BERT : 문장을 “이해/표현”하는 데 강한 인코더
GPT : 문장을 “생성/연속 예측”하는 데 강한 디코더
5.10 Part G. 실무/연구 동향 (강의 위에 최소 확장)
5.10.1 PEFT(예: LoRA) — “가볍게 적응시키는 파인튜닝”
대형 모델 전체를 업데이트하면 비용/메모리가 큼
그래서 일부 저랭크 어댑터만 학습 해 빠르게 적응
대표: LoRA (arXiv:2106.09685)
면접용 한 줄
“요즘은 full fine-tuning 대신 LoRA 같은 PEFT로 비용을 줄이고 빠르게 도메인 적응한다.”
5.10.2 RAG — “모르는 지식은 검색으로 보강”
모델 파라미터에 지식을 ‘다’ 넣기보다
검색으로 관련 문서(근거)를 가져와 생성에 결합
대표 개념 정리로 널리 인용되는 축: RAG (arXiv:2005.11401)
면접용 한 줄
“최신/사내 지식과 근거가 필요하면 RAG로 문서를 붙여 환각을 줄인다.”
5.11 Part H. (시험/면접 대비) 15초 답변 템플릿 6개
5.11.1 왜 프리트레인이 필요한가?
“자연어는 입력 데이터는 많지만 레이블이 만들기 어려워서, 자기지도 과제로 대규모 사전학습을 하고 소량의 레이블로 다운스트림 태스크에 적응시키는 프리트레인–파인튜닝 전략이 강해졌습니다.”
5.11.2 GPT와 BERT의 구조 차이?
“GPT는 디코더 기반 causal LM이라 과거만 보고 다음 토큰을 생성하고, BERT는 인코더 기반 양방향 self-attention으로 좌우 문맥을 함께 보며 표현을 학습합니다.”
5.11.3 GPT-1의 2-stage는?
“1단계에서 언레이블 텍스트로 LM을 프리트레인하고, 2단계에서 태스크 레이블로 파인튜닝하며 필요하면 LM 손실을 (\lambda)로 섞어 일반성을 유지합니다.”
5.11.4 BERT의 MLM 80/10/10 이유?
“추론 때 [MASK]가 없으므로 [MASK]에 과적응하지 않게 랜덤/원토큰을 섞어 견고한 문맥 표현을 학습합니다.”
5.11.5 Zero-shot/Few-shot의 핵심?
“파라미터 업데이트 없이, 프롬프트에 지시문과 예시를 넣어 조건부 생성으로 태스크를 수행하는 방식입니다.”
5.11.6 요즘 현업 파인튜닝/운영 흐름?
“대형 모델은 LoRA 같은 PEFT로 일부만 학습해 비용을 줄이고, 최신 지식/근거가 필요하면 RAG로 검색 문서를 결합합니다.”
5.12 Part I. 연습문제 + 채점 기준
5.12.1 개념 퀴즈 8문항
(p4) 자연어에서 “레이블링이 어렵다”는 말이 의미하는 두 가지를 쓰시오.
(p5) 프리트레인–파인튜닝에서 freeze를 하는 이유를 데이터 크기 관점에서 설명하시오.
(p7) zero-shot과 transfer learning을 구분하는 가장 쉬운 기준은?
(p14) GPT의 Causal LM은 어떤 조건부 확률을 최대화하는가?
(p15) (L=L{\text{task}}+\lambda L {\text{LM}})에서 (\lambda)를 작게 두는 직관은?
(p28) BERT 입력 임베딩 3종과 역할을 각각 쓰시오.
(p29) SQuAD에서 start/end를 예측하는 점수화는 어떤 형태인가?
(p39–p43) BPE가 OOV를 줄이는 원리를 2~3줄로 설명하시오.
5.12.2 채점 기준(핵심만)
3번: 파라미터 업데이트 유무 를 말하면 정답
5번: “태스크에 집중하면서도 LM 일반성을 조금 유지(과적합 완화)”면 정답
7번: “각 토큰 벡터와 start/end 벡터의 dot product(선형 점수) 후 softmax”면 정답
6. Hugging Face Library
아래는 네가 정리해둔 실습 코드를 교재형으로 “형식/수식(표기)/코드(실행가능)”까지 통일 해서, 앞뒤 흐름이 끊기지 않게 다시 엮은 최종본이야.
(마지막에 바로 실행 가능한 .ipynb / .py 파일 도 같이 줌)
6.1 이 장의 목표
6.1.1 우리가 “정확히” 하려는 것
pipeline()으로 즉시 추론(inference) 하기
AutoTokenizer로 토큰화 → id 변환 → 텐서 입력 흐름 이해하기
datasets.load_dataset()로 TSV/JSON 데이터 로드 하기
map()으로 전처리(예: HTML unescape) 하기
PyTorch로 학습 루프(training loop) + scheduler 까지 최소 단위로 돌려보기
6.2 실습 준비
6.2.1 설치(로컬/코랩 공통)
pip install -U transformers datasets accelerate torch tqdm
6.2.2 디바이스 선택(공통)
import torch
device = torch. device( "cuda" if torch. cuda. is_available( ) else "cpu" )
device
6.3 Pipeline 빠른 시작
6.3.1 Pipeline이 해주는 일(한 줄 정의)
pipeline(task)는 내부적으로 아래를 자동으로 묶어준다.
[
\text{pipeline} = \text{Tokenizer} \circ \text{Model} \circ \text{PostProcess}
]
즉, 토크나이징 → 모델 forward → 후처리(확률/디코딩) 까지 “한 방”에 처리한다.
6.3.2 (실습 1) fill-mask
from transformers import pipeline
unmasker = pipeline( "fill-mask" )
unmasker( "This course will teach you all about <mask> models" , top_k= 2 )
핵심 포인트
문장 안에 <mask>를 넣으면, pipeline이 해당 모델의 mask 토큰 으로 맞춰서 처리한다.
재현성을 올리려면 모델을 명시하는 게 좋다:
unmasker = pipeline( "fill-mask" , model= "bert-base-uncased" )
6.3.3 (실습 2) sentiment-analysis (docx 텍스트 코드 반영)
from transformers import AutoTokenizer, pipeline
model_name = "klue/roberta-base"
tokenizer = AutoTokenizer. from_pretrained( model_name)
classifier = pipeline( "sentiment-analysis" , model= model_name, tokenizer= tokenizer)
classifier( "이 강의 진짜 도움 많이 됐어요!" )
6.4 Tokenizer → id → Model 입력
6.4.1 토크나이저의 역할(정확 정의)
텍스트 (x)가 들어오면, 모델이 먹을 수 있는 텐서 묶음으로 변환한다.
[
x ;\rightarrow; {\text{input_ids},;\text{attention_mask},;\text{token_type_ids(optional)}}
]
input_ids: 토큰 id 시퀀스
attention_mask: 패딩(0) vs 실제 토큰(1)
token_type_ids: 문장쌍(A/B) 구분(BERT류에서 주로 사용)
6.4.2 (실습 3) docx 이미지 예시 그대로 + 실패 라인 유지
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer. from_pretrained( checkpoint)
model = AutoModelForSequenceClassification. from_pretrained( checkpoint)
sequence = "I've been waiting for a HuggingFace course my whole life."
tokens = tokenizer. tokenize( sequence)
ids = tokenizer. convert_tokens_to_ids( tokens)
input_ids = torch. tensor( ids)
model( input_ids)
왜 실패하나? (원인 “정확히”)
대부분의 Transformer 모델 입력은 배치 차원(batch dimension) 을 기대한다.
지금 input_ids shape:
[
(seq_len,)
]
모델이 기대하는 기본 shape:
[
(batch,;seq_len)
]
6.4.3 Fix(실행되게 만들기): 배치 차원 추가
input_ids = torch. tensor( [ ids] )
model( input_ids)
6.4.4 실무/실습에서 “정석”(추천): tokenizer가 바로 텐서 만들게 하기
이게 제일 덜 틀리고, attention_mask도 자동으로 들어가서 안정적이다.
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer. from_pretrained( checkpoint)
model = AutoModelForSequenceClassification. from_pretrained( checkpoint)
sequence = "I've been waiting for a HuggingFace course my whole life."
inputs = tokenizer( sequence, return_tensors= "pt" )
outputs = model( ** inputs)
logits = outputs. logits
pred = logits. argmax( dim= - 1 ) . item( )
print ( "pred:" , pred, "label:" , model. config. id2label[ pred] )
출력 텐서 shape(시험/디버깅 핵심)
[
\text{logits shape} = (batch,;num_labels)
]
6.5 Tokenizer 내부 구조(backend_tokenizer) + normalizer
6.5.1 왜 보나?
“토큰화가 내부에서 어떻게 동작하는지”를 실제로 확인 하는 용도
특히 normalize_str는 악센트/특수문자 정규화 같은 전처리 감각을 잡기 좋다.
6.5.2 (실습 4) backend_tokenizer + normalizer
from transformers import AutoTokenizer
tokenizer = AutoTokenizer. from_pretrained( "bert-base-uncased" )
print ( type ( tokenizer. backend_tokenizer) )
print ( tokenizer. backend_tokenizer. normalizer. normalize_str( "Héllò hôw are ü?" ) )
6.6 Datasets 로드
from datasets import load_dataset
data_files = { "train" : "drugsComTrain_raw.tsv" , "test" : "drugsComTest_raw.tsv" }
drug_dataset = load_dataset( "csv" , data_files= data_files, delimiter= "\t" )
빠른 확인
drug_dataset[ "train" ] [ "condition" ] [ : 3 ]
6.6.2 JSON 로드(SQuAD_it 예시)
from datasets import load_dataset
data_files = { "train" : "SQuAD_it-train.json" , "test" : "SQuAD_it-test.json" }
squad_it_dataset = load_dataset( "json" , data_files= data_files, field= "data" )
샘플 1개 확인:
squad_it_dataset[ "train" ] [ 0 ]
6.6.3 단일 JSON 로드(일반형)
from datasets import load_dataset
load_dataset( "json" , data_files= "myfile.json" )
6.7 map()으로 전처리(HTML unescape)
6.7.1 목적
리뷰 텍스트에 &, " 같은 HTML 엔티티가 남아있으면 모델 입력이 지저분해진다.
html.unescape로 정리한다.
6.7.2 (실습 5) batched map 적용
import html
new_drug_dataset = drug_dataset. map (
lambda x: { "review" : [ html. unescape( o) for o in x[ "review" ] ] } ,
batched= True ,
)
new_drug_dataset
핵심 포인트
6.8 Training loop (tqdm) + Scheduler
6.8.1 학습 루프가 하는 일(정확 구조)
각 스텝에서:
배치 텐서를 디바이스로 이동
forward: ( \hat{y} = f_\theta(x) )
loss 계산 (보통 Cross Entropy)
backward: ( \nabla_\theta L )
optimizer step
scheduler step
grad reset
분류의 표준 loss는:
[
L = -\sum_{c} y_c \log(\text{softmax}(\text{logits})_c)
]
6.8.2 (실습 6) 진행바 포함 training loop (네 코드 흐름 그대로)
from tqdm import tqdm
progress_bar = tqdm( range ( num_training_steps) )
model. train( )
for epoch in range ( num_epochs) :
for batch in train_dataloader:
batch = { k: v. to( device) for k, v in batch. items( ) }
outputs = model( ** batch)
loss = outputs. loss
loss. backward( )
optimizer. step( )
lr_scheduler. step( )
optimizer. zero_grad( )
progress_bar. update( 1 )
6.8.3 (실습 7) get_scheduler로 LR Scheduler 만들기
from transformers import get_scheduler
num_epochs = 3
num_training_steps = num_epochs * len ( train_dataloader)
lr_scheduler = get_scheduler(
"linear" ,
optimizer= optimizer,
num_warmup_steps= 0 ,
num_training_steps= num_training_steps,
)
print ( num_training_steps)
linear 스케줄 직관
학습이 진행될수록 LR을 선형으로 줄이는 형태
warmup을 쓰면 초반엔 LR을 점점 올린 뒤, 이후 감소
6.9 실습에서 제일 많이 터지는 오류 TOP 6 (바로 해결형)
배치 차원 누락
해결: torch.tensor([ids]) 또는 tokenizer(..., return_tensors="pt")
attention_mask 없음
해결: 수동 입력 말고 tokenizer() 출력 dict 사용
모델/토크나이저 mismatch
해결: 같은 checkpoint로 둘 다 로드
fill-mask에서 마스크 토큰 혼동
해결: pipeline에는 <mask> 쓰면 안전, 직접이면 tokenizer.mask_token 확인
datasets.map에서 batched 처리 실수
GPU 사용 시 device 인자 미지정
해결: pipeline은 device=0, torch는 .to(device)
6.10 바로 실행 가능한 파일
원하면 다음 단계로 HuggingFace실습.docx 이미지들을 “이미지 번호별 → 코드 셀로 정렬 → 중복 제거 → 실행 순서로 재배치” 해서, docx 전체를 1개의 완성 노트북 으로 합치는 버전도 바로 만들어줄게.