SwiGLU
SwiGLU는 SiLU 활성화가 적용된 프로젝션에 두 번째 선형 프로젝션을 곱하는 구조로, Llama, PaLM, Qwen의 게이트형 피드포워드 레이어에 사용됩니다. 코드를 포함합니다.
SwiGLU(Swish 게이트 선형 유닛)는 트랜스포머의 피드포워드 계층을 변형한 게이트 방식입니다. 각 토큰 벡터를 두 번 투영하고, 한 투영값에 SiLU(Swish) 활성화 함수를 적용한 뒤 두 값을 요소별로 곱하고, 곱의 결과를 모델 차원으로 다시 투영합니다. FFN(x) = (SiLU(xW) ⊙ xV)W₂입니다. Noam Shazeer는 2020년 논문 GLU Variants Improve Transformer에서 이를 소개했으며, 이후 PaLM, Llama, Mistral, Qwen과 같은 대규모 언어 모델(LLM)의 피드포워드 블록으로 자리 잡았습니다. 각 숫자에 독립적으로 작용하는 ReLU나 GELU와 달리, SwiGLU에는 학습된 가중치가 포함되어 있어 그 자체로 작은 계층을 구성합니다.
SwiGLU 작동 방식#
표준 트랜스포머 피드포워드 네트워크(FFN)는 하나의 가중치 행렬로 각 토큰 벡터의 차원을 확장하고, 활성화 함수를 적용한 다음 두 번째 행렬로 차원을 다시 축소합니다. SwiGLU는 첫 번째 행렬과 활성화 함수를 게이트 선형 유닛(GLU)으로 대체합니다. GLU는 동일한 입력을 두 개의 병렬 투영으로 처리합니다:
- 게이트 투영: xW에 SiLU, 즉 x · σ(x)를 적용합니다. 그 결과 강한 음수 입력에는 0에 가까운 값이, 양수 입력에는 입력에 가까운 값이 생성됩니다.
- 값 투영: xV는 선형 상태를 유지하며 콘텐츠를 전달합니다.
- 요소별 곱: 두 값을 곱하면 입력에 따라 게이트가 각 은닉 특성의 값을 키우거나 줄이거나 거의 0으로 만들 수 있으며, 출력 투영 W₂는 결과를 다시 모델 차원으로 변환합니다.
게이팅 개념은 Dauphin과 동료들이 2016년 게이트 합성곱 언어 모델에 사용한 시그모이드 게이트를 갖춘 GLU에서 비롯되었습니다. Shazeer의 논문에서는 같은 구조에 서로 다른 게이트 함수를 적용하고 각 변형에 활성화 함수의 이름을 붙였습니다. GLU는 시그모이드, ReGLU는 ReLU, GEGLU는 GELU, SwiGLU는 Swish를 사용하며, 쌍선형 계층은 활성화 함수를 사용하지 않습니다. T5 코드베이스를 따라 이러한 계층에서는 편향 항을 제거합니다.
LLM에서 SwiGLU가 ReLU와 GELU를 대체한 이유#
게이트 피드포워드 계층은 가중치 행렬을 두 개가 아닌 세 개 사용하므로, Shazeer는 매개변수 수와 연산량을 동일하게 유지하기 위해 은닉 차원을 2/3로 줄였습니다. T5-base 모델에서는 유닛 수를 3,072개에서 2,048개로 줄였습니다. 동일한 크기에서 SwiGLU는 학습 단계 524,288회 후 홀드아웃 로그 퍼플렉시티 1.636을 기록했습니다. ReLU는 1.677, GELU는 1.679를 기록했으며, GLUE 및 SuperGLUE 언어 이해 벤치마크에서도 더 높은 평균 점수를 얻었습니다. 논문은 성능 향상의 이론을 제시하지 않으며, 결론에서는 이러한 아키텍처의 성공을 "다른 모든 것과 마찬가지로 신의 자비 덕분"이라고 설명합니다.
이 결과는 대규모 모델에서도 이어졌습니다. Google의 PaLM은 2022년에 SwiGLU를 채택했고, Meta의 LLaMA는 2023년에 ReLU를 SwiGLU로 대체했습니다. 은닉 차원은 2/3 × 4d를 사용하고 256의 배수로 올림했으며, 이에 따라 4,096차원 7B 모델의 은닉 유닛은 11,008개가 되었습니다. Llama 2, Llama 3, Mistral, Qwen도 이 설계를 유지했습니다. Mixtral과 같은 전문가 혼합(MoE) 모델에서는 각 전문가가 SwiGLU 피드포워드 블록으로 구성됩니다.
PyTorch에서 SwiGLU 구현#
아래 PyTorch 코드 조각은 512차원 모델에 표준 ReLU 피드포워드 계층과 SwiGLU 계층을 구성하고 크기를 비교합니다:
import torch
import torch.nn.functional as F
from torch import nn
d_model = 512
x = torch.randn(4, d_model) # four token vectors
# Standard transformer FFN: two matrices around a 4x wider ReLU hidden layer
relu_ffn = nn.Sequential(nn.Linear(d_model, 2048, bias=False), nn.ReLU(), nn.Linear(2048, d_model, bias=False))
# SwiGLU FFN: three matrices, hidden width cut to about 2/3 of 2048
w_gate = nn.Linear(d_model, 1365, bias=False)
w_value = nn.Linear(d_model, 1365, bias=False)
w_out = nn.Linear(1365, d_model, bias=False)
y = w_out(F.silu(w_gate(x)) * w_value(x)) # (SiLU(xW) * xV) W2
relu_params = sum(p.numel() for p in relu_ffn.parameters())
swiglu_params = sum(m.weight.numel() for m in (w_gate, w_value, w_out))
print(f"ReLU FFN: output {tuple(relu_ffn(x).shape)}, {relu_params:,} parameters")
print(f"SwiGLU FFN: output {tuple(y.shape)}, {swiglu_params:,} parameters")출력은 ReLU FFN: output (4, 512), 2,097,152 parameters과 SwiGLU FFN: output (4, 512), 2,096,640 parameters입니다. 은닉 유닛이 1,365개, 즉 2,048개의 약 2/3일 때, SwiGLU의 세 행렬에 포함된 가중치 수는 ReLU의 두 행렬과 거의 같습니다. 따라서 품질 차이는 게이팅에서 비롯됩니다. 많은 구현에서는 게이트 행렬과 값 행렬을 하나의 투영으로 결합한 다음 출력을 절반씩 나누어, 더 작은 행렬 곱셈 두 번 대신 더 큰 행렬 곱셈 한 번을 수행합니다.
SwiGLU와 관련 용어 비교#
- SiLU(Swish): SiLU는 게이트 내부에서 사용되는 요소별 함수입니다. SwiGLU는 세 가지 투영으로 구성된 게이트 계층 전체를 가리킵니다.
- GLU 및 GEGLU: 시그모이드 게이트 또는 GELU 게이트를 사용하는 형제 변형입니다. Shazeer의 테스트에서 GEGLU는 로그 퍼플렉시티 1.633으로 SwiGLU와 비슷한 결과를 냈으며, Google의 Gemma 모델에서 사용됩니다.
- 어텐션: 어텐션도 데이터에 따라 달라지는 가중치를 생성하지만 토큰 간에 정보를 혼합합니다. SwiGLU는 각 토큰 내에서 독립적으로 특성을 게이트합니다.
- 비전 모델: 게이트 피드포워드 계층은 비전 및 멀티모달 모델에도 사용됩니다. Tsinghua University 연구자들이 개발한 오픈 보캐뷸러리 탐지기로 Ultralytics 패키지에서 실행되는 YOLOE는 잔차 SwiGLU 블록을 사용해 클래스 프롬프트의 텍스트 임베딩을 개선합니다. 이 블록은
set_classes()호출당 한 번 실행되고 내보내기 시 제거되므로 프레임별 추가 비용이 발생하지 않습니다.










