Post

[AI] 손실 함수(Loss Function)와 경사 하강법(Gradient Descent method) 그리고 간단하게 구현해보기

[AI] 손실 함수(Loss Function)와 경사 하강법(Gradient Descent method) 그리고 간단하게 구현해보기

손실 함수(Loss Function)경사 하강법(Gradient Descent Method)에 대해 알아보자.

신경망(Neural Network)은 학습을 통해 최적의 가중치(Weight)편향(Bias)을 찾아내야 한다. 손실 함수(Loss Function)가 최솟값일 때 가중치편향이 최적의 값을 갖는다.

손실 함수(Loss Function)

손실 함수(Loss Function)는 신경망이 정답에 가까운 답을 내기 위한 학습을 할 때 쓰인다. 손실 함수(Loss Function)는 신경망의 출력과 정답 레이블의 차이가 어느정도로 큰지를 나타내주는 함수이다.

1. 오차제곱합(Sum of Squares for Error, SSE)

\[SSE = \frac{1}{2} \sum_{k=1}^{n} (y_k - t_k)^2\]

$y_k$: 신경망의 출력값 $t_k$: 정답 데이터 $n$: 데이터의 개수

주로 회귀 문제에서 사용하며, 예측값과 실제값의 차이를 제곱하고 합산한다.
SSE는 ‘거리’관점으로 오차를 측정한다고 볼 수 있다.

2. 교차엔트로피오차 (Cross Entropy Error, CEE)

\[CEE = - \sum_{k=1}^{n} t_k \log y_k\]

주로 분류 문제에서 사용하며, 정답만 로그값을 취하고 오차를 계산한다.
CEE는 ‘정보 이론’관점에서 실제 확률 분포 $t$와 예측 확률 분포 $y$ 사이의 거리를 측정한다고 볼 수 있다.

\[t = [0, ... , 1, ... , 0]\]

이 표기와 같이 정답은 1을, 오답은 0으로 표기하는 기법을 원-핫 인코딩(One-Hot Encoding)이라고 한다.
CEE에서는 $t_k$가 원-핫 인코딩일 때, 정답인 라벨에 대해서만 계산하고 오답일 경우에는 0으로 계산한다.

경사 하강법(Gradient Descent Method)

신경망은 초기에 가중치편향을 임의의 수로 설정한다.
신경망의 출력값과 정답 레이블을 손실 함수를 통해 신경망이 얼마나 정답에 가까운지 알 수 있다. 이 때 손실 함수가 최솟값을 갖도록 하는 가중치편향과 같은 매개변수들을 경사 하강법(Gradient Descent Method)를 통해 구할 수 있다.

경사법(Gradient Method)
경사법은 최솟값을 찾을 때에는 경사 하강법, 최댓값을 찾을 때는 경사 상승법이라고 한다. 손실 함수의 부호를 반전시키면 사실상 같은 문제기 때문에 본질적으로는 중요하지 않다. 그러나 일반적으로 경사 하강법으로 등장할 때가 많다.

경사 하강법은 현 위치에서 기울기를 구하고 기울어진 방향으로 일정 거리만큼 이동하는 과정을 반복하여 최솟값이 되는 장소를 찾는다.

경사법을 수식으로 나타내면 다음과 같다.

\[x_{new} = x_{old} - \eta \frac{\partial f}{\partial x_{old}}\]

$\eta$는 학습률(Learning Rate)이라고 한다. 매개변수 값을 얼마나 이동시킬지를 결정한다.

간단히 구현해보기

경사 하강법으로 $f(x_0, x_1)=x_0^2+x_1^2$의 최솟값을 구해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np

def numerical_gradient(f, x):
    h = 1e-4
    grad = np.array([0.0,0.0])

    for i in range(2):
        x[i] += h
        fxh1 = f(x)
        x[i] -= 2*h
        fxh2 = f(x)

        grad[i] = (fxh1 - fxh2) / (2*h)
        x[i] += h
    return grad

def gd(f, x, lr=0.1, num=100):
  for i in range(num):
    x -= lr * numerical_gradient(f, x)
  return x

def func(x):
  return x[0]**2 + x[1]**2

init_x = np.array([-3.0, 4.0]) #초기값
print(gd(func, init_x))

gradient를 구하는 numerical_gradient함수는 중심 차분(Central Difference)을 이용하였다.

[-3.0, 4.0]을 초기값으로 넣었더니 [-6.11110793e-10 8.14814391e-10]라는 결과값이 나왔다. 이는 함수의 최솟값을 가지는 [0, 0]과 매우 유사한 값이다.

Desktop View

점선은 함수의 등고선을 나타낸다.

This post is licensed under CC BY 4.0 by the author.