Что такое logits, softmax и softmax_cross_entropy_with_logits?


351

Я просматривал здесь документы по тензорному API . В документации tenorflow они использовали ключевое слово logits. Что это? Во многих методах в документации API это написано как

tf.nn.softmax(logits, name=None)

Если написано logitsтолько это Tensors, зачем сохранять другое имя как logits?

Другое дело, что есть два метода, которые я не смог дифференцировать. Они были

tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

Каковы различия между ними? Документы мне не понятны. Я знаю, что tf.nn.softmaxделает. Но не другой. Пример будет действительно полезным.

Ответы:


427

Logits просто означает, что функция работает с немасштабированным выходом более ранних слоев и что относительный масштаб для понимания единиц измерения является линейным. В частности, это означает, что сумма входных данных может не равняться 1, что значения не являются вероятностями (у вас может быть значение 5).

tf.nn.softmaxпроизводит только результат применения функции softmax к входному тензору. Softmax «сдавливает» входы так, что sum(input) = 1это способ нормализации. Форма вывода softmax совпадает с формой ввода: она просто нормализует значения. Выходные данные softmax можно интерпретировать как вероятности.

a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508  0.205666    0.25120102  0.37474789]]

Напротив, tf.nn.softmax_cross_entropy_with_logitsвычисляет кросс-энтропию результата после применения функции softmax (но делает все это вместе более математически аккуратно). Это похоже на результат:

sm = tf.nn.softmax(x)
ce = cross_entropy(sm)

Перекрестная энтропия является суммарной метрикой: она суммирует элементы. Выходной сигнал тензора tf.nn.softmax_cross_entropy_with_logitsформы [2,5]имеет форму [2,1](первое измерение рассматривается как партия).

Если вы хотите провести оптимизацию, чтобы минимизировать перекрестную энтропию, и вы мягко используете максимальную величину после последнего слоя, вы должны использовать ее tf.nn.softmax_cross_entropy_with_logitsвместо того, чтобы делать это самостоятельно, поскольку она охватывает численно нестабильные угловые случаи математически правильным образом. В противном случае вы в конечном итоге будете взламывать его, добавляя маленькие эпсилоны здесь и там.

Отредактировано 2016-02-07: Если у вас есть одноклассные метки, где объект может принадлежать только одному классу, вы можете теперь рассмотреть возможность использования, tf.nn.sparse_softmax_cross_entropy_with_logitsчтобы вам не приходилось конвертировать ваши метки в плотный массив с одним горячим массивом. Эта функция была добавлена ​​после выпуска 0.6.0.


1
Что касается softmax_cross_entropy_with_logits, я не знаю, правильно ли я его использую. Результат не так стабилен в моем коде. Один и тот же код выполняется дважды, общая точность изменяется с 0,6 до 0,8. cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.nn.softmax(tf.add(tf.matmul(x,W),b)),y) cost=tf.reduce_mean(cross_entropy), Но когда я пользуюсь другим способом, pred=tf.nn.softmax(tf.add(tf.matmul(x,W),b)) cost =tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))результат стабильнее и лучше.
Рида

15
Вы дважды софтмаксинг на первой линии. softmax_cross_entropy_with_logits ожидает немасштабированные логиты, а не вывод tf.nn.softmax. Вы просто хотите tf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W, b))в вашем случае.
дга

7
@dga Я думаю, что в вашем коде есть опечатка, которая bдолжна быть за скобками,tf.nn.softmax_cross_entropy_with_logits(tf.add(tf.matmul(x, W), b)
jrieke

1
что значит «что относительная шкала для понимания единиц линейна». часть вашего первого предложения значит?
Чарли Паркер

5
Проголосовано, но ваш ответ немного неверен, когда вы говорите, что «[t] форма вывода softmax совпадает с входом - он просто нормализует значения». Softmax не просто «сдавливает» значения, так что их сумма равна 1. Он также перераспределяет их, и это, возможно, является основной причиной, по которой он используется. См. Stackoverflow.com/questions/17187507/… , особенно ответ Петра Чаплы.
Паоло Перротта

282

Укороченная версия:

Предположим, у вас есть два тензора, в которых y_hatсодержатся вычисленные оценки для каждого класса (например, из y = W * x + b) и y_trueсодержатся метки истинного кодирования в горячем виде.

y_hat  = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded

Если вы интерпретируете баллы y_hatкак ненормализованные логарифмические вероятности, то они являются логитами .

Кроме того, общая кросс-энтропийная потеря рассчитывается следующим образом:

y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))

