通过约束来最小化以求解系数

时间:2016-11-26 20:19:48

标签: python-3.x numpy scipy

我的目标是根据y=a*x**2 + b *x+c进行二次曲线拟合,并在两个变量变量a<0c<=0和约束2*a*x+b >=0上进行边界。简而言之,我希望拟合在y(x = 0)<= 0的第一象限中是单调递增函数。我的示例代码包含使用scipy.optimize.minimize函数的三个试验:

(1)我没有指定jacobian:在常规数据上工作得很好。

(2)指定jacobian:甚至无法预测常规数据:jacobian定义的一些问题。

(3)应用约束:约束定义引发错误。

我可以引起你的注意,让这个程序运行吗?

import numpy as np
from scipy.optimize import minimize

# scattr-irregular
#xip=np.array([ 0.02237461, 0.0983837 , 0.25707382, 0.56959641, 1.33419197, 4.95835927])
#yip=np.array([0.20085822, 0.23583258, 0.28996988, 0.36350284, 0.47981232, 0.67602165] )
#scatter- regular
xip=np.array([2.12E-01,3.43E-01,5.01E-01,7.01E-01,9.73E-01,1.15E+00,1.34E+00,1.41E+00])
yip=np.array([5.94E-02,1.28E-01,2.05E-01,2.90E-01,3.86E-01,4.34E-01,4.78E-01,4.93E-01])

import  matplotlib.pyplot as plt
plt.scatter(xip,yip, label = 'scatter')

xipfit=np.linspace(0, max(xip), 200)

#minimize.scipy
def func(abc,x,y):
    """ Objective function """
    return ((abc[0]*x**2+abc[1]*x**1+abc[2]-y)**2).sum()

def func_deriv(abc, x,y):
    """ Derivative of objective function """
    dfda = 2*(abc[0]*x**2+abc[1]*x**1+abc[2]-y)*x**2
    dfdb = 2*(abc[0]*x**2+abc[1]*x**1+abc[2]-y)*x**1
    dfdc = 2*(abc[0]*x**2+abc[1]*x**1+abc[2]-y)* 1
    return np.array([ dfda.sum(), dfdb.sum(), dfdc.sum() ])  

#2*a*x+b >=0    
cons = ({'type': 'ineq',
         'fun' : lambda abc: np.array( [ 2*abc[0]*xip.sum()+abc[1] ]) ,
         'jac' : lambda abc: np.array([2*xip.sum(),  1,  0])\
         })    
######################################################    
###1. wO jacobian input; works for specific data.    
coeffs_WOjac= minimize(func, x0=[-1.0,1.0,-1], args=(xip,yip),\
                jac=False,\
                method='SLSQP',\
                bounds=((-1e6,0),(0,1e6),(-1e6,0)),\
                options={'disp': True})
yipfit_WOjac = coeffs_WOjac.x[0]*xipfit**2\
                +coeffs_WOjac.x[1]*xipfit \
                +coeffs_WOjac.x[2]
print(coeffs_WOjac)                
plt.plot(xipfit,yipfit_WOjac,label='WOjac', linewidth=4)
######################################################                
###2. wit jacobian input: fit is not correct. jacobain correct ?             
coeffs_Wjac= minimize(func, x0=[-1.0,1.0,-1], args=(xip,yip),\
                jac=func_deriv,\
                method='SLSQP', \
                bounds=((-1e6,0),(-1e6,1e6),(-1e6,0)),\
                options={'disp': True})
yipfit_Wjac = coeffs_Wjac.x[0]*xipfit**2\
                +coeffs_Wjac.x[1]*xipfit \
                +coeffs_Wjac.x[2]
print(coeffs_Wjac)
plt.plot(xipfit,yipfit_Wjac,label='Wjac', color= 'red',linewidth=1.5)
######################################################                
###3. wO jacobian and constraints  
coeffs_WOjac_constr = minimize(func, x0=[-1.0,1.0,-1], args=(xip,yip),\
                jac=False,\
                constraints=cons,\
                method='SLSQP', 
                bounds=((-1e6,0),(-1e6,1e6),(-1e6,0)),\
                options={'disp': True})                
yipfit_WOjac_constr = coeffs_WOjac_constr.x[0]*xipfit**2\
                +coeffs_WOjac_constr.x[1]*xipfit \
                +coeffs_WOjac_constr.x[2]

plt.plot(xipfit,yipfit_WOjac_constr,label='Wjac_constr', linewidth=2)


plt.legend(loc='upper left')
plt.grid()                

我同时尝试在此post中尝试lmfit功能。因此,虽然也引起了对这篇文章的关注。

编辑:代码已重新格式化为取消/评论个别方法。

edit2:正确定义雅可比行列式。

编辑3:工作代码。纳入评论的变化。在cons子程序中删除了xip,yip。

0 个答案:

没有答案