미분

미분은 '특정 순간'의 변화량이며, 수식은 다음과 같다.

함수의 미분

이는 결국 x의 '작은 변화'가 함수 f(x)를 얼마나 변화시키느냐를 의미한다. 

이때 시간의 작은 변화, 즉 시간을 뜻하는 h를 한없이 0에 가깝게 한다는 의미를 lim h->0 로 나타낸다.

 

# 나쁜 구현 예
def numerical_diff(f,x):
    h = 10e-50 # 작은 값. 이 방식은 결국 반올림 오차 문제를 일으키게 된다.
    return (f(x+h) - f(x)) / h

함수 f의 차분 문제도 있다. 

'진정한 미분'x 위치의 함수의 기울기(접선)에 해당하지만, 이번 구현에서의 미분은 (x+h)와 x 사이의 기울기에 해당한다.

 

def numerical_diff(f,x):
    h = 1e-4 #0.0001
    return (f(x+h) - f(x-h)) / (2*h)

문제점들을 해결한 코드이다.

 

 

편미분

여기선 변수가 2개이기 때문에 '어느 변수에 대한 미분이냐', 즉 x0과 x1 중 어느 변수에 대한 미분이냐를 구별해야 한다.

편미분은 변수가 하나인 미분과 마찬가지로 특정 장소의 기울기를 구한다. 

단, 여러 변수 중 목표 변수 하나에 초점을 맞추고 다른 변수는 값을 고정한다. 

 

 

위 글은 「밑바닥부터 시작하는 딥러닝」을 참고하여 작성한 글입니다.

'Study > Deep Learning' 카테고리의 다른 글

머신러닝 Data 종류  (0) 2021.10.14
머신러닝 기본 프로세스  (0) 2021.10.14
딥러닝의 응용분야  (0) 2021.10.13
머신러닝/딥러닝 기초  (0) 2021.10.13
신경망 학습  (0) 2020.11.06

여기서 학습이란 훈련 데이터로부터 가중치 매개변수의 최적값을 자동으로 획득하는 것을 뜻한다.

 

데이터 주도 학습

기계학습의 중심에는 데이터가 존재한다. 

기계학습에서는 사람의 개입을 최소화하고 수집한 데이터로부터 패턴을 찾으려 시도한다.

그런 방법의 하나로, 이미지에서 특징(feature)을 추출하고 그 특징의 패턴을 기계학습 기술로 학습 하는 방법이 있다.

여기서 말하는 특징은 입력 데이터(입력 이미지)에서 본질적인 데이터(중요한 데이터)를 

정확하게 추출할 수 있도록 설계된 변환기를 가리킨다.

이미지의 특징은 보통 벡터로 기술하고, 컴퓨터 비전 분야에서는 SIFT, SURF, HOG 등의 특징을 많이 사용한다.

 

이와 같은 기계학습에서는 모아진 데이터로부터 규칙을 찾아내는 역할을 '기계'가 담당한다.

다만, 이미지를 벡터로 변환할 때 사용하는 특징은 여전히 '사람'이 설계한다.

 

딥러닝을 종단간 기계학습(end-to-end machine learning)이라고도 한다. 

데이터(입력)에서 목표한 결과(출력)를 사람의 개입 없이 얻는다는 뜻을 담는다.

 

 

훈련 데이터와 시험 데이터

기계학습 문제는 데이터를 훈련 데이터시험 데이터로 나눠 학습과 실험을 수행하는 것이 일반적이다.

우선 훈련 데이터만으로 학습하며 최적의 매개변수를 찾는다.

그런 다음 시험 데이터를 사용하여 앞서 훈련한 모델의 실력을 평가한다.

 

범용 능력은 아직 보지 못한 데이터(훈련 데이터에 포함되지 않는 데이터)로도 문제를 올바르게 풀어내는 능력이다.

이 능력을 획득하는 것이 기계학습의 최종 목표다.

 

데이터셋 하나로만 매개변수의 학습과 평가를 수행하면 올바른 평가가 될 수 없다.

(예: 한 사람의 글씨체만 학습하는 경우) 

한 데이터셋에만 지나치게 최적화된 상태를 오버피팅overfitting 이라고 한다.

