Wat is het verschil tussen een sigmoid gevolgd door de kruisentropie en sigmoid_cross_entropy_with_logits in TensorFlow?

Bij het proberen om kruis-entropie te krijgen met de sigmoid-activeringsfunctie, is er een verschil tussen

  1. loss1 = -tf.reduce_sum(p*tf.log(q), 1)
  2. 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)

pen qzijn 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 qtf.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 pen qanders. In het eenvoudigste geval is elke pen qeen 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 pwas 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 peen 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 sigmoidvóó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_logitsberekent:

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 prob1slechts een onderdeel is van kruis-entropie, dus het bevat alleen de juiste waarde als p1:

[[ 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=1in 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:

  1. voor softmax kruis-entropie heeft het eigenlijk één kansverdeling
  2. 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

Other episodes