पायथन में सॉफ्टमैक्स फ़ंक्शन को कैसे लागू किया जाए


247

से Udacity की गहरी सीखने वर्ग , y_i की softmax बस घातीय पूरे वाई वेक्टर के घातीय की राशि से विभाजित है:

यहां छवि विवरण दर्ज करें

S(y_i)सॉफ्टमैक्स फ़ंक्शन कहां है 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)

जो पहले कार्यान्वयन के समान उत्पादन करता है , भले ही पहला कार्यान्वयन स्पष्ट रूप से प्रत्येक स्तंभ और अधिकतम का अंतर लेता है और फिर योग द्वारा विभाजित होता है।

क्या कोई गणितीय रूप से दिखा सकता है क्यों? क्या एक सही है और दूसरा गलत है?

क्या कोड और समय जटिलता के संदर्भ में कार्यान्वयन समान हैं? कौन सा अधिक कुशल है?


6
मैं उत्सुक हूं कि आपने इसे अधिकतम फ़ंक्शन के साथ इस तरह से लागू करने का प्रयास क्यों किया। आपने उस तरीके से क्या सोचा है?
BBischof

1
मुझे नहीं पता, मैंने सोचा कि अधिकतम को 0 के रूप में माना जाता है और ग्राफ़ को बाईं ओर ले जाने और 0 पर क्लिप को पसंद करने में मदद करता है। फिर मेरी सीमा किस तरह से छोटी -inf to +infहै -inf to 0। मुझे लगता है कि मैं पछाड़ रहा था। हाहाहा
अलवास

1
मेरे पास अभी भी एक उप) प्रश्न हैं जिनका उत्तर नीचे नहीं दिया गया है। axis = 0उडेसिटी द्वारा सुझाए गए उत्तर में क्या महत्व है ?
परवा ठक्कर

3
यदि आप सुन्न प्रलेखन पर एक नज़र डालते हैं, तो यह चर्चा करता है कि योग क्या है (एक्स, अक्ष = 0) - और इसी तरह अक्ष = 1-- करता है। संक्षेप में, यह उस दिशा को प्रदान करता है जिसमें सारणियों के एक सरणी का योग है। इस मामले में, यह इसे वैक्टर के साथ योग करने के लिए कहता है। इस मामले में, जो सॉफ्टमैक्स फ़ंक्शन में हर के अनुरूप है।
बीबीकॉफ

3
यह हर दूसरे सप्ताह की तरह है, उस बिंदु तक एक अधिक सही उत्तर है जहां मेरा गणित यह तय करने के लिए पर्याप्त नहीं है कि कौन सही है =) कोई भी गणित जो उत्तर नहीं दे पाया है वह निर्णय लेने में मदद कर सकता है जो सही है?
अल्वस

जवाबों:


137

वे दोनों सही हैं, लेकिन आपकी दृष्टि संख्यात्मक स्थिरता के दृष्टिकोण से पसंद की जाती है।

आप से शुरू करते हैं

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

इस तथ्य का उपयोग करके कि हमारे पास एक ए (बी - सी) = (ए ए बी) / (ए सी) है

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

= e ^ x / sum(e ^ x)

जो अन्य उत्तर कहता है। आप अधिकतम (x) को किसी भी चर के साथ बदल सकते हैं और इसे रद्द कर देंगे।


4
आगे के स्पष्टीकरण के लिए अपने उत्तर @TrevorM को सुधारें: ^ ^ (b - c) = (a ^ b) / (^) का उपयोग करके e ^ (x - मैक्स (x)) / sum (e - (x - max (x)) c) हमारे पास, = e ^ x / {e ^ max (x) * sum (e ^ x / e ^ max (x))} = e ^ x / sum (e ^ x)
shanky_thebearer

5
@ ट्रेवर मेरिफिल्ड, मुझे नहीं लगता कि पहले दृष्टिकोण को कोई "अनावश्यक शब्द" मिला था। वास्तव में यह दूसरे दृष्टिकोण से बेहतर है। मैंने इस बिंदु को एक अलग जवाब के रूप में जोड़ा है।
शगुन सोढानी

