Loading [MathJax]/jax/output/CommonHTML/jax.js
본문 바로가기
Machine Learning

Classification task에서 Cross-Entropy

by devson 2024. 5. 18.

classification task에서는 loss function으로 Cross-Entropy을 주로 사용한다.

 

binary classification일 때는 이 BinaryCrossentropy를 사용하고

multi-class classification인 경우엔 CategoricalCrossentropy를 사용하게 되는데,

명확하게 차이에 대한 이해 없이 기계적으로 사용하기도 하였다.

 

이번 포스팅에서는 classification task에서 사용되는 Cross-Entropy에 대해서 알아보도록 하겠다.

시작에 앞서
- 이 포스팅에서는 정보이론적으로 Cross-Entropy를 다루지 않는다.
- 코드 예제는 Tensorflow를 기준으로 진행한다.

 


Multi-class classification 분류 문제에서 Cross-Entropy

Multi-class classification의 경우 output layer에서 Softmax를 한 뒤, CategoricalCrossntropy를 사용하여 Cross-Entropy를 구한다.

(one-hot encoding을 하지 않은 경우 SparseCategoricalCrossentropy를 사용하지만 내부적으로는 동일하기 때문에 이는 넘어가겠다)

 

이에 대한 수식은 다음과 같다.

Categorical Cross-Entropy=ni=1yilog(ˆyi)

(batch로 처리하는 경우엔 해당 batch의 Cross-Entropy 값들의 평균을 구해주면 된다)

 

예를 들어 다음과 같이 레이블 데이터와 그에 대한 예측 데이터가 있다고 하였을 때

y=[0,0,1,0,0]
ˆy=[0.01,0.09,0.88,0.015,0.005]

Cross-Entropy 값은 다음과 같이 구할 수 있다.

CCE=(0log(0.01)+0log(0.09)+1log(0.88)+0log(0.015)+0log(0.005))
=(0+0+log(0.88)+0+0)
=log(0.88)
=0.1278

 

코드로 Cross-Entropy 값을 구해보면 수식을 통해 구한 값과 유사하게 나오는 것을 확인할 수 있다.

import numpy as np
from tensorflow.keras.losses import CategoricalCrossentropy
y = np.array([0, 0, 1, 0 ,0])
y_hat = np.array([0.01, 0.09, 0.88, 0.015, 0.005])
print(CategoricalCrossentropy()(y, y_hat))
# tf.Tensor(0.12783338, shape=(), dtype=float32)

 

Binary classification에서 Cross-Entropy

Binary classification의 경우 output layer에서 Sigmoid를 한 뒤,

BinaryCrossentropy를 사용하여 Cross-Entropy를 구한다.

 

이에 대한 수식은 다음과 같다.

Binary Cross-Entropy=(ylog(ˆy)+(1y)log(1ˆy))

(batch로 처리하는 경우엔 해당 batch의 Cross-Entropy 값들의 평균을 구해주면 된다)

 

예를 들어 다음과 같이 레이블 데이터와 그에 대한 예측 데이터가 있다고 하였을 때

y=0
ˆy=0.013

Cross-Entropy 값은 다음과 같이 구할 수 있다.

BCE=(0log(0.013)+(10)log(10.013))
=log(0.987)
=0.013094

 

코드로 Cross-Entropy 값을 구해보면 수식을 통해 구한 값과 유사하게 나오는 것을 확인할 수 있다.

import numpy as np
from tensorflow.keras.losses import BinaryCrossentropy
y = np.array([0])
y_hat = np.array([0.013])
print(BinaryCrossentropy()(y, y_hat))
# tf.Tensor(0.013085251, shape=(), dtype=float32)

 

왜 Binary Cross-Entropy와 Binary Cross-Entropy는 다른 수식을 사용하는가?

수식 자체만 놓고 봤을 때는 서로 다른 수식이라고 이해할 수 있지만, 근본적으로는 같은 수식을 사용한다고 볼 수 있다.

 

Binary classificationclass가 2개(1과 0)인 Multi-class classification 이라고 볼 수도 있는데,

이때의 Categorical Cross-Entropy는 다음과 같이 구할 수 있게된다.

 

ni=1yilog(ˆyi)=(ylog(ˆy)+(1y)log(1ˆy))

(class 0에 대한 확률 = 1 - class 1에 대한 확률)

 

이는 곧 Binary Cross-Entropy와 동일하다는 것을 확인할 수 있다.

 

추가적으로 아래와 같이 Binary classification을 0과 1에 대한 Multi-class classification 구조로 바꾼 뒤,

Cross-Entropy 값을 계산하였을 때도 동일한 것을 확인할 수 있다.

import numpy as np
from tensorflow.keras.losses import BinaryCrossentropy
binary_y = np.array([1])
binary_y_hat = np.array([0.6])
print("Binary:\t\t", BinaryCrossentropy()(binary_y, binary_y_hat))
multi_y_true = np.array([1, 0])
multi_y_pred = np.array([0.6, 0.4])
print("Multi-class:\t", CategoricalCrossentropy()(multi_y_true, multi_y_pred))
# Binary: tf.Tensor(0.5108256, shape=(), dtype=float32)
# Multi-class: tf.Tensor(0.5108256, shape=(), dtype=float32)

 

이와 관련된 Sigmoid와 Softmax의 관계에 대해서는 여기를 참고하길 바란다.

 

Multi-label classification 분류 문제에서 Cross-Entropy

Multi-label classification의 경우 Cross-Entropy를 구하는 것은

각 class에 대해 Binary Cross-Entropy를 구하여 더하는 것이라고 보면된다.

 

Tensorflow를 통해 위 Multi-label classification에 대한 모델링한다면 아래와 같이 코드가 나올 수 있다.

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
model = tf.keras.models.Sequential([
...
# output layer
Dense(3, activation="sigmoid")
])
model.compile(loss="binary_crossentropy",
...)

 

예를 들어 다음과 같이 레이블 데이터와 그에 대한 예측 데이터가 있다고 하였을 때

y=[1,0,1]
ˆy=[0.8,0.15,0.96]

 

Cross-Entropy 값은 다음과 같이 구할 수 있다.

BCE=(1log(0.8)+(11)log(10.8)
+0log(0.15)+(10)log(10.15)
+1log(0.96)+(11)log(10.96))
=(log(0.8)+log(0.85)+log(0.96))
=0.4265

 

코드로 Cross-Entropy 값을 구해보면 수식을 통해 구한 값과 다르게 나오는데,

코드 상으로는 Cross-Entropy를 모두 더한 뒤에 class 수 만큼 값을 나눠주기 때문이다.

(3을 곱해주면 앞서 수식을 통해 구한 값과 유사한 값이 나온다)

import numpy as np
from tensorflow.keras.losses import BinaryCrossentropy
y = np.array([1, 0, 1])
y_hat = np.array([0.8, 0.15, 0.96])
print(BinaryCrossentropy()(y, y_hat))
# tf.Tensor(0.14216149, shape=(), dtype=float32)

 


 

참고

'Machine Learning' 카테고리의 다른 글

앙상블 기법  (0) 2024.06.02
ROC Curve  (0) 2024.05.23
L1, L2 Regularization  (0) 2024.05.07
Feature scaling 과 머신러닝 학습  (0) 2024.04.26
Gradient Descent  (0) 2024.03.03

댓글