Python'da Softmax işlevi nasıl uygulanır


247

Gönderen Udacity en derin öğrenme sınıfının , Y_I ait SoftMax bütün Y vektörü üstel toplamına bölünmesiyle üstel basitçe:

resim açıklamasını buraya girin

S(y_i)Softmax fonksiyonu nerede y_ive eüstel ve jhayır. girdi vektörü Y'deki sütunlar.

Aşağıdakileri denedim:

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

döndüren:

[ 0.8360188   0.11314284  0.05083836]

Ancak önerilen çözüm şuydu:

def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    return np.exp(x) / np.sum(np.exp(x), axis=0)

ilk uygulama ile aynı çıktıyı üretir, ancak ilk uygulama her bir sütunun ve maks'in farkını açıkça alsa da toplama bölünür.

Birisi neden matematiksel olarak gösterebilir? Biri doğru, diğeri yanlış mı?

Uygulama, kod ve zaman karmaşıklığı açısından benzer mi? Hangisi daha verimli?


6
Neden bir maks fonksiyonuyla bu şekilde uygulamaya çalıştığınızı merak ediyorum. Seni bu şekilde düşündüren ne oldu?
BBischof

1
Bilmiyorum, ben maksimum 0 olarak tedavi düşündüm ve bir tür grafik sola hareket gibi ve 0 0 klip yardımcı olur. Sonra aralığı çeşit dan kısaltmak -inf to +infiçin -inf to 0. Sanýrým çok düţünüyordum. hahahaaa
alvas

1
Hala bir alt sorum var). Önemi nedir axis = 0Udacity önerdiği yanıtında?
Parva Thakkar

3
Numpy belgelerine bakarsanız, toplamı (x, eksen = 0) ve benzer şekilde eksen = 1-- ne yaptığını tartışır. Kısacası, bir dizi dizinin toplanacağı yönü sağlar. Bu durumda, vektörler boyunca toplamasını söyler. Bu durumda, softmax fonksiyonundaki paydalara karşılık gelir.
BBischof

3
Her hafta olduğu gibi, matematiğimin kimin doğru olduğuna karar vermek için yeterince iyi olmadığı noktaya kadar daha doğru bir cevap var =) Cevap vermeyen herhangi bir matematik vızıltısı hangisinin doğru olduğuna karar vermenize yardımcı olabilir mi?
alvas

Yanıtlar:


137

Her ikisi de doğrudur, ancak sayısal kararlılık açısından sizin tercih edilir.

İle başlıyorsun

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

A ^ (b - c) = (a ^ b) / (a ​​^ c)

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

= e ^ x / sum(e ^ x)

Diğer cevap budur. Max (x) değerini herhangi bir değişkenle değiştirebilirsiniz ve iptal edilir.


4
Cevabınızı daha fazla açıklama için @TrevorM biçiminde yeniden biçimlendirin: ^ (b - c) = (a ^ b) / (a ​​^ kullanarak e ^ (x - maks (x)) / toplam (e ^ (x - maks (x)) c) Elimizdeki, = e ^ x / {e ^ maks (x) * toplamı (e ^ x / e ^ maks (x))} = e ^ x / toplamı (e ^ x)
shanky_thebearer

5
@Trevor Merrifield, ilk yaklaşımın "gereksiz bir terim" olduğunu sanmıyorum. Aslında ikinci yaklaşımdan daha iyidir. Bu noktayı ayrı bir cevap olarak ekledim.
Shagun Sodhani

6
@Shagun Doğru. İkisi matematiksel olarak eşdeğerdir, ancak sayısal kararlılığı düşünmemiştim.
Trevor Merrifield

Umursamıyorsunuz: İnsanların yorumları okumaması (veya yorumların kaybolması) durumunda "gereksiz terimi" düzenledim. Bu sayfa arama motorlarından biraz trafik alıyor ve bu şu anda insanların gördüğü ilk cevap.
Alex Riley

Neden max (abs (x)) değil de max (x) çıkardığınızı merak ediyorum (değeri belirledikten sonra işareti düzeltin). Tüm değerleriniz sıfırın altında ve mutlak değerlerinde çok büyükse ve yalnızca değer (maksimum) sıfıra yakınsa, maksimum değeri çıkarmak hiçbir şeyi değiştirmez. Hala sayısal olarak kararsız olmaz mıydı?
Cerno

102

(Şey ... burada hem soruda hem de cevaplarda çok karışıklık var ...)

Başlangıç ​​olarak, iki çözüm (yani sizin ve önerilen çözüm) eşdeğer değildir ; onlar ne sadece 1-D puanı Dizilerin özel durum için eşdeğer olarak. Udacity sınavında sağlanan örnekte 2-B skor dizisini de deneseydiniz bunu keşfederdiniz.

Sonuç olarak, iki çözüm arasındaki tek gerçek axis=0argümandır. Durumun böyle olduğunu görmek için, çözümünüzü ( your_softmax) ve tek farkın axisargüman olduğu bir çözümü deneyelim :

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

Söylediğim gibi, 1-D skor dizisi için sonuçlar gerçekten aynı:

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)