6
@ शगुन आप सही हैं। दोनों गणितीय रूप से समकक्ष हैं लेकिन मैंने संख्यात्मक स्थिरता पर विचार नहीं किया था।
ट्रेवर मेरिफिल्ड

आशा है कि आप बुरा नहीं मानेंगे: मैंने "अनावश्यक शब्द" को संपादित किया है जब लोग टिप्पणी नहीं पढ़ते हैं (या टिप्पणियां गायब हो जाती हैं)। इस पेज को सर्च-इंजन से काफी ट्रैफिक मिलता है और यह वर्तमान में लोगों द्वारा देखा गया पहला उत्तर है।
एलेक्स रिले

मुझे आश्चर्य है कि आप अधिकतम (x) और अधिकतम (abs (x)) को क्यों घटाते हैं (मान का निर्धारण करने के बाद संकेत को ठीक करें)। यदि आपके सभी मूल्य शून्य से नीचे हैं और उनके पूर्ण मूल्य में बहुत बड़े हैं, और केवल मूल्य (अधिकतम) शून्य के करीब है, तो अधिकतम घटाना कुछ भी नहीं बदलेगा। क्या यह अभी भी संख्यात्मक रूप से अस्थिर नहीं होगा?
सेर्नो

102

(खैर - यहाँ बहुत उलझन है, सवाल और जवाब दोनों में ...)

के साथ शुरू करने के लिए, दो समाधान (यानी तुम्हारा और सुझाया गया एक) समतुल्य नहीं हैं ; वे होते हैं केवल 1-डी स्कोर सरणियों के विशेष मामले के लिए बराबर हो। अगर आपने उदाहरण के तौर पर यूडेसिटी क्विज़ में 2-डी स्कोर ऐरे की कोशिश की है तो आपको इसका पता चल जाएगा।

परिणाम-वार, दो समाधानों के बीच एकमात्र वास्तविक अंतर axis=0तर्क है। यह देखने के लिए कि यह मामला है, चलिए आपके समाधान की कोशिश करते हैं ( your_softmax) और जहाँ एक ही अंतर axisतर्क है:

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

जैसा कि मैंने कहा, 1-डी स्कोर सरणी के लिए, परिणाम वास्तव में समान हैं:

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)

फिर भी, यहां 2-डी स्कोर सरणी के लिए परिणाम एक उदाहरण के रूप में उडेसिटी क्विज में दिए गए हैं:

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

परिणाम अलग-अलग हैं - दूसरा एक वास्तव में उडेस क्विज़ में अपेक्षित के साथ समान है, जहां सभी कॉलम वास्तव में 1 के बराबर हैं, जो पहले (गलत) परिणाम के मामले में नहीं है।

इसलिए, सभी उपद्रव वास्तव में कार्यान्वयन विवरण के लिए थे - axisतर्क। Numpy.sum प्रलेखन के अनुसार :

डिफ़ॉल्ट, अक्ष = कोई नहीं, इनपुट सरणी के सभी तत्वों का योग करेगा

यहाँ हम पंक्ति-वार योग करना चाहते हैं, इसलिए axis=0। 1-डी सरणी के लिए, (केवल) पंक्ति का योग और सभी तत्वों का योग समान होता है, इसलिए उस मामले में आपके समान परिणाम ...

axisमुद्दा एक तरफ अपने क्रियान्वयन (यानी अपनी अधिकतम पहले घटाना पसंद) वास्तव में है बेहतर सुझाव दिया समाधान की तुलना में! वास्तव में, यह सॉफ्टमैक्स फ़ंक्शन को लागू करने का अनुशंसित तरीका है - औचित्य के लिए यहां देखें (संख्यात्मक स्थिरता, यहां कुछ अन्य उत्तरों द्वारा भी इंगित किया गया है)।


ठीक है, अगर आप सिर्फ बहुआयामी सरणी के बारे में बात कर रहे हैं। पहला समाधान आसानी से जोड़कर तय किया जा सकता है axisदोनों के लिए तर्क maxऔर sum। हालांकि, पहला कार्यान्वयन अभी भी बेहतर है क्योंकि आप लेने के दौरान आसानी से ओवरफ्लो कर सकते हैंexp
लुई यांग