по существу эквивалентно полной кросс-энтропийной потере, вычисленной с помощью функции softmax_cross_entropy_with_logits():

total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))

Длинная версия:

В выходном слое вашей нейронной сети вы, вероятно, вычислите массив, который содержит оценки классов для каждого из ваших обучающих экземпляров, например, из вычислений y_hat = W*x + b. В качестве примера ниже я создал y_hatмассив размером 2 x 3, в котором строки соответствуют обучающим экземплярам, ​​а столбцы - классам. Итак, здесь есть 2 тренировочных экземпляра и 3 класса.

import tensorflow as tf
import numpy as np

sess = tf.Session()

# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5,  1.5,  0.1],
#        [ 2.2,  1.3,  1.7]])

Обратите внимание, что значения не нормализованы (то есть строки не суммируют до 1). Чтобы их нормализовать, мы можем применить функцию softmax, которая интерпретирует входные данные как ненормализованные логарифмические вероятности (или логиты ) и выводит нормализованные линейные вероятности.

y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863  ,  0.61939586,  0.15274114],
#        [ 0.49674623,  0.20196195,  0.30129182]])

Важно полностью понимать, что говорит выход softmax. Ниже я показал таблицу, которая более четко представляет результат выше. Можно видеть, что, например, вероятность того, что тренировочный экземпляр 1 будет «Классом 2», составляет 0,619. Вероятности классов для каждого обучающего экземпляра нормированы, поэтому сумма каждой строки равна 1,0.

                      Pr(Class 1)  Pr(Class 2)  Pr(Class 3)
                    ,--------------------------------------
Training instance 1 | 0.227863   | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182

Итак, теперь у нас есть классовые вероятности для каждого обучающего экземпляра, где мы можем взять argmax () каждой строки, чтобы сгенерировать окончательную классификацию. Исходя из вышеизложенного, мы можем сгенерировать, что обучающий экземпляр 1 принадлежит «Классу 2», а обучающий экземпляр 2 принадлежит «Классу 1».

Верны ли эти классификации? Нам нужно сравнить с настоящими ярлыками из учебного набора. Вам потребуется y_trueмассив с горячим кодированием , где снова строки - это обучающие экземпляры, а столбцы - это классы. Ниже я создал пример y_trueмассива «один горячий», где истинная метка для обучающего экземпляра 1 - «Класс 2», а истинная метка для обучающего экземпляра 2 - «Класс 3».

y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0.,  1.,  0.],
#        [ 0.,  0.,  1.]])

Распределение вероятностей y_hat_softmaxблизко к распределению вероятностей в y_true? Мы можем использовать кросс-энтропийную потерю для измерения ошибки.

Формула для кросс-энтропийной потери

Мы можем вычислить кросс-энтропийную потерю построчно и посмотреть результаты. Ниже мы видим, что тренировочный экземпляр 1 имеет потерю 0,479, в то время как обучающий экземпляр 2 имеет более высокую потерю 1.200. Этот результат имеет смысл, поскольку в нашем примере выше y_hat_softmaxпоказано, что наибольшая вероятность для обучающего экземпляра 1 была для «класса 2», который соответствует обучающему экземпляру 1 в y_true; однако прогноз для обучающего экземпляра 2 показал наибольшую вероятность для «класса 1», который не соответствует истинному классу «класса 3».

loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 ,  1.19967598])

То, что мы действительно хотим, это общая потеря по всем тренировочным экземплярам. Таким образом, мы можем вычислить:

total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944

Использование softmax_cross_entropy_with_logits ()

Вместо этого мы можем вычислить общую кросс-энтропийную потерю, используя tf.nn.softmax_cross_entropy_with_logits()функцию, как показано ниже.

loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 ,  1.19967598])

total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922

Обратите внимание, что total_loss_1и total_loss_2дают по существу эквивалентные результаты с некоторыми небольшими различиями в самых последних цифрах. Тем не менее, вы также можете использовать второй подход: он занимает на одну строку кода меньше и накапливает меньше числовых ошибок, потому что softmax выполняется для вас внутри softmax_cross_entropy_with_logits().


