使用参数作为 scipy.optimize.curve_fit 的边界

问题描述

我想知道是否可以为 curve_fit() 中的参数设置边界,使得边界依赖于另一个参数。例如,假设我想将一条线的斜率设置为大于截距。

def linear(x,m,b):
    
    return lambda x: (m*x) + b

def plot_linear(x,y):

    B = ([b,-np.inf],[np.inf,np.inf])
    p,v = curve_fit(linear,x,y,bounds = B)

    xs = np.linspace(min(x),max(x),1000)
    
    plt.plot(x,'.')
    plt.plot(xs,linear(xs,*p),'-')

我知道这不起作用,因为参数 b 在边界中调用之前没有定义,但我不确定是否有办法使这个工作?

解决方法

我们总是可以重新参数化 w.r.t.具体的曲线拟合问题。例如,如果您想拟合 y=mx+b s.t. m >= b,它可以用另一个参数 k 重写为 m=b+k*k ,我们可以用参数 b,k 现在如下:

def linear(x,m,b):    
    return m*x + b

def linear2(x,k,b):   # constrained fit,m = b + k**2 >= b 
    return (b+k**2)*x + b

def plot_linear(x,y):    
    p,v = curve_fit(linear,x,y)
    print(p)    
    # [3.1675609  6.01025041]
    p2,v2 = curve_fit(linear2,y)
    print(p2)
    # [2.13980283e-05 4.99368661e+00]
    xs = np.linspace(min(x),max(x),1000)        
    plt.plot(x,y,'.')
    plt.plot(xs,linear(xs,*p),'r-',label='unconstrained fit')
    plt.plot(xs,linear2(xs,*p2),'b-',label='constrained (m>b) fit')
    plt.legend()

现在让我们在以下数据上拟合曲线,同时使用约束和无约束拟合函数(注意无约束最优拟合的斜率将小于截距)

x = np.linspace(0,1,100)
y = 3*x + 5 + 2*np.random.rand(len(x))
plot_linear(x,y)

enter image description here