▶ 직관
- 분류 문제에서 평가 지표로 쓰이는 함수이다.
- 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}) $$
예시
귤 속 과일을 분류하는 모델 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