Що таке logits, softmax та softmax_cross_entropy_with_logits?


352

Я переглядав тут документи з tensorflow API . У документації на tensorflow вони використовували ключове слово під назвою 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

Логіти просто означають, що функціонує функція на немасштабному виході попередніх шарів і що відносна шкала для розуміння одиниць лінійна. Це означає, зокрема, сума входів може не дорівнювати 1, що значення не є ймовірностями (у вас може бути вхід 5).

tf.nn.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 не просто "зменшує" значення, щоб їх сума дорівнювала 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, яка інтерпретує вхід як ненормалізовані ймовірності журналу (aka logits ) та виводить нормалізовані лінійні ймовірності.

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?
ауро

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це логіт, це те, що Дж. Хінтон постійно повторює у відеороликах курсу.


1

Відповідь Tensorflow 2.0 : Пояснення dgaта stackoverflowuser2010дуже детальна інформація про Логіти та пов'язані з ними функції.

Всі ці функції, при використанні в 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))

тоді це не буде працювати. Оскільки журнал -ve не визначено. Тож використання активації softmax дозволить подолати цю проблему.

Це моє розуміння, будь ласка, виправте мене, якщо я помиляюся.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.