1. 손실함수
- 신경망이 최적의 매개변수 값을 탐색하는데 사용하는 지표
1.1. 오차제곱합
- 가장 많이 쓰이는 손실 함수는 오차제곱합(SSE, sum of squares for error)이다.
$$
\text{E} = \frac{1}{2}\sum_{k} (y_k - t_k)^2
$$
- $y_k$는 신경망의 출력, $t_k$는 정답 레이블, k는 데이터의 차원 수를 나타낸다.
import numpy as np
def sum_squares_error(y, t):
return 0.5 * np.sum((y-t)**2)
# 정답은 2인 원-핫 인코딩
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
# 예1 : '2'일 확률이 가장 높다고 추정(0.6)
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
print(sum_squares_error(np.array(y), np.array(t)))
# 예2 : '7'일 확률이 가장 높다고 추정(0.6)
y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
print(sum_squares_error(np.array(y), np.array(t)))
"""
출력
0.09750000000000003
0.5975
"""
- 오차 제곱합을 구현한 sum_squares_error() 함수와 예제 출력 2개이다.
- 정답인 출력은 오차가 0.097
- 오답인 출력은 오차가 0.597
- 오차제곱합 기준으로는 첫 번째 추정 결과가 정답에 더 가까울 것으로 판단할 수 있다.
1.2. 교차 엔트로피 오차
$$
\text{E} = -\sum_{k} t_k\log y_k
$$
- log는 밑이 e인 자연로그($log_e$)이다. $y_k$는 신경망의 출력, $t_k$는 정답 레이블
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
print(cross_entropy_error(np.array(y), np.array(t)))
print(cross_entropy_error(np.array(y), np.array(t)))
"""
출력
0.510825457099338
2.302584092994546
"""
- cross_entropy_error() 함수를 보면 np.log를 계산할 때 delta 라는 값을 더했는데
- 이는 np.log() 함수에 0을 입력하면 마이너스 무한대인 -inf가 되어 더 이상 계산을 진행할 수 없게 되기 때문이다.
- 정답인 출력은 오차가 0.510
- 오답인 출력은 오차가 2.302
2. 미니배치 학습
- 머신러닝은 훈련 데이터를 사용해 손실 함수의 값을 구하고, 그 값을 최대한 줄여주는 매개변수를 찾아낸다.
- 이렇게 하려면 모든 훈련 데이터를 대상으로 손실 함수 값을 구해야한다.
- 지금까지는 데이터 하나에 대한 손실 함수만을 구했으니, 이제 훈련 데이터 모두에 대한 손실 함수의 합을 구해보겠다.
2.1. 미니배치 학습(교차 엔트로피)
- 정답 레이블이 원-핫 인코딩일 때
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
print(x_train.shape) # (60000, 784)
print(t_train.shape) # (60000, 10)
train_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
delta = 1e-7
return -np.sum(t * np.log(y + delta)) / batch_size
- 정답 레이블이 원-핫 인코딩이 아니라 '2'나 '7'등의 숫자 레이블로 주어졌을 때의 교차 엔트로피 오차 함수는 다음과 같이 구현할 수 있다.
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
delta = 1e-7
return -np.sum(np.log(y[np.arange(batch_size), t] + delta)) / batch_size
2.2. 왜 손실함수를 설정하는가?
- 머신러닝에서 정확도라는 지표를 놔두고 손실함수를 설정하는 이유는 무엇일까?
- 이 의문은 신경망 학습에서의 미분의 역할에 주목한다면 해결된다.
- 신경망 학습에서는 최적의 매개변수(가중치와 편향)를 탐색할 때 손실 함수의 값을 최대한 작게 하는 매개변수 값을 찾는다.
- 이때 매개변수의 미분(정확히는 기울기)을 계산하고, 그 미분 값을 단서로 매개변수의 값을 서서히 갱신하는 과정을 반복한다.
- 정확도를 지표로 삼아서는 안 되는 이유는 미분 값이 대부분의 장소에서 0이 되어 매개변수를 갱신할 수 없기 때문이다.
- 신경망을 학습할 때 정확도를 지표로 삼아서는 안된다. 정확도를 지표로 하면 매개변수의 미분이 대부분의 장소에서 0이 되기 때문이다.
'TIL > 밑바닥부터 시작하는 딥러닝' 카테고리의 다른 글
학습 알고리즘 (1) | 2024.06.18 |
---|---|
경사법 (1) | 2024.06.16 |
소프트맥스 함수 (0) | 2024.06.15 |
Numpy 다차원 배열의 계산 (0) | 2024.06.14 |
활성화 함수 (0) | 2024.06.14 |