Я подтверждаю все вышесказанное. Простой код: M = tf.random.uniform([100, 10], minval=-1.0, maxval=1.0); labels = tf.one_hot(tf.random.uniform([100], minval=0, maxval=10 , dtype='int32'), 10); tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=M) - tf.reduce_sum(-tf.nn.log_softmax(M)*tf.one_hot(labels, 10), -1)возвращает значение, близкое к нулю, везде
Сами А. Хайя

51

tf.nn.softmaxвычисляет прямое распространение через слой softmax. Вы используете его во время оценки модели, когда вычисляете вероятности, которые выводит модель.

tf.nn.softmax_cross_entropy_with_logitsвычисляет стоимость для слоя softmax. Используется только во время тренировки .

Логиты - это ненормализованные логарифмические вероятности, которые выводят модель (значения выводятся до того, как к ним применяется нормализация softmax).


2
Я понял Почему бы не вызвать функцию tf.nn.softmax_cross_entropy_sans_normalization?
AURO

8
@auro, потому что он нормализует значения (внутри) во время вычисления кросс-энтропии. Задача tf.nn.softmax_cross_entropy_with_logitsсостоит в том, чтобы оценить, насколько модель отклоняется от золотых меток, а не обеспечить нормализованный результат.
erickrf

1
В случае использования tf.nn.sparse_softmax_cross_entropy_with_logits () вычисляет стоимость разреженного слоя softmax и, таким образом, его следует использовать только во время обучения, что будет альтернативой при запуске модели с новыми данными, возможно ли получить вероятности из этого один.
SerialDev

2
@SerialDev, невозможно получить вероятности от tf.nn.sparse_softmax_cross_entropy_with_logits. Чтобы получить вероятности используйте tf.nn.softmax.
Нандееш

4

Приведенных выше ответов достаточно для описания задаваемого вопроса.

Кроме того, Tensorflow оптимизировал операцию применения функции активации, а затем расчета стоимости с использованием собственной активации, за которой следуют функции стоимости. Следовательно, это хорошая практика для использования: tf.nn.softmax_cross_entropy()болееtf.nn.softmax(); tf.nn.cross_entropy()

Вы можете найти заметную разницу между ними в ресурсоемкой модели.


1
Ответ выше явно не прочитал вопрос .. Все они говорят то же самое, что известно, но не отвечают на сам вопрос
Euler_Salter

@abhish Вы имели в виду, tf.nn.softmaxа затем tf.losses.softmax_cross_entropy?
ankurrc

4

То, что когда-либо идет, softmaxявляется logit, это то, что Дж. Хинтон повторяет в видеофильмах Coursera все время.


1

Совместимый ответ Tensorflow 2.0 : объяснения dgaи stackoverflowuser2010очень подробные сведения о Logits и связанных с ними функциях.

Все эти функции, при использовании в, Tensorflow 1.xбудут работать нормально, но если вы перенесете свой код из 1.x (1.14, 1.15, etc)в 2.x (2.0, 2.1, etc..), использование этих функций приведет к ошибке.

Следовательно, указание совместимых вызовов 2.0 для всех функций, которые мы обсуждали выше, если мы перейдем 1.x to 2.x, на благо сообщества.

Функции в 1.x :

  1. tf.nn.softmax
  2. tf.nn.softmax_cross_entropy_with_logits
  3. tf.nn.sparse_softmax_cross_entropy_with_logits

Соответствующие функции при миграции с 1.x на 2.x :

  1. tf.compat.v2.nn.softmax
  2. tf.compat.v2.nn.softmax_cross_entropy_with_logits
  3. tf.compat.v2.nn.sparse_softmax_cross_entropy_with_logits

Для получения дополнительной информации о миграции с 1.x на 2.x, пожалуйста, обратитесь к этому Руководству по миграции .


0

Еще одна вещь, которую я определенно хотел бы выделить, так как logit - это просто необработанный вывод, обычно вывод последнего слоя. Это может быть и отрицательным значением. Если мы будем использовать его для оценки «кросс-энтропии», как указано ниже:

-tf.reduce_sum(y_true * tf.log(logits))

тогда это не сработает. Как лог-ве не определен. Таким образом, с помощью активации Softmax, эта проблема будет решена.

Это мое понимание, пожалуйста, поправьте меня, если я ошибаюсь.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.