我试图拟合双极S形曲线 - 我希望得到以下曲线:
但是我需要它移动和伸展。我有以下输入:
x[0] = 8, x[48] = 2
因此超过48个周期我需要使用双极S型函数从8下降到2来近似一个很好的平滑衰减。有什么想法我如何得出适合这些参数的曲线?
这是我到目前为止所做的,但我需要改变sigmoid函数:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
plt.plot([sigmoid(float(z)) for z in range(1,48)])
答案 0 :(得分:2)
你可以像这样重新定义sigmoid函数
def sigmoid(x, a, b, c, d):
""" General sigmoid function
a adjusts amplitude
b adjusts y offset
c adjusts x offset
d adjusts slope """
y = ((a-b) / (1 + np.exp(x-(c/2))**d)) + b
return y
x = np.arange(49)
y = sigmoid(x, 8, 2, 48, 0.3)
plt.plot(x, y)
Severin的答案可能更强大,但如果你想要的只是一个快速而肮脏的解决方案,这应该没问题。
In [2]: y[0]
Out[2]: 7.9955238269969806
In [3]: y[48]
Out[3]: 2.0044761730030203
答案 1 :(得分:1)
来自通用双极S形函数:
f(x,m,b)= 2/(1+exp(-b*(x-m))) - 1
有两个参数和两个未知数 - 转换m
和比例b
你有两个条件:f(0)= 8,f(48)= 2
采取第一个条件,表达b
vs m
,连同第二个条件写非线性函数来解决,然后使用SciPy中的fsolve
以数字方式解决它,然后恢复b
和m
。
此处通过类似的方法问答:How to random sample lognormal data in Python using the inverse CDF and specify target percentiles?
答案 2 :(得分:1)
或者,您也可以使用curve_fit
,如果您有两个以上的数据点,这可能会派上用场。输出如下:
如您所见,图表包含所需的数据点。我使用了@ lanery的功能;你当然可以选择你喜欢的任何功能。这是包含一些内联注释的代码:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def sigmoid(x, a, b, c, d):
return ((a - b) / (1. + np.exp(x - (c / 2)) ** d)) + b
# one needs at least as many data points as parameters, so I just duplicate the data
xdata = [0., 48.] * 2
ydata = [8., 2.] * 2
# plot data
plt.plot(xdata, ydata, 'bo', label='data')
# fit the data
popt, pcov = curve_fit(sigmoid, xdata, ydata, p0=[1., 1., 50., 0.5])
# plot the result
xdata_new = np.linspace(0, 50, 100)
plt.plot(xdata_new, sigmoid(xdata_new, *popt), 'r-', label='fit')
plt.legend(loc='best')
plt.show()