Bununla birlikte, Udacity testinde bir test örneği olarak verilen 2-D skor dizisinin sonuçları:

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]]

Sonuçlar farklıdır - ikincisi Udacity sınavında beklenen ile tamamen aynıdır, burada tüm sütunlar gerçekten 1'dir, bu da ilk (yanlış) sonuç için geçerli değildir.

Yani, tüm yaygara aslında bir uygulama detayı içindi - axisargüman. Göre numpy.sum belgelerinde :

Default, axis = None, giriş dizisinin tüm öğelerini toplar

buradayken, satır olarak özetlemek istiyoruz axis=0. Bir 1-D dizi için, (sadece) satırın toplamı ve tüm elemanların toplamı aynı olur, bu nedenle bu durumda aynı sonuçlarınız ...

axisSorun bir yana, senin uygulaması (maks birinci çıkarmak için yani tercih) aslında iyi önerilen çözümü daha! Aslında, softmax işlevini uygulamanın önerilen yolu budur - gerekçe için buraya bakın ( burada diğer bazı cevaplarla da gösterilen sayısal kararlılık).


Sadece çok boyutlu diziden bahsediyorsanız. İlk çözüm axishem maxve 'ye argüman eklenerek kolayca düzeltilebilir sum. Ancak, ilk uygulama hala daha iyidir çünkü çekerken kolayca taşabilirsinizexp
Louis Yang

@LouisYang Takip etmiyorum; "ilk" çözüm hangisidir? Tek Hangi mu değil kullanabilir exp? Burada axisargüman eklemek dışında başka neler değiştirildi ?
desertnaut

İlk çözüm @alvas'ın çözümüne atıfta bulunur. Aradaki fark, alvas'ın sorusunda önerilen çözümün, maks. Bu kolayca taşmaya neden olabilir, örneğin exp (1000) / (exp (1000) + exp (1001)) vs exp (-1) / (exp (-1) + exp (0)) matematikte aynıdır, ancak birincisi taşacak.
Louis Yang

@LouisYang hala, yorumunuzun gerekliliğini anladığımdan emin değilim - tüm bunlar cevapta zaten açık bir şekilde ele alındı.
desertnaut

@LouisYang, iş parçacığının (sonraki) popülaritesinin sizi aldatmasına izin vermeyin ve kendi cevabının sunulduğu bağlamı hayal etmeye çalışın: şaşkın bir OP (" her ikisi de aynı sonucu verir ") ve (hala!) Kabul edilmiş bir cevap " her ikisinin de doğru " olduğunu iddia ederek (iyi değiller ). Bu sorunun cevabı asla " softmax'ı genel olarak hesaplamanın en doğru ve etkili yolu " değildi; Sadece haklı kılmak içinmiş neden de, spesifik Udacity yarışması tartışılan, 2 çözümleridir değil eşdeğeri.
desertnaut

56

Yani, bu gerçekten çölcülüğün cevabına bir yorum ama itibarım nedeniyle henüz yorum yapamam. Belirttiği gibi, sürümünüz yalnızca girdiniz tek bir örnek içeriyorsa doğrudur. Girişiniz birkaç örnekten oluşuyorsa, yanlıştır. Ancak, çölün çözümü de yanlıştır. Sorun şu ki, 1-boyutlu girdi aldıktan sonra 2-boyutlu girdi alıyor. Bunu size göstereyim.

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

Çöl örnekleri alalım:

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

Bu çıktı:

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]])