오버피팅을 피하는 것도 기계학습의 중요한 과제다.

 

 

손실 함수

신경망 학습에서는 현재의 상태를 '하나의 지표'로 표현한다.

그리고 그 지표를 가장 좋게 만들어주는 가중치 매개변수의 값을 탐색한다.

신경망 학습에서 사용하는 지표는 손실 함수 loss function 라고 한다.

이 손실 함수는 임의의 함수를 사용할 수도 있지만 

일반적으로는 오차제곱합교차 엔트로피 오차를 사용한다.

 

 

오차제곱합

가장 많이 쓰이는 손실 함수는 오차제곱합 sum of squares for error, SSE 이다.

(yk는 신경망의 출력(신경망이 추정한 값), tk는 정답 레이블, k는 데이터의 차원 수)

 

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

y는 소프트맥스 함수의 출력이다. 소프트맥수 함수의 출력은 확률로 해석할 수 있다.

이 예에서는 이미지가 2일 확률이 확률이 가장 높다고 해석할 수 있다.

t에서 나타낸 것처럼 한 원소만 1로 하고 그 외에는 0으로 나타내는 표기법을 원-핫 인코딩이라 한다.

 

import numpy as np

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'의 확률이 가장 높다고 추정함

def sum_squares_error(y,t):
    return 0.5 * np.sum((y-t)**2)

>>> sum_squares_error(np.array(y),np.array(t))
0.097500000000000031

한편, t는 그대로 두고 y가 '5'일 확률이 가장 높다고 추정한다면

>>> y= [0.1, 0.05, 0.05, 0.0, 0.6, 0.1, 0.0, 0.1, 0.0, 0.0] # '5'일 확률이 가장 높다고 추정함
>>> sum_squares_error(np.array(y),np.array(t))
0.6475

첫 번째 예의 손실 함수 쪽 출력이 작으며 정답 레이블과의 오차도 작다는 것을 알 수 있다.

즉, 오차제곱합 기준으로는 첫 번째 추정 결과가(오차가 더 작으니) 정답에 더 가까울 것으로 판단할 수 있다.

 

 

교차 엔트로피 오차

또 다른 손실 함수로서 교차 엔트로피 오차 cross entropy error, CEE 도 자주 이용한다.

 

(log는 밑이 e인 자연로그, yk는 신경망의 출력, tk는 정답 레이블)

실질적으로 정답일 때의 추정(tk가 1일 떄의 yk)의 자연로그를 계산하는 식이다.

자연로그 y=logx 의 그래프

정답에 해당하는 출력이 커질수록 0에 다가가다가, 그 출력이 1일 때 0이 된다.

반대로 정답일 때의 출력이 작아질수록 오차는 커진다.

 

def cross_entropy_error(y,t):
    delta = 1e-7
    return -np.sum(t*np.log(y+delta))

 

여기서 np.log를 계산할 때 아주 작은 값인 delta를 더했다. 이는 np.log()함수에 0을 입력하면 마이너스 무한대를 나타내는 -inf가 되어 더 이상 계산을 진행할 수 없게 되기 때문이다.

즉, 마이너스 무한대가 발생하지 않도록 한 것이다.

 

>>> cross_entropy_error(np.array(y),np.array(t)) # 정답
0.510825457099338
>>> cross_entropy_error(np.array(y),np.array(t)) # 정답 X
2.9957302735559908

위 코드(오차제곱합)의 예시와 똑같이 적용한 결과이다. 

결과(오차 값)가 더 작은 첫 번째 추정이 정답일 가능성이 높다고 판단한 것으로, 앞서 오차제곱합의 판단과 일치하다.

 

미니배치 학습

딥러닝은 훈련 데이터를 이용해 학습하면서, 훈련 데이터에 대한 손실함수의 값을 구하고 그 값을 최소로하는 매개변수(가중치, 편향)를 찾아내는 것이다. 이를 위해서는 모든 훈련 데이터를 대상으로 손실함수 값을 구해야 한다. 보통 딥러닝은 미니배치(Mini-batch) 학습을 하기때문에 미니배치 크기만큼의 데이터에 대한 각각의 손실함수를 구해 평균을 내어 '평균 손실 함수'를 계산한다.

