Cara mengimplementasikan fungsi Softmax di Python

247

Dari kelas pembelajaran mendalam Udacity , softmax y_i hanyalah eksponensial yang dibagi dengan jumlah eksponensial dari seluruh vektor Y:

masukkan deskripsi gambar di sini

Di mana S(y_i)fungsi softmax y_idan eadalah eksponensial dan jtidak. 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?

alva
sumber
6
Saya ingin tahu mengapa Anda mencoba mengimplementasikannya dengan fungsi maksimal. Apa yang membuatmu berpikir seperti itu?
BBischof
1
Saya tidak tahu, saya pikir memperlakukan maksimum sebagai 0 dan semacam suka memindahkan grafik ke kiri dan klip di 0 membantu. Kemudian rentang saya agak dipersingkat dari -inf to +infke -inf to 0. Saya kira saya terlalu banyak berpikir. hahahaaa
alvas
1
Saya masih memiliki satu sub) pertanyaan yang sepertinya tidak dijawab di bawah ini. Apa pentingnya axis = 0jawaban yang disarankan oleh Udacity?
Parva Thakkar
3
jika Anda melihat pada dokumentasi numpy, ia membahas berapa jumlah (x, sumbu = 0) - dan demikian pula sumbu = 1-- tidak. Singkatnya, ini memberikan arah untuk menjumlahkan array array. Dalam hal ini, ia memberitahukannya untuk menjumlahkan sepanjang vektor. Dalam hal ini, itu sesuai dengan penyebut dalam fungsi softmax.
BBischof
3
Seperti setiap minggu, ada jawaban yang lebih benar sampai pada titik di mana matematika saya tidak cukup baik untuk memutuskan siapa yang benar =) Siapa pun ahli matematika yang tidak memberikan jawaban dapat membantu memutuskan mana yang benar?
alvas

Jawaban:

137

Keduanya benar, tetapi milik Anda lebih disukai dari sudut pandang stabilitas numerik.

Anda mulai dengan

