В чем разница между sparse_softmax_cross_entropy_with_logits и softmax_cross_entropy_with_logits?

111

Недавно я наткнулся на tf.nn.sparse_softmax_cross_entropy_with_logits, и я не могу понять, в чем разница по сравнению с tf.nn.softmax_cross_entropy_with_logits .

Является единственным отличие , что обучающие векторы yдолжны быть один горячей закодированными при использовании sparse_softmax_cross_entropy_with_logits?

Читая API, я не нашел другой разницы по сравнению с softmax_cross_entropy_with_logits. Но зачем тогда нужна дополнительная функция?

Не должен softmax_cross_entropy_with_logitsдавать такие же результаты, как sparse_softmax_cross_entropy_with_logitsесли бы он был снабжен однократно закодированными обучающими данными / векторами?

daniel451
источник
1
Мне интересно увидеть сравнение их производительности, если оба могут использоваться (например, с эксклюзивными метками изображений); Я ожидал, что разреженная версия будет более эффективной, по крайней мере, с точки зрения памяти.
Ибо Ян
1
См. Также этот вопрос , в котором обсуждаются все функции кросс-энтропии в тензорном потоке (оказывается, их много).
Максим

Ответы:

175

Наличие двух разных функций - это удобство , поскольку они дают одинаковый результат.

Отличие простое:

  • Ведь sparse_softmax_cross_entropy_with_logitsметки должны иметь форму [batch_size] и dtype int32 или int64. Каждая метка представляет собой int в диапазоне [0, num_classes-1].
  • Ведь softmax_cross_entropy_with_logitsметки должны иметь форму [batch_size, num_classes] и dtype float32 или float64.

Этикетки, используемые в, softmax_cross_entropy_with_logitsявляются одной из самых популярных версий этикеток, используемых в sparse_softmax_cross_entropy_with_logits.

Еще одно крошечное отличие заключается в том sparse_softmax_cross_entropy_with_logits, что с помощью вы можете указать -1 в качестве метки, чтобы 0на этой метке были потери .

Оливье Муиндро
источник
15
-1 правильный? Как сказано в документации: «Каждая запись в метках должна быть индексом в [0, num_classes). Другие значения вызовут исключение, когда эта операция выполняется на CPU, и вернут NaN для соответствующих строк потерь и градиентов на GPU».
user1761806
1
[0, num_classes) = [0, num_classes-1]
Karthik C
24

Я просто хотел бы добавить к принятому ответу 2 вещи, которые вы также можете найти в документации TF.

Первый:

tf.nn.softmax_cross_entropy_with_logits

ПРИМЕЧАНИЕ. Хотя классы являются взаимоисключающими, их вероятности не обязательны. Все, что требуется, - это чтобы каждая строка меток представляла собой допустимое распределение вероятностей. В противном случае расчет градиента будет неверным.

Второй:

tf.nn.sparse_softmax_cross_entropy_with_logits

ПРИМЕЧАНИЕ: Для этой операции вероятность данной метки считается исключительной. То есть мягкие классы не разрешены, и вектор меток должен предоставлять единственный конкретный индекс для истинного класса для каждой строки логитов (каждой записи мини-пакета).

Drag0
источник
4
Что использовать, если классы не исключают друг друга. Я имею в виду, если мы объединяем несколько категориальных ярлыков?
Hayro
Я тоже это читал. Это означает, что мы применяем классовую вероятность к перекрестной энтропии, а не принимаем ее за единичный вектор.
Шаман Сиривардхана
@Hayro - Вы имеете в виду, что не можете выполнить одно горячее кодирование? Думаю, вам стоит взглянуть на другую модель. Здесь упоминается что-то вроде «было бы более подходящим создать 4 бинарных классификатора логистической регрессии», чтобы сначала убедиться, что вы можете разделить классы.
Ashley
21

Обе функции вычисляют одни и те же результаты, а sparse_softmax_cross_entropy_with_logits вычисляет перекрестную энтропию непосредственно на разреженных метках вместо их преобразования с помощью однократного кодирования .

В этом можно убедиться, запустив следующую программу:

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

Здесь я создаю случайный logitsвектор длины dimsи генерирую метки с горячим кодированием (где элемент in posравен 1, а другие - 0).

После этого я вычисляю softmax и sparse softmax и сравниваю их результат. Попробуйте запустить его несколько раз, чтобы убедиться, что он всегда дает одинаковый результат.

Сальвадор Дали
источник