Z klasy głębokiego uczenia Udacity softmax y_i jest po prostu wykładniczym podzielonym przez sumę wykładniczego całego wektora Y:
Gdzie S(y_i)
jest funkcja softmax y_i
i e
jest wykładnicza i j
jest nie. kolumn w wektorze wejściowym Y.
Próbowałem następujące:
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))
który zwraca:
[ 0.8360188 0.11314284 0.05083836]
Ale sugerowanym rozwiązaniem było:
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
return np.exp(x) / np.sum(np.exp(x), axis=0)
co daje takie same wyniki jak pierwsza implementacja , mimo że pierwsza implementacja wyraźnie bierze różnicę między każdą kolumną a wartością maksymalną, a następnie dzieli przez sumę.
Czy ktoś może matematycznie pokazać, dlaczego? Czy jedno jest prawidłowe, a drugie złe?
Czy implementacja jest podobna pod względem złożoności kodu i czasu? Który jest bardziej wydajny?
-inf to +inf
do-inf to 0
. Chyba przesadziłem. hahahaaaaxis = 0
sugerowana odpowiedź Udacity?Odpowiedzi:
Oba są poprawne, ale twoje jest preferowane z punktu widzenia stabilności numerycznej.
Zaczynasz od
Wykorzystując fakt, że a ^ (b - c) = (a ^ b) / (a ^ c) mamy
Tak mówi druga odpowiedź. Możesz zamienić max (x) na dowolną zmienną i to by się anulowało.
źródło
(Cóż ... tutaj wiele zamieszania, zarówno w pytaniu, jak iw odpowiedziach ...)
Na początek dwa rozwiązania (tj. Twoje i sugerowane) nie są równoważne; okazuje się, że są równoważne tylko w szczególnym przypadku tablic wyników 1-D. Odkryłbyś to, gdybyś wypróbował również tablicę wyników 2-D w podanym przykładzie quizu Udacity.
Pod względem wyników jedyną faktyczną różnicą między tymi dwoma rozwiązaniami jest
axis=0
argument. Aby zobaczyć, że tak jest, spróbujmy rozwiązania (your_softmax
) i jedyną różnicą jestaxis
argument:Jak powiedziałem, dla tablicy wyników 1-D wyniki są rzeczywiście identyczne:
Niemniej jednak oto wyniki dla tablicy wyników 2-D podane w quizie Udacity jako przykład testu:
Wyniki są różne - druga jest rzeczywiście identyczna z oczekiwaną w quizie Udacity, gdzie wszystkie kolumny rzeczywiście sumują się do 1, co nie jest w przypadku pierwszego (błędnego) wyniku.
Tak więc całe zamieszanie dotyczyło szczegółów implementacyjnych -
axis
argumentu. Zgodnie z dokumentacją numpy.sum :podczas gdy tutaj chcemy podsumować wierszowo, stąd
axis=0
. W przypadku tablicy 1-D suma (tylko) wiersza i suma wszystkich elementów są identyczne, stąd twoje identyczne wyniki w tym przypadku ...axis
Problem na bok, implementacja (czyli wybór odjąć max pierwszy) jest rzeczywiście lepsze niż sugerowane rozwiązanie! W rzeczywistości jest to zalecany sposób implementacji funkcji softmax - patrz tutaj uzasadnienie (stabilność liczbowa, na co wskazują również inne odpowiedzi tutaj).źródło
axis
argument do obumax
isum
. Jednak pierwsza implementacja jest jeszcze lepsza, ponieważ można łatwo przepełnić podczas przyjmowaniaexp
exp
? Co jeszcze tu zmodyfikowano poza dodaniemaxis
argumentu?To naprawdę komentarz do odpowiedzi desertnaut, ale nie mogę tego jeszcze komentować z powodu mojej reputacji. Jak zauważył, twoja wersja jest poprawna tylko wtedy, gdy twój wkład składa się z pojedynczej próbki. Jeśli dane wejściowe składają się z kilku próbek, są błędne. Jednak rozwiązanie desertnaut jest również błędne. Problem polega na tym, że raz przyjmuje dane jednowymiarowe, a następnie przyjmuje dane dwuwymiarowe. Pozwól, że ci to pokażę.
Weźmy przykład pustynnych:
To jest wynik:
Widać, że wersja desernauts zawiodłaby w tej sytuacji. (Nie byłoby tak, gdyby dane wejściowe były tylko jednowymiarowe jak np. Tablica ([1, 2, 3, 6]).
Użyjmy teraz 3 próbek, ponieważ z tego powodu używamy dwuwymiarowego wejścia. Poniższy x2 nie jest taki sam jak ten z przykładu dezerterów.
Dane wejściowe składają się z partii z 3 próbkami. Ale próbka pierwsza i trzecia są w zasadzie takie same. Oczekujemy teraz 3 wierszy aktywacji softmax, przy czym pierwsza powinna być taka sama jak trzecia, a także taka sama jak nasza aktywacja x1!
Mam nadzieję, że widać, że tak jest tylko w przypadku mojego rozwiązania.
Dodatkowo, oto wyniki implementacji softmax TensorFlows:
A wynik:
źródło
s = s[:, np.newaxis]
,s = s.reshape(z.shape[0],1)
powinien również działać.Powiedziałbym, że chociaż oba są poprawne matematycznie, pod względem implementacji, pierwszy jest lepszy. Podczas obliczania softmax wartości pośrednie mogą stać się bardzo duże. Dzielenie dwóch dużych liczb może być niestabilne numerycznie. Te notatki (ze Stanford) wspominają sztuczkę normalizacyjną, która jest zasadniczo tym, co robisz.
źródło
sklearn oferuje również implementację softmax
źródło
Z matematycznego punktu widzenia obie strony są równe.
I możesz to łatwo udowodnić. Let's
m=max(x)
. Teraz twoja funkcjasoftmax
zwraca wektor, którego i-ta współrzędna jest równazauważ, że działa to na dowolne
m
, ponieważ na wszystkie (nawet złożone) liczbye^m != 0
z punktu widzenia złożoności obliczeniowej są one również równoważne i oba działają
O(n)
czasie, gdzien
jest rozmiar wektora.z punktu widzenia stabilności numerycznej preferowane jest pierwsze rozwiązanie, ponieważ
e^x
rośnie ono bardzo szybko, a nawet przy dość niewielkich wartościachx
przepełnia się. Odejmowanie maksymalnej wartości pozwala pozbyć się tego przelewu. Aby praktycznie doświadczyć rzeczy, o których mówiłem, spróbuj włączyćx = np.array([1000, 5])
obie funkcje. Jeden zwróci prawidłowe prawdopodobieństwo, drugi przepełni sięnan
twoje rozwiązanie działa tylko dla wektorów (quiz Udacity chce, abyś również obliczył dla macierzy). Aby to naprawić, musisz użyć
sum(axis=0)
źródło
EDYTOWAĆ . Począwszy od wersji 1.2.0, scipy zawiera softmax jako specjalną funkcję:
https://scipy.github.io/devdocs/generated/scipy.special.softmax.html
Napisałem funkcję nakładającą softmax na dowolną oś:
Odejmowanie maksimum, jak opisali inni użytkownicy, jest dobrą praktyką. Tutaj napisałem szczegółowy post .
źródło
Tutaj możesz dowiedzieć się, dlaczego skorzystali
- max
.Stamtąd:
źródło
Bardziej zwięzła wersja to:
źródło
Aby zaoferować alternatywne rozwiązanie, rozważ przypadki, w których twoje argumenty są bardzo duże, takie,
exp(x)
że niedopełnienie (w przypadku ujemnym) lub przepełnienie (w przypadku dodatnim). Tutaj chcesz pozostać w przestrzeni dziennika tak długo, jak to możliwe, wykładniczo tylko na końcu, gdzie możesz ufać, że wynik będzie dobrze zachowany.źródło
axis=0
jako argument dologsumexp
.Potrzebowałem czegoś kompatybilnego z wyjściem gęstej warstwy z Tensorflow .
Rozwiązanie @desertnaut nie działa w tym przypadku, ponieważ mam partie danych. Dlatego przyjechałem z innym rozwiązaniem, które powinno działać w obu przypadkach:
Wyniki:
Ref: Tensorflow softmax
źródło
Sugerowałbym to:
Będzie działał zarówno dla partii stochastycznej, jak i wsadowej.
Aby uzyskać więcej informacji, zobacz: https://medium.com/@ravish1729/analysis-of-softmax-function-ad058d6a564d
źródło
Aby zachować stabilność numeryczną, należy odjąć max (x). Poniżej znajduje się kod funkcji softmax;
def softmax (x):
źródło
Już odpowiedziałem bardzo szczegółowo w powyższych odpowiedziach.
max
jest odejmowane, aby uniknąć przepełnienia. Dodam tutaj jeszcze jedną implementację w python3.źródło
Wydaje się, że wszyscy publikują swoje rozwiązania, więc opublikuję moje:
Otrzymuję dokładnie takie same wyniki jak importowane ze sklearn:
źródło
źródło
Na podstawie wszystkich odpowiedzi i notatek CS231n pozwól, że podsumuję:
Stosowanie:
Wynik:
źródło
Chciałbym uzupełnić nieco więcej zrozumienia problemu. Tutaj poprawne jest odjęcie maksimum tablicy. Ale jeśli uruchomisz kod w innym poście, okaże się, że nie daje właściwej odpowiedzi, gdy tablica ma wymiary 2D lub wyższe.
Oto kilka sugestii:
Postępuj zgodnie z wynikiem, aby uzyskać poprawną odpowiedź, wykonując wektoryzację. Ponieważ jest to związane z pracą domową na uczelni, nie mogę tutaj opublikować dokładnego kodu, ale jeśli nie rozumiesz, chciałbym podać więcej sugestii.
źródło
Funkcja softmax ma na celu zachowanie stosunku wektorów w przeciwieństwie do zgniatania punktów końcowych sigmoidem, gdy wartości są nasycone (tj. Mają tendencję do +/- 1 (tanh) lub od 0 do 1 (logistyka)). Wynika to z faktu, że zachowuje więcej informacji o szybkości zmian w punktach końcowych, a zatem ma większe zastosowanie do sieci neuronowych z kodowaniem wyjściowym 1-z-N (tj. Jeśli zgniecimy punkty końcowe, trudniej będzie odróżnić 1 -of-N klasy wyjściowej, ponieważ nie jesteśmy w stanie stwierdzić, która z nich jest „największa” lub „najmniejsza”, ponieważ została zmiażdżona.); powoduje również, że całkowita suma wyjściowa wynosi 1, a wyraźny zwycięzca będzie bliższy 1, podczas gdy inne liczby, które są blisko siebie, sumują się do 1 / p, gdzie p jest liczbą neuronów wyjściowych o podobnych wartościach.
Odejmowanie maksymalnej wartości od wektora polega na tym, że gdy robisz wykładniki, możesz uzyskać bardzo wysoką wartość, która przycina liczbę zmiennoprzecinkową na maksymalnej wartości, co prowadzi do remisu, czego nie ma w tym przykładzie. Staje się to WIELKIM problemem, jeśli odejmiesz maksymalną wartość, aby uzyskać liczbę ujemną, a następnie masz ujemny wykładnik, który gwałtownie zmniejsza wartości zmieniając stosunek, co wystąpiło w pytaniu plakatu i dało niepoprawną odpowiedź.
Odpowiedź dostarczona przez Udacity jest NAPRAWDĘ nieefektywna. Pierwszą rzeczą, którą musimy zrobić, to obliczyć e ^ y_j dla wszystkich składników wektora, ZACHOWAJ TE WARTOŚCI, następnie zsumuj je i podziel. Tam gdzie Udacity się popsuło, obliczają e ^ y_j dwa razy !!! Oto poprawna odpowiedź:
źródło
Celem było osiągnięcie podobnych wyników za pomocą Numpy i Tensorflow. Jedyną zmianą w stosunku do oryginalnej odpowiedzi jest
axis
parametr dlanp.sum
interfejsu API.Wstępne podejście :
axis=0
- Nie zapewnia to jednak zamierzonych wyników, gdy wymiary są N.Zmodyfikowane podejście :
axis=len(e_x.shape)-1
- Zawsze sumuj według ostatniego wymiaru. Zapewnia to podobne wyniki jak funkcja softmax tensorflow.źródło
Oto uogólnione rozwiązanie wykorzystujące numpy i porównanie dla poprawności z tensorflow ans scipy:
Przygotowywanie danych:
Wynik:
Softmax za pomocą tensorflow:
Wynik:
Softmax za pomocą scipy:
Wynik:
Softmax przy użyciu numpy ( https://nolanbconaway.github.io/blog/2017/softmax-numpy ):
Wynik:
źródło
Funkcja softmax to funkcja aktywacji, która przekształca liczby w prawdopodobieństwa, które sumują się do jednego. Funkcja softmax wyprowadza wektor, który reprezentuje rozkłady prawdopodobieństwa listy wyników. Jest to również podstawowy element wykorzystywany w zadaniach klasyfikacji w ramach głębokiego uczenia się.
Funkcja Softmax jest używana, gdy mamy wiele klas.
Jest to przydatne do znalezienia klasy, która ma maks. Prawdopodobieństwo.
Funkcja Softmax jest idealnie wykorzystywana w warstwie wyjściowej, gdzie tak naprawdę staramy się osiągnąć prawdopodobieństwo zdefiniowania klasy każdego wejścia.
Wynosi od 0 do 1.
Funkcja Softmax przekształca logi [2,0, 1,0, 0,1] w prawdopodobieństwa [0,7, 0,2, 0,1], a prawdopodobieństwa sumują się do 1. Logity są surowymi wynikami uzyskanymi przez ostatnią warstwę sieci neuronowej. Przed aktywacją. Aby zrozumieć funkcję softmax, musimy spojrzeć na wynik warstwy (n-1).
Funkcja softmax jest w rzeczywistości funkcją arg max. Oznacza to, że nie zwraca największej wartości z wejścia, ale pozycję największych wartości.
Na przykład:
Przed softmax
Po softmax
Kod:
źródło