Implementation/Loss

[Loss] 크로스 엔트로피

Eric_Park 2021. 9. 22. 13:07

- Cross Entropy

Entropy 는 확률분포 p 가 가지는 정보의 확신도 혹은 정보량을 수치로 표현한 것이며, 

Cross-Entropy 는 정보 이론에서, 두 확률 분포 p 와 q를 구분하기 위해 필요한 평균 비트 수를 의미한다.

 

# Define data
p = [0.10, 0.40, 0.50]
q = [0.80, 0.15, 0.05]

# Define Entropy
def entropy(p):
	return -sum([p[i] * np.log2(p[i]) for i in range(len(p))])

# Define Cross-Entropy  
def cross_entropy(p, q):
    return -sum([p[i] * np.log2(q[i]) for i in range(len(p))])

정보 이론에서의 Cross-Entropy 의 정의는 두 확률 분포 p, q 를 구분하기 위해 필요한 평균 비트 수를 의미한다. 

 

따라서, np.log2(p[i]) 안의 p 값이 q로 바뀐 것을 확인해 볼 수 있다. 

 

풀어서 말하면, P(x) 확률에다가 Q(x) 일 때의 엔트로피를 곱하게 되므로, P의 분포가 주어질 때, Q의 확률분포를 가정함

으로써 늘어나는 정보량을 측정해 보겠다는 말이다. 

 

Cross-Entropy 를 검색해서 찾아보다 보면은, KL divergence 라는 내용을 마주칠 수 있는데, 코드상 정의는 아래와 같다. 

# calculate the kl divergence KL(P || Q)
def kl_divergence(p, q):
	return sum(p[i] * np.log2(p[i]/q[i]) for i in range(len(p)))

kl-divergence 가 측정하게 되는 값은 cross-entropy 와 조금 다르다. 

 

cross-entropy 가 p를 q 분포를 가정했을 때 나타나는 총 정보량을 의미한다면, 

kl-divergence 는 p 대신 q 분포를 가정했을 때 나타나는 '추가적인' 정보량을 의미한다. 

 

코드상에서는 p(entropy) -> q(cross-entropy) -> p/q(kl-divergence) 로 확인 가능하다. 

 

H(x) 가 x 분포의 entropy 라고 가정한다면, 아래가 성립한다. 

### H(p,q) = H(p) + KL(P || Q)

 

유추해 볼 수 있는 특징들..  

H(p,q) != H(q,p)

H(p,p) == H(p)

 

- Loss function 으로서의 Cross Entropy

보통 loss function 으로의 cross entropy 는 딥러닝에서의 분류 문제에 많이 사용하게 된다. 

간단한 이진 분류의 예를 들어보자. 

p = [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]

def entropy(p):
	return -sum([p[i] * np.log2(p[i]) for i in range(len(p))])

계산해보면, entropy 의 결과값이 0에 수렴하게 된다.
이는 실제 데이터는 관측시에 확률의 관측이 아닌 실측을 하게 되므로
각 현상을 목격할 확률이 100%가 되었을 때의 결과와 유사하다.

 

하지만 y_pred 는 각 클래스가 될 수 있는 확률분포를 output 으로 가져오므로, 이 output 이 정답 label 에 가깝게

만드는 모델을 만드는 것이 entropy 가 딥러닝 모델 안에서 loss function 으로 작동하는 원리이다. 

 

# define classification data
p = [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
q = [0.8, 0.9, 0.9, 0.6, 0.8, 0.1, 0.4, 0.2, 0.1, 0.3]

# calculate cross entropy for each example
results = list()
for i in range(len(p)):
	# create the distribution for each event {0, 1}
	expected = [1.0 - p[i], p[i]]
	predicted = [1.0 - q[i], q[i]]
	# calculate cross entropy for the two events
	ce = cross_entropy(expected, predicted)
	print('>[y=%.1f, yhat=%.1f] ce: %.3f nats' % (p[i], q[i], ce))
	results.append(ce)
print(results)
print(np.mean(results))
### 0.3562
p = [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
q = [0.8, 0.9, 0.9, 0.6, 0.8, 0.1, 0.4, 0.2, 0.1, 0.3]
bca = tf.keras.losses.BinaryCrossentropy(from_logits=True)
bca(p, q).numpy()
### 0.5964

keras 에서 가져온 BinaryCrossentropy 로 계산했을 때의 값과 하드코딩했을 때의 값이 다른데, 이 부분은 

확인이 좀 더 필요하다. 

 

#ref : https://machinelearningmastery.com/cross-entropy-for-machine-learning/