Ini adalah fungsi sigmoid logistik:
Saya tahu x. Bagaimana saya bisa menghitung F (x) dengan Python sekarang?
Katakanlah x = 0,458.
F (x) =?
Ini adalah fungsi sigmoid logistik:
Saya tahu x. Bagaimana saya bisa menghitung F (x) dengan Python sekarang?
Katakanlah x = 0,458.
F (x) =?
Jawaban:
Ini harus dilakukan:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
Dan sekarang Anda dapat mengujinya dengan menelepon:
>>> sigmoid(0.458)
0.61253961344091512
Pembaruan : Perhatikan bahwa di atas terutama dimaksudkan sebagai terjemahan langsung satu-ke-satu dari ekspresi yang diberikan ke dalam kode Python. Ini tidak diuji atau dikenal sebagai implementasi yang baik secara numerik. Jika Anda tahu Anda membutuhkan implementasi yang sangat kuat, saya yakin ada orang lain di mana orang benar-benar memikirkan masalah ini.
math.exp
dengan np.exp
Anda tidak akan mendapatkan NaN, meskipun Anda akan mendapatkan peringatan runtime.
math.exp
dengan berbagai numpy dapat menghasilkan beberapa kesalahan, seperti: TypeError: only length-1 arrays can be converted to Python scalars
. Untuk menghindarinya sebaiknya Anda gunakan numpy.exp
.
x = max(-709,x)
sebelum ekspresi?
Ini juga tersedia di 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
yang hanya merupakan pembungkus yang mahal (karena ini memungkinkan Anda untuk mengukur dan menerjemahkan fungsi logistik) dari fungsi scipy lainnya:
In [3]: from scipy.special import expit
In [4]: expit(0.458)
Out[4]: 0.61253961344091512
Jika Anda khawatir tentang pertunjukan, teruskan membaca, jika tidak gunakan saja 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
Seperti yang diharapkan logistic.cdf
(lebih) lebih lambat dari expit
. expit
masih lebih lambat daripada sigmoid
fungsi python ketika dipanggil dengan nilai tunggal karena itu adalah fungsi universal yang ditulis dalam C ( http://docs.scipy.org/doc/numpy/reference/ufuncs.html ) dan dengan demikian memiliki panggilan overhead. Overhead ini lebih besar dari percepatan perhitungan yang expit
diberikan oleh sifat kompilasi ketika dipanggil dengan nilai tunggal. Tetapi menjadi diabaikan ketika datang ke array besar:
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))
....:
(Anda akan melihat perubahan kecil dari math.exp
menjadi np.exp
(yang pertama tidak mendukung array, tetapi jauh lebih cepat jika Anda hanya memiliki satu nilai untuk dihitung))
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
Tetapi ketika Anda benar-benar membutuhkan kinerja, praktik umum adalah memiliki tabel yang sudah dikomputasi dari fungsi sigmoid yang menampung RAM, dan menukar beberapa presisi dan memori untuk beberapa kecepatan (misalnya: http://radimrehurek.com/2013/09 / word2vec-in-python-bagian-dua-mengoptimalkan / )
Juga, perhatikan bahwa expit
implementasinya stabil secara numerik sejak versi 0.14.0: https://github.com/scipy/scipy/issues/3385
Inilah cara Anda menerapkan sigmoid logistik dengan cara yang stabil secara numerik (seperti dijelaskan di sini ):
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)
Atau mungkin ini lebih akurat:
import numpy as np
def sigmoid(x):
return math.exp(-np.logaddexp(0, -x))
Secara internal, ini mengimplementasikan kondisi yang sama seperti di atas, tetapi kemudian menggunakan log1p
.
Secara umum, sigmoid logistik multinomial adalah:
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
dan rebased_q
oleh tau
? karena saya mencobanya dan saya tidak mendapatkan probabilitas yang berjumlah 1
q
) dengan suhu Anda. rebased_q bisa berupa apa saja: tidak mengubah jawaban; itu meningkatkan stabilitas numerik.
nat_to_exp
setara dengan softmax (seperti yang Anda sebutkan dalam jawaban Anda yang lain)? Salin-tempel dari itu mengembalikan probabilitas yang tidak berjumlah 1
cara lain
>>> def sigmoid(x):
... return 1 /(1+(math.e**-x))
...
>>> sigmoid(0.458)
pow
sering diimplementasikan dalam hal exp
dan log
, jadi menggunakan exp
secara langsung hampir pasti lebih baik.
x
sangat negatif.
Cara lain dengan mengubah tanh
fungsi:
sigmoid = lambda x: .5 * (math.tanh(.5 * x) + 1)
Saya merasa banyak yang mungkin tertarik pada parameter gratis untuk mengubah bentuk fungsi sigmoid. Kedua untuk banyak aplikasi Anda ingin menggunakan fungsi sigmoid cermin. Ketiga, Anda mungkin ingin melakukan normalisasi sederhana misalnya nilai output antara 0 dan 1.
Mencoba:
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
Dan untuk menggambar dan membandingkan:
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
Akhirnya:
x = np.linspace(0,1,100)
Travel_function = draw_function_on_2x2_grid(x)
Jawaban bagus dari @unwind. Namun itu tidak dapat menangani angka negatif ekstrim (melempar OverflowError).
Peningkatan saya:
def sigmoid(x):
try:
res = 1 / (1 + math.exp(-x))
except OverflowError:
res = 0.0
return res
Tensorflow juga mencakup sigmoid
fungsi:
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
Versi stabil fungsi logistic sigmoid.
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)
Satu liner ...
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
atau numpy array
:Jawaban teratas adalah metode yang dioptimalkan untuk perhitungan titik tunggal, tetapi ketika Anda ingin menerapkan metode ini ke seri panda atau array numpy, itu membutuhkan apply
, yang pada dasarnya adalah untuk loop di latar belakang dan akan beralih ke setiap baris dan menerapkan metode. Ini cukup tidak efisien.
Untuk mempercepat kode kita, kita dapat menggunakan vektorisasi dan siaran numpy:
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
Atau dengan pandas Series
:
x = pd.Series(np.arange(-5,5))
np.divide(1, 1+np.exp(-x))
Anda dapat menghitungnya sebagai:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
atau konseptual, lebih dalam dan tanpa impor:
def sigmoid(x):
return 1 / (1 + 2.718281828 ** -x)
atau Anda dapat menggunakan numpy untuk matriks:
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)
Kode di atas adalah fungsi sigmoid logistik di python. Jika saya tahu itu x = 0.467
, Fungsi sigmoid F(x) = 0.385
,. Anda dapat mencoba mengganti nilai x yang Anda tahu dalam kode di atas, dan Anda akan mendapatkan nilai yang berbeda F(x)
.
sigmoid = lambda x: 1 / (1 + math.exp(-x))