Transformer 구조를 공부하다 보면 FFN(Feed-Forward Network)이라는 용어가 자주 등장합니다.
이 FFN은 사실상 MLP(Multi-Layer Perceptron)의 특별한 형태이며, 각 토큰 위치에 독립적으로 동일한 MLP를 적용하는 Position-wise MLP라고 불립니다.
이 글에서는 FFN의 구조와 작동 방식, 그리고 일반적인 MLP와의 차이점을 코드와 함께 쉽게 정리해보겠습니다.
Transformer FFN은 2층으로 구성된 단순한 MLP입니다.
| 층 | 연산 | 설명 |
|---|---|---|
| 1층 | 차원 확장 (보통 4배) | |
| 활성화 | 비선형성 부여 | |
| 2층 | 원래 차원으로 복원 |
예시:
| 항목 | FFN (Transformer) | 일반적인 MLP |
|---|---|---|
| 위치 의존성 | ❌ 없음 (Position-wise) | 보통 없음 |
| 파라미터 공유 | ✅ 동일 FFN을 모든 토큰에 적용 | 일반적으로 아님 |
| 연산 방식 | 각 토큰에 독립적으로 MLP 적용 | 전체 입력에 한 번에 적용 |
| 계층 수 | 2층 (Linear → ReLU → Linear) | 다양함 (2층 이상 가능) |
MLP는 입력 벡터를 선형변환 → 활성화 → 선형변환의 과정을 거치는 기본적인 신경망입니다.
원문 정의:
"applied to each position separately and identically"
| 설명 | 의미 |
|---|---|
| separately | 위치마다 독립 처리 |
| identically | 동일한 가중치 사용 |
| 레이어 간에는 다름 | 레이어마다 FFN 파라미터는 다름 |
| 구분 | 일반 MLP | Position-wise MLP |
|---|---|---|
| 입력 구조 | 개별 벡터 or 배치 | 시퀀스 (위치 정보 포함) |
| 위치 인식 | ❌ 없음 | ✅ 위치마다 처리 |
| 처리 방식 | 전체 입력에 한 번 적용 | 각 토큰에 독립 적용 |
| 파라미터 공유 | 입력 샘플 간 공유 | 시퀀스 내 위치 간 공유 |
| 입력 Shape | 의미 | 출력 Shape |
|---|---|---|
[batch_size, d_in] | 벡터(batch 단위) | [batch_size, d_out] |
[batch_size, seq_len, d_in] | 시퀀스 (batch × 토큰) | [batch_size, seq_len, d_out] |
mlp = nn.Sequential(
nn.Linear(d_in, d_hidden),
nn.ReLU(),
nn.Linear(d_hidden, d_out)
)
x = torch.randn(batch_size, d_in)
y = mlp(x) # 출력: [batch_size, d_out]
ffn = nn.Sequential(
nn.Linear(d_model, d_ff),
nn.ReLU(),
nn.Linear(d_ff, d_model)
)
x = torch.randn(batch_size, seq_len, d_model)
y = ffn(x) # 출력: [batch_size, seq_len, d_model]
📌 nn.Linear는 마지막 차원에만 적용되므로, 각 토큰에 자동으로 position-wise로 처리됩니다.
입력 시퀀스:
x₁ (512차원)
x₂ (512차원)
x₃ (512차원)
↓ 동일한 MLP 적용
FFN(x₁)
FFN(x₂)
FFN(x₃)
↓ 출력 시퀀스
y₁ (512차원)
y₂ (512차원)
y₃ (512차원)
| 항목 | 내용 |
|---|---|
| FFN 구조 | Linear → ReLU → Linear (2층 MLP) |
| 핵심 개념 | Position-wise MLP |
| 처리 방식 | 각 토큰에 동일한 FFN 독립 적용 |
| 효율성 | 병렬 처리 가능, shape 보존 |
| PyTorch 구현 | nn.Linear 사용으로 간단 구현 가능 |
Transformer의 FFN은 단순하지만 강력한 구조입니다.
이를 Position-wise MLP로 이해하면, Transformer의 병렬성과 효율성의 핵심도 함께 이해할 수 있습니다.