비선형성이 신경망을 강력하게 만들어
계층 사이에 비선형 활성화가 없으면 여러 선형 계층도 결국 하나의 더 큰 선형 변환으로 합쳐져. 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() 안에서 한 번만 쓸 거라면 함수형으로 호출해도 좋아.