본문 바로가기
ML&DL/손실함수

[손실 함수] 크로스 엔트로피, 로그 손실 (cross-entropy, log loss)

by Back2Baek 2023. 12. 29.

 ▶ 직관

  • 분류 문제에서 평가 지표로 쓰이는 함수이다.
  • cross-entropy(CE) log loss
  • cross-entropy : multi class 
  • log loss: binary class 
  • 값이 낮을 수록 해당 모델의 성능이 좋다는 의미.

해당 함수의 의의는 단순히 정답을 맞춘 것 이상으로, 얼만큼 정확하게 맞췄냐에 대해 평가하기 위함.

낮은 확률로 단순히 때려 맞췄는지, 높은 확률로 정확히 맞췄는지에 대해 평가하기 위한 지표. 

 

> 예측에 대한 자신감 정도

 

 


  • cross-entropy  log loss
  • cross-entropy : multi class 
  • log loss: binary class 

위 내용 대해 다시 살펴보자면,

LogLoss가 이진 분류에 대한 수식, CE는 이를 다중 분류로 확장시킨 수식임을 확인할 수 있다.

 

$$ LogLoss = -\sum_{i=1}^{N}[y_{i}\ast\log(p_{i}) + (1-y_{i})\ast\log(1-p_{i})] $$

$$ Cross-Entropy = -\frac{1}{N}\sum_{i=1}^{N}\sum_{j=1}^{M}y_{ij}\ast\log(p_{ij}) $$


 

예시

https://en.wikipedia.org/wiki/File:Mandarins_-_whole_and_halved.jpg, https://en.wikipedia.org/wiki/File:Grapefruits_-_whole-halved-segments.jpg, https://en.wikipedia.org/wiki/File:Lemon_-_whole_and_split.jpg

 

귤 속 과일을 분류하는 모델 A와 B가 있다고 가정해보자.

 

레몬 이미지가 주어졌을 때 각 모델의 예측 확률은,

A는 {귤: 0.1, 자몽: 0.2, 레몬: 0.7}

B는 {귤: 0.3, 자몽: 0.3, 레몬: 0.4} 로 예측.

 

즉, 두 모델 다 레몬을 정답으로 예측.

훈련 데이터에 한해, 다른 이미지에 대해서도 정답은 같은나 정답에 대한 확률 값은 A가 더 높게 나오는 상황.

 

단순히 정답인지 아닌지에 대한 평가 지표(accuracy, recall, precision... 등) 으로 평가했다면 두 모델의 성능은 같은 상황.

 

하지만 Cross-Entropy 를 사용한다면 A가 더 정확한 모델이라는 평가를 내릴 수 있다.

 

Python 코드

1. numpy를 이용해 직접 구현한 코드

import numpy as np

def log_loss(y_true, y_pred, epsilon=1e-15):
	assert len(y_true) == len(y_pred)

    # log(0)을 방지하기 위해
    # 0에 근사한 값을 최소로, 1에 근사한 값을 최대로 설정하여
    # 해당 범위를 벗어나는 값은 각각 최소값과 최대값으로 대체.
    y_pred = np.clip(y_pred, epsilon, 1 - epsilon)
    
    # 예측 학률 정규화하여 확률의 합이 1 보장
    y_pred = y_pred / y_pred.sum(axis=1)[:, np.newaxis]
    
    # log loss 계산a
    num_data = len(y_true)
    log_loss = -np.sum(y_true * np.log(y_pred)) / num_data
    
    return log_loss

y_true = np.array([[1, 0, 0],
                   [0, 1, 0],
                   [0, 0, 1]])

y_pred = np.array([[0.9, 0.05, 0.05],
                   [0.05, 0.85, 0.1],
                   [0.05, 0.1, 0.85]])
                   
print('Log Loss:', log_loss(y_true, y_pred))
# Log Loss: 0.14346612488445873

 

 

 

2. sckit-learn의 log_loss 함수를 이용하는 코드

sklearn.metrics.log_loss(y_true, y_pred, *, eps='auto', normalize=True, sample_weight=None, labels=None
from sklearn.metrics import log_loss

y_true = np.array([[1, 0, 0],
                [0, 1, 0],
                [0, 0, 1]])

y_pred = np.array([[0.9, 0.05, 0.05],
                [0.05, 0.85, 0.1],
                [0.05, 0.1, 0.85]])
                
print('Log Loss:', log_loss(y_true,y_pred))
# Log Loss: 0.14346612488445873