Dari kelas pembelajaran mendalam Udacity , softmax y_i hanyalah eksponensial yang dibagi dengan jumlah eksponensial dari seluruh vektor Y:
Di mana S(y_i)
fungsi softmax y_i
dan e
adalah eksponensial dan j
tidak. kolom dalam vektor input Y.
Saya sudah mencoba yang berikut ini:
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))
yang mengembalikan:
[ 0.8360188 0.11314284 0.05083836]
Tetapi solusi yang disarankan adalah:
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
return np.exp(x) / np.sum(np.exp(x), axis=0)
yang menghasilkan output yang sama dengan implementasi pertama , meskipun implementasi pertama secara eksplisit mengambil perbedaan dari setiap kolom dan maks dan kemudian membaginya dengan jumlah.
Dapatkah seseorang menunjukkan mengapa secara matematis? Apakah yang satu benar dan yang lain salah?
Apakah implementasinya serupa dalam hal kompleksitas kode dan waktu? Mana yang lebih efisien?
-inf to +inf
ke-inf to 0
. Saya kira saya terlalu banyak berpikir. hahahaaaaxis = 0
jawaban yang disarankan oleh Udacity?Jawaban:
Keduanya benar, tetapi milik Anda lebih disukai dari sudut pandang stabilitas numerik.
Anda mulai dengan
Dengan menggunakan fakta bahwa a ^ (b - c) = (a ^ b) / (a ^ c) yang kita miliki
Itulah yang dikatakan oleh jawaban lainnya. Anda bisa mengganti maks (x) dengan variabel apa pun dan itu akan dibatalkan.
sumber
(Yah ... banyak kebingungan di sini, baik dalam pertanyaan maupun dalam jawaban ...)
Untuk mulai dengan, dua solusi (yaitu milik Anda dan yang disarankan) tidak setara; mereka kebetulan setara hanya untuk kasus khusus dari array skor 1-D. Anda akan menemukannya jika Anda juga mencoba array skor 2-D dalam contoh kuis Udacity.
Dari segi hasil, satu-satunya perbedaan aktual antara kedua solusi adalah
axis=0
argumen. Untuk melihat bahwa ini masalahnya, mari kita coba solusi Anda (your_softmax
) dan satu-satunya di mana perbedaannya adalahaxis
argumen:Seperti yang saya katakan, untuk array skor 1-D, hasilnya memang identik:
Namun demikian, berikut adalah hasil untuk array skor 2-D yang diberikan dalam kuis Udacity sebagai contoh uji:
Hasilnya berbeda - yang kedua memang identik dengan yang diharapkan dalam kuis Udacity, di mana semua kolom memang berjumlah 1, yang tidak demikian dengan hasil pertama (salah).
Jadi, semua keributan itu sebenarnya untuk detail implementasi -
axis
argumen. Menurut dokumentasi numpy.sum :sementara di sini kita ingin menjumlahkan bijaksana, maka
axis=0
. Untuk larik 1-D, jumlah baris (hanya) dan jumlah semua elemen kebetulan identik, maka hasil identik Anda dalam hal itu ...The
axis
masalah samping, (yaitu pilihan Anda kurangi max pertama) implementasi Anda sebenarnya lebih baik daripada solusi yang disarankan! Bahkan, ini adalah cara yang disarankan untuk mengimplementasikan fungsi softmax - lihat di sini untuk justifikasi (stabilitas numerik, juga ditunjukkan oleh beberapa jawaban lain di sini).sumber
axis
argumen ke keduanyamax
dansum
. Namun, implementasi pertama masih lebih baik karena Anda dapat dengan mudah meluap saat mengambilexp
exp
? Apa lagi yang telah dimodifikasi di sini selain menambahkanaxis
argumen?Jadi, ini benar-benar komentar untuk jawaban desertnaut tetapi saya belum bisa mengomentarinya karena reputasi saya. Seperti yang ia tunjukkan, versi Anda hanya benar jika input Anda terdiri dari satu sampel tunggal. Jika input Anda terdiri dari beberapa sampel, itu salah. Namun, solusi desertnaut juga salah. Masalahnya adalah sekali dia mengambil input 1 dimensi dan kemudian dia mengambil input 2 dimensi. Biarkan saya menunjukkan ini kepada Anda.
Mari kita ambil contoh desertnaut:
Ini hasilnya:
Anda dapat melihat bahwa versi desernaut akan gagal dalam situasi ini. (Tidak akan jika input hanya satu dimensi seperti np.array ([1, 2, 3, 6]).
Sekarang mari kita gunakan 3 sampel karena itulah alasan mengapa kita menggunakan input 2 dimensi. X2 berikut ini tidak sama dengan yang dari contoh desernauts.
Input ini terdiri dari batch dengan 3 sampel. Tetapi sampel satu dan tiga pada dasarnya sama. Kami sekarang mengharapkan 3 baris aktivasi softmax di mana yang pertama harus sama dengan yang ketiga dan juga sama dengan aktivasi x1 kami!
Saya harap Anda dapat melihat bahwa ini hanya masalah dengan solusi saya.
Selain itu, berikut adalah hasil implementasi softmax TensorFlows:
Dan hasilnya:
sumber
s = s[:, np.newaxis]
,s = s.reshape(z.shape[0],1)
juga harus bekerja.Saya akan mengatakan bahwa meskipun keduanya benar secara matematis, implementasi-bijaksana, yang pertama lebih baik. Saat menghitung softmax, nilai perantara mungkin menjadi sangat besar. Membagi dua angka besar bisa menjadi tidak stabil secara numerik. Catatan ini (dari Stanford) menyebutkan trik normalisasi yang pada dasarnya adalah apa yang Anda lakukan.
sumber
sklearn juga menawarkan implementasi softmax
sumber
Dari sudut pandang matematika kedua belah pihak sama.
Dan Anda dapat dengan mudah membuktikan ini. Mari kita
m=max(x)
. Sekarang fungsi Andasoftmax
mengembalikan vektor, yang koordinat ke-i-nya sama denganperhatikan bahwa ini berfungsi untuk semua
m
, karena untuk semua nomor (bahkan kompleks)e^m != 0
dari sudut pandang kompleksitas komputasi mereka juga setara dan keduanya berjalan dalam
O(n)
waktu, di manan
ukuran vektor.dari sudut pandang stabilitas numerik , solusi pertama lebih disukai, karena
e^x
tumbuh sangat cepat dan bahkan untuk nilai yang cukup kecilx
akan melimpah. Mengurangi nilai maksimum memungkinkan untuk menyingkirkan limpahan ini. Untuk secara praktis mengalami hal-hal yang saya bicarakan, cobax = np.array([1000, 5])
masukkan ke dalam kedua fungsi Anda. Satu akan mengembalikan probabilitas yang benar, yang kedua akan melimpah bersamanan
solusi Anda hanya berfungsi untuk vektor (kuis Udacity ingin Anda menghitungnya untuk matriks juga). Untuk memperbaikinya Anda perlu menggunakan
sum(axis=0)
sumber
EDIT . Pada versi 1.2.0, scipy menyertakan softmax sebagai fungsi khusus:
https://scipy.github.io/devdocs/generated/scipy.special.softmax.html
Saya menulis sebuah fungsi yang menerapkan softmax pada sumbu apa pun:
Mengurangi maks, seperti yang dijelaskan pengguna lain, adalah praktik yang baik. Saya menulis posting terperinci di sini .
sumber
Di sini Anda dapat mengetahui mengapa mereka digunakan
- max
.Dari sana:
sumber
Versi yang lebih ringkas adalah:
sumber
Untuk menawarkan solusi alternatif, pertimbangkan kasus-kasus di mana argumen Anda sangat besar besarnya sehingga
exp(x)
akan melimpah (dalam kasus negatif) atau melimpah (dalam kasus positif). Di sini Anda ingin tetap berada di ruang log selama mungkin, hanya berharap pada akhir di mana Anda dapat percaya hasilnya akan berperilaku baik.sumber
axis=0
sebagai argumenlogsumexp
.Saya membutuhkan sesuatu yang kompatibel dengan output dari lapisan padat dari Tensorflow .
Solusi dari @desertnaut tidak berfungsi dalam kasus ini karena saya memiliki banyak data. Oleh karena itu, saya datang dengan solusi lain yang harus bekerja dalam kedua kasus:
Hasil:
Ref: Tensorflow softmax
sumber
Saya akan menyarankan ini:
Ini akan bekerja untuk stokastik maupun batch.
Untuk detail lebih lanjut, lihat: https://medium.com/@ravish1729/analysis-of-softmax-function-ad058d6a564d
sumber
Untuk menjaga stabilitas numerik, maks (x) harus dikurangi. Berikut ini adalah kode untuk fungsi softmax;
def softmax (x):
sumber
Sudah dijawab dengan sangat rinci dalam jawaban di atas.
max
dikurangi untuk menghindari luapan. Saya menambahkan di sini satu lagi implementasi di python3.sumber
Semua orang tampaknya memposting solusi mereka sehingga saya akan memposting solusi saya:
Saya mendapatkan hasil yang sama persis dengan yang diimpor dari sklearn:
sumber
sumber
Berdasarkan semua tanggapan dan catatan CS231n , izinkan saya untuk merangkum:
Pemakaian:
Keluaran:
sumber
Saya ingin menambah sedikit pemahaman tentang masalah ini. Ini benar untuk mengurangi maks array. Tetapi jika Anda menjalankan kode di posting lain, Anda akan menemukan itu tidak memberikan jawaban yang benar ketika array adalah dimensi 2D atau lebih tinggi.
Di sini saya memberi Anda beberapa saran:
Ikuti hasilnya Anda akan mendapatkan jawaban yang benar dengan melakukan vektorisasi. Karena ini terkait dengan pekerjaan rumah di perguruan tinggi, saya tidak dapat memposting kode yang tepat di sini, tetapi saya ingin memberikan lebih banyak saran jika Anda tidak mengerti.
sumber
Tujuan dari fungsi softmax adalah untuk mempertahankan rasio vektor-vektor yang bertentangan dengan meremas titik-akhir dengan sigmoid sebagai nilai-nilai jenuh (yaitu cenderung +/- 1 (tanh) atau dari 0 ke 1 (logistik)). Ini karena mempertahankan lebih banyak informasi tentang laju perubahan pada titik akhir dan dengan demikian lebih berlaku untuk jaring saraf dengan 1-of-N Output Encoding (yaitu jika kita menekan titik akhir akan lebih sulit untuk membedakan 1 -dari-N kelas output karena kita tidak bisa membedakan mana yang "terbesar" atau "terkecil" karena mereka terjepit.); juga itu membuat jumlah output total menjadi 1, dan pemenang yang jelas akan lebih dekat ke 1 sedangkan angka lain yang dekat satu sama lain akan berjumlah 1 / p, di mana p adalah jumlah neuron output dengan nilai yang sama.
Tujuan mengurangi nilai maks dari vektor adalah bahwa ketika Anda melakukan eksponen Anda mungkin mendapatkan nilai yang sangat tinggi yang klip float pada nilai maksimum yang mengarah ke dasi, yang tidak terjadi dalam contoh ini. Ini menjadi masalah BESAR jika Anda mengurangi nilai maks untuk membuat angka negatif, maka Anda memiliki eksponen negatif yang dengan cepat mengecilkan nilai yang mengubah rasio, yang merupakan apa yang terjadi dalam pertanyaan poster dan menghasilkan jawaban yang salah.
Jawaban yang diberikan oleh Udacity sangat tidak efisien. Hal pertama yang perlu kita lakukan adalah menghitung e ^ y_j untuk semua komponen vektor, TETAPKAN NILAI-NILAI MEREKA, kemudian jumlahkan semuanya, dan bagi. Di mana Udacity kacau adalah mereka menghitung e ^ y_j DUA KALI !!! Inilah jawaban yang benar:
sumber
Tujuannya adalah untuk mencapai hasil yang sama menggunakan Numpy dan Tensorflow. Satu-satunya perubahan dari jawaban asli adalah
axis
parameter untuknp.sum
api.Pendekatan awal :
axis=0
- Namun ini tidak memberikan hasil yang diinginkan ketika dimensi N.Pendekatan yang dimodifikasi :
axis=len(e_x.shape)-1
- Selalu jumlah pada dimensi terakhir. Ini memberikan hasil yang serupa dengan fungsi softmax tensorflow.sumber
Berikut ini adalah solusi umum menggunakan numpy dan perbandingan untuk kebenaran dengan tensorflow ans scipy:
Persiapan data:
Keluaran:
Softmax menggunakan tensorflow:
Keluaran:
Softmax menggunakan scipy:
Keluaran:
Softmax menggunakan numpy ( https://nolanbconaway.github.io/blog/2017/softmax-numpy ):
Keluaran:
sumber
Fungsi softmax adalah fungsi aktivasi yang mengubah angka menjadi probabilitas yang berjumlah satu. Fungsi softmax menghasilkan vektor yang mewakili distribusi probabilitas dari daftar hasil. Ini juga merupakan elemen inti yang digunakan dalam tugas-tugas klasifikasi pembelajaran yang mendalam.
Fungsi Softmax digunakan ketika kita memiliki beberapa kelas.
Ini berguna untuk mengetahui kelas yang memiliki maks. Kemungkinan.
Fungsi Softmax idealnya digunakan di lapisan output, di mana kita benar-benar mencoba untuk mendapatkan probabilitas untuk menentukan kelas dari setiap input.
Itu berkisar dari 0 hingga 1.
Fungsi Softmax mengubah log [2,0, 1,0, 0,1] menjadi probabilitas [0,7, 0,2, 0,1], dan jumlah probabilitasnya menjadi 1. Log adalah output skor mentah oleh lapisan terakhir dari jaringan saraf. Sebelum aktivasi berlangsung. Untuk memahami fungsi softmax, kita harus melihat output dari layer (n-1).
Fungsi softmax sebenarnya adalah fungsi arg max. Itu berarti bahwa itu tidak mengembalikan nilai terbesar dari input, tetapi posisi nilai terbesar.
Sebagai contoh:
Sebelum softmax
Setelah softmax
Kode:
sumber