4.2 손실 함수

 

신경망 학습에서 현재의 상태를 '하나의 지표'로 표현하는데, 그 지표가 바로 손실 함수이다. 손실 함수는 가중치 매개변수의 값의 탐색에 따라서 달라진다. 손실 함수는 임의의 함수를 사용할 수 도 있지만, 일반적으로 평균 제곱 오차와 교차 엔트로피 오차를 사용한다.

 

4.2.1 평균 제곱 오차 (Mean squared error, MSE)

 

y_k: 신경망의 출력

t_k: 정답 레이블

k: 데이터 차원 수

 

import numpy as np

#평균 제곱 오차
def mean_squared_error(y, t):
    return 0.5 * np.sum((y-t)**2)

t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] #정답은 '2'
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0] # '2'일 확률이 가장 높다고 추정(0.6)
y2 = [0.1,0.05,0.1,0.0,0.05,0.1,0.0,0.6,0.0,0.0] # '7'일 확률이 가장 높다고 추정(0.6)

print(mean_squared_error(np.array(y), np.array(t)))
print(mean_squared_error(np.array(y2), np.array(t)))


>>>
0.09750000000000003
0.5975

위 코드를 살펴보자, 정답 레이블은 2번째 (0부터 세서)라고 규정하고 있다. 이 때 2번을 답으로 추정했다면 오차가 0.09가 나오지만, '7'이라고 추정하는 경우 0.59정도의 오차를 가진다. 즉 답을 맞게 추정할수록 오차가 적게 나온다.

 

 

4.2.2 교차 엔트로피 오차 (Cross entropy error, CEE)

 

오랜만에 듣는 이름이다. 대1 때 처음 배우고는 기억이 안나는 개념인데... 엔트로피는 일단 무질서도를 의미한다. 

(로그는 상용로그가 아닌 자연로그이다)

def cross_entropy_error(y, t):
    delta = 1e-7
    return -np.sum(t*np.log(y+delta)) #log 0 을 방지하기 위한 값

t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
y2 = [0.1,0.05,0.1,0.0,0.05,0.1,0.0,0.6,0.0,0.0]

print(cross_entropy_error(np.array(y), np.array(t)))
print(cross_entropy_error(np.array(y2), np.array(t)))

>>>
0.510825457099338
2.302584092994546

 

4.2.3 미니배치 학습

 

훈련 데이터로부터 일부만 골라 학습을 수행하는 것을 미니배치(mini-batch)라고 한다.

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)

train_size = x_train.shape[0] #60000만 개 데이터
batch_size = 10 # 무작위로 10개만 뽑을 것
batch_mask = np.random.choice(train_size, batch_size) #랜덤하게 10개 뽑음
x_batch = x_train[batch_mask] #tuple을 담은 array가 생성됨
t_batch = t_train[batch_mask] #tuple을 담은 array가 생성됨

 

4.2.4 (배치용) 교차 엔트로피 오차 구현하기

 

레이블 표현 사용까지 포함

def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size) #reshape로 (1,n)꼴로 변환
        y = y.reshape(1, y.size) #이미 (1,n)이지만 추가
    
    batch_size = y.shape[0]
    return -np.sum(t *np.log(y[np.arange(batch_size), t])) /batch_size

원-핫 인코딩 인 경우

t*np.log(y)

이 부분에서 굉장히 애를 먹었다... 단순한 로그 문법부터, 원-핫 인코딩과, 레이블 표현 시 코드가 달라지는 것 때문에

 

이 부분에 대해서 정리가 잘된 게시글이 있어 함께 표시한다.

 

https://medium.com/@john_analyst/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%84%EC%B2%98%EB%A6%AC-%EB%A0%88%EC%9D%B4%EB%B8%94-%EC%9D%B8%EC%BD%94%EB%94%A9%EA%B3%BC-%EC%9B%90%ED%95%AB-%EC%9D%B8%EC%BD%94%EB%94%A9-f0220df21df1

 

데이터 전처리 : 레이블 인코딩과 원핫 인코딩

기본적으로 사이킷런의 머신러닝 알고리즘은 문자열 값을 입력 값으로 허락하지 않는다.

medium.com

 

+ Recent posts