web-dev-qa-db-fra.com

À propos de tf.nn.softmax_cross_entropy_with_logits_v2

J'ai remarqué que tf.nn.softmax_cross_entropy_with_logits_v2(labels, logits) effectue principalement 3 opérations:

  1. Appliquez softmax aux logits (y_hat) afin de les normaliser: y_hat_softmax = softmax(y_hat).

  2. Calculez la perte d'entropie croisée: y_cross = y_true * tf.log(y_hat_softmax)

  3. Somme sur une classe différente pour une instance: -tf.reduce_sum(y_cross, reduction_indices=[1])

Le code emprunté à ici le démontre parfaitement.

y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))

# first step
y_hat_softmax = tf.nn.softmax(y_hat)

# second step
y_cross = y_true * tf.log(y_hat_softmax)

# third step
result = - tf.reduce_sum(y_cross, 1)

# use tf.nn.softmax_cross_entropy_with_logits_v2
result_tf = tf.nn.softmax_cross_entropy_with_logits_v2(labels = y_true, logits = y_hat)

with tf.Session() as sess:
    sess.run(result)
    sess.run(result_tf)
    print('y_hat_softmax:\n{0}\n'.format(y_hat_softmax.eval()))
    print('y_true: \n{0}\n'.format(y_true.eval()))
    print('y_cross: \n{0}\n'.format(y_cross.eval()))
    print('result: \n{0}\n'.format(result.eval()))
    print('result_tf: \n{0}'.format(result_tf.eval()))

Production:

y_hat_softmax:
[[0.227863   0.61939586 0.15274114]
[0.49674623 0.20196195 0.30129182]]

y_true: 
[[0. 1. 0.]
[0. 0. 1.]]

y_cross: 
[[-0.         -0.4790107  -0.        ]
[-0.         -0.         -1.19967598]]

result: 
[0.4790107  1.19967598]

result_tf: 
[0.4790107  1.19967598]

Cependant, l'un des labels à chaud comprend 0 ou 1, donc l'entropie croisée pour un tel cas binaire est formulée comme suit comme indiqué dans ici et ici :

binary_cross_entropy

J'écris du code pour cette formule dans la cellule suivante, dont le résultat est différent de celui ci-dessus. Ma question est laquelle est la meilleure ou la bonne? Tensorflow a-t-il une fonction pour calculer également l'entropie croisée selon cette formule?

y_true = np.array([[0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
y_hat_softmax_from_tf = np.array([[0.227863, 0.61939586, 0.15274114], 
                              [0.49674623, 0.20196195, 0.30129182]])
comb = np.dstack((y_true, y_hat_softmax_from_tf))
#print(comb)

print('y_hat_softmax_from_tf: \n{0}\n'.format(y_hat_softmax_from_tf))
print('y_true: \n{0}\n'.format(y_true))

def cross_entropy_fn(sample):
    output = []
    for label in sample:
        if label[0]:
            y_cross_1 = label[0] * np.log(label[1])
        else:
            y_cross_1 = (1 - label[0]) * np.log(1 - label[1])
        output.append(y_cross_1)
    return output

y_cross_1 = np.array([cross_entropy_fn(sample) for sample in comb])
print('y_cross_1: \n{0}\n'.format(y_cross_1))

result_1 = - np.sum(y_cross_1, 1)
print('result_1: \n{0}'.format(result_1))

production

y_hat_softmax_from_tf: 
[[0.227863   0.61939586 0.15274114]
[0.49674623 0.20196195 0.30129182]]

y_true: 
[[0. 1. 0.]
[0. 0. 1.]]

y_cross_1: 
[[-0.25859328 -0.4790107  -0.16574901]
[-0.68666072 -0.225599   -1.19967598]]

result_1: 
[0.90335299 2.11193571]
14
user3744927

Votre formule est correcte, mais elle ne fonctionne que pour la classification binaire. Le code de démonstration dans tensorflow classe 3 classes. C'est comme comparer des pommes à des oranges. ne des réponses vous vous référez à la mentionne aussi:

Cette formulation est souvent utilisée pour un réseau avec une sortie prédisant deux classes (généralement l'appartenance à une classe positive pour 1 et négative pour une sortie 0). Dans ce cas, je ne peux avoir qu'une seule valeur - vous pouvez perdre la somme par rapport à i.

La différence entre ces deux formules (entropie croisée binaire vs entropie croisée multinomiale) et quand chacune est applicable est bien décrite dans cette question .

La réponse à votre deuxième question est oui, il existe une telle fonction appelée tf.nn.sigmoid_cross_entropy_with_logits . Voir la question mentionnée ci-dessus.

6
Maxim