본문 바로가기
Tensorflow

[ANN] 06. Loss Function of Neural Network

by 청양호박이 2020. 5. 13.

지금까지 인공신경망(ANN)의 개요부터 Layer의 구조, 활성화함수(AF) 그리고 출력층설계와 순전파 (Forward Propagation) 까지 알아보았습니다. 이렇게 되면 학습전의 인공신경망(ANN)의 로직은 어느정도 알아보았다고 생각됩니다. 이제 남은 부분은 학습에 대한 부분과 이를 인공신경망 내 변수들에게 반영하는 방법입니다.

 

오늘은 그 중에서 학습을 위한 손실함수(Loss)에 대해서 알아보겠습니다. 

 

  • 인공신경망(ANN)의 개요 및 퍼셉트론과의 차이점
  • 인공신경망(ANN)의 활성화함수(AF, Activation Function)
  • 인공신경망(ANN)의 출력층 설계 및 순전파(Forward Propagation)
  • 인공신경망(ANN)의 손실함수(Loss) 구현
  • 수치미분 및 편미분, 그리고 GDA
  • 인공신경망(ANN)의 역전파(Back Propagation) 개념
  • 인공신경망(ANN)의 역전파(Back Propagation) 구현

 

 

1. 학습이란 (fit)


손실함수를 알아보기 전에, 우선 학습에 대해서 알아보고자 합니다. 왜 학습이 필요할까요?? 이전에 순전파(Forward Propagation)에서 봤듯이 학습이 없다면... 내가 필요한 변수 즉 weight와 bias에 특정 값을 세팅하고 단지 결과를 확인하는게 끝이게 됩니다.

 

그럼 그 결과와 실제 결과를 비교해서 보정하여 결과의 정확도를 높이는 작업을 해야하는데 그것이 바로 학습의 목적입니다. 결국 지금까지 알아본 신경망의 weight와 bias를 자동으로 구하고 이를 보정하여 적절한 변수를 도출하는것이 그 목적입니다. 

 

이제는 남은 문제는 학습은 한다고치고, 보정을 해야한다면 자동으로 보정하는게 중요합니다. 왜냐하면 이전에 순전파로 알아보았을때, hidden layer가 2개만 포함되도 그 변수가 많이 존재하는데 node수가 크거나 layer가 깊어지면 변수의 개수가 1000개, 10000개가 되는건 우스운일이 되기 때문입니다. 이 부분은 아마 다음시간 이후부터 알아볼 수 있을 것 같습니다.

 

 

2. 학습의 종류


오래 전부터 인류는 주어진 문제로부터 해결하기 위해서 학습을 했고, 그 방법은 진화하겠지만 여전히 발생하는 문제에 대해서 학습을 합니다. Deep Learning이라는 용어가 나오기까지... 학습의 변화는 아래와 같이 진행되었습니다.

 

(1) 전통적 : Data -> 사람이 data에서 feature(특징)를 추출 -> 사람의 알고리즘 -> Ans

(2) ML(Machine Learing) : Data -> 사람이 data에서 feature(특징)를 추출 -> ML -> Ans

(3) DL(Deep Learning) : Data -> DL -> Ans

 

점점 사람이 하던 일을 기계가 대신하게 됩니다. 인공신경망(ANN)개념이 들어가면서 부터는 아예 기계가 모든것을 수행하게 되죠. 그 알고리즘이 어떻게 되는지 조차 사람은 이해하기 어렵게 되었습니다. 

 

 

3. 학습 데이터


나중에 학습을 진행할때 발생하는 문제점을 다루는 시간을 만들어 보겠지만 간단하게 학습 시 데이터를 사용하는 방법에 대해서 알아보겠습니다. 

 

일반적으로 주어진 Dataset에 대해서 학습용(Training)과 검증용(Testing)으로 일정비율을 나누게 됩니다. 뭐 나누는 방식도 여러가지 (Random split, k-fold...등)가 있지만 이건 다음에 다루고... 이렇게 하는 이유는 Dataset을 나누지 않고 전체를 학습에 사용하게되면 딱 그 Dataset에만 맞춰진 모델이 생성되게 됩니다. 그렇게 되면 다른 데이터가 들어올때 예측에 실패하게되는 overfitting 문제가 발생하게 되죠.

 

따라서 약 7:3의 비율로 Dataset을 나누고, 7의 데이터로 모델의 Training을 수행하고 3의 데이터로 검증을 하여 underfitting과 overfitting의 적절한 구간을 찾는 것입니다.

 

 

4. 손실함수(Loss Function)


기존에 Regression에서도 알아본 바와 같이 인공신경망(ANN)도 결국 가설을 세우게 되는 것이고, 그 가설이 가장 정답을 구하는 로직에 근사하게 도출을 해야 합니다. 

 

이러한 가설의 정확도는 오차를 통해서 높일 수 있는데, 이를 손실함수(Loss Function)이라고 합니다. 이 손실함수를 통해서 도출되는 값을 낮추는 것이 궁극적인 목적이 됩니다. 

 

이러한 손실함수에는 대표적으로 2가지가 존재합니다. MSE(Mean Square Error: 평균제곱오차)와 CEE(Cross Entropy Error: 교차엔트로피오차) 입니다. 

 

[MSE, Mean Square Error]

 

E = np.mean((y_hat - y)^2)

 

신경망을 통해서 나온 결과와 원래 정답지의 차의 제곱의 평균을 구한것이 MSE입니다. 이를 코드를 통해서 확인해 보면 아래와 같습니다.

import numpy as np
import matplotlib.pyplot as plt

def MSE(y_hat, y):
    return np.mean((y_hat - y)**2)

그렇다면, 테스트를 위해서 모델을 통해서 정답이 7로 도출된 결과와 실제 target이 7로 일치하는 경우에 대해서 확인해 보겠습니다.

 

