짧은 버전 :
y_hat
각 클래스에 대해 계산 된 점수 (예 : y = W * x + b)와 y_true
하나의 핫 인코딩 된 실제 레이블 이 포함 된 두 개의 텐서가 있다고 가정합니다 .
y_hat = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded
당신이 점수를 해석하면 y_hat
표준화 로그 확률로, 그 후에는 logits .
또한 다음과 같이 계산 된 총 교차 엔트로피 손실 :
y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))
본질적으로 다음 함수로 계산 된 총 교차 엔트로피 손실과 softmax_cross_entropy_with_logits()
같습니다.
total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
긴 버전 :
신경망의 출력 레이어에서 계산과 같은 각 트레이닝 인스턴스에 대한 클래스 점수를 포함하는 배열을 계산할 수 있습니다 y_hat = W*x + b
. 예를 들어 아래 y_hat
에서 2 x 3 배열로 만들었습니다. 여기서 행은 교육 인스턴스에 해당하고 열은 클래스에 해당합니다. 여기에 2 개의 훈련 인스턴스와 3 개의 수업이 있습니다.
import tensorflow as tf
import numpy as np
sess = tf.Session()
# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5, 1.5, 0.1],
# [ 2.2, 1.3, 1.7]])
값은 정규화되지 않습니다 (예 : 행의 합이 1이 아님). 정규화하기 위해 입력을 정규화되지 않은 로그 확률 (일명 logits ) 로 해석하고 정규화 된 선형 확률을 출력 하는 softmax 함수를 적용 할 수 있습니다 .
y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863 , 0.61939586, 0.15274114],
# [ 0.49674623, 0.20196195, 0.30129182]])
softmax 출력의 내용을 완전히 이해하는 것이 중요합니다. 아래에는 위의 출력을보다 명확하게 나타내는 표가 나와 있습니다. 예를 들어, 훈련 인스턴스 1이 "클래스 2"일 확률은 0.619임을 알 수있다. 각 교육 인스턴스의 클래스 확률은 정규화되므로 각 행의 합계는 1.0입니다.
Pr(Class 1) Pr(Class 2) Pr(Class 3)
,--------------------------------------
Training instance 1 | 0.227863 | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182
이제 각 훈련 인스턴스에 대한 클래스 확률이 있으며, 여기서 각 행의 argmax ()를 사용하여 최종 분류를 생성 할 수 있습니다. 위에서 우리는 훈련 인스턴스 1이 "클래스 2"에 속하고 훈련 인스턴스 2가 "클래스 1"에 속한다는 것을 생성 할 수 있습니다.
이러한 분류가 정확합니까? 훈련 세트의 실제 레이블을 기준으로 측정해야합니다. one-hot 인코딩 y_true
배열 이 필요합니다 . 여기서 행은 학습 인스턴스이고 열은 클래스입니다. 아래에서는 y_true
교육 인스턴스 1의 실제 레이블이 "클래스 2"이고 교육 인스턴스 2의 실제 레이블이 "클래스 3"인 one-hot 배열 의 예를 만들었습니다 .
y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0., 1., 0.],
# [ 0., 0., 1.]])
확률 분포는 확률 분포와 y_hat_softmax
비슷 y_true
합니까? 교차 엔트로피 손실 을 사용하여 오류를 측정 할 수 있습니다 .
교차 엔트로피 손실을 행 단위로 계산하고 결과를 볼 수 있습니다. 아래에서 훈련 인스턴스 1의 손실은 0.479이고 훈련 인스턴스 2의 손실은 1.200입니다. 위의 예에서 y_hat_softmax
훈련 인스턴스 1의 가장 높은 확률은 "클래스 2"일 가능성이 있음을 보여 주었 으므로이 결과는 의미 가 있습니다 y_true
. 그러나 훈련 사례 2에 대한 예측은 "클래스 1"에 대한 확률이 가장 높았으며 이는 실제 클래스 "클래스 3"과 일치하지 않습니다.
loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 , 1.19967598])
우리가 정말로 원하는 것은 모든 교육 인스턴스에 대한 총 손실입니다. 따라서 다음을 계산할 수 있습니다.
total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944
softmax_cross_entropy_with_logits () 사용
대신 tf.nn.softmax_cross_entropy_with_logits()
아래와 같이 함수를 사용하여 총 교차 엔트로피 손실을 계산할 수 있습니다.
loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 , 1.19967598])
total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922
참고 그 total_loss_1
와 total_loss_2
매우 마지막 자리에서 몇 가지 작은 차이와 생산 본질적으로 동등한 결과. 그러나 두 번째 방법을 사용할 수도 있습니다. softmax가 내부에서 수행되기 때문에 코드 한 줄이 덜 걸리고 수치 오류가 적습니다 softmax_cross_entropy_with_logits()
.
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.nn.softmax(tf.add(tf.matmul(x,W),b)),y) cost=tf.reduce_mean(cross_entropy)
. 그러나 다른 방법을 사용pred=tf.nn.softmax(tf.add(tf.matmul(x,W),b)) cost =tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))
하면 결과가 안정적이며 더 좋습니다.