scipy中优化和拟合相关内容主要在optimize这个类中

(1)最小化(求最小值)minimize(fun,x0,args)

def func2(x,l):#多元函数
    return l*x[0]**2-3*x[1]**2+8
min_value2=optimize.minimize(func2,np.array([3,4]),args=(3,))
print(min_value2.x)#最小值点
print(min_value2.fun)#最小值

#在指定范围内求最小值
min_value2=optimize.minimize(func2,np.array([3,4]),args=(5,),bounds=[(0,4),(0,4)])
print(min_value2.x)#最小值点
print(min_value2.fun)#最小值

它的基本用法需要传入上个参数,fun是要优化函数的形式,x0是x的初值,应该为array类型,args传入的是一个元组,里面是被优化函数除x以外的参数的值,如有需要还可以传入bounds参数,用以限制x的取值范围,在制定范围内求最小值。

另外求最小值的函数还有fmin()和fmin_powell()函数,具体使用如下:

def func3(x,k):#一元函数
    return k*x**2+2*x-6
min_value3=optimize.fmin(func3,np.array(3),args=(4,),xtol=1e-6,ftol=1e-6)
print(min_value3)#最小值点
print(func3(min_value3,4))#最小值

#fmin_powell()无约束优化方法,无需求导
se=optimize.fmin_powell(func3,np.array(3),args=(4,),xtol=1e-6,ftol=1e-6)
print(se)#最小值点
print(func3(se,4))

前三个参数与minimize一致,需要注意的是,这两个函数求最小值采用的非求导方式,而是迭代方式,xtol 和ytol 是迭代终止条件,当x变化小于xtol y变化小于ytol时停止,其只输出最小值点,最小值需要传入函数计算。

(2)拟合

最小二乘法(leastsq)拟合

#直线拟合
xdata=np.array([0,1,2,3,4,5])
ydata=3*xdata+np.random.randn(6)
def func4(p,x):
    k,b=p#一元函数
    return k*x+b
#定义误差
def err(p,x,y):
    return func4(p,x)-y
#最小二乘法
p0 = [1, 20]#初值
Para =optimize.leastsq(err, np.array(p0), args=(xdata, ydata))
k, b = Para[0]
print("k=", k, "b=", b)
#可视化
plt.plot(xdata, ydata, 'o')
plt.plot(xdata, func4([k, b], xdata))
plt.show()

leastsq()函数需要传入至少三个参数,第一个参数是误差函数,其为目标拟合函数值(需要自己根据数据设置)-实际值,第二个参数是,目标拟合函数里面除x 之外的参数的初值,一般随便给,第三个参数是有要拟合的数据 x y 构成的元组。

自定义拟合(curve_fit)

def fuc(x,a,b,c):#目标拟合曲线
    return a*np.exp(-b*x)+c
xdata=np.linspace(0,4,50)
ydata=fuc(xdata,2.5,1.3,0.5)
y_ol=ydata+0.2*np.random.normal(size=len(xdata))
#拟合
popt_1, pcov =optimize.curve_fit(fuc, xdata, y_ol)
print("m",popt_1)
plt.plot(xdata,fuc(xdata,*popt_1))
plt.plot(xdata,y_ol,'o')
plt.show()

curve_fit()函数至少要传入三个参数,第一个是fun 目标拟合曲线形式,需自己根据数据定义,xdata是要拟合数据x值,y_ol是要拟合数据y值。同时其也可以限定参数范围拟合

#限定参数范围:0<=a<=3, 0<=b<=1, 0<=c<=0.5
#popt_2, pcov = curve_fit(func, xdata, ydata, bounds=(0, [3., 1., 0.5]))

(3)评价拟合效果

这里求多个指标进行评价,y_pred为根据拟合曲线计算值,y_true是实际值

def get_pingjia(y_pred,y_true):
    n=y_true.size

    #计算方差
    SSE=np.sum((y_pred-y_true)**2)
    #计算均方误差
    MSE=SSE/n
    #计算均方根误差 接近0越好
    RMSE = np.sqrt(MSE)
    #计算R方
    R2=1-SSE/np.sum((y_true-np.mean(y_true))**2)

    return SSE,MSE,RMSE,R2

print(get_pingjia(y_pred,y_ture))

(4)求解非线性方程组

#eg求解
"""
f1(x1,x2,x3)=0
f2(x1,x2,x3)=0
f3(x1,x2,x3)=0
具体例
5x1+3=0
4x0^2-2sin(x1x2)=0
x1*x2-1.5=0
"""
#定义函数形式
def fc(x):
    x0,x1,x2=x
    return np.array([5*x1+3,4*x0**2-2*np.sin(x1*x2),x1*x2-1.5])

#求解
res=optimize.fsolve(fc,[1,1,1])#x0 初值
print(res)

通过这个例子可以看出fsolve需要两个参数 第一个是要解的方程组形式,需要右边都化为0 左边就是传入的参数,第二个是解的初值一般随便给。

#如果已知的的是 这些方程的雅可比矩阵
#则传入雅可比矩阵,并且在fsolve 后传入参数:fprime=jacobian
#什么是雅可比矩阵?
#f1 分别对 x0 x1 x2求导为第一行
#f2 分别对 x0 x1 x2求导为第二行
#f3 分别对 x0 x1 x2求导为第三行
#这样就构成了雅可比矩阵

更多推荐