본문 바로가기
C.W.K.
Stream
Lesson 03 of 08 · published

활성화: ReLU, GELU, SiLU와 친구들

~10 min · activation, relu, gelu, silu

Level 0텐서 탐구자
0 XP0/62 lessons0/13 achievements
0/120 XP to next level120 XP to go0% complete

비선형성이 신경망을 강력하게 만들어

계층 사이에 비선형 활성화가 없으면 여러 선형 계층도 결국 하나의 더 큰 선형 변환으로 합쳐져. nn.Linear를 몇 번 호출하든 학습 가능한 행렬 하나와 다르지 않다는 뜻이야. 활성화 함수가 있어야 신경망이 복잡한 함수를 배울 수 있어.

실제로 자주 쓰는 활성화 함수

  • ReLU: max(0, x)야. CNN과 초기 MLP의 은닉층에서 기본값처럼 쓰여. 계산이 싸고 효과적이지만 너무 많은 뉴런이 계속 0만 내면 '죽은 ReLU' 문제가 생겨.
  • GELU: 가우시안 오차 선형 유닛이야. BERT, GPT, ViT 같은 현대적인 Transformer의 기본값이야. ReLU보다 부드럽고 조금 느리지만 어텐션 기반 모델에서는 경험적으로 더 좋은 경우가 많아.
  • SiLU(Swish라고도 해): x * sigmoid(x)야. EfficientNet 같은 현대적인 ConvNet과 여러 비전 Transformer에서 널리 쓰여. LLaMA 계열의 FFN 게이팅인 SwiGLU에도 들어가.
  • 시그모이드: 값을 (0, 1) 범위로 압축해. 이진 분류 출력이나 LSTM 게이트, 게이트형 MLP 같은 구조에 써. 깊은 은닉층에서는 기울기가 포화될 수 있으니 피하는 게 좋아.
  • Tanh: 값을 (-1, 1) 범위로 압축해. 요즘은 주로 LSTM 같은 기존 구조에서 만나며, 시그모이드와 같은 포화 문제가 있어.
  • 소프트맥스: 로짓을 확률 분포로 바꿔. 거의 항상 마지막 차원에 적용하며, 분류기의 마지막 활성화나 어텐션 점수를 정규화할 때 사용해.

모듈 형태와 함수형 형태

대부분의 활성화 함수는 nn.ReLU() 같은 모듈 형태와 F.relu(x) 같은 함수형 형태를 모두 제공해. 상태가 없어서 기능은 같아. print(model)이나 model.modules()에 나타나게 하려면 __init__에서 모듈로 만들고, forward() 안에서 한 번만 쓸 거라면 함수형으로 호출해도 좋아.

Code

코드의 핵심 목록·python
import torch
import torch.nn as nn
import torch.nn.functional as F

x = torch.randn(4, 8)

# Module form
relu = nn.ReLU()(x)
gelu = nn.GELU()(x)
silu = nn.SiLU()(x)
sigmoid = nn.Sigmoid()(x)
tanh = nn.Tanh()(x)

# Functional form — same result, no module to declare
relu_f = F.relu(x)
gelu_f = F.gelu(x)
silu_f = F.silu(x)

# Softmax — almost always on the last dim
probs = F.softmax(x, dim=-1)
print(probs.sum(-1))   # tensor([1., 1., 1., 1.])
작업 별 활성화 고르기·python
import torch.nn as nn

# Vision CNN — ReLU is fine, ConvNeXt-style uses GELU
cnn_block = nn.Sequential(nn.Conv2d(3, 32, 3, padding=1), nn.ReLU())

# Transformer block — GELU is the modern default
xfm_ffn = nn.Sequential(nn.Linear(512, 2048), nn.GELU(), nn.Linear(2048, 512))

# Modern ConvNet (EfficientNet flavor) — SiLU
modern_cnn = nn.Sequential(nn.Conv2d(3, 32, 3, padding=1), nn.SiLU())

# Binary classifier output — sigmoid
binary_head = nn.Sequential(nn.Linear(512, 1), nn.Sigmoid())
소프트맥스: 마지막 차원, 수치적으로 안정적인 변형·python
import torch
import torch.nn.functional as F

logits = torch.randn(4, 10)            # batch=4, classes=10

# Probabilities — for inspection / sampling
probs = F.softmax(logits, dim=-1)
assert torch.allclose(probs.sum(dim=-1), torch.ones(4))

# log-softmax — numerically stable for log-likelihood losses
log_probs = F.log_softmax(logits, dim=-1)

# F.nll_loss expects log-probabilities; F.cross_entropy expects raw logits
# (it does log_softmax internally — that's why CE doesn't need a softmax layer
#  in your network)

External links

Exercise

간단한 성능 측정을 해 봐. 무작위 (32, 1024) 텐서를 ReLU, GELU, SiLU에 각각 10,000번 통과시키고 시간을 재. ReLU가 실제로 가장 빠를 거야. GELU와 SiLU는 조금 느리지만 실전에서는 크게 신경 쓰지 않아도 될 정도인지 직접 확인해 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.