@LouisYang मैं अनुसरण नहीं कर रहा हूं; "पहला" समाधान कौन सा है? कौन सा उपयोग नहीं करता है exp? एक axisतर्क जोड़ने के अलावा और क्या यहाँ संशोधित किया गया है?
रेगिस्तान में

पहला समाधान @alvas से समाधान का उल्लेख है। अंतर यह है कि एलाव के प्रश्न में सुझाए गए समाधान अधिकतम को घटाने का हिस्सा गायब है। यह आसानी से उदाहरण के लिए अतिप्रवाह पैदा कर सकता है, ऍक्स्प (1000) / (एक्सप (1000) + एक्सप (1001)) बनाम एक्सप (-1) / (एक्सप (-1) + एक्सप (0)) गणित में समान हैं लेकिन पहला ओवरफ्लो होगा।
लुई यांग

@LouisYang अभी भी, सुनिश्चित नहीं है कि मैं आपकी टिप्पणी की आवश्यकता को समझता हूं - यह सब पहले से ही जवाब में स्पष्ट रूप से संबोधित किया गया है।
रेगिस्तान में

@LouisYang कृपया (बाद में) थ्रेड की लोकप्रियता को आपको मूर्ख न बनने दें, और उस संदर्भ की कल्पना करने की कोशिश करें जहां स्वयं का उत्तर दिया गया था: एक हैरान ओपी (" दोनों एक ही परिणाम देते हैं "), और एक (अभी भी!) स्वीकार किए जाते हैं। दावा है कि " दोनों सही हैं " (ठीक है, वे नहीं हैं )। इसका उत्तर कभी नहीं था " सामान्य रूप से सॉफ्टमैक्स की गणना करने का सबसे सही और कुशल तरीका "; यह सिर्फ औचित्य साबित करने के लिए होती क्यों , में विशिष्ट Udacity प्रश्नोत्तरी पर चर्चा की, 2 समाधान कर रहे हैं नहीं के बराबर।
रेगिस्तान में

56

तो, यह वास्तव में रेगिस्तान के जवाब के लिए एक टिप्पणी है लेकिन मैं अपनी प्रतिष्ठा के कारण अभी तक इस पर टिप्पणी नहीं कर सकता। जैसा कि उन्होंने बताया, यदि आपके इनपुट में एक ही नमूना है, तो आपका संस्करण केवल सही है। यदि आपके इनपुट में कई नमूने हैं, तो यह गलत है। हालांकि, डेजर्टनॉट का समाधान भी गलत है। समस्या यह है कि एक बार वह 1-आयामी इनपुट लेता है और फिर वह 2-आयामी इनपुट लेता है। मुझे यह दिखाओ।

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

आओ हम रेगिस्तान का उदाहरण लें:

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

यह आउटपुट है:

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

आप देख सकते हैं कि desernauts संस्करण इस स्थिति में विफल हो जाएगा। (यह नहीं होगा कि इनपुट np.array ([1, 2, 3, 6]) की तरह केवल एक आयामी था।

अब हम 3 नमूनों का उपयोग करते हैं यही कारण है कि हम एक 2 आयामी इनपुट का उपयोग करते हैं। निम्नलिखित एक्स 2 desernauts उदाहरण से एक के रूप में ही नहीं है।

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

इस इनपुट में 3 नमूनों वाला एक बैच होता है। लेकिन नमूना एक और तीन अनिवार्य रूप से समान हैं। अब हम सॉफ्टमैक्स एक्टीवेशन की 3 पंक्तियों की उम्मीद करते हैं जहाँ पहली तीसरी के समान होनी चाहिए और दूसरी हमारी एक्स 1 की सक्रियता भी!

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

मुझे आशा है कि आप देख सकते हैं कि यह केवल मेरे समाधान के मामले में है।

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

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

इसके अतिरिक्त, यहाँ 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})

और परिणाम:

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
यह एक टिप्पणी का एक नरक रहा होगा ;-)
माइकल बेंजामिन 14

27
np.exp (z) / np.sum (np.exp (z), axis = 1, Keepdims = True) आपके सॉफ्टमैक्स फ़ंक्शन के समान परिणाम पर पहुंचता है। एस के साथ कदम अनावश्यक हैं।
पाबोर्रे