Bu durumda ıssızlık versiyonunun başarısız olacağını görebilirsiniz. (Girdi, np.array ([1, 2, 3, 6] gibi) sadece bir boyutlu olsaydı olmaz.

Şimdi 2 örnek kullanmamızın nedeni bu yüzden 3 örnek kullanalım. Aşağıdaki x2, desernauts örneğindekiyle aynı değildir.

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

Bu girdi 3 numuneli bir gruptan oluşur. Ancak bir ve üç numaralı örnek aslında aynıdır. Şimdi birincisinin üçüncü ile aynı olması ve aynı zamanda x1 aktivasyonumuzla aynı olması gereken 3 sıra softmax aktivasyonu bekliyoruz!

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]])

Umarım bu benim çözümümde sadece durumdur.

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

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

Ayrıca, TensorFlows softmax uygulamasının sonuçları:

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})

Ve sonuç:

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)

6
Bu bir yorum cehennemi olurdu ;-)
Michael Benjamin

27
np.exp (z) / np.sum (np.exp (z), eksen = 1, keepdims = True) softmax işlevinizle aynı sonuca ulaşır. s ile adımlar gereksizdir.
PabTorre

Yer of` olarak s = s[:, np.newaxis], s = s.reshape(z.shape[0],1)çalışma da bağlanmamalıdır.
Aralık'ta Debashish

2
bu sayfada birçok yanlış / verimsiz çözüm var. Kendinize bir iyilik yapın ve PabTorre's kullanın
Miss Palmer

@PabTorre Bunu mu demek istediniz: axis = -1 ekseni = 1 tek boyutlu girdi için çalışmaz
DiehardTheTryhard

36

Her ikisi de matematiksel olarak doğru, uygulama açısından doğru olsa da, birincisinin daha iyi olduğunu söyleyebilirim. Softmax hesaplanırken, ara değerler çok büyük olabilir. İki büyük sayının bölünmesi sayısal olarak kararsız olabilir. Bu notlar (Stanford'dan) aslında yaptığınız şey olan bir normalleştirme hilesinden bahsediyor.


3
Felaket iptali etkileri göz ardı edilemez.
Cesar

24

sklearn ayrıca softmax uygulaması sunar

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]]) 

3
Bu , bazı üçüncü taraf kitaplıklarındaki kullanılabilirlikle değil , uygulamanın kendisiyle ilgili olan belirli soruyu tam olarak nasıl cevaplıyor ?
desertnaut

8
Her iki yaklaşımın sonuçlarını doğrulamak için üçüncü taraf bir uygulama arıyordum. Bu yorum bu şekilde yardımcı olur.
Eugenio F. Martinez Pacheco

13

Matematiksel açıdan her iki taraf eşittir.

Ve bunu kolayca kanıtlayabilirsiniz. Haydi m=max(x). Şimdi fonksiyonunuz softmaxi-th koordinatı eşit olan bir vektör döndürür

resim açıklamasını buraya girin

Bunun mtüm (hatta karmaşık) sayılar için işe yaradığına dikkat edine^m != 0

  • bakış hesaplama karmaşıklığı açısından da denktir ve her ikisi de çalışır O(n)zamanda, nbir vektör boyutudur.

  • gelen sayısal stabilite nedeniyle bakış açısından, birinci çözelti tercih edilir e^x, çok hızlı büyür, hatta oldukça küçük değerleri için xbu taşma. Maksimum değerin çıkarılması, bu taşma işleminden kurtulmanızı sağlar. Bahsettiğim şeyleri pratik olarak deneyimlemek için x = np.array([1000, 5])her iki işlevinize de beslemeye çalışın . Biri doğru olasılığı döndürür, ikincisi isenan

  • çözümünüz sadece vektörler için çalışır (Udacity sınavı matrisler için de hesaplamanızı ister). Düzeltmek için kullanmanız gerekirsum(axis=0)


1
Vektör yerine matris üzerinde softmax hesaplamak için ne zaman yararlı olur? yani hangi modeller matris çıktı? Daha da boyutlu olabilir mi?
mrgloom

2
"sayısal kararlılık açısından ikinci çözüm tercih edilir ..." ifadesinde ilk çözüm mü demek istediniz ?
Dataman

10

DÜZENLE . 1.2.0 sürümünden itibaren, scipy özel bir işlev olarak softmax içerir:

https://scipy.github.io/devdocs/generated/scipy.special.softmax.html

Herhangi bir eksen üzerinde softmax uygulayan bir fonksiyon yazdım:

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

Diğer kullanıcıların açıkladığı gibi maks. Değerin çıkarılması iyi bir uygulamadır. Burada bunun hakkında ayrıntılı bir yazı yazdım .


9

Burada neden kullandıklarını öğrenebilirsiniz - max.

Buradan:

"Uygulamada Softmax işlevini hesaplamak için kod yazarken, üstel değerler nedeniyle ara terimler çok büyük olabilir. Büyük sayıları bölmek sayısal olarak kararsız olabilir, bu nedenle normalleştirme hilesi kullanmak önemlidir."



4

Alternatif bir çözüm sunmak için, argümanlarınızın aşırı derecede büyük olduğu durumlarda exp(x)(taşma (negatif durumda) veya taşma (pozitif durumda) dikkate alınmalıdır . Burada mümkün olduğunca uzun süre günlük alanında kalmak istiyorum, sadece sonuca güvenebileceğiniz sonunda üssel olarak iyi davranacağız.

import scipy.special as sc
import numpy as np

def softmax(x: np.ndarray) -> np.ndarray:
    return np.exp(x - sc.logsumexp(x))

Bunu poster koduna eşit yapmak için, axis=0bağımsız değişken olarak eklemeniz gerekir logsumexp.
Björn Lindqvist

Alternatif olarak, logsumexp'ye geçmek için ekstra argümanlar paketinden çıkarılabilir.
PikalaxALT

3

Tensorflow'dan yoğun bir katmanın çıktısı ile uyumlu bir şeye ihtiyacım vardı .

@Desertnaut'un çözümü bu durumda çalışmaz çünkü veri yığınlarım var. Bu nedenle, her iki durumda da çalışması gereken başka bir çözümle geldim:

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)

Sonuçlar:

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]]

Referans: Tensorflow softmax


Cevabın , soruda açıklanan çok özel bir ayarı ifade ettiğini unutmayın ; hiçbir zaman 'softmax'ı genel olarak herhangi bir koşulda veya beğeninize göre veri biçiminde nasıl hesaplayacağınız' anlamına gelmiyordu ...
desertnaut

Görüyorum, bunu buraya koydum çünkü soru "Udacity'nin derin öğrenme sınıfına" atıfta bulunuyor ve modelinizi oluşturmak için Tensorflow kullanıyorsanız bu işe yaramaz. Çözümünüz serin ve temizdir, ancak yalnızca çok özel bir senaryoda çalışır. Yine de teşekkürler.
Lucas Casagrande


1

Sayısal kararlılığı korumak için max (x) çıkarılmalıdır. Softmax fonksiyonunun kodu aşağıdadır;

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

1

Zaten yukarıdaki cevaplarda çok ayrıntılı olarak cevaplandı. maxtaşmayı önlemek için çıkarılır. Burada python3'te bir uygulama daha ekliyorum.

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

1

Herkes çözümünü paylaşıyor gibi görünüyor, bu yüzden benimkini göndereceğim:

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

Sklearn'den içe aktarılanla aynı sonuçları elde ediyorum:

from sklearn.utils.extmath import softmax

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

SO hoş geldiniz. Kodunuzun soruya nasıl yanıt verdiğine ilişkin açıklama her zaman yardımcı olur.
Nick

1

Tüm yanıtlara ve CS231n notlarına dayanarak, özetlememe izin verin:

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

Kullanımı:

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

Çıktı:

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

0

Sorunun biraz daha anlaşılmasını desteklemek istiyorum. Burada dizinin maksimum değerini çıkarmak doğrudur. Ancak kodu diğer gönderide çalıştırırsanız, dizi 2B veya daha yüksek boyutlar olduğunda size doğru cevap vermediğini görürsünüz.

İşte size bazı önerilerde bulunuyorum:

  1. Maksimum almak için x ekseni boyunca yapmaya çalışın, 1D dizisi alırsınız.
  2. Maksimum dizinizi orijinal şekle yeniden şekillendirin.
  3. Np.exp üstel değer alır mı?
  4. Eksen boyunca np.sum yapın.
  5. Nihai sonuçları alın.

Sonucu takip edin, vektörizasyon yaparak doğru cevabı alacaksınız. Üniversite ödevi ile ilgili olduğu için, burada tam kodu gönderemiyorum, ancak anlamadıysanız daha fazla öneri vermek istiyorum.


1
Herhangi bir kolej ödevi ile ilgili değildir, sadece bir sonraki adımda doğru cevabın verildiği akredite olmayan bir derste
derecelendirilmemiş

0

Softmax fonksiyonunun amacı, uç noktaların doymuş (yani +/- 1 (tanh) veya 0 ila 1 (lojistik)) olarak bir sigmoid ile ezilmesinin aksine vektörlerin oranını korumaktır. Bunun nedeni, uç noktalardaki değişim oranı hakkında daha fazla bilgi tutması ve bu nedenle 1-N-N Çıkış Kodlaması olan sinir ağları için daha uygulanabilir olmasıdır (yani, uç noktaları ezersek, 1'i ayırt etmek daha zor olurdu. -of-N çıkış sınıfı çünkü hangisinin "en büyük" ya da "en küçük" olduğunu söyleyemeyiz çünkü ezildiler.); ayrıca toplam çıkış toplamı 1 olur ve açık kazanan 1'e yakın olurken, birbirine yakın olan diğer sayılar 1 / p'ye toplanır, burada p benzer değerlere sahip çıkış nöronlarının sayısıdır.

Vektörden maksimum değeri çıkarmanın amacı, e ^ y üsleri yaptığınızda, şamandırayı bir bağlamaya yol açan maksimum değere bağlayan çok yüksek bir değer elde edebilmenizdir, bu örnekte durum böyle değildir. Negatif bir sayı yapmak için maksimum değeri çıkarırsanız BÜYÜK bir sorun olur, o zaman posterin sorusunda meydana gelen ve yanlış cevabı veren oranı değiştiren değerleri hızla küçülten negatif bir üssünüz olur.

Udacity tarafından verilen cevap KORKUNÇ verimsizdir. Yapmamız gereken ilk şey, tüm vektör bileşenleri için e ^ y_j hesaplamak, BU DEĞERLERİ TUTMAK, sonra bunları özetlemek ve bölmektir. Udacity'nin dağıldığı yerde e ^ y_j TWICE !!! İşte doğru cevap:

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)

0

Amaç Numpy ve Tensorflow kullanarak benzer sonuçlar elde etmekti. Orijinal cevaptaki tek değişiklik api axisparametresidir np.sum.

Başlangıç ​​yaklaşımı : axis=0- Ancak bu, boyutlar N olduğunda amaçlanan sonuçlar sağlamaz.

Değiştirilmiş yaklaşım : axis=len(e_x.shape)-1- Her zaman son boyuta göre toplayın. Bu, tensorflow'un softmax fonksiyonu ile benzer sonuçlar verir.

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)

0

İşte tensorflow ve scipy ile doğruluk için numpy ve karşılaştırma kullanarak genelleştirilmiş çözüm:

Veri Hazırlama:

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)

Çıktı:

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

Tensorflow kullanarak Softmax:

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

Çıktı:

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.]]

Scipy kullanarak Softmax:

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

Çıktı:

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.]]

Numpy kullanarak softmax ( 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))

Çıktı:

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.]]

0

Softmax işlevi sayıları bire eşit olasılıklara dönüştüren bir etkinleştirme işlevidir. Softmax işlevi, bir sonuç listesinin olasılık dağılımlarını temsil eden bir vektör üretir. Ayrıca derin öğrenme sınıflandırma görevlerinde kullanılan temel bir unsurdur.

Birden fazla sınıfımız olduğunda Softmax işlevi kullanılır.

Maks. Değere sahip sınıfı bulmak için kullanışlıdır. Olasılık.

Softmax işlevi ideal olarak her bir girdinin sınıfını tanımlama olasılıklarına ulaşmaya çalıştığımız çıktı katmanında kullanılır.

0 ile 1 arasında değişir.

Softmax işlevi logları [2.0, 1.0, 0.1] olasılıklara [0.7, 0.2, 0.1] ve olasılıklar 1'e dönüştürür. Logits, bir sinir ağının son katmanı tarafından üretilen ham skorlardır. Aktivasyon gerçekleşmeden önce. Softmax fonksiyonunu anlamak için, (n-1). Katmanın çıkışına bakmalıyız.

Softmax işlevi aslında bir arg max işlevidir. Bu, girdiden en büyük değeri değil en büyük değerlerin konumunu döndürdüğü anlamına gelir.

Örneğin:

Softmax'tan önce

X = [13, 31, 5]

Softmax'tan sonra

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

Kod:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.