亲爱的 Stackoverflow 社区, 我正在尝试构建自定义 sigmoid 形函数,因为我想在预处理过程中缩放数据。基本上,目标是获得一个 sigmoid 形函数,其输出从 0 到 1,并且仅采用正输入值(当输入接近 0 时,它接近 0;如果输入接近无穷大,则它接近 1)。关键是我希望能够随意选择“S”形状的拐点。我这里有一个小草图(原谅我的绘画技巧).
我想要选择的点被标记为 A 和 B,理想情况下它们位于将函数的线性部分与渐近线连接起来的曲线的中间位置。
这是我到目前为止的做法,我尝试将经典的逻辑函数拟合到两点,这是函数:
def sigmoid(x,x0, k):
y = 1 / (1 + np.exp(-k * (x - x0)))
return y
这里适合:
ydata = [0.1, 0.9]
xdata = [0.22, 1.34]
p0 = [np.median(xdata), 1] # this is a mandatory initial guess
from scipy.optimize import curve_fit
popt, pcov = curve_fit(sigmoid, xdata, ydata, p0=p0, method='dogbox')
这里 xdata 对应于 x 轴上的 A 和 B 点(我希望能够改变),ydata 是我想要将 A 和 B 映射到的任意点,以便使它们大致位于S曲线(我不知道是否有更好的方法)
然后是剧情
x = np.linspace(0, 5, 1000)
y = sigmoid(x,*popt)
plt.figure()
plt.plot(xdata, ydata, 'o', label='10th/90th percentiles')
plt.plot(x, y, label='sigmoid curve')
plt.ylim(0, 1.3)
plt.legend(loc='best')
plt.show()
产生数字:(忽略图例中的百分位数标签,这些是我的 A/b 点)
这不是一个很好的形状。特别是对于 0,过渡并不那么平滑和渐进。我想基本上将函数向右移动,以获得更平滑的曲线,同时仍然在拐点处截取我的 A、B 点。您对我如何实现这一目标有什么建议吗?在 sigmoid 函数的定义中添加偏移是行不通的,因为偏移量只会被曲线拟合覆盖。有没有更聪明的方法来解决这个问题,而不是我看不到的方法?
必须使用标准的 sigmoid 函数吗?您是否尝试过诸如平移绝对函数的平滑版本之类的东西?
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2,5,100)
a = 1
f = lambda x, eps : ((x-a)/np.sqrt((x-a)**2+eps) + 1)/2
plt.figure()
for eps in np.logspace(-3,0,4):
plt.plot(x,f(x,eps),"--", label = str(eps))
plt.legend()
plt.show()