e ^ (x - max(x)) / sum(e^(x - max(x))

Dengan menggunakan fakta bahwa a ^ (b - c) = (a ^ b) / (a ​​^ c) yang kita miliki

= e ^ x / (e ^ max(x) * sum(e ^ x / e ^ max(x)))

= e ^ x / sum(e ^ x)

Itulah yang dikatakan oleh jawaban lainnya. Anda bisa mengganti maks (x) dengan variabel apa pun dan itu akan dibatalkan.

Trevor Merrifield
sumber
4
Memformat ulang jawaban Anda @TrevorM untuk klarifikasi lebih lanjut: e ^ (x - maks (x)) / jumlah (e ^ (x - maks (x)) menggunakan a ^ (b - c) = (a ^ b) / (a ​​^ c) yang kita miliki, = e ^ x / {e ^ maks (x) * jumlah (e ^ x / e ^ maks (x))} = e ^ x / jumlah (e ^ x)
shanky_thebearer
5
@ Trevor Merrifield, saya rasa pendekatan pertama tidak mendapatkan "istilah yang tidak perlu". Bahkan lebih baik daripada pendekatan kedua. Saya telah menambahkan poin ini sebagai jawaban terpisah.
Shagun Sodhani
6
@ Shagun Anda benar. Keduanya setara secara matematis tapi saya belum mempertimbangkan stabilitas numerik.
Trevor Merrifield
Harap Anda tidak keberatan: Saya mengedit "istilah yang tidak perlu" jika orang tidak membaca komentar (atau komentar menghilang). Halaman ini mendapatkan sedikit lalu lintas dari mesin pencari dan ini adalah jawaban pertama yang dilihat orang.
Alex Riley
Saya ingin tahu mengapa Anda mengurangi max (x) dan tidak max (abs (x)) (memperbaiki tanda setelah menentukan nilainya). Jika semua nilai Anda di bawah nol dan sangat besar dalam nilai absolutnya, dan hanya nilai (maksimum) yang mendekati nol, mengurangi maksimum tidak akan mengubah apa pun. Bukankah masih tidak stabil secara numerik?
Cerno
102

(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=0argumen. Untuk melihat bahwa ini masalahnya, mari kita coba solusi Anda ( your_softmax) dan satu-satunya di mana perbedaannya adalah axisargumen:

import numpy as np

# your solution:
def your_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()

# correct solution:
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(axis=0) # only difference

Seperti yang saya katakan, untuk array skor 1-D, hasilnya memang identik:

scores = [3.0, 1.0, 0.2]
print(your_softmax(scores))
# [ 0.8360188   0.11314284  0.05083836]
print(softmax(scores))
# [ 0.8360188   0.11314284  0.05083836]
your_softmax(scores) == softmax(scores)
# array([ True,  True,  True], dtype=bool)

Namun demikian, berikut adalah hasil untuk array skor 2-D yang diberikan dalam kuis Udacity sebagai contoh uji:

scores2D = np.array([[1, 2, 3, 6],
                     [2, 4, 5, 6],
                     [3, 8, 7, 6]])

print(your_softmax(scores2D))
# [[  4.89907947e-04   1.33170787e-03   3.61995731e-03   7.27087861e-02]
#  [  1.33170787e-03   9.84006416e-03   2.67480676e-02   7.27087861e-02]
#  [  3.61995731e-03   5.37249300e-01   1.97642972e-01   7.27087861e-02]]

print(softmax(scores2D))
# [[ 0.09003057  0.00242826  0.01587624  0.33333333]
#  [ 0.24472847  0.01794253  0.11731043  0.33333333]
#  [ 0.66524096  0.97962921  0.86681333  0.33333333]]

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 - axisargumen. Menurut dokumentasi numpy.sum :

Defaultnya, axis = None, akan menjumlahkan semua elemen dari array input

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 axismasalah 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).

desertnaut
sumber
Nah, jika Anda hanya berbicara tentang array multi dimensi. Solusi pertama dapat dengan mudah diperbaiki dengan menambahkan axisargumen ke keduanya maxdan sum. Namun, implementasi pertama masih lebih baik karena Anda dapat dengan mudah meluap saat mengambilexp
Louis Yang
@LouisYang saya tidak mengikuti; yang merupakan solusi "pertama"? Yang mana yang tidak digunakan exp? Apa lagi yang telah dimodifikasi di sini selain menambahkan axisargumen?
desertnaut
Solusi pertama merujuk ke solusi dari @alvas. Perbedaannya adalah bahwa solusi yang disarankan dalam pertanyaan alvas hilang bagian dari mengurangi maks. Ini dapat dengan mudah menyebabkan overflow misalnya, exp (1000) / (exp (1000) + exp (1001)) vs exp (-1) / (exp (-1) + exp (0)) sama dalam matematika tetapi yang pertama akan meluap.
Louis Yang
@LouisYang masih, tidak yakin saya mengerti perlunya komentar Anda - semua ini sudah dibahas secara eksplisit dalam jawabannya.
desertnaut
@LouisYang tolong jangan biarkan popularitas thread (selanjutnya) menipu Anda, dan coba bayangkan konteks di mana jawaban sendiri ditawarkan: OP bingung (" keduanya memberikan hasil yang sama "), dan jawaban (masih!) Diterima mengklaim bahwa " keduanya benar " (well, mereka tidak ). Jawabannya tidak pernah dimaksudkan sebagai " itu cara yang paling benar & efisien untuk menghitung softmax secara umum "; itu hanya untuk membenarkan mengapa , dalam kuis Udacity spesifik yang dibahas, 2 solusi tidak setara.
desertnaut
56

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.

import numpy as np

# your solution:
def your_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()

# desertnaut solution (copied from his answer): 
def desertnaut_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(axis=0) # only difference

# my (correct) solution:
def softmax(z):
    assert len(z.shape) == 2
    s = np.max(z, axis=1)
    s = s[:, np.newaxis] # necessary step to do broadcasting
    e_x = np.exp(z - s)
    div = np.sum(e_x, axis=1)
    div = div[:, np.newaxis] # dito
    return e_x / div

Mari kita ambil contoh desertnaut:

x1 = np.array([[1, 2, 3, 6]]) # notice that we put the data into 2 dimensions(!)

Ini hasilnya:

your_softmax(x1)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

desertnaut_softmax(x1)
array([[ 1.,  1.,  1.,  1.]])

softmax(x1)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

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.

x2 = np.array([[1, 2, 3, 6],  # sample 1
               [2, 4, 5, 6],  # sample 2
               [1, 2, 3, 6]]) # sample 1 again(!)

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!

your_softmax(x2)
array([[ 0.00183535,  0.00498899,  0.01356148,  0.27238963],
       [ 0.00498899,  0.03686393,  0.10020655,  0.27238963],
       [ 0.00183535,  0.00498899,  0.01356148,  0.27238963]])


desertnaut_softmax(x2)
array([[ 0.21194156,  0.10650698,  0.10650698,  0.33333333],
       [ 0.57611688,  0.78698604,  0.78698604,  0.33333333],
       [ 0.21194156,  0.10650698,  0.10650698,  0.33333333]])

softmax(x2)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047],
       [ 0.01203764,  0.08894682,  0.24178252,  0.65723302],
       [ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

Saya harap Anda dapat melihat bahwa ini hanya masalah dengan solusi saya.

softmax(x1) == softmax(x2)[0]
array([[ True,  True,  True,  True]], dtype=bool)

softmax(x1) == softmax(x2)[2]
array([[ True,  True,  True,  True]], dtype=bool)

Selain itu, berikut adalah hasil implementasi softmax TensorFlows:

import tensorflow as tf
import numpy as np
batch = np.asarray([[1,2,3,6],[2,4,5,6],[1,2,3,6]])
x = tf.placeholder(tf.float32, shape=[None, 4])
y = tf.nn.softmax(x)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(y, feed_dict={x: batch})

Dan hasilnya:

array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037045],
       [ 0.01203764,  0.08894681,  0.24178252,  0.657233  ],
       [ 0.00626879,  0.01704033,  0.04632042,  0.93037045]], dtype=float32)