जगह of` में s = s[:, np.newaxis], s = s.reshape(z.shape[0],1)काम भी करना चाहिए।
देबाशीष

2
इस पृष्ठ पर इतने सारे गलत / अक्षम समाधान। अपने आप को एक एहसान करो और PabTorre का उपयोग करें
मिस पामर

@PabTorre का मतलब आपने अक्ष = -1 है? अक्ष = 1 एकल आयामी इनपुट के लिए काम नहीं करेगा
DiehardTheTryhard

36

मैं कहूंगा कि जबकि दोनों गणितीय रूप से सही हैं, कार्यान्वयन-वार, पहले एक बेहतर है। सॉफ्टमैक्स की गणना करते समय, मध्यवर्ती मान बहुत बड़े हो सकते हैं। दो बड़ी संख्याओं को विभाजित करना संख्यात्मक रूप से अस्थिर हो सकता है। इन नोट्स (स्टैनफोर्ड से) एक सामान्यीकरण चाल का उल्लेख करते हैं जो अनिवार्य रूप से आप क्या कर रहे हैं।


3
तबाही रद्द करने के प्रभावों को कम करके आंका नहीं जा सकता।
सीजर

24

स्केलेरन सॉफ्टमैक्स के कार्यान्वयन की भी पेशकश करता है

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
यह वास्तव में कैसे विशिष्ट प्रश्न का उत्तर देता है, जो कार्यान्वयन के बारे में है और किसी तीसरे पक्ष के पुस्तकालय में उपलब्धता के बारे में नहीं है?
रेगिस्तान

8
मैं दोनों दृष्टिकोणों के परिणामों को सत्यापित करने के लिए तीसरे पक्ष के कार्यान्वयन की तलाश कर रहा था। इस तरह से यह टिप्पणी मदद करती है।
यूजीनियो एफ। मार्टिनेज पचेको

13

गणितीय दृष्टिकोण से दोनों पक्ष समान हैं।

और आप इसे आसानी से साबित कर सकते हैं। चलो m=max(x)। अब आपका फ़ंक्शन softmaxएक वेक्टर लौटाता है, जिसका i-th समन्वय समान है

यहां छवि विवरण दर्ज करें

ध्यान दें कि यह किसी भी के लिए काम करता है m, क्योंकि सभी (यहां तक ​​कि जटिल) संख्याओं के लिएe^m != 0

  • कम्प्यूटेशनल जटिलता के दृष्टिकोण से वे समान हैं और दोनों समय में चलते हैं O(n), जहां nएक वेक्टर का आकार है।

  • से संख्यात्मक स्थिरता की दृष्टि, पहले समाधान प्राथमिकता दी जाती है, क्योंकि e^xबहुत तेजी से बढ़ता है और यहां तक कि के सुंदर छोटे मानों के लिए xयह अतिप्रवाह होगा। अधिकतम मूल्य घटाना इस अतिप्रवाह से छुटकारा पाने की अनुमति देता है। व्यावहारिक रूप से उस सामान का अनुभव करने के लिए, जिसके बारे में मैं बात कर रहा था, x = np.array([1000, 5])जो आपके दोनों कार्यों में खिलाने की कोशिश कर रहा था । एक सही संभावना लौटाएगा, दूसरा ओवरफ्लो होगाnan

  • आपका समाधान केवल वैक्टर के लिए काम करता है (उदिता क्विज़ चाहता है कि आप इसकी गणना मैट्रिस के लिए भी करें)। इसे ठीक करने के लिए आपको इसका उपयोग करने की आवश्यकता हैsum(axis=0)


1
जब यह वेक्टर पर नहीं बल्कि मैट्रिक्स पर सॉफ्टमैक्स की गणना करने में सक्षम होने के लिए उपयोगी है? यानी क्या मॉडल आउटपुट मैट्रिक्स? क्या यह और भी अधिक आयामी हो सकता है?
मृग्लोम

2
क्या आप का मतलब है कि पहला समाधान "संख्यात्मक स्थिरता के दृष्टिकोण से, दूसरा समाधान पसंद किया गया है ..."?
दातमन

10

संपादित करें । संस्करण 1.2.0 के रूप में, स्कैपी में एक विशेष फ़ंक्शन के रूप में सॉफ्टमैक्स शामिल हैं:

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

मैंने किसी भी अक्ष पर सॉफ्टमैक्स लगाने वाला एक फ़ंक्शन लिखा:

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

अन्य उपयोगकर्ताओं के रूप में वर्णित अधिकतम घटाना, अच्छा अभ्यास है। मैंने इसके बारे में एक विस्तृत पोस्ट लिखी यहाँ है


9

यहां आप पता लगा सकते हैं कि उन्होंने क्यों इस्तेमाल किया- max

वहां से:

"जब आप व्यवहार में सॉफ्टमैक्स फ़ंक्शन की गणना के लिए कोड लिख रहे हैं, तो घातांक के कारण मध्यवर्ती शब्द बहुत बड़े हो सकते हैं। बड़ी संख्या को विभाजित करना संख्यात्मक रूप से अस्थिर हो सकता है, इसलिए सामान्यीकरण चाल का उपयोग करना महत्वपूर्ण है।"



4

वैकल्पिक समाधान की पेशकश करने के लिए, उन मामलों पर विचार करें जहां आपके तर्क बहुत बड़े हैं जैसे कि exp(x)(नकारात्मक मामले में) या अतिप्रवाह (सकारात्मक मामले में) बह निकलेगा। यहां आप यथासंभव लंबे समय तक लॉग स्पेस में बने रहना चाहते हैं, केवल उस छोर पर एक्सपेक्टिनाईंग करें जहां आप भरोसा कर सकते हैं कि परिणाम अच्छी तरह से व्यवहार किया जाएगा।

import scipy.special as sc
import numpy as np

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

इसे पोस्टर कोड के बराबर बनाने के लिए, आपको axis=0एक तर्क के रूप में जोड़ना होगा logsumexp
ब्योर्न लिंडक्विस्ट

वैकल्पिक रूप से, कोई भी लॉग्सफ्रेम के पास जाने के लिए अतिरिक्त आर्गन को अनपैक कर सकता है।
पिकालैक्सल टीटी

3

मुझे टेंसरफ़्लो से एक घने परत के उत्पादन के साथ संगत कुछ की आवश्यकता थी ।

से समाधान @Desertnaut इस मामले में काम नहीं करता है क्योंकि मेरे पास डेटा के बैच हैं। इसलिए, मैं एक और समाधान के साथ आया जो दोनों मामलों में काम करना चाहिए:

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)

परिणाम:

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: टेंसरफ्लो सॉफ्टमैक्स


बस ध्यान रखें कि उत्तर प्रश्न में वर्णित एक बहुत विशिष्ट सेटिंग को संदर्भित करता है ; यह कभी भी 'किसी भी परिस्थिति में, या अपनी पसंद के डेटा प्रारूप में सामान्य रूप से सॉफ्टमैक्स की गणना करने के लिए' होने का मतलब नहीं था ...
डेजर्टनट

मैं देखता हूं, मैंने इसे यहां रखा है क्योंकि यह प्रश्न "उडेसिटी के डीप लर्निंग क्लास" को संदर्भित करता है और यह काम नहीं करेगा यदि आप अपने मॉडल के निर्माण के लिए टेन्सरफ्लो का उपयोग कर रहे हैं। आपका समाधान शांत और साफ है लेकिन यह केवल एक बहुत विशिष्ट परिदृश्य में काम करता है। फिर भी धन्यवाद।
लुकास कासाग्रेन्डे

2

मैं यह सुझाव दूंगा:

def softmax(z):
    z_norm=np.exp(z-np.max(z,axis=0,keepdims=True))
    return(np.divide(z_norm,np.sum(z_norm,axis=0,keepdims=True)))

यह स्टोकेस्टिक के साथ-साथ बैच के लिए काम करेगा।
अधिक विवरण के लिए देखें: https://medium.com/@ravish1729/analysis-of-softmax-function-ad058d6a564d


1

संख्यात्मक स्थिरता को बनाए रखने के लिए, अधिकतम (x) घटाया जाना चाहिए। निम्नलिखित सॉफ्टमैक्स फ़ंक्शन के लिए कोड है;

डीएफ़ सॉफ्टमैक्स (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

उपरोक्त उत्तरों में पहले ही बहुत विस्तार से बताया गया है। maxअतिप्रवाह से बचने के लिए घटाया जाता है। मैं यहाँ 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))

1

हर कोई अपने समाधान पोस्ट करने लगता है तो मैं अपना पोस्ट करूँगा:

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

मुझे sklearn से आयातित के समान सटीक परिणाम मिलते हैं:

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

एसओ में आपका स्वागत है। आपका कोड कैसे प्रश्न का उत्तर देता है, इसकी व्याख्या हमेशा मददगार होती है।
निक

1

सभी प्रतिक्रियाओं और CS231n नोटों के आधार पर , मुझे सारांशित करने की अनुमति दें:

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

उपयोग:

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

आउटपुट:

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

मैं समस्या के बारे में थोड़ी और समझ के पूरक होना चाहूंगा। यहाँ यह सरणी का अधिकतम घटाना सही है। लेकिन अगर आप दूसरे पोस्ट में कोड चलाते हैं, तो आप पाएंगे कि यह आपको सही उत्तर नहीं दे रहा है जब सरणी 2 डी या उच्चतर आयाम है।

यहाँ मैं आपको कुछ सुझाव देता हूँ:

  1. अधिकतम प्राप्त करने के लिए, इसे एक्स-एक्सिस के साथ करने की कोशिश करें, आपको 1 डी सरणी मिलेगी।
  2. अपने अधिकतम सरणी को मूल आकार में फेरबदल करें।
  3. क्या np.exp को घातीय मान मिलता है।
  4. अक्ष के साथ np.sum करें।
  5. अंतिम परिणाम प्राप्त करें।

परिणाम का पालन करें आपको वैश्वीकरण करके सही उत्तर मिलेगा। चूंकि यह कॉलेज के होमवर्क से संबंधित है, इसलिए मैं यहां सटीक कोड पोस्ट नहीं कर सकता, लेकिन अगर आप नहीं समझते हैं तो मैं और सुझाव देना चाहूंगा।


1
यह किसी भी कॉलेज के होमवर्क से संबंधित नहीं है, केवल गैर-मान्यता प्राप्त पाठ्यक्रम में एक अनियोजित अभ्यास प्रश्नोत्तरी के लिए, जहां अगले चरण में सही उत्तर प्रदान किया जाता है ...
सुनसान

0

सॉफ्टमैक्स फंक्शन का उद्देश्य अंतः-बिंदुओं को व्यंग्यात्मक रूप से संतृप्त करने के लिए वैक्टर के अनुपात को संरक्षित करना है क्योंकि मान संतृप्त होते हैं (जैसे + +- 1 (तन) या 0 से 1 (लॉजिस्टिक))। ऐसा इसलिए है क्योंकि यह अंत-बिंदुओं पर परिवर्तन की दर के बारे में अधिक जानकारी रखता है और इस प्रकार 1-एन-एन आउटपुट एन्कोडिंग के साथ तंत्रिका जाल पर लागू होता है (अर्थात यदि हमने अंतिम बिंदुओं को अलग किया है तो यह 1 को अलग करना कठिन होगा। -ऑफ़-एन आउटपुट क्लास क्योंकि हम यह नहीं बता सकते हैं कि कौन सा "सबसे बड़ा" या "सबसे छोटा" है, क्योंकि वे स्क्विट हो गए हैं); यह भी कुल आउटपुट 1 को बनाता है, और स्पष्ट विजेता 1 के करीब होगा जबकि अन्य संख्याएं जो एक दूसरे के करीब हैं वे 1 / p तक राशि प्राप्त करेंगे, जहां पी समान मूल्यों के साथ आउटपुट न्यूरॉन्स की संख्या है।

वेक्टर से अधिकतम मूल्य को घटाने का उद्देश्य यह है कि जब आप e ^ y प्रतिपादक करते हैं तो आपको बहुत अधिक मूल्य मिल सकता है जो फ्लोट को अधिकतम मूल्य पर एक टाई की ओर ले जाता है, जो इस उदाहरण में ऐसा नहीं है। यह एक बड़ी समस्या बन जाती है यदि आप एक ऋणात्मक संख्या बनाने के लिए अधिकतम मान घटाते हैं, तो आपके पास एक नकारात्मक प्रतिपादक है जो तेजी से अनुपात को बदलने वाले मानों को सिकोड़ता है, जो कि पोस्टर के प्रश्न में हुआ है और गलत उत्तर दिया है।

उडेसिटी द्वारा दिया गया उत्तर हॉरिबली अक्षम्य है। पहली चीज़ जो हमें करने की ज़रूरत है, वह सभी वेक्टर घटकों के लिए ई ^ y_j की गणना करना है, कीप्स वैल्यूज़, फिर उन्हें योग करें, और विभाजित करें। जहां उर्वशी ने गड़बड़ की है, वे ई ^ य_ज ट्वाइस की गणना करते हैं !!! यहाँ सही जवाब है:

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

लक्ष्य को Numpy और Tensorflow का उपयोग करके समान परिणाम प्राप्त करना था। मूल उत्तर से एकमात्र परिवर्तन के axisलिए पैरामीटर हैnp.sum एपीआई के ।

प्रारंभिक दृष्टिकोण :axis=0 - हालांकि यह तब अपेक्षित परिणाम प्रदान नहीं करता है जब आयाम एन होते हैं।

संशोधित दृष्टिकोण : axis=len(e_x.shape)-1- हमेशा अंतिम आयाम पर योग करें। यह टेंसरफ़्लो के सॉफ्टमैक्स फ़ंक्शन के समान परिणाम प्रदान करता है।

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

यहाँ सामान्यीकृत घोल का उपयोग किया जाता है और टेंसोफ़्लो एन्स के साथ शुद्धता के लिए तुलना की जाती है:

डेटा तैयारी:

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)

आउटपुट:

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

सॉफ्टमैक्स टेंसरफ़्लो का उपयोग कर:

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

आउटपुट:

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

स्कूप का उपयोग कर सॉफ्टमैक्स:

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

आउटपुट:

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

सॉफ्टमैक्स का उपयोग कर सुन्न ( 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))

आउटपुट:

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

सॉफ्टमैक्स फ़ंक्शन एक सक्रियण फ़ंक्शन है जो संख्याओं को संभावनाओं में बदल देता है जो एक के बराबर है। सॉफ्टमैक्स फ़ंक्शन एक वेक्टर को आउटपुट करता है जो परिणामों की सूची की संभावना वितरण का प्रतिनिधित्व करता है। यह गहन शिक्षण वर्गीकरण कार्यों में उपयोग किया जाने वाला एक मुख्य तत्व भी है।

सॉफ्टमैक्स फ़ंक्शन का उपयोग तब किया जाता है जब हमारे पास कई कक्षाएं होती हैं।

यह उस वर्ग का पता लगाने के लिए उपयोगी है जिसमें अधिकतम है। संभावना।

सॉफ्टमैक्स फ़ंक्शन आदर्श रूप से आउटपुट परत में उपयोग किया जाता है, जहां हम वास्तव में प्रत्येक इनपुट के वर्ग को परिभाषित करने के लिए संभावनाओं को प्राप्त करने की कोशिश कर रहे हैं।

यह 0 से 1 तक होता है।

सॉफ्टमैक्स फ़ंक्शन लॉग्स [2.0, 1.0, 0.1] को संभावनाओं [0.7, 0.2, 0.1] में बदल देता है, और 1. 1 राशि वाले योगांश एक तंत्रिका नेटवर्क की अंतिम परत द्वारा कच्चे स्कोर आउटपुट होते हैं। सक्रिय होने से पहले। सॉफ्टमैक्स फ़ंक्शन को समझने के लिए, हमें (n-1) वें लेयर के आउटपुट को देखना होगा।

सॉफ्टमैक्स फ़ंक्शन वास्तव में, एक अर्ग मैक्स फ़ंक्शन है। इसका मतलब है कि यह इनपुट से सबसे बड़ा मूल्य नहीं लौटाता है, लेकिन सबसे बड़े मूल्यों की स्थिति है।

उदाहरण के लिए:

सॉफ्टमैक्स से पहले

X = [13, 31, 5]

सॉफ्टमैक्स के बाद

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

कोड:

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.