[Good Case]

y_hat = [0.1, 0.01, 0.05, 0.2, 0.14, 0.07, 0.6, 0.3, 0.1, 0.1]
y = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

y_hat = np.array(y_hat)
y = np.array(y)

print(MSE(y_hat, y))
===============================================================

0.034710000000000005

결과를 보듯이 0~9를 판별하는 모델이라고 가정할때, 신경망의 결과를 y_hat = [0.1, 0.01, 0.05, 0.2, 0.14, 0.07, 0.6, 0.3, 0.1, 0.1] 이라고하고, 정답지를 y_hat의 가장높은 위치로 즉 정답에 맞게(가장큰 위치, 7)로 세팅하였습니다. y = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]  

 

이 결과로 도출된 MSE는 위의 결과가 됩니다. 그렇다면 예측을 잘못했을때의 결과는 어떻게 될까요?? Test로 아래와 같이 세팅을 해보도록 하겠습니다.

 

y_hat = [0.1, 0.01, 0.6, 0.2, 0.14, 0.07, 0.05, 0.3, 0.1, 0.1]

y = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

 

ANN의 결과인 y_hat에서 2의 위치를 0.05 -> 0.6으로 바꾸고, 7의 위치를 0.6 -> 0.05로 바꾸었습니다.

 

[Bad Case]

y_hat = [0.1, 0.01, 0.6, 0.2, 0.14, 0.07, 0.05, 0.3, 0.1, 0.1]
y = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

y_hat = np.array(y_hat)
y = np.array(y)

print(MSE(y_hat, y))
==============================================================

0.14470999999999998

이렇게 되면 MSE는 약 0.034에서 0.144로 급격하게 증가하게되고, 이는 손실이 크기 때문에 작게하는 방향으로 학습을 진행하게 될 것입니다.

 

[CEE, Cross Entropy Error]

 

E = - np.sum(y * np.log(y_hat))

 

신경망을 통해서 나온 결과에 log를 취하고 그 결과를 정답지와 곱해서 합을 구한 후 (-)의 결과를 구한것이 CEE입니다.  코드를 통해서 본다면 아래와 같습니다.

def CEE(y_hat, y):
    return -np.sum(y * np.log(y_hat))

단, 여기서 log( )를 취할때는 주의할 점이 있습니다. 수학적인 계산에는 전혀 무리가 없을수 있으나, 이를 코드로 구현을 하게 된다면... 특정상황에서는 log( )가 -inf(infinity)를 뱉어내게 됩니다. 이는 Softmax의 exp( )에서 반대상황을 겪었었습니다. 

 

그 이유는 아래의 log함수 모양을 보면 알 수 있습니다. 

x = np.arange(0.0, 5.0, 0.01)
y = np.log(x)

print(np.log(0))

plt.plot(x, y)
plt.show()
==============================

-inf

log함수는 exp와 달리 0에 근접할 수록 음의 방향으로 급격하게 떨어지게 됩니다. 따라서 특정 상황이 된다면 연산이 불가능하게 됩니다. 역시 이를 방지하기 위해서는 log에 들어가는 수가 0이아닌 엄청나게 작은수가 되게 하면 결국은 0이 아니게 되기 때문에 -inf로 인한 문제를 해결할 수 있습니다.

 

결국 이를 위해서 1e-7 이라는 아주 작은 수를 더해줌으로써 문제를 해결할 수 있습니다.

def CEE(y_hat, y):
    alpha = 1e-7
    return -np.sum(y * np.log(y_hat + alpha))

alpha라는 새로운 변수를 생성하고, 그 변수에는 1e-7 이라는 작은 수를 할당하였습니다. 그러면 이제는 위에 MSE에서 테스트해 본 y_hat과 y의 값으로 테스트를 해보겠습니다. 

y_hat_G = [0.1, 0.01, 0.05, 0.2, 0.14, 0.07, 0.6, 0.3, 0.1, 0.1]
y_G = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

y_hat_B = [0.1, 0.01, 0.6, 0.2, 0.14, 0.07, 0.05, 0.3, 0.1, 0.1]
y_B = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

y_hat_G = np.array(y_hat_G)
y_G = np.array(y_G)

y_hat_B = np.array(y_hat_B)
y_B = np.array(y_B)

print(CEE(y_hat_G, y_G))
print(CEE(y_hat_B, y_B))
=================================================================

0.510825457099338
2.9957302735559908

y_hat_G와 y_G는 정답이 일치하는 set이고 손실함수의 결과는 0.51입니다. 반면에, y_hat_B와 y_B는 정답이 틀린 set이고 손실함수의 결과는 2.99로 많이 높아집니다. 결국 CEE도 동일하게 정답과 멀어질 경우 손실이 커지고, 이를 작게하는 방향으로 학습이 진행 될 것입니다.

 

 

0. 마무리


우리의 궁극적인 목적은 얼마나 최적값에 정확하게 일치하는가 입니다. 그럼 정확도를 사용하면 될 것인데... 뭐하러 손실함수를 이용해가면서 힘들어 하는가!! 

 

정확도는 말 그대로 일치/불일치로 민감한 변화에 반응없이 어느순간은 상태가 변하는... 예전에 퍼셉트론(Perceptron)에서 알아본 Step Funciton과 동일한 로직입니다. 따라서 미세하게 변하는 Loss Function을 사용해야 학습이 가능하게 됩니다.

 

뒤에서는 이 Loss Function을 통해서 학습하는 방법을 알아볼 것인데... 이를 위해서 해당 함수의 미분을 통한 기울기로 판단하게 됩니다. 이는 기존에 Gradient Descent Algorithm(GDA)로 알아봤었습니다. 

 

- Ayotera Lab -

댓글