신경망 뉴런의 출력에 비선형성을 더하는 함수로, 이게 없으면 층을 아무리 쌓아도 하나의 선형 변환과 같아 복잡한 패턴을 배우지 못한다. 숨은 층에는 ReLU나 GELU, 마지막 층에는 문제 종류에 맞춰 Sigmoid나 Softmax를 쓴다.
| 함수 | 하는 일 | 주로 쓰는 곳 |
|---|---|---|
| ReLU | 음수는 0, 양수는 그대로 | 일반 신경망·CNN의 숨은 층 |
| GELU | ReLU를 부드럽게 만든 형태 | 트랜스포머, LLM |
| Sigmoid | 출력을 0~1로 압축 | 이진 분류 마지막 층 |
| Softmax | 여러 출력을 합이 1인 확률로 | 다중 클래스 분류 마지막 층 |
층과 층 사이에 넣는 함수는 대부분 ReLU로 시작하면 된다. 계산이 단순해서 빠르고, 층이 깊어져도 학습이 잘 된다. 트랜스포머 계열을 만들거나 가져다 쓸 때는 GELU나 SwiGLU가 표준처럼 쓰이므로 원래 구조의 설정을 그대로 따르는 게 안전하다.
Sigmoid나 tanh를 숨은 층에 많이 쌓으면 기울기가 점점 작아져 앞쪽 층이 거의 배우지 못하는 그래디언트 소실이 생기기 쉽다. 그래서 요즘은 숨은 층에 잘 쓰지 않는다.
마지막 층의 활성화 함수는 모델이 내놓을 답의 모양을 정한다. 무엇을 예측하는지에 따라 아래처럼 고른다.
| 문제 | 마지막 층 | 출력 |
|---|---|---|
| 이진 분류 (스팸인가?) | Sigmoid | 0~1 확률 하나 |
| 다중 클래스 (고양이/개/새) | Softmax | 합이 1인 확률 여러 개 |
| 여러 라벨 동시 (태그 달기) | 라벨마다 Sigmoid | 라벨별 독립 확률 |
| 회귀 (집값 예측) | 없음 (선형) | 범위 제한 없는 숫자 |
PyTorch에서는 nn.Linear 같은 층 사이에 nn.ReLU(), nn.GELU()를 레이어처럼 추가한다. Keras에서는 Dense(64, activation="relu")처럼 층을 만들 때 이름으로 지정하면 된다.
주의할 점은 손실 함수와의 중복이다. PyTorch의 nn.CrossEntropyLoss는 내부에서 Softmax 계산을 포함하므로, 모델 끝에 Softmax를 또 넣으면 안 된다. 확률이 필요하면 추론할 때만 따로 적용한다.
ReLU는 음수 입력에서 기울기가 0이라, 어떤 뉴런은 계속 0만 내보내며 학습에서 빠져 버린다(죽은 ReLU). 손실이 줄지 않고 0인 출력이 많다면 음수 쪽에도 작은 기울기를 남기는 Leaky ReLU나 ELU로 바꿔 본다. 다만 학습률이나 가중치 초기화가 원인인 경우도 많으니 그쪽도 함께 확인한다.
활성화 함수는 따로 쓰는 도구라기보다 신경망을 짤 때마다 정하는 설정값이다. 직접 학습시키는 모델이면 숨은 층과 마지막 층을 각각 고르고, 이미 만들어진 모델을 가져다 쓰면 원래 설정을 그대로 둔다.
| 어디서 | 어떻게 쓰나 |
|---|---|
| 이미지 분류 모델 직접 학습 | 숨은 층은 ReLU, 마지막 층은 클래스 수만큼 Softmax |
| 스팸 판별·태그 달기 | 답이 하나면 Sigmoid 하나, 태그가 여러 개면 라벨마다 Sigmoid |
| 트랜스포머·LLM 파인튜닝 | 원래 구조의 GELU·SwiGLU를 바꾸지 않고 그대로 사용 |
| 수치 예측 (가격·수요) | 숨은 층은 ReLU, 마지막 층은 활성화 없이 선형 출력 |