Из класса глубокого обучения Udacity , softmax у_i - это просто экспонента, деленная на сумму экспоненты всего вектора Y:
Где S(y_i)
функция softmax y_i
и e
экспоненциальная, а j
нет. столбцов во входном векторе Y.
Я пробовал следующее:
import numpy as np
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum()
scores = [3.0, 1.0, 0.2]
print(softmax(scores))
который возвращает:
[ 0.8360188 0.11314284 0.05083836]
Но предлагаемое решение было:
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
return np.exp(x) / np.sum(np.exp(x), axis=0)
который выдает тот же результат, что и первая реализация , хотя первая реализация явно принимает разность каждого столбца и максимума, а затем делит на сумму.
Может кто-то математически показать, почему? Один правильный, а другой неправильный?
Схожи ли реализация с точки зрения сложности кода и времени? Что является более эффективным?
-inf to +inf
до-inf to 0
. Я думаю, что я переосмыслил. hahahaaaaxis = 0
в предложенном ответе от Udacity?Ответы:
Они оба верны, но ваш предпочтен с точки зрения численной стабильности.
Вы начинаете с
Используя тот факт, что a ^ (b - c) = (a ^ b) / (a ^ c) мы имеем
Вот что говорит другой ответ. Вы можете заменить max (x) на любую переменную, и она будет отменена.
источник
(Ну ... здесь много путаницы, как в вопросе, так и в ответах ...)
Начнем с того, что два решения (то есть ваше и предложенное) не эквивалентны; они случаются эквивалентным только для частного случая 1-D бигованных массивов. Вы бы обнаружили это, если бы попробовали также двумерный массив очков в представленном примере теста Udacity.
С точки зрения результатов, единственное фактическое различие между двумя решениями - это
axis=0
аргумент. Чтобы увидеть, что это так, давайте попробуем ваше решение (your_softmax
), и единственное, где различие заключается вaxis
аргументе:Как я уже сказал, для одномерного массива результатов результаты действительно идентичны:
Тем не менее, вот результаты для двумерного массива оценок, приведенного в тесте Udacity в качестве тестового примера:
Результаты разные - второй действительно идентичен ожидаемому в викторине Udacity, где все столбцы действительно равны 1, что не относится к первому (неправильному) результату.
Таким образом, вся суета была на самом деле за детали реализации -
axis
аргумент. Согласно документации numpy.sum :в то время как здесь мы хотим суммировать построчно, следовательно
axis=0
. Для одномерного массива сумма (только) строки и сумма всех элементов оказываются идентичными, следовательно, в этом случае ваши идентичные результаты ...Если
axis
оставить в стороне проблему, ваша реализация (т. Е. Ваш выбор сначала вычесть максимум) на самом деле лучше предложенного решения! Фактически, это рекомендуемый способ реализации функции softmax - см. Здесь обоснование (числовая стабильность, также указанная некоторыми другими ответами здесь).источник
axis
аргумент к обоимmax
иsum
. Тем не менее, первая реализация еще лучше , так как вы можете легко переполнение при приемеexp
exp
? Что еще было изменено здесь, кроме добавленияaxis
аргумента?Итак, это действительно комментарий к ответу десернаута, но я пока не могу его комментировать из-за своей репутации. Как он указал, ваша версия верна только в том случае, если ваш вклад состоит из одного образца. Если ваш вход состоит из нескольких образцов, это неправильно. Однако решение пустынетаут также неверно. Проблема состоит в том, что, как только он берет одномерный ввод, а затем он берет двумерный ввод. Позвольте мне показать это вам.
Давайте возьмем пример пустынных:
Это вывод:
Вы можете видеть, что версия desernauts потерпит неудачу в этой ситуации. (Не было бы, если бы ввод был только одномерный, как np.array ([1, 2, 3, 6]).
Теперь давайте используем 3 сэмпла, поэтому мы используем двумерный ввод. Следующий x2 не совпадает с примером из примера desernauts.
Этот вход состоит из партии с 3 образцами. Но образец один и три по сути одинаковы. Теперь мы ожидаем 3 ряда активаций softmax, где первый должен совпадать с третьим, а также с нашей активацией x1!
Я надеюсь, вы видите, что это только в моем решении.
Кроме того, вот результаты реализации softmax TensorFlows:
И результат:
источник
s = s[:, np.newaxis]
,s = s.reshape(z.shape[0],1)
также должно работать.Я бы сказал, что хотя оба математически верны, с точки зрения реализации, первый лучше. При вычислении softmax промежуточные значения могут стать очень большими. Деление двух больших чисел может быть численно нестабильным. В этих заметках (из Стэнфорда) упоминается трюк нормализации, который, по сути, то, что вы делаете.
источник
Sklearn также предлагает реализацию Softmax
источник
С математической точки зрения обе стороны равны.
И вы можете легко доказать это. Давай
m=max(x)
. Теперь ваша функцияsoftmax
возвращает вектор, i-я координата которого равнаобратите внимание, что это работает для любого
m
, потому что для всех (даже сложных) чиселe^m != 0
с точки зрения сложности вычислений они также эквивалентны и оба выполняются во
O(n)
времени, гдеn
есть размер вектора.с точки зрения числовой устойчивости , первое решение является предпочтительным, потому что
e^x
растет очень быстро и даже при довольно небольших значенияхx
оно будет переполнено. Вычитание максимального значения позволяет избавиться от этого переполнения. Чтобы на практике испытать то, о чем я говорил, попробуйте выполнитьx = np.array([1000, 5])
обе ваши функции. Один вернет правильную вероятность, второй переполнитсяnan
ваше решение работает только для векторов (викторина Udacity хочет, чтобы вы рассчитали его и для матриц). Для того, чтобы это исправить, вам нужно использовать
sum(axis=0)
источник
РЕДАКТИРОВАТЬ . Начиная с версии 1.2.0, scipy включает softmax в качестве специальной функции:
https://scipy.github.io/devdocs/generated/scipy.special.softmax.html
Я написал функцию, применяющую softmax к любой оси:
Вычитание максимума, как описывали другие пользователи, является хорошей практикой. Я написал подробный пост об этом здесь .
источник
Здесь вы можете узнать, почему они использовали
- max
.Оттуда:
источник
Более краткая версия:
источник
Чтобы предложить альтернативное решение, рассмотрите случаи, когда ваши аргументы чрезвычайно велики по величине, такие
exp(x)
как недопущение (в отрицательном случае) или переполнение (в положительном случае). Здесь вы хотите оставаться в пространстве журнала как можно дольше, возводя в степень только в конце, где вы можете быть уверены, что результат будет хорошим.источник
axis=0
в качестве аргументаlogsumexp
.Мне нужно было что-то совместимое с выводом плотного слоя из Tensorflow .
Решение от @desertnaut в этом случае не работает, потому что у меня есть пакеты данных. Поэтому я пришел с другим решением, которое должно работать в обоих случаях:
Полученные результаты:
Ссылка: Tensorflow softmax
источник
Я бы предложил это:
Это будет работать как для стохастика, так и для пакета.
Для получения дополнительной информации см .: https://medium.com/@ravish1729/analysis-of-softmax-function-ad058d6a564d.
источник
Чтобы сохранить числовую стабильность, необходимо вычесть max (x). Ниже приведен код для функции softmax;
def softmax (x):
источник
Уже подробно ответили в приведенных выше ответах.
max
вычитается, чтобы избежать переполнения. Я добавляю сюда еще одну реализацию в python3.источник
Кажется, что все публикуют свое решение, поэтому я опубликую свое:
Я получаю те же результаты, что и импортированные из sklearn:
источник
источник
Основываясь на всех ответах и примечаниях CS231n , позвольте мне подвести итог:
Использование:
Вывод:
источник
Я хотел бы добавить немного больше понимания проблемы. Здесь правильно вычесть максимум из массива. Но если вы запустите код в другом посте, вы обнаружите, что он не дает правильного ответа, когда массив имеет размеры 2D или выше.
Здесь я даю вам несколько советов:
Следуя полученному результату, вы получите правильный ответ, выполнив векторизацию. Поскольку это связано с домашней работой колледжа, я не могу опубликовать точный код здесь, но я хотел бы дать больше советов, если вы не понимаете.
источник
Цель функции softmax состоит в том, чтобы сохранить соотношение векторов, а не сдавливать конечные точки сигмоидом, поскольку значения насыщаются (т. Е. Стремятся к +/- 1 (tanh) или от 0 до 1 (логистический)). Это связано с тем, что он сохраняет больше информации о скорости изменения в конечных точках и, таким образом, более применим к нейронным сетям с выходным кодированием 1 из N (т. Е. Если мы раздавим конечные точки, было бы сложнее дифференцировать 1). выходного класса -N, потому что мы не можем сказать, какой из них является "самым большим" или "самым маленьким", потому что они были сжаты.); также это делает общую выходную сумму равной 1, и чистый победитель будет ближе к 1, в то время как другие числа, которые близки друг к другу, будут суммироваться до 1 / p, где p - число выходных нейронов с аналогичными значениями.
Цель вычитания максимального значения из вектора состоит в том, что когда вы выполняете e ^ y экспоненты, вы можете получить очень высокое значение, которое обрезает число с плавающей точкой при максимальном значении, приводящем к привязке, что не имеет место в этом примере. Это становится БОЛЬШОЙ проблемой, если вы вычитаете максимальное значение, чтобы получить отрицательное число, тогда у вас есть отрицательный показатель, который быстро сжимает значения, изменяющие соотношение, что и произошло в вопросе автора и дало неправильный ответ.
Ответ от Udacity УЖАСНО неэффективен. Первое, что нам нужно сделать, это вычислить e ^ y_j для всех компонент вектора, СОХРАНЯТЬ ЭТИ ЗНАЧЕНИЯ, затем суммировать их и делить. Где Udacity испортил это они вычисляют e ^ y_j ДВАЖДЫ !!! Вот правильный ответ:
источник
Цель состояла в том, чтобы достигнуть подобных результатов, используя Numpy и Tensorflow. Единственное отличие от исходного ответа - это
axis
параметр дляnp.sum
API.Первоначальный подход :
axis=0
- Это, однако, не дает ожидаемых результатов, когда измерения равны N.Модифицированный подход :
axis=len(e_x.shape)-1
- Всегда суммируйте по последнему измерению. Это обеспечивает результаты, аналогичные функции softmax тензорного потока.источник
Вот обобщенное решение, использующее numpy и сравнение для корректности с tenorflow и scipy:
Подготовка данных:
Вывод:
Softmax с использованием тензор потока:
Вывод:
Softmax с использованием scipy:
Вывод:
Softmax с использованием numpy ( https://nolanbconaway.github.io/blog/2017/softmax-numpy ):
Вывод:
источник
Функция softmax - это функция активации, которая превращает числа в вероятности, которые в сумме равны единице. Функция softmax выводит вектор, который представляет распределения вероятностей списка результатов. Это также основной элемент, используемый в задачах классификации глубокого обучения.
Функция Softmax используется, когда у нас есть несколько классов.
Это полезно для определения класса, который имеет макс. Вероятность.
Функция Softmax идеально используется в выходном слое, где мы на самом деле пытаемся получить вероятности для определения класса каждого входа.
Он варьируется от 0 до 1.
Функция Softmax превращает логиты [2.0, 1.0, 0.1] в вероятности [0.7, 0.2, 0.1], а вероятности составляют 1. Логиты - это необработанные результаты, полученные последним слоем нейронной сети. До активации происходит. Чтобы понять функцию softmax, мы должны посмотреть на вывод (n-1) -го слоя.
Функция softmax фактически является функцией arg max. Это означает, что он не возвращает наибольшее значение из входных данных, но положение самых больших значений.
Например:
До софтмакс
После софтмакс
Код:
источник