(N은 미니배치 크기,  tnk는 n번째 데이터의 k차원째의 값)

이는 데이터 하나에 대한 손실 함수를 단순히 N개의 데이터로 확장한 것이고, 마지막에 N으로 나누어 정규화하고 있다.

N으로 나눔으로써 '평균 손실 함수'를 구하는 것이다.

 

빅데이터 수준이 되면 훈련 데이터가 수천만개도 넘는 거대한 값이 된다. 

이런 경우 데이터 일부를 추려 전체의 '근사치'로 이용할 수 있다. 

신경망 학습에서도 훈련 데이터로부터 일부만 골라 학습을 수행한다. 이 일부를 미니배치라고 한다. 

 

미니배치 학습을 하는 코드를 구현해보자.

 

import sys, os
sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet

# 데이터 읽기
(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) #(600000,10)

(load_mnist는 MNIST 데이터셋을 읽어오는 함수. 이 함수는 훈련 데이터와 시험 데이터를 읽음.

호출할 때 원-핫 인코딩으로 호출)

 

MNIST 데이터를 읽은 결과, 훈련 데이터는 60,000개고, 입력 데이터는 784(28x28)열인 이미지 데이터임을 알 수 있다.

또, 정답 레이블은 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]

 

np.random.choice() 로는 지정한 범위의 수 중에서 무작위로 원하는 개수만 꺼낼 수 있다.

이 함수가 출력한 배열을 미니배치로 뽑아낼 데이터의 인덱스로 사용하면 된다.

 

 

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

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]
    return -np.sum(t*np.log(y + 1e-7)) / batch_size

 

(y는 신경망의 출력, t는 정답 레이블)

y가 1차원이라면,  즉 데이터 하나당 교차 엔트로피 오차를 구하는 경우는 reshape 함수로 데이터의 형상을 바꾼다.

그리고 배치의 크기로 나눠 정규화하고 이미지 1장당 평균의 교차 엔트로피 오차를 계산한다.

 

정답 레이블이 원-핫 인코딩이 아니라 '2'나 '6' 등의 숫자 레이블로 주어졌을 때의 교차 엔트로피 오차는 다음과 같이 구현한다.

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]
    return -np.sum(np.log(y[np.arange(batch_size),t] + 1e-7)) / batch_size

 

 

왜 손실 함수를 설정할까?

이 의문은 신경망 학습에서의 '미분'의 역할에 주목하면 해결된다. 

신경망 학습에서는 최적의 매개변수(가중치와 편향)를 탐색할 때 손실 함수의 값을 가능한 한 작게 하는 매개변수 값을 찾는다.

이때 매개변수의 미분(기울기)을 계산하고, 그 미분 값을 단서로 매개변수의 값을 서서히 갱신하는 과정을 반복한다. 

미분 값이 양수나 음수면 매개변수를 변화시켜 손실 함수의 값을 줄일 수 있다.

그러나 미분 값이 0이면, 가중치 매개변수를 어느 쪽으로 움직여도 손실 함수의 값은 줄어들지 않는다.

그래서 가중치 매개변수의 갱신은 거기서 멈춘다.

 

정확도를 지표로 삼아서는 안되는 이유는 미분 값이 대부분의 장소에서 0이 되어 매개변수를 갱신할 수 없기 때문이다.

 

한 신경망이 100장 중 42장을 올바로 인식한다고 하면 정확도는 42%다. 매개변수를 약간만 조정해서는 정확도가 개선되지 않고 일정하게 유지된다. 그러나, 손실 함수를 지표로 삼을 때는 매개변수 값이 조금 변하면 그에 반응하여 손실 함수의 값도 연속적으로 변화한다. 

 

 

위 글은 「밑바닥부터 시작하는 딥러닝」을 참고하여 작성한 글입니다.

'Study > Deep Learning' 카테고리의 다른 글

머신러닝 Data 종류  (0) 2021.10.14
머신러닝 기본 프로세스  (0) 2021.10.14
딥러닝의 응용분야  (0) 2021.10.13
머신러닝/딥러닝 기초  (0) 2021.10.13
수치 미분  (0) 2020.11.06

+ Recent posts