python fsolve_Python-optimize.leastsq()和optimize.fsolve()
利用leastsq()函數對數據進行最小二乘算法擬合。
先來看個簡單的線性的例子:
#假設要擬合的數據點(xdata,ydata)如下
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
xdata=np.array([8.19,2.72,6.39,8.71,4.7,2.66,3.78])
ydata=np.array([7.01,2.78,6.47,6.71,4.1,4.23,4.05])
#先作圖看下大概的(xdata,ydata)的形狀
plt.plot(xdata, ydata, 'b.', label='data')
#plt.show()
#可得形狀如下
#通過散點(xdata,ydata)的形狀,可使用線性函數y=k*x+b來擬合數據點。首先定義殘差函數y-f(x)
def residual(p):
k,b=p
return ydata-(k*xdata+b)
result=optimize.leastsq(residual,[0,0])
#leastsq函數的調用形式:scipy.optimize.leastsq(func, x0, args=(), Dfun=None, full_output=0, col_deriv=0, ftol=1.49012e-08, xtol=1.49012e-08, gtol=0.0, maxfev=0, epsfcn=None, factor=100, diag=None)
#leastsq函數中的func和x0為必須的參數,其中func為殘差函數y-f(x)(該例為residual函數,即ydata-(k*xdata+b));x0為待定參數估計的初始值,可以驗證,leastsq函數對初始估計值不敏感,但是最好還是基于經驗取一個大概的值,不然結果會失真,這一點在后面會繼續講到。
#由于在該例的residual函數中,p為兩個待定參數k和b的值,所以該例中leastsq函數的x0位置要傳入一個二維的列表,而且不能寫成r=optimize.leastsq(residual,0,0)。如果寫成r=optimize.leastsq(residual,0,0),那么后面的0會傳入leastsq函數的args這個參數中。這里需要注意位置的對應關系。
#所以無論residual函數中有多少個待定參數(該例為k和b兩個),都寫成一個類似于該例一樣的數組p,然后在調用leastsq函數時,用一個待定參數初始值的估計值組成的數組(該例為[0,0])傳入leastsq函數中。
print (result[0])
#最后將數據點和擬合曲線放在一張圖中
ydatafit=result[0][0]*xdata+result[0][1]
#k=result[0][0]; b=result[0][1]
plt.plot(xdata,ydatafit, 'r-', label='fit: a=%5.3f, b=%5.3f' % tuple(result[0]))
plt.show()
#再來看個數據稍微復雜的例子:
#假設要擬合的數據點(xdata,ydata)如下,這里通過函數加入噪聲來形成要擬合的數據點
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
def func(x):
return 2.5 * np.exp(-1.3 * x) + 0.5
xdata = np.linspace(0, 4, 50)
y=func(xdata)
ydata=y+0.2*np.random.normal(size=xdata.size)
#至此,得到了要擬合的數據點(xdata,ydata),如下圖所示
plt.plot(xdata, ydata, 'b.', label='data')
#plt.show()
'''
#這里我們首先以先知者的角色來以形式為y=a* np.exp(-b?* x) +?c的函數來擬合數據:
def residual(p):
a,b,c=p
return ydata-(a*?np.exp(-b?*?xdata)?+?c)
#注意這里不要寫成returnydata-a*?np.exp(-b?*?xdata)?+?c
result=optimize.leastsq(residual,[1,1,1])
print (result[0])
#最后將數據點和擬合曲線放在一張圖中
a,b,c=result[0]
ydatafit=a*?np.exp(-b?*?xdata)?+?c
plt.plot(xdata,ydatafit, 'r-', label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(result[0]))
plt.show()
'''
#以上,我們是以一個先知者的角色來選取函數y=a* np.exp(-b?* x) +?c來擬合,因為數據點是通過這個函數再加入一些噪聲形成的。正常地,我們應該通過觀測數據點的分布圖,然后想到可以利用類似于一個指數函數的形式y=a* x**b?+?c來擬合。過程如下
def residual(p):
a,b,c=p
return ydata-(a* xdata**b?+?c)
result=optimize.leastsq(residual,[1,1,1])
print (result[0])
#最后將數據點和擬合曲線放在一張圖中
a,b,c=result[0]
ydatafit=a*xdata**b+c
plt.plot(xdata,ydatafit, 'r-', label='fit: a=%5.3f, b=%5.3f, c=%5.3f'?% tuple(result[0]))
plt.show()
#這里,如果我們改變待定參數的初始估計值,如改為result=optimize.leastsq(residual,[1,100,1]),則形狀如下
#顯然不是我們想要的結果,所以說雖然leastsq()函數對待定參數的初始估計值不敏感,但是估計值也應該在合理范圍中。如果出現類似于上圖這種不合理的結果,則再次調整初始估計值則可。
總結一下leastsq()函數的使用:1.首先對于給定數據點的散點形狀先進行一個分析,大致判斷一個函數的形式。2.寫成這個函數的殘差函數y-f(x)。3.傳入兩個必須的參數,即殘差函數和待定參數的初始估計值進入leastsq()函數中進行擬合,注意待定參數的初始值要取得較為合理。
#講到將殘差函數傳入某函數中進行分析,optimize.fsolve()函數也是需要傳入殘差函數來計算的,該函數主要是來計算非線性方程組
#optimize.fsolve()函數的調用形式為:scipy.optimize.fsolve(func, x0, args=(), fprime=None, full_output=0, col_deriv=0, xtol=1.49012e-08, maxfev=0, band=None, epsfcn=None, factor=100, diag=None),其中前兩個參數func和x0是必須的參數,func為殘差函數,x0為待求參數的初始估計值。
#例子如下,要求的非線性方程組如下圖
import numpy as np
from scipy import optimize
#定義殘差函數
def residual(p):
x0,x1,x2 = p
return[5*np.cos(x1)+3*x0,4*x0**2-2*np.sin(x1*x2),x1*np.sin(x2)-1.5]
result = optimize.fsolve(residual,[1,1,1])
print (result)
#result=[0.06717167 1.61111025 1.94435388]
#此外,optimize.fslove()函數提供了fprime參數(見該函數的調用形式的第三個參數)來傳遞未知數的雅各比矩陣從而加速計算,傳遞的雅各比矩陣每i行是第i個方程分別為x0、x1、x2...的導數。如求解上例的代碼可以改寫為:
import numpy as np
from scipy import optimize
def residual(p):
x0,x1,x2 = p
return[5*np.cos(x1)+3*x0,4*x0**2-2*np.sin(x1*x2),x1*np.sin(x2)-1.5]
def func(p):
x0,x1,x2 = p
return[[3, -5*np.sin(x1), 0], [8*x0, -2*x2*np.cos(x1*x2), -2*x1*np.cos(x1*x2)], [0, np.sin(x2), x1*np.cos(x2)]]
#如[3, -5*np.sin(x1), 0]的三個數則為第一個方程5*np.cos(x1)+3*x0分別對x0、x1、x2的導數,其余類似
result = optimize.fsolve(residual,[1,1,1], fprime=func)
print (result)
#result=[0.06717167 1.61111025 1.94435388]
總結
以上是生活随笔為你收集整理的python fsolve_Python-optimize.leastsq()和optimize.fsolve()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 生命之花_python股票
- 下一篇: 体检前如何快速降血压?