머신러닝·신경망

DL / 24번째 글

활성화 함수: ReLU·Sigmoid·GELU의 모든 것

신경망의 비선형성을 담당하는 활성화 함수를 완전 정복한다. Sigmoid, Tanh, ReLU, Leaky ReLU, GELU, Swish의 수식·특성·한계를 비교하고, 실무에서 어떤 상황에 어떤 함수를 선택해야 하는지를 알아본다.

PALDYN Team7 MIN READ

지난 글에서 신경망이 층별 행렬 연산으로 이루어진다는 것을 배웠고, 활성화 함수 없이는 아무리 층을 쌓아도 선형 변환에 불과하다는 것을 확인했다. 이번 글은 그 핵심인 활성화 함수(Activation Function)를 집중적으로 파헤친다. 활성화 함수는 신경망에 비선형성을 부여해 복잡한 패턴 학습을 가능하게 한다. 어떤 함수가 있는지, 각각 어떤 특성과 한계를 가지는지, 실무에서 어떻게 선택하는지를 코드와 함께 완전히 이해한다.

왜 비선형 활성화가 필요한가

선형 변환 y = Wx + b을 아무리 쌓아도 결국 하나의 선형 변환으로 축약된다. 비선형 활성화 함수가 있어야 신경망이 보편 함수 근사기(Universal Function Approximator)가 될 수 있다. 이것이 활성화 함수의 존재 이유다.

좋은 활성화 함수의 조건:

  1. 비선형성: 선형 모델로 표현 불가능한 함수를 근사할 수 있어야 함
  2. 미분 가능성: 역전파(gradient descent) 계산이 가능해야 함
  3. 계산 효율: 순전파/역전파 시 빠르게 계산될 수 있어야 함
  4. 기울기 소실 방지: 깊은 네트워크에서 기울기가 소멸되지 않아야 함

Sigmoid 함수

σ(z)=11+e−z\sigma(z) = \frac{1}{1 + e^{-z}}

출력 범위가 (0, 1)이므로 이진 분류의 출력층에 자주 사용된다. 하지만 은닉층에서는 잘 쓰이지 않는다.

import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt

x = torch.linspace(-6, 6, 200)

sigmoid = torch.sigmoid(x)
# 기울기: σ(z)·(1−σ(z)) → 최대값 0.25 (z=0에서)
# z가 크거나 작으면 기울기 ≈ 0 → 기울기 소실 문제

Sigmoid의 문제점:

  • 기울기 소실(Vanishing Gradient): z가 크거나 작으면 기울기가 0에 수렴. 깊은 네트워크에서 초기 층의 학습이 거의 안 됨
  • 비제로 중심 출력: 출력이 항상 양수여서 가중치 업데이트가 항상 같은 방향으로만 이루어짐 → 지그재그 수렴

Tanh 함수

tanh⁡(z)=ez−e−zez+e−z\tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}

Sigmoid의 스케일 조정 버전으로, 출력이 (-1, 1) 범위로 제로 중심(zero-centered)이다. Sigmoid보다 낫지만 기울기 소실 문제는 여전히 존재한다. RNN에서 주로 사용된다.

ReLU

ReLU(z)=max⁡(0,z)\text{ReLU}(z) = \max(0, z)

ReLU(Rectified Linear Unit)는 2010년대 딥러닝 혁명을 이끈 활성화 함수다. 단순하지만 매우 효과적이다.

# ReLU 구현
relu = F.relu(x)
# 미분: z > 0이면 1, z < 0이면 0
# → 양수 영역에서 기울기 소실 없음
# → 계산이 매우 빠름 (단순 max 연산)

# Leaky ReLU: 음수 영역의 기울기를 작게 유지
leaky_relu = F.leaky_relu(x, negative_slope=0.01)
# 미분: z > 0이면 1, z < 0이면 0.01

ReLU 장점:

  • 양수 영역에서 기울기 소실 없음
  • 계산 비용이 매우 낮음 (max 연산)
  • 희소 활성화: 음수 입력을 0으로 만들어 뉴런의 선택적 활성화

Dying ReLU 문제: 학습 중 일부 뉴런의 입력이 항상 음수가 되면, 해당 뉴런은 영구적으로 출력 0을 내보내고 기울기도 0이 되어 더 이상 학습하지 않는다. 해결책: Leaky ReLU, ELU, 낮은 학습률, 배치 정규화.

