我有一个适合一组点的对数函数
def log_func(x, a, b):
return a * np.log(x) + b
popt, pcov = curve_fit(log_func, x, yn)
这导致如下图 - Plotted Curve
但是,系统有一些限制,范围应该固定在0到100之间。我特意在这些边界处传递了点(即x = np.array([3200 ... other points ... 42000 ])
和y = np.array([0 ... other points ... 100 ] )
,但显然曲线没有必须修复这些价值观。
我已经读过我可以添加参数的边界(这里是a
和b
),但有没有办法通过专门强制曲线通过两个端点来约束输出。或者,我是否必须对函数引入某种极端惩罚,以产生强制结果在0到100之间的参数?
答案 0 :(得分:0)
您可以将曲线拟合问题表示为约束优化问题,并使用scipy.optimize.minimize
来解决它。考虑到最优a
应为正的数据集,可以得出拟合函数范围的要求等于约束a*np.log(3200)+b>=0
和a*np.log(42000)+b<=100
。
可以如下进行(我使用了简单的数据集)。
from scipy.optimize import minimize
x = np.array([3200, 14500, 42000])
yn = np.array([0, 78, 100])
def LS_obj(p):
a, b = p
return ((log_func(x, a, b) - yn)**2).sum()
cons = ({'type': 'ineq', 'fun': lambda p: p[0] * np.log(3200) + p[1]},
{'type': 'ineq', 'fun': lambda p: 100 -p[0] * np.log(42000) - p[1]})
p0 = [10,-100] #initial estimate
sol = minimize(LS_obj,p0 ,constraints=cons)
print(sol.x) #optimal parameters
[ 36.1955 -285.316 ]
下图比较了curve_fit
和minimize
解决方案。正如所料,minimize
解决方案在所需范围内。