BERT, GPT
Seq2Seq 구조가 항상 정답일까 #
트랜스포머는 인코더(이해) + 디코더(생성)가 결합된 완벽한 번역기다.
하지만 AI 엔지니어들은 깨닫는다. 우리가 풀고싶은 문제가 번역(A시퀀스를 B시퀀스로 변환)이 아니라는 것을.
- Understanding의 문제: 어떤 문장이 긍정인지 부정인지 분류하거나 문서에서 정답을 찾아내는 작업에는 굳이 단어를 새롭게 생성하는 디코더가 필요없다.
- Generation의 문제: 소설을 쓰거나 사용자와 대화를 나누는 작업은 굳이 완성된 원본 문장을 깊게 분석하는 인코더 없이, 그냥 앞 문맥만 보고 다음 단어를 끝말잇기하듯 뱉어내는 디코더만 있어도 충분하다.
"트랜스포머를 반으로 쪼개자. 문맥을 이해하는 데 특화된 인코더만 때어내서 극대화하고 말을 만들어내는데 특화된 디코더만 때어내서 극대화하자" 라는 개념이 나오게 된다.
BERT (Bidirectional Encoder Representations form Transformers) #
문장의 깊은 의미와 문맥을 양방향(Bidrectional)으로 완벽하게 이해하는것이다.
트랜스포머의 Encoder 블록만 여러층 쌓아 올린 구조이다.
마스크드 언어 모델 MLM (Masked Language Modeling) #
인코더는 문장의 모든 단어를 동시에 바라볼 수 있다. (셀프 어텐션) 이를 이용해 BERT는 빈칸을 채우는 시험을 본다.
입력 문장의 단어 중 15%를 무작위로 [MASK] 하여 가려버린다.
- ex. 나는 오늘 맛있는
[MASK]를 먹었다.
모델은 [MASK] 자리에 올 단어가 무엇인지 가려진 단어의 왼쪽 문맥 (나는 오늘 아침을 맛있는)과 오른쪽 문맥 ("을 먹었다")를 동시에 양방향으로 참조하여 유추한다.
이 가혹한 빈칸 채우기 혼란속에 수억 개의 문장을 반복하면, 모델은 단어들 사이의 복잡한 문법과 의미론적 관계를 매우 깊이있게 이해하게 된다. 분류 감성 분석등에 탁월한 것이다.
GPT Generative Pre-trained Transformer #
주어진 문맥을 바탕으로 가장 자연스러운 다음 단어를 예측하여 문장을 생성하는 것이다.
트랜스포머의 Decoder 블록만을 쌓아 여러개 올린 구조고 단 인코더가 없으므로 인코더-디코드 크로스 어텐션 계층은 제거가 된다.
자기 회귀 언어 모델 Autoregressive Language Modeling #
GPT는 양방향으로 문맥을 보지 않는다. 글을 읽거나 쓸 때 처럼 왼쪽에서 오른쪽으로 단방향 Unidirectional만 문맥을 본다
수학적으로 이는 조건부 확률 를 극대화 하는 과정이고 즉, 이전 까지의 단어들이 주어졌을 때, 다음에 올 단어의 확률을 맞추는 끝말잇기 훈련이다.
미래의 단어를 미리 보고 답을 맞추는 부정행위를 막기 위해 3단계에서 언급한 마스크드 셀프 어텐션을 강력하게 적용한다. 현재 시점 이후의 단어(미래)들과 어텐션 스코어는 모두 infinity로 가린다.
BERT로 챗봇을 만들수 없는 이유 #
양방향으로 문맥을 더 깊게 이해하는 BERT는 GPT보다 우월해보일 수 있지만 BERT는 본질적으로 Generation을 할 수 없다.
BERT는 문장 전체가 주어져야만 그 안에서 관계를 파악하고 아무것도 없는 백지상태에서 첫 단어를 뱉고 그 다음 단어를 뱉어내는 순차적인 생성 로직이 아키텍처에 없다.
반면 GPT는 처음부터 앞 단어들만 보고 다음 단어를 예측하는 구조로 훈련되어 있기 때문에 꼬리에 꼬리를 무는 대화 ChatGPT, 텍스트 생성에 완벽하게 부합하다. 처음에는 단순해보였지만 모델 사이즈 파라미터 수를 기하급수적으로 키우자 이 단순한 다음 단어 예측 메커니즘이 인간 수즌의 추론 능력을 창발하게 되었다.
Example #
BERT, GPT 두 모델의 아키텍처적 차이는 결국 셀프 어텐션 내부의 마스크 형태 하나로 갈린다.
import torch
seq_len = 5 # 5단어짜리 문장 가정
# ---------------------------------------------------------
# 1. BERT의 어텐션 마스크 (Padding Mask 위주)
# ---------------------------------------------------------
# BERT는 양방향을 모두 보아야 하므로, 미래를 가리는 마스크가 없습니다.
# 단지 문장 길이를 맞추기 위해 채워 넣은 무의미한 [PAD] 토큰만 가려줍니다.
# 예: 3단어 문장 + 2개 패딩 -> [Word, Word, Word, PAD, PAD]
bert_mask = torch.tensor([
[1, 1, 1, 0, 0], # 1은 어텐션 허용, 0은 어텐션 차단(-inf로 처리됨)
[1, 1, 1, 0, 0],
[1, 1, 1, 0, 0],
[1, 1, 1, 0, 0],
[1, 1, 1, 0, 0]
])
print("BERT Mask (모든 실제 단어가 서로를 참조 가능):\n", bert_mask)
# ---------------------------------------------------------
# 2. GPT의 어텐션 마스크 (Causal Mask / Look-ahead Mask)
# ---------------------------------------------------------
# GPT는 미래의 단어를 보면 안 되므로, 하삼각 행렬(Lower Triangular) 형태로
# 자기 자신과 자기보다 과거에 있는 단어만 참조하도록 마스킹합니다.
# torch.tril (triangular lower) 함수를 사용합니다.
gpt_mask = torch.tril(torch.ones(seq_len, seq_len))
print("\nGPT Mask (미래 단어 참조 불가):\n", gpt_mask)
# 출력 결과 해석:
# 첫 번째 단어(행 1)는 첫 번째 단어만 볼 수 있음. [1, 0, 0, 0, 0]
# 두 번째 단어(행 2)는 첫 번째, 두 번째 단어만 볼 수 있음. [1, 1, 0, 0, 0]
# ...
이렇게 마스크 행렬의 형태 하나가 행렬 곱셈 연산에 개입함으로써 똑같은 트랜스포머의 셀프 어텐션 모듈이 문맥을 관조하는 BERT가 될지 말을 이어나갈 GPT가 될지 결정하게 된다.