Dies ist eine logistische Sigmoidfunktion:
Ich weiß x. Wie kann ich jetzt F (x) in Python berechnen?
Sagen wir x = 0,458.
F (x) =?
Dies ist eine logistische Sigmoidfunktion:
Ich weiß x. Wie kann ich jetzt F (x) in Python berechnen?
Sagen wir x = 0,458.
F (x) =?
Antworten:
Dies sollte es tun:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
Und jetzt können Sie es testen, indem Sie anrufen:
>>> sigmoid(0.458)
0.61253961344091512
Update : Beachten Sie, dass das oben Gesagte hauptsächlich als direkte Eins-zu-Eins-Übersetzung des angegebenen Ausdrucks in Python-Code gedacht war. Es ist nicht getestet oder bekannt, dass es sich um eine numerisch einwandfreie Implementierung handelt. Wenn Sie wissen, dass Sie eine sehr robuste Implementierung benötigen, gibt es sicher andere, bei denen die Leute tatsächlich über dieses Problem nachgedacht haben.
math.exp
mit np.exp
Ihnen nicht NaNs bekommen, obwohl Sie Laufzeit - Warnungen erhalten.
math.exp
mit einem numpy-Array kann zu Fehlern führen, z TypeError: only length-1 arrays can be converted to Python scalars
. Um dies zu vermeiden, sollten Sie verwenden numpy.exp
.
x = max(-709,x)
vor dem Ausdruck verringert werden ?
Es ist auch in scipy verfügbar: 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
Dies ist nur ein kostspieliger Wrapper (da Sie damit die logistische Funktion skalieren und übersetzen können) einer anderen Scipy-Funktion:
In [3]: from scipy.special import expit
In [4]: expit(0.458)
Out[4]: 0.61253961344091512
Wenn Sie über Aufführungen besorgt sind, lesen Sie weiter, andernfalls verwenden Sie einfach 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
Wie erwartet logistic.cdf
ist (viel) langsamer als expit
. expit
ist immer noch langsamer als die Python- sigmoid
Funktion, wenn sie mit einem einzelnen Wert aufgerufen wird, da es sich um eine universelle Funktion handelt, die in C ( http://docs.scipy.org/doc/numpy/reference/ufuncs.html ) geschrieben ist und daher einen Aufrufaufwand hat. Dieser Overhead ist größer als die Rechengeschwindigkeit, expit
die durch seine kompilierte Natur gegeben ist, wenn er mit einem einzelnen Wert aufgerufen wird. Aber es wird vernachlässigbar, wenn es um große Arrays geht:
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))
....:
(Sie werden die winzige Änderung von math.exp
nach bemerken np.exp
(die erste unterstützt keine Arrays, ist jedoch viel schneller, wenn Sie nur einen Wert berechnen müssen))
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
Wenn Sie jedoch wirklich Leistung benötigen, ist es üblich, eine vorberechnete Tabelle der Sigmoid-Funktion im RAM zu haben und Präzision und Speicher gegen eine gewisse Geschwindigkeit einzutauschen (zum Beispiel: http://radimrehurek.com/2013/09) / word2vec-in-python-part-two-optimizing / )
Beachten Sie außerdem, dass die expit
Implementierung seit Version 0.14.0 numerisch stabil ist: https://github.com/scipy/scipy/issues/3385
So würden Sie das logistische Sigmoid numerisch stabil implementieren (wie hier beschrieben ):
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)
Oder vielleicht ist das genauer:
import numpy as np
def sigmoid(x):
return math.exp(-np.logaddexp(0, -x))
Intern implementiert es die gleiche Bedingung wie oben, verwendet dann aber log1p
.
Im Allgemeinen lautet das multinomiale logistische Sigmoid:
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
und rebased_q
durch tau
? weil ich das versucht habe und keine Wahrscheinlichkeiten bekomme, die sich zu 1 summieren
q
) durch Ihre Temperatur. rebased_q kann alles sein: Es ändert nichts an der Antwort. es verbessert die numerische Stabilität.
nat_to_exp
Sind Sie sicher , dass dies Softmax entspricht (wie Sie in Ihrer anderen Antwort erwähnt haben)? Durch Kopieren und Einfügen werden Wahrscheinlichkeiten zurückgegeben, die nicht 1 ergeben
ein anderer Weg
>>> def sigmoid(x):
... return 1 /(1+(math.e**-x))
...
>>> sigmoid(0.458)
pow
wird oft in Bezug auf exp
und implementiert log
, daher ist die exp
direkte Verwendung mit ziemlicher Sicherheit besser.
x
es sehr negativ ist.
Ein anderer Weg durch Transformation der tanh
Funktion:
sigmoid = lambda x: .5 * (math.tanh(.5 * x) + 1)
Ich glaube, viele könnten an freien Parametern interessiert sein, um die Form der Sigmoidfunktion zu verändern. Zweitens möchten Sie für viele Anwendungen eine gespiegelte Sigmoid-Funktion verwenden. Drittens möchten Sie vielleicht eine einfache Normalisierung durchführen, zum Beispiel liegen die Ausgabewerte zwischen 0 und 1.
Versuchen:
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
Und zum Zeichnen und Vergleichen:
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
Schließlich:
x = np.linspace(0,1,100)
Travel_function = draw_function_on_2x2_grid(x)
Gute Antwort von @unwind. Es kann jedoch keine extrem negativen Zahlen verarbeiten (OverflowError auslösen).
Meine Verbesserung:
def sigmoid(x):
try:
res = 1 / (1 + math.exp(-x))
except OverflowError:
res = 0.0
return res
Tensorflow enthält auch eine sigmoid
Funktion:
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
Eine numerisch stabile Version der logistischen Sigmoidfunktion.
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)
Ein Einzeiler ...
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
oder numpy array
:Die besten Antworten sind optimierte Methoden für die Einzelpunktberechnung. Wenn Sie diese Methoden jedoch auf eine Pandas-Reihe oder ein Numpy-Array anwenden möchten, ist dies erforderlich apply
ist im Grunde eine Schleife im Hintergrund und wird über jede Zeile iteriert und die Methode . Das ist ziemlich ineffizient.
Um unseren Code zu beschleunigen, können wir Vektorisierung und Numpy Broadcasting verwenden:
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
Oder mit einem pandas Series
:
x = pd.Series(np.arange(-5,5))
np.divide(1, 1+np.exp(-x))
Sie können es berechnen als:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
oder konzeptionell, tiefer und ohne Importe:
def sigmoid(x):
return 1 / (1 + 2.718281828 ** -x)
oder Sie können numpy für Matrizen verwenden:
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)
Der obige Code ist die logistische Sigmoid-Funktion in Python. Wenn ich das weiß x = 0.467
, Die Sigmoidfunktion , F(x) = 0.385
. Sie können versuchen, einen beliebigen Wert von x zu ersetzen, den Sie im obigen Code kennen, und Sie erhalten einen anderen Wert von F(x)
.
sigmoid = lambda x: 1 / (1 + math.exp(-x))