GELU

GELU(z)=z⋅Φ(z)\text{GELU}(z) = z \cdot \Phi(z)

GELU(Gaussian Error Linear Unit)의 식에서 Φ는 표준 정규 분포의 CDF다. 실용적 근사:

GELU(z)≈0.5z(1+tanh⁡[2π(z+0.044715z3)])\text{GELU}(z) \approx 0.5z\left(1 + \tanh\left[\sqrt{\frac{2}{\pi}}(z + 0.044715z^3)\right]\right)

# GELU — BERT, GPT 등 트랜스포머에서 사용
gelu = F.gelu(x)

# Swish (SiLU) — LLaMA, Mistral 등에서 사용
swish = F.silu(x)  # z * sigmoid(z)

# 비교
print(f"GELU(1.0) = {F.gelu(torch.tensor(1.0)):.4f}")
print(f"ReLU(1.0) = {F.relu(torch.tensor(1.0)):.4f}")
print(f"Swish(1.0) = {F.silu(torch.tensor(1.0)):.4f}")
# GELU(1.0) = 0.8413
# ReLU(1.0) = 1.0000
# Swish(1.0) = 0.7311

GELU는 ReLU보다 부드럽고(미분 가능), 음수 입력에서도 작은 값을 허용한다. BERT, GPT, ViT 등 대부분의 트랜스포머 모델이 GELU를 사용한다.

활성화 함수 비교

출력층에서의 활성화 함수

은닉층과 달리 출력층의 활성화 함수는 문제 유형에 따라 결정된다.

문제 유형 활성화 함수 이유
이진 분류 Sigmoid 확률 (0~1) 출력
다중 분류 Softmax 클래스 확률 합 = 1
회귀 없음 (Linear) 임의의 실수값
다중 레이블 Sigmoid (각각) 독립적 이진 판단
# 소프트맥스: 다중 분류 출력
logits = torch.tensor([2.0, 1.0, 0.5])
probs = torch.softmax(logits, dim=0)
print(probs)  # [0.6590, 0.2424, 0.0986]
print(probs.sum())  # tensor(1.0000) ← 합산 항상 1

# 실제로는 CrossEntropyLoss가 softmax를 내부 포함
# → 출력층에 Softmax 명시적으로 넣지 않아도 됨
criterion = torch.nn.CrossEntropyLoss()

활성화 함수 구현

실무 선택 가이드

  • 은닉층 기본값: ReLU. 대부분의 경우 잘 동작한다.
  • 트랜스포머 은닉층: GELU 또는 SiLU(Swish). 성능이 약간 더 좋다.
  • RNN 게이트: Sigmoid와 Tanh 조합 (LSTM/GRU 설계 자체에 내장)
  • 깊은 네트워크에서 ReLU 문제 시: Leaky ReLU, ELU, 또는 배치 정규화 추가
  • 출력층: 문제 유형에 따라 결정 (위 표 참고)

활성화 함수는 학습 안정성에 큰 영향을 미친다. 다음 글에서 배울 역전파(Backpropagation)에서 활성화 함수의 미분이 핵심 역할을 한다.


읽어주셔서 감사합니다. 😊

LATEST

머신러닝·신경망의 최신 글

머신러닝·신경망2026.05.08

문맥적 임베딩: ELMo부터 BERT까지

정적 임베딩의 다의어 문제를 해결하는 문맥적 임베딩의 원리, ELMo의 양방향 LSTM 레이어 표현, BERT의 트랜스포머 기반 서브워드 임베딩 추출법을 수식과 코드로 완전히 해설한다.

12 MIN
머신러닝·신경망2026.05.08

FastText: 부분 단어로 OOV를 정복하다

FastText가 문자 n-gram 기반의 부분 단어 모델로 OOV 문제를 해결하는 방법, 한국어 형태론에서의 강점, 실전 학습과 추론 코드를 완전히 해설한다.

11 MIN
머신러닝·신경망2026.05.08

GloVe: 전역 공기 통계로 단어 벡터를 만들다

GloVe가 공기 행렬의 전역 통계와 국소 문맥 창의 장점을 결합하는 방법, 목적 함수의 수학적 의미, 사전 학습 벡터 활용법을 깊이 있게 다룬다.

11 MIN