Bij het proberen om kruis-entropie te krijgen met de sigmoid-activeringsfunctie, is er een verschil tussen
loss1 = -tf.reduce_sum(p*tf.log(q), 1)
loss2 = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=p, logits=logit_q),1)
Maar ze zijn hetzelfde met de softmax-activeringsfunctie.
Hier volgt de voorbeeldcode:
import tensorflow as tf
sess2 = tf.InteractiveSession()
p = tf.placeholder(tf.float32, shape=[None, 5])
logit_q = tf.placeholder(tf.float32, shape=[None, 5])
q = tf.nn.sigmoid(logit_q)
sess.run(tf.global_variables_initializer())
feed_dict = {p: [[0, 0, 0, 1, 0], [1,0,0,0,0]], logit_q: [[0.2, 0.2, 0.2, 0.2, 0.2], [0.3, 0.3, 0.2, 0.1, 0.1]]}
loss1 = -tf.reduce_sum(p*tf.log(q),1).eval(feed_dict)
loss2 = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=p, logits=logit_q),1).eval(feed_dict)
print(p.eval(feed_dict), "\n", q.eval(feed_dict))
print("\n",loss1, "\n", loss2)
Antwoord 1, autoriteit 100%
Je verwart de cross-entropie met binaireen multi-classproblemen.
Cross-entropie met meerdere klassen
De formule die je gebruikt is correct en komt direct overeen met tf.nn.softmax_cross_entropy_with_logits
:
-tf.reduce_sum(p * tf.log(q), axis=1)
p
en q
zijn naar verwachting kansverdelingen over N klassen. In het bijzonder kan N 2 zijn, zoals in het volgende voorbeeld:
p = tf.placeholder(tf.float32, shape=[None, 2])
logit_q = tf.placeholder(tf.float32, shape=[None, 2])
q = tf.nn.softmax(logit_q)
feed_dict = {
p: [[0, 1],
[1, 0],
[1, 0]],
logit_q: [[0.2, 0.8],
[0.7, 0.3],
[0.5, 0.5]]
}
prob1 = -tf.reduce_sum(p * tf.log(q), axis=1)
prob2 = tf.nn.softmax_cross_entropy_with_logits(labels=p, logits=logit_q)
print(prob1.eval(feed_dict)) # [ 0.43748799 0.51301527 0.69314718]
print(prob2.eval(feed_dict)) # [ 0.43748799 0.51301527 0.69314718]
Merk op dat q
tf.nn.softmax
, dwz voert een kansverdeling uit. Het is dus nog steeds een multi-class cross-entropie formule, alleen voor N = 2.
Binaire kruis-entropie
Deze keer is de juiste formule
p * -tf.log(q) + (1 - p) * -tf.log(1 - q)
Hoewel het wiskundig gezien een gedeeltelijk geval is van het geval met meerdere klassen, is de betekenisvan p
en q
anders. In het eenvoudigste geval is elke p
en q
een getal, overeenkomend met een kans van klasse A.
Belangrijk: raak niet in de war door het algemene p * -tf.log(q)
-gedeelte en de som. Vorige p
was een een-hot vector, nu is het een getal, nul of één. Hetzelfde geldt voor q
– het was een kansverdeling, nu is het een getal (waarschijnlijkheid).
Als p
een vector is, wordt elk afzonderlijk onderdeel beschouwd als een onafhankelijke binaire classificatie. Zie dit antwoorddat het verschil schetst tussen softmax- en sigmoid-functies in tensorflow. Dus de definitie p = [0, 0, 0, 1, 0]
betekent niet een one-hot vector, maar 5 verschillende features, waarvan 4 uit en 1 aan. De definitie q = [0.2, 0.2, 0.2, 0.2, 0.2]
betekent dat elk van de 5 functies is ingeschakeld met een waarschijnlijkheid van 20%.
Dit verklaart het gebruik van de functie sigmoid
vóór de kruis-entropie: het doel is om de logit te verkleinen tot een [0, 1]
-interval.
De bovenstaande formule geldt nog steeds voor meerdere onafhankelijke functies, en dat is precies wat tf.nn.sigmoid_cross_entropy_with_logits
berekent:
p = tf.placeholder(tf.float32, shape=[None, 5])
logit_q = tf.placeholder(tf.float32, shape=[None, 5])
q = tf.nn.sigmoid(logit_q)
feed_dict = {
p: [[0, 0, 0, 1, 0],
[1, 0, 0, 0, 0]],
logit_q: [[0.2, 0.2, 0.2, 0.2, 0.2],
[0.3, 0.3, 0.2, 0.1, 0.1]]
}
prob1 = -p * tf.log(q)
prob2 = p * -tf.log(q) + (1 - p) * -tf.log(1 - q)
prob3 = p * -tf.log(tf.sigmoid(logit_q)) + (1-p) * -tf.log(1-tf.sigmoid(logit_q))
prob4 = tf.nn.sigmoid_cross_entropy_with_logits(labels=p, logits=logit_q)
print(prob1.eval(feed_dict))
print(prob2.eval(feed_dict))
print(prob3.eval(feed_dict))
print(prob4.eval(feed_dict))
Je zou moeten zien dat de laatste drie tensoren gelijk zijn, terwijl de prob1
slechts een onderdeel is van kruis-entropie, dus het bevat alleen de juiste waarde als p
1
:
[[ 0. 0. 0. 0.59813893 0. ]
[ 0.55435514 0. 0. 0. 0. ]]
[[ 0.79813886 0.79813886 0.79813886 0.59813887 0.79813886]
[ 0.5543552 0.85435522 0.79813886 0.74439669 0.74439669]]
[[ 0.7981388 0.7981388 0.7981388 0.59813893 0.7981388 ]
[ 0.55435514 0.85435534 0.7981388 0.74439663 0.74439663]]
[[ 0.7981388 0.7981388 0.7981388 0.59813893 0.7981388 ]
[ 0.55435514 0.85435534 0.7981388 0.74439663 0.74439663]]
Het moet nu duidelijk zijn dat het nemen van een som van -p * tf.log(q)
langs axis=1
in deze instelling echter geen zin heeft het zou een geldige formule zijn in geval van meerdere klassen.
Antwoord 2
u kunt de verschillen tussen softmax en sigmoid kruisentropie op de volgende manier begrijpen:
- voor softmax kruis-entropie heeft het eigenlijk één kansverdeling
- voor sigmoïde kruisentropie heeft het in feite meerdere onafhankelijk binaire kansverdelingen, elke binaire kansverdeling kan worden behandeld als kansverdeling met twee klassen
dus hoe dan ook, de kruis-entropie is:
p * -tf.log(q)
voor softmax kruis-entropie ziet het er precies zo uit als bovenstaande formule,
maar voor sigmoid ziet het er een beetje anders uit, want het heeft een multi-binaire kansverdeling
voor elke binaire kansverdeling is het
p * -tf.log(q)+(1-p) * -tf.log(1-q)
p en (1-p) die u kunt behandelen als waarschijnlijkheid met twee klassen binnen elke binaire kansverdeling