Qual é a diferença entre sparse_softmax_cross_entropy_with_logits e softmax_cross_entropy_with_logits?

111

Recentemente, encontrei tf.nn.sparse_softmax_cross_entropy_with_logits e não consigo descobrir qual é a diferença em comparação com tf.nn.softmax_cross_entropy_with_logits .

É a única diferença que os vetores de treinamento yprecisam ser codificados em um ponto ao usar sparse_softmax_cross_entropy_with_logits?

Lendo a API, não consegui encontrar nenhuma outra diferença em comparação com softmax_cross_entropy_with_logits. Mas então por que precisamos da função extra?

Não deve softmax_cross_entropy_with_logitsproduzir os mesmos resultados que sparse_softmax_cross_entropy_with_logits, se for fornecido com dados / vetores de treinamento codificados em um único ponto?

daniel451
fonte
1
Estou interessado em ver uma comparação de seu desempenho se ambos podem ser usados ​​(por exemplo, com rótulos de imagem exclusivos); Eu esperaria que a versão esparsa fosse mais eficiente, pelo menos em termos de memória.
Yibo Yang
1
Veja também esta questão , que discute todas as funções de entropia cruzada em tensorflow (acontece que existem muitas delas).
Máximo

Respostas:

175

Ter duas funções diferentes é uma conveniência , pois elas produzem o mesmo resultado.

A diferença é simples:

  • Para sparse_softmax_cross_entropy_with_logits, os rótulos devem ter a forma [batch_size] e o dtype int32 ou int64. Cada rótulo é um int no intervalo [0, num_classes-1].
  • Para softmax_cross_entropy_with_logits, os rótulos devem ter a forma [batch_size, num_classes] e dtype float32 ou float64.

As etiquetas usadas em softmax_cross_entropy_with_logitssão a única versão quente das etiquetas usadas em sparse_softmax_cross_entropy_with_logits.

Outra pequena diferença é que com sparse_softmax_cross_entropy_with_logits, você pode dar -1 como um rótulo para ter perda 0neste rótulo.

Olivier Moindrot
fonte
15
O -1 está correto? Como diz a documentação: "Cada entrada nos rótulos deve ser um índice em [0, num_classes). Outros valores irão gerar uma exceção quando esta operação for executada na CPU e retornar NaN para perdas correspondentes e linhas de gradiente na GPU."
user1761806
1
[0, num_classes) = [0, num_classes-1]
Karthik C
24

Eu gostaria apenas de adicionar 2 coisas à resposta aceita que você também pode encontrar na documentação do TF.

Primeiro:

tf.nn.softmax_cross_entropy_with_logits

NOTA: Embora as classes sejam mutuamente exclusivas, suas probabilidades não precisam ser. Tudo o que é necessário é que cada linha de rótulos seja uma distribuição de probabilidade válida. Se não forem, o cálculo do gradiente estará incorreto.

Segundo:

tf.nn.sparse_softmax_cross_entropy_with_logits

NOTA: Para esta operação, a probabilidade de um determinado rótulo é considerada exclusiva. Ou seja, classes suaves não são permitidas e o vetor de rótulos deve fornecer um único índice específico para a classe verdadeira para cada linha de logits (cada entrada de minibatch).

Drag0
fonte
4
O que devemos usar se as classes não forem mutuamente exclusivas. Quer dizer, se estivermos combinando vários rótulos categóricos?
Hayro
Eu também li isso. Portanto, isso significa que aplicamos a probabilidade de classe na entropia cruzada, em vez de considerá-la como um vetor de uma ocorrência.
Shamane Siriwardhana
@Hayro - Quer dizer que você não consegue fazer uma codificação quente? Acho que você teria que olhar para um modelo diferente. Isso mencionou algo como "seria mais apropriado construir 4 classificadores de regressão logística binária" Para primeiro ter certeza de que você pode separar as classes.
ashley
21

Ambas as funções calculam os mesmos resultados e sparse_softmax_cross_entropy_with_logits calcula a entropia cruzada diretamente nos rótulos esparsos em vez de convertê-los com codificação one-hot .

Você pode verificar isso executando o seguinte programa:

import tensorflow as tf
from random import randint

dims = 8
pos  = randint(0, dims - 1)

logits = tf.random_uniform([dims], maxval=3, dtype=tf.float32)
labels = tf.one_hot(pos, dims)

res1 = tf.nn.softmax_cross_entropy_with_logits(       logits=logits, labels=labels)
res2 = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=tf.constant(pos))

with tf.Session() as sess:
    a, b = sess.run([res1, res2])
    print a, b
    print a == b

Aqui, crio um logitsvetor aleatório de comprimento dimse gero rótulos codificados com um único elemento (em que o elemento in posé 1 e os outros são 0).

Depois disso, calculo o softmax e o softmax esparso e comparo sua saída. Tente executá-lo novamente algumas vezes para se certificar de que sempre produz o mesmo resultado

Salvador Dalí
fonte