यह एक लॉजिस्टिक सिग्मोइड फ़ंक्शन है:
म x जानता हूं। अब मैं पायथन में एफ (एक्स) की गणना कैसे कर सकता हूं?
मान लीजिए कि x = 0.458 है।
F (x) =?
यह एक लॉजिस्टिक सिग्मोइड फ़ंक्शन है:
म x जानता हूं। अब मैं पायथन में एफ (एक्स) की गणना कैसे कर सकता हूं?
मान लीजिए कि x = 0.458 है।
F (x) =?
जवाबों:
यह करना चाहिए:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
और अब आप इसे कॉल करके जांच सकते हैं:
>>> sigmoid(0.458)
0.61253961344091512
अद्यतन : ध्यान दें कि उपरोक्त मुख्य रूप से पायथन कोड में दिए गए अभिव्यक्ति के सीधे एक-से-एक अनुवाद के रूप में था। यह एक संख्यात्मक ध्वनि कार्यान्वयन के लिए परीक्षण या ज्ञात नहीं है। यदि आप जानते हैं कि आपको बहुत मजबूत कार्यान्वयन की आवश्यकता है, तो मुझे यकीन है कि अन्य लोग भी हैं जहां लोगों ने वास्तव में इस समस्या को कुछ सोचा है।
math.exp
साथ प्रतिस्थापित करते हैं np.exp
तो आपको NaN नहीं मिलेगा, हालाँकि आपको रनटाइम चेतावनियाँ मिलेंगी।
math.exp
numpy सरणी के साथ कुछ त्रुटियों की तरह, उपज कर सकते हैं: TypeError: only length-1 arrays can be converted to Python scalars
। इससे बचने के लिए आपको उपयोग करना चाहिए numpy.exp
।
x = max(-709,x)
अभिव्यक्ति के समक्ष जोड़कर संख्यात्मक अस्थिरता को कम किया जा सकता है ?
यह scipy में भी उपलब्ध है: http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.logistic.html
In [1]: from scipy.stats import logistic
In [2]: logistic.cdf(0.458)
Out[2]: 0.61253961344091512
जो केवल एक महंगा रैपर है (क्योंकि यह आपको दूसरे स्कैपी फ़ंक्शन के पैमाने और लॉजिस्टिक फ़ंक्शन का अनुवाद करने की अनुमति देता है):
In [3]: from scipy.special import expit
In [4]: expit(0.458)
Out[4]: 0.61253961344091512
यदि आप प्रदर्शन के बारे में चिंतित हैं तो पढ़ना जारी रखें, अन्यथा सिर्फ उपयोग करें expit
।
In [5]: def sigmoid(x):
....: return 1 / (1 + math.exp(-x))
....:
In [6]: %timeit -r 1 sigmoid(0.458)
1000000 loops, best of 1: 371 ns per loop
In [7]: %timeit -r 1 logistic.cdf(0.458)
10000 loops, best of 1: 72.2 µs per loop
In [8]: %timeit -r 1 expit(0.458)
100000 loops, best of 1: 2.98 µs per loop
जैसा कि अपेक्षित logistic.cdf
है (बहुत) की तुलना में धीमा है expit
। expit
अभी भी अजगर sigmoid
फ़ंक्शन की तुलना में धीमा है, जब इसे एकल मान के साथ कहा जाता है क्योंकि यह C ( http://docs.scipy.org/doc/numpy/reference/ufuncs.html ) में लिखा गया एक सार्वभौमिक कार्य है और इस तरह एक कॉल हेडहेड है। यह ओवरहेड expit
एक एकल मूल्य के साथ बुलाए जाने पर अपने संकलित प्रकृति द्वारा दिए गए गणना गति से बड़ा है । लेकिन जब यह बड़े सरणियों में आता है तो यह नगण्य हो जाता है:
In [9]: import numpy as np
In [10]: x = np.random.random(1000000)
In [11]: def sigmoid_array(x):
....: return 1 / (1 + np.exp(-x))
....:
(आप से छोटे परिवर्तन दिखाई देगा math.exp
करने के लिए np.exp
(पहले एक सरणियों का समर्थन नहीं करता है, लेकिन बहुत तेजी से अगर आप गणना करने के लिए केवल एक मान हो है))
In [12]: %timeit -r 1 -n 100 sigmoid_array(x)
100 loops, best of 1: 34.3 ms per loop
In [13]: %timeit -r 1 -n 100 expit(x)
100 loops, best of 1: 31 ms per loop
लेकिन जब आपको वास्तव में प्रदर्शन की आवश्यकता होती है, तो एक आम बात यह है कि सिग्मॉइड फ़ंक्शन की एक प्री-कॉम्प्लेक्स टेबल है जो रैम में है, और कुछ गति के लिए सटीक और मेमोरी का व्यापार करता है (उदाहरण के लिए: http://radimrehurek.com/2013/09) / word2vec-in-python-part-two-optimizing / )
यह भी ध्यान दें कि expit
कार्यान्वयन 0.14.0 के बाद से संख्यात्मक रूप से स्थिर है: https://github.com/scipy/scipy/issues/3385
यहाँ बताया गया है कि आप सांकेतिक रूप से स्थिर तरीके से लॉजिस्टिक सिग्मॉइड को कैसे लागू करेंगे (जैसा यहाँ वर्णित है ):
def sigmoid(x):
"Numerically-stable sigmoid function."
if x >= 0:
z = exp(-x)
return 1 / (1 + z)
else:
z = exp(x)
return z / (1 + z)
या शायद यह अधिक सटीक है:
import numpy as np
def sigmoid(x):
return math.exp(-np.logaddexp(0, -x))
आंतरिक रूप से, यह ऊपर जैसी स्थिति को लागू करता है, लेकिन फिर उपयोग करता है log1p
।
सामान्य तौर पर, बहुराष्ट्रीय लॉजिस्टिक सिग्मोइड है:
def nat_to_exp(q):
max_q = max(0.0, np.max(q))
rebased_q = q - max_q
return np.exp(rebased_q - np.logaddexp(-max_q, np.logaddexp.reduce(rebased_q)))
max_q
और rebased_q
द्वारा tau
? क्योंकि मैंने कोशिश की थी और मुझे संभावना नहीं है कि 1 को राशि
q
) को अपने तापमान से विभाजित करें । rebased_q कुछ भी हो सकता है: यह जवाब नहीं बदलता है; यह संख्यात्मक स्थिरता में सुधार करता है।
nat_to_exp
सॉफ्टमैक्स के बराबर हैं (जैसा कि आपने अपने अन्य उत्तर में उल्लेख किया है)? इसकी कॉपी-पेस्ट संभावनाएँ लौटाता है जो
दूसरा रास्ता
>>> def sigmoid(x):
... return 1 /(1+(math.e**-x))
...
>>> sigmoid(0.458)
pow
अक्सर के मामले में लागू किया गया है exp
और log
, इसलिए का उपयोग कर exp
सीधे लगभग निश्चित रूप से बेहतर है।
x
बहुत नकारात्मक होने पर ओवरफ्लो से पीड़ित होता है।
tanh
फ़ंक्शन को परिवर्तित करके दूसरा तरीका :
sigmoid = lambda x: .5 * (math.tanh(.5 * x) + 1)
मुझे लगता है कि सिग्मॉइड फ़ंक्शन के आकार को बदलने के लिए कई को मुफ्त मापदंडों में रुचि हो सकती है। कई अनुप्रयोगों के लिए दूसरा जिसे आप मिरर किए गए सिग्मॉइड फ़ंक्शन का उपयोग करना चाहते हैं। तीसरा, आप एक सामान्य सामान्यीकरण करना चाहते हैं उदाहरण के लिए आउटपुट मान 0 और 1 के बीच हैं।
प्रयत्न:
def normalized_sigmoid_fkt(a, b, x):
'''
Returns array of a horizontal mirrored normalized sigmoid function
output between 0 and 1
Function parameters a = center; b = width
'''
s= 1/(1+np.exp(b*(x-a)))
return 1*(s-min(s))/(max(s)-min(s)) # normalize function to 0-1
और आकर्षित करने और तुलना करने के लिए:
def draw_function_on_2x2_grid(x):
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
plt.subplots_adjust(wspace=.5)
plt.subplots_adjust(hspace=.5)
ax1.plot(x, normalized_sigmoid_fkt( .5, 18, x))
ax1.set_title('1')
ax2.plot(x, normalized_sigmoid_fkt(0.518, 10.549, x))
ax2.set_title('2')
ax3.plot(x, normalized_sigmoid_fkt( .7, 11, x))
ax3.set_title('3')
ax4.plot(x, normalized_sigmoid_fkt( .2, 14, x))
ax4.set_title('4')
plt.suptitle('Different normalized (sigmoid) function',size=10 )
return fig
आखिरकार:
x = np.linspace(0,1,100)
Travel_function = draw_function_on_2x2_grid(x)
@Unwind से अच्छा जवाब। हालाँकि यह अत्यधिक नकारात्मक संख्या (अतिप्रवाह को फेंकना) को संभाल नहीं सकता है।
मेरा सुधार:
def sigmoid(x):
try:
res = 1 / (1 + math.exp(-x))
except OverflowError:
res = 0.0
return res
Tensorflow में एक sigmoid
फ़ंक्शन भी शामिल है :
https://www.tensorflow.org/versions/r1.2/api_docs/python/tf/sigmoid
import tensorflow as tf
sess = tf.InteractiveSession()
x = 0.458
y = tf.sigmoid(x)
u = y.eval()
print(u)
# 0.6125396
लॉजिस्टिक सिग्मोइड फ़ंक्शन का एक संख्यात्मक रूप से स्थिर संस्करण।
def sigmoid(x):
pos_mask = (x >= 0)
neg_mask = (x < 0)
z = np.zeros_like(x,dtype=float)
z[pos_mask] = np.exp(-x[pos_mask])
z[neg_mask] = np.exp(x[neg_mask])
top = np.ones_like(x,dtype=float)
top[neg_mask] = z[neg_mask]
return top / (1 + z)
एक लाइनर ...
In[1]: import numpy as np
In[2]: sigmoid=lambda x: 1 / (1 + np.exp(-x))
In[3]: sigmoid(3)
Out[3]: 0.9525741268224334
pandas DataFrame/Series
या वेक्टर विधि numpy array
:शीर्ष उत्तर एकल बिंदु गणना के लिए अनुकूलित तरीके हैं, लेकिन जब आप इन तरीकों को पांडा श्रृंखला या संख्यात्मक सरणी में लागू करना चाहते हैं, तो इसके लिए आवश्यक है apply
, जो मूल रूप से पृष्ठभूमि में लूप के लिए है और प्रत्येक पंक्ति पर पुनरावृति करेगा और विधि लागू करेगा। यह काफी अक्षम है।
हमारे कोड को गति देने के लिए, हम वैश्वीकरण और संख्यात्मक प्रसारण का उपयोग कर सकते हैं:
x = np.arange(-5,5)
np.divide(1, 1+np.exp(-x))
0 0.006693
1 0.017986
2 0.047426
3 0.119203
4 0.268941
5 0.500000
6 0.731059
7 0.880797
8 0.952574
9 0.982014
dtype: float64
या एक के साथ pandas Series
:
x = pd.Series(np.arange(-5,5))
np.divide(1, 1+np.exp(-x))
आप इसकी गणना इस प्रकार कर सकते हैं:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
या वैचारिक, गहरा और बिना किसी आयात के:
def sigmoid(x):
return 1 / (1 + 2.718281828 ** -x)
या आप matrices के लिए numpy का उपयोग कर सकते हैं:
import numpy as np #make sure numpy is already installed
def sigmoid(x):
return 1 / (1 + np.exp(-x))
import numpy as np
def sigmoid(x):
s = 1 / (1 + np.exp(-x))
return s
result = sigmoid(0.467)
print(result)
उपरोक्त कोड पाइथन में लॉजिस्टिक सिग्मोइड फ़ंक्शन है। तो मैं जानता हूँ कि x = 0.467
, अवग्रह समारोह, F(x) = 0.385
। आप उपरोक्त कोड में आपके द्वारा ज्ञात किसी भी x का मान बदलने का प्रयास कर सकते हैं, और आपको एक अलग मान मिलेगा F(x)
।
sigmoid = lambda x: 1 / (1 + math.exp(-x))