밑바닥부터 시작하는 딥러닝 1 - 출력층과 손실 함수
신경망이 숫자를 출력했다고 해서 바로 학습이 되는 것은 아니다. 출력값을 문제에 맞게 해석해야 하고, 그 결과가 얼마나 틀렸는지도 수치로 평가해야 한다.
이 글에서는 출력층의 소프트맥스와 손실 함수, 특히 교차 엔트로피 오차를 쉬운 채점 방식으로 정리한다.
이번 글에서 잡을 것
- 회귀 문제는 보통 항등 함수를 사용한다.
- 분류 문제는 소프트맥스 함수로 출력을 확률처럼 해석한다.
- 손실 함수는 신경망의 나쁨을 나타내는 벌점이다.
- 교차 엔트로피는 정답 클래스에 준 확률을 중심으로 벌점을 계산한다.
출력층은 문제 종류에 따라 달라진다
| 문제 | 예시 | 출력층 함수 | 출력 해석 |
|---|---|---|---|
| 회귀 | 몸무게 예측 | 항등 함수 | 숫자 자체 |
| 분류 | 숫자 0~9 분류 | 소프트맥스 | 각 클래스의 확률처럼 해석 |
항등 함수는 입력을 그대로 내보낸다. 소프트맥스는 여러 출력값을 0과 1 사이 값으로 바꾸고, 전체 합이 1이 되게 만든다.
소프트맥스에서 오버플로를 조심하는 이유
소프트맥스는 지수 함수 `exp`를 사용한다. 입력값이 너무 크면 컴퓨터가 표현할 수 있는 범위를 넘어 `inf`가 될 수 있다. 그래서 보통 입력값 중 최댓값을 빼고 계산한다.
def softmax(a):
c = np.max(a)
exp_a = np.exp(a - c)
return exp_a / np.sum(exp_a)
왜 결과가 유지될까
모든 입력에서 같은 값을 빼면 지수 함수의 비율은 유지된다. 값의 크기만 안전한 범위로 내려 계산이 안정된다.
손실 함수는 벌점이다
손실 함수는 현재 신경망이 얼마나 못하고 있는지를 나타내는 지표다. 학습의 목표는 이 벌점을 줄이는 방향으로 가중치와 편향을 바꾸는 것이다.
오차제곱합
예측과 정답의 차이를 제곱해 더한다.
교차 엔트로피
정답 클래스에 얼마나 높은 확률을 줬는지 본다.
학습 목표
손실 함수 값을 작게 만드는 매개변수를 찾는다.
교차 엔트로피를 쉽게 보면
교차 엔트로피는 객관식 시험을 채점하는 깐깐한 채점관처럼 볼 수 있다. 정답이 2라면, 이 채점관은 오직 '정답 2에 몇 % 확률을 줬는가'를 본다.
| 정답 확률 | 벌점 크기 | 해석 |
|---|---|---|
| 0.9 | 작음 | 정답을 강하게 확신 |
| 0.6 | 보통 | 정답 가능성을 꽤 높게 봄 |
| 0.1 | 큼 | 정답을 거의 모름 |
원-핫 정답이면 왜 한 항만 남는가
교차 엔트로피 수식이 낯선 이유는 모든 클래스에 대해 더하는 모양으로 쓰여 있기 때문이다. 하지만 정답 레이블이 원-핫 벡터라면 정답 위치만 1이고 나머지는 0이다. 그래서 실제로는 정답 클래스의 확률 하나만 벌점 계산에 남는다.
| 클래스 | 예측 y | 정답 t | t * log(y) | 해석 |
|---|---|---|---|---|
| 0 | 0.10 | 0 | 0 | 정답이 아니므로 사라짐 |
| 1 | 0.05 | 0 | 0 | 정답이 아니므로 사라짐 |
| 2 | 0.60 | 1 | log(0.60) | 정답 클래스라 남음 |
| 3 | 0.25 | 0 | 0 | 정답이 아니므로 사라짐 |
교차 엔트로피를 숫자로 느껴보기
정답이 2번 클래스라고 해보자. 교차 엔트로피는 사실상 정답 클래스에 준 확률만 본다. 정답 확률이 높으면 벌점이 작고, 낮으면 벌점이 커진다.
| 정답 클래스 확률 | 계산 | 벌점 |
|---|---|---|
| 0.9 | -log(0.9) | 약 0.105 |
| 0.6 | -log(0.6) | 약 0.511 |
| 0.1 | -log(0.1) | 약 2.303 |
직관
오답 후보들에 어떤 확률을 나눠줬는지보다, 정답에 충분한 확신을 줬는지가 벌점을 크게 좌우한다.
추론 때 소프트맥스를 생략할 수 있는 이유
소프트맥스는 출력값을 확률처럼 해석하기 좋게 바꾸지만, 가장 큰 값의 위치 자체는 바꾸지 않는다. 그래서 단순히 정답 클래스를 고르는 추론 단계에서는 소프트맥스를 생략하고 `argmax`만 써도 된다.
| 출력 전 점수 | 소프트맥스 후 | 가장 큰 위치 |
|---|---|---|
| [2.0, 1.0, 0.1] | [가장 큼, 작음, 더 작음] | 0번 |
| [0.2, 3.0, 1.5] | [작음, 가장 큼, 중간] | 1번 |
단, 학습 때는 다르다
손실 함수를 계산해 매개변수를 학습할 때는 소프트맥스와 손실 함수가 함께 쓰인다.
코드로 확률과 벌점 확인하기
소프트맥스는 점수를 확률처럼 바꾸고, 교차 엔트로피는 정답 확률이 낮을수록 벌점을 크게 만든다.
import numpy as np
def softmax(x):
x = x - np.max(x)
return np.exp(x) / np.sum(np.exp(x))
score = np.array([2.0, 1.0, 0.1])
y = softmax(score)
print(np.round(y, 3))
print(np.sum(y))
print(round(-np.log(0.6), 3))
print(round(-np.log(0.1), 3))
예상 출력
[0.659 0.242 0.099]
1.0
0.511
2.303
스스로 점검
- 회귀와 분류에서 출력층 함수를 다르게 쓰는 이유를 설명할 수 있는가?
- 소프트맥스에서 최댓값을 빼는 이유를 말할 수 있는가?
- 교차 엔트로피가 무엇을 벌점으로 보는지 설명할 수 있는가?
이번 글에서 기억할 것
- 회귀 문제는 보통 항등 함수를 사용한다.
- 분류 문제는 소프트맥스 함수로 출력을 확률처럼 해석한다.
- 손실 함수는 신경망의 나쁨을 나타내는 벌점이다.
- 교차 엔트로피는 정답 클래스에 준 확률을 중심으로 벌점을 계산한다.
다음 글로 이어지는 질문
다음 글에서는 정확도 대신 손실 함수를 쓰는 이유와 미분의 역할을 본다.
한 줄 정리: 출력층은 답을 해석하는 방식이고, 손실 함수는 그 답이 얼마나 나쁜지를 학습 가능한 숫자로 바꾸는 장치다.