ChuckFive
sumber
6
Itu akan menjadi komentar yang luar biasa ;-)
Michael Benjamin
27
np.exp (z) / np.sum (np.exp (z), sumbu = 1, keepdims = True) mencapai hasil yang sama dengan fungsi softmax Anda. langkah-langkah dengan s tidak perlu.
PabTorre
Di tempat ` s = s[:, np.newaxis], s = s.reshape(z.shape[0],1)juga harus bekerja.
Debashish
2
begitu banyak solusi yang salah / tidak efisien pada halaman ini. Bantulah diri Anda dan gunakan PabTorre's
Miss Palmer
@ LabTorre maksud Anda sumbu = -1? axis = 1 tidak akan bekerja untuk input dimensi tunggal
DiehardTheTryhard
36

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.

Shagun Sodhani
sumber
3
Efek dari pembatalan bencana tidak dapat diremehkan.
Cesar
24

sklearn juga menawarkan implementasi softmax

from sklearn.utils.extmath import softmax
import numpy as np

x = np.array([[ 0.50839931,  0.49767588,  0.51260159]])
softmax(x)

# output
array([[ 0.3340521 ,  0.33048906,  0.33545884]]) 
Roman Orac
sumber
3
Bagaimana tepatnya ini menjawab pertanyaan spesifik, yaitu tentang implementasi itu sendiri dan bukan tentang ketersediaan di beberapa perpustakaan pihak ketiga?
desertnaut
8
Saya mencari implementasi pihak ketiga untuk memverifikasi hasil dari kedua pendekatan. Inilah cara komentar ini membantu.
Eugenio F. Martinez Pacheco
13

Dari sudut pandang matematika kedua belah pihak sama.

Dan Anda dapat dengan mudah membuktikan ini. Mari kita m=max(x). Sekarang fungsi Anda softmaxmengembalikan vektor, yang koordinat ke-i-nya sama dengan

masukkan deskripsi gambar di sini

perhatikan 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 mana nukuran vektor.

  • dari sudut pandang stabilitas numerik , solusi pertama lebih disukai, karena e^xtumbuh sangat cepat dan bahkan untuk nilai yang cukup kecil xakan melimpah. Mengurangi nilai maksimum memungkinkan untuk menyingkirkan limpahan ini. Untuk secara praktis mengalami hal-hal yang saya bicarakan, coba x = 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 menggunakansum(axis=0)

Salvador Dali
sumber
1
Kapan berguna untuk dapat menghitung softmax pada matriks dan bukan pada vektor? yaitu model apa yang menghasilkan matriks? Bisakah ini menjadi lebih dimensi?
mrgloom
2
maksud Anda solusi pertama dalam "dari sudut pandang stabilitas numerik, solusi kedua lebih disukai ..."?
Dataman
10

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:

def softmax(X, theta = 1.0, axis = None):
    """
    Compute the softmax of each element along an axis of X.

    Parameters
    ----------
    X: ND-Array. Probably should be floats. 
    theta (optional): float parameter, used as a multiplier
        prior to exponentiation. Default = 1.0
    axis (optional): axis to compute values along. Default is the 
        first non-singleton axis.

    Returns an array the same size as X. The result will sum to 1
    along the specified axis.
    """

    # make X at least 2d
    y = np.atleast_2d(X)

    # find axis
    if axis is None:
        axis = next(j[0] for j in enumerate(y.shape) if j[1] > 1)

    # multiply y against the theta parameter, 
    y = y * float(theta)

    # subtract the max for numerical stability
    y = y - np.expand_dims(np.max(y, axis = axis), axis)

    # exponentiate y
    y = np.exp(y)

    # take the sum along the specified axis
    ax_sum = np.expand_dims(np.sum(y, axis = axis), axis)

    # finally: divide elementwise
    p = y / ax_sum

    # flatten if X was 1D
    if len(X.shape) == 1: p = p.flatten()

    return p

Mengurangi maks, seperti yang dijelaskan pengguna lain, adalah praktik yang baik. Saya menulis posting terperinci di sini .

Nolan Conaway
sumber
9

Di sini Anda dapat mengetahui mengapa mereka digunakan - max.

Dari sana:

"Ketika Anda menulis kode untuk menghitung fungsi Softmax dalam praktiknya, istilah perantara mungkin sangat besar karena eksponensial. Membagi angka besar bisa secara numerik tidak stabil, jadi penting untuk menggunakan trik normalisasi."

Sadegh Salehi
sumber
4

Versi yang lebih ringkas adalah:

def softmax(x):
    return np.exp(x) / np.exp(x).sum(axis=0)
Pimin Konstantin Kefaloukos
sumber
9
ini dapat mengalami aritmatika melimpah
minhle_r7
4

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.

import scipy.special as sc
import numpy as np

def softmax(x: np.ndarray) -> np.ndarray:
    return np.exp(x - sc.logsumexp(x))
PikalaxALT
sumber
Agar sama dengan kode poster, Anda perlu menambahkan axis=0sebagai argumen logsumexp.
Björn Lindqvist
Atau, seseorang dapat membongkar arg tambahan untuk dilewatkan ke logsumexp.
PikalaxALT
3

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:

def softmax(x, axis=-1):
    e_x = np.exp(x - np.max(x)) # same code
    return e_x / e_x.sum(axis=axis, keepdims=True)

Hasil:

logits = np.asarray([
    [-0.0052024,  -0.00770216,  0.01360943, -0.008921], # 1
    [-0.0052024,  -0.00770216,  0.01360943, -0.008921]  # 2
])

print(softmax(logits))

#[[0.2492037  0.24858153 0.25393605 0.24827873]
# [0.2492037  0.24858153 0.25393605 0.24827873]]

Ref: Tensorflow softmax

Lucas Casagrande
sumber
Ingatlah bahwa jawabannya mengacu pada latar yang sangat spesifik yang dijelaskan dalam pertanyaan; itu tidak pernah dimaksudkan sebagai 'cara menghitung softmax secara umum dalam keadaan apa pun, atau dalam format data yang Anda sukai' ...
desertnaut
Saya mengerti, saya meletakkan ini di sini karena pertanyaannya merujuk pada "kelas pembelajaran mendalam Udacity" dan itu tidak akan berhasil jika Anda menggunakan Tensorflow untuk membangun model Anda. Solusi Anda keren dan bersih tetapi hanya bekerja dalam skenario yang sangat spesifik. Bagaimanapun, terima kasih.
Lucas Casagrande
1

Untuk menjaga stabilitas numerik, maks (x) harus dikurangi. Berikut ini adalah kode untuk fungsi softmax;

def softmax (x):

if len(x.shape) > 1:
    tmp = np.max(x, axis = 1)
    x -= tmp.reshape((x.shape[0], 1))
    x = np.exp(x)
    tmp = np.sum(x, axis = 1)
    x /= tmp.reshape((x.shape[0], 1))
else:
    tmp = np.max(x)
    x -= tmp
    x = np.exp(x)
    tmp = np.sum(x)
    x /= tmp


return x
Rahul Ahuja
sumber
1

Sudah dijawab dengan sangat rinci dalam jawaban di atas. maxdikurangi untuk menghindari luapan. Saya menambahkan di sini satu lagi implementasi di python3.

import numpy as np
def softmax(x):
    mx = np.amax(x,axis=1,keepdims = True)
    x_exp = np.exp(x - mx)
    x_sum = np.sum(x_exp, axis = 1, keepdims = True)
    res = x_exp / x_sum
    return res

x = np.array([[3,2,4],[4,5,6]])
print(softmax(x))
Debashish
sumber
1

Semua orang tampaknya memposting solusi mereka sehingga saya akan memposting solusi saya:

def softmax(x):
    e_x = np.exp(x.T - np.max(x, axis = -1))
    return (e_x / e_x.sum(axis=0)).T

Saya mendapatkan hasil yang sama persis dengan yang diimpor dari sklearn:

from sklearn.utils.extmath import softmax
Julian
sumber
1
import tensorflow as tf
import numpy as np

def softmax(x):
    return (np.exp(x).T / np.exp(x).sum(axis=-1)).T

logits = np.array([[1, 2, 3], [3, 10, 1], [1, 2, 5], [4, 6.5, 1.2], [3, 6, 1]])

sess = tf.Session()
print(softmax(logits))
print(sess.run(tf.nn.softmax(logits)))
sess.close()
Raja
sumber
Selamat datang di SO. Penjelasan tentang bagaimana kode Anda menjawab pertanyaan selalu membantu.
Nick
1

Berdasarkan semua tanggapan dan catatan CS231n , izinkan saya untuk merangkum:

def softmax(x, axis):
    x -= np.max(x, axis=axis, keepdims=True)
    return np.exp(x) / np.exp(x).sum(axis=axis, keepdims=True)

Pemakaian:

x = np.array([[1, 0, 2,-1],
              [2, 4, 6, 8], 
              [3, 2, 1, 0]])
softmax(x, axis=1).round(2)

Keluaran:

array([[0.24, 0.09, 0.64, 0.03],
       [0.  , 0.02, 0.12, 0.86],
       [0.64, 0.24, 0.09, 0.03]])
remykarem
sumber
0

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:

  1. Untuk mendapatkan maks, coba lakukan bersama sumbu x, Anda akan mendapatkan array 1D.
  2. Bentuk kembali array maksimal Anda ke bentuk aslinya.
  3. Apakah np.exp mendapatkan nilai eksponensial.
  4. Lakukan np.sum sepanjang sumbu.
  5. Dapatkan hasil akhir.

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.

Hao Xu
sumber
1
Ini tidak terkait dengan pekerjaan rumah di perguruan tinggi mana pun, hanya kuis praktik yang tidak di-
unruk
0

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:

def softmax(y):
    e_to_the_y_j = np.exp(y)
    return e_to_the_y_j / np.sum(e_to_the_y_j, axis=0)

sumber
0

Tujuannya adalah untuk mencapai hasil yang sama menggunakan Numpy dan Tensorflow. Satu-satunya perubahan dari jawaban asli adalah axisparameter untuk np.sumapi.

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.

def softmax_fn(input_array):
    """
    | **@author**: Prathyush SP
    |
    | Calculate Softmax for a given array
    :param input_array: Input Array
    :return: Softmax Score
    """
    e_x = np.exp(input_array - np.max(input_array))
    return e_x / e_x.sum(axis=len(e_x.shape)-1)
kingspp
sumber
0

Berikut ini adalah solusi umum menggunakan numpy dan perbandingan untuk kebenaran dengan tensorflow ans scipy:

Persiapan data:

import numpy as np

np.random.seed(2019)

batch_size = 1
n_items = 3
n_classes = 2
logits_np = np.random.rand(batch_size,n_items,n_classes).astype(np.float32)
print('logits_np.shape', logits_np.shape)
print('logits_np:')
print(logits_np)

Keluaran:

logits_np.shape (1, 3, 2)
logits_np:
[[[0.9034822  0.3930805 ]
  [0.62397    0.6378774 ]
  [0.88049906 0.299172  ]]]

Softmax menggunakan tensorflow:

import tensorflow as tf

logits_tf = tf.convert_to_tensor(logits_np, np.float32)
scores_tf = tf.nn.softmax(logits_np, axis=-1)

print('logits_tf.shape', logits_tf.shape)
print('scores_tf.shape', scores_tf.shape)

with tf.Session() as sess:
    scores_np = sess.run(scores_tf)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np,axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

Keluaran:

logits_tf.shape (1, 3, 2)
scores_tf.shape (1, 3, 2)
scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.4965232  0.5034768 ]
  [0.64137274 0.3586273 ]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

Softmax menggunakan scipy:

from scipy.special import softmax

scores_np = softmax(logits_np, axis=-1)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np, axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

Keluaran:

scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.4965232  0.5034768 ]
  [0.6413727  0.35862732]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

Softmax menggunakan numpy ( https://nolanbconaway.github.io/blog/2017/softmax-numpy ):

def softmax(X, theta = 1.0, axis = None):
    """
    Compute the softmax of each element along an axis of X.

    Parameters
    ----------
    X: ND-Array. Probably should be floats.
    theta (optional): float parameter, used as a multiplier
        prior to exponentiation. Default = 1.0
    axis (optional): axis to compute values along. Default is the
        first non-singleton axis.

    Returns an array the same size as X. The result will sum to 1
    along the specified axis.
    """

    # make X at least 2d
    y = np.atleast_2d(X)

    # find axis
    if axis is None:
        axis = next(j[0] for j in enumerate(y.shape) if j[1] > 1)

    # multiply y against the theta parameter,
    y = y * float(theta)

    # subtract the max for numerical stability
    y = y - np.expand_dims(np.max(y, axis = axis), axis)

    # exponentiate y
    y = np.exp(y)

    # take the sum along the specified axis
    ax_sum = np.expand_dims(np.sum(y, axis = axis), axis)

    # finally: divide elementwise
    p = y / ax_sum

    # flatten if X was 1D
    if len(X.shape) == 1: p = p.flatten()

    return p


scores_np = softmax(logits_np, axis=-1)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np, axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

Keluaran:

scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.49652317 0.5034768 ]
  [0.64137274 0.3586273 ]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]
mrgloom
sumber
0

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

X = [13, 31, 5]

Setelah softmax

array([1.52299795e-08, 9.99999985e-01, 5.10908895e-12]

Kode:

import numpy as np

# your solution:

def your_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() 

# correct solution: 

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(axis=0) 

# only difference
krishna veer
sumber