이 시리즈는 R로 딥러닝을 구현하고 설명하는 것에 목표를 둔 글입니다. 신경망 챕터에 이어서 3번째 순서입니다. 이전 글과 내용이 이어집니다. 이전 글들은 이곳에서 찾아 보실 수 있습니다.

손실 함수란 ?

이제 신경망에서 어떻게 학습이 이루어지는지 본격적으로 알아보겠습니다. 신경망에서는 학습을 통해 모델의 성능을 나아지게 합니다. 그렇다면 모델의 학습 상태는 어떻게 확인할 수 있을까요? 즉 어느 정도로 모델의 성능이 향상하는지 알 수 있는 방법이 있을까요? 먼저 사람이 행복한 상태를 나타낼 때를 예를 들어봅시다. 사람들은 보통 지금 행복하냐는 질문에 행복하다 혹은 불행하다라 답을 합니다. 하지만, 누군가가 나는 지금 10.3 만큼 행복하다 혹은 나는 -7 만큼 불행해라고 답하게 되면 질문자는 아마 황당할 것입니다.

그러나 모델에 대해서는 이러한 수치적 지표가 모델이 현재 상태를 말해주는 방법입니다. 이 수치적 지표를 토대로 최적의 변수값을 찾아 나아가는게 신경망 학습에서 사용하는 방법입니다. 신경망 학습에서 사용하는 지표의 이름은 손실 함수라 합니다. 손실 함수는 신경망 모델이 훈련데이터를 얼마나 처리하지 못함을 판단하는 지표로 평균 제곱 오차와 교차 엔트로피 오차가 있습니다.

평균 제곱 오차

손실 함수로 가장 많이 사용되는 함수는 평균 제곱 오차(Mean Squared Error) 함수입니다. 평균 제곱 오차는 신경망 모델이 각 분류 기준들에 대해 확률적으로 추정한 값과 기존 정답 라벨의 값 사이의 차를 제곱합하여 2로 나눈 값입니다. 분류 기준의 개수는 최소 2개 이상이고 정답은 1개지만 원핫 인코딩으로 분류 개수를 맞춰준다면, 서로 뺄 수 있으며 그 값들을 제곱하고 모든 분류기준들에 대한 값들을 더하고 2로 나누어주면 평균제곱오차를 구할 수 있습니다.

예를 들어 모델이 2를 정답이라 (0부터 9까지이기 때문에 인덱스 값에서 -1한 숫자가 정답이다) 판단한 확률이 60%이고 0,5,7을 정답이라 판단한 확률이 10%이며, 1,4를 정답이라 판단한 확률이 5% 이고, 실제 정답이 2인 경우를 가정해보겠습니다. 이때 평균 제곱 오차 값을 계산하면 다음과 같습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
y  <- matrix(c(0.1,0.05,0.6,0,0.05,0.1,0,0.1,0,0), nrow = 1)
t  <- matrix(c(0,0,1,0,0,0,0,0,0,0), nrow = 1)
> y
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]  0.1 0.05  0.6    0 0.05  0.1    0  0.1    0     0
> t
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    0    0    1    0    0    0    0    0    0     0
> sum((y-t)^2)/2
[1] 0.0975

이제 평균 제곱 오차의 계산 과정을 함수화 해보겠습니다. 만들어진 평균 제곱 오차 함수에 모델이 정답을 맞춘 경우와 맞추지 못한 경우 두 가지를 가정해서 계산을 해보았습니다. y2는 모델이 7을 정답이라 판단한 것으로 정답을 맞추지 못한 경우입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
y1 <- matrix(c(0.1,0.05,0.6,0,0.05,0.1,0,0.1,0,0), nrow = 1)
y2 <- matrix(y <- c(0.1,0.05,0.1,0,0.05,0.1,0,0.6,0,0), nrow = 1)
t <- matrix(c(0,0,1,0,0,0,0,0,0,0), nrow = 1)
> y1
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]  0.1 0.05  0.6    0 0.05  0.1    0  0.1    0     0
> y2
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]  0.1 0.05  0.1    0 0.05  0.1    0  0.6    0     0
> t
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    0    0    1    0    0    0    0    0    0     0
mean_squared_error <- function(y, t){
    return((1/NROW(y))*sum((y-t)^2))
}

> mean_squared_error(y1,t)
[1] 0.0975
> mean_squared_error(y2,t)
[1] 1.195

계산 결과 모델이 정답을 맞추지 못한 경우가 정답을 맞춘 경우보다 평균 제곱 오차의 값이 크게 올라갑니다. 즉 평균 제곱 오차 함수의 값이 작으면, 모델의 추정 결과가 정답과 오차도 작다는 것을 알 수 있습니다.

교차 엔트로피 오차

다른 손실 함수로는 교차 엔트로피 오차(Cross Entropy Error)가 있습니다. 교차 엔트로피 오차는 로그 값을 이용합니다. 정답이라 추정하는 값에 로그 값과 정답 라벨 값을 서로 곱하여 합한 값에 -1을 곱해주면 됩니다. 예를 들면, 계산 과정은 다음과 같습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
y  <- matrix(c(0.1,0.05,0.6,0,0.05,0.1,0,0.1,0,0), nrow = 1)
t  <- matrix(c(0,0,1,0,0,0,0,0,0,0), nrow = 1)

> y
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]  0.1 0.05  0.6    0 0.05  0.1    0  0.1    0     0
> t
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    0    0    1    0    0    0    0    0    0     0
> -sum(t*log(y+1e-7))
[1] 0.5108255

계산 과정에 1e-7의 값을 추가해 주었는데 그 이유는 로그0은 -Inf 값으로 출력되는 것을 방지하기 위해서 입니다. 이에 따라 결과에 지장을 주지 않는 아주 작은 값을 더해서 -무한대 값을 방지해줄 수 있습니다. 이 과정을 함수화하면 다음과 같습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
y1  <- matrix(c(0.1,0.05,0.6,0,0.05,0.1,0,0.1,0,0), nrow = 1)
y2  <- matrix(y <- c(0.1,0.05,0.1,0,0.05,0.1,0,0.6,0,0), nrow = 1)
t <- matrix(c(0,0,1,0,0,0,0,0,0,0), nrow = 1)

> y1
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]  0.1 0.05  0.6    0 0.05  0.1    0  0.1    0     0
> y2
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]  0.1 0.05  0.1    0 0.05  0.1    0  0.6    0     0
> t
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    0    0    1    0    0    0    0    0    0     0

cross_entropy_error_single <- function(y, t) {
  return(-sum(t*log(y+1e-7)))
}

> cross_entropy_error_single(y1,t)
[1] 0.5108255
> cross_entropy_error_single(y2,t)
[1] 2.302584

교차 엔트로피 오차 역시 손실 함수로서 평균 제곱 오차와 마찬가지로 모델이 정답을 맞춘 경우와 그렇지 못한 경우를 살펴보면, 정답을 맞추지 못한 경우에 그 값이 더 크게 됨을 알 수 있습니다. 0.51과 2.3으로 값의 차이가 크게 드러나게 됩니다. 이를 통해 평균 제곱 오차와 마찬가지로 교차 엔트로피 오차의 값이 작으면 모델의 추정 결과와 정답 간의 오차가 적은 것을 확인할 수 있습니다. 정리하면 손실 함수의 경우 작은 값을 가질 때 모델이 추정 결과가 더 나은 결과이며 즉 더 나은 모델임을 알 수 있습니다.