一、使用牛頓法可以用來求解的根。
具體原理如下:
首先初始化一個點爲,然後求解在處的切線,設切線爲,處的斜率爲 ,則切線爲。
此切線與x軸交於,此時在x軸上的點爲,然後在處求切線,交x軸爲。
不斷重複此步驟最終得到的解。
因爲我們想要求解的根。因此我們讓。可以得到得到此公式
由上式可以得到簡化的迭代公式,使用此公式不斷的進行迭代。然後通過設置閾值得到數值解。
求此函數
具體代碼如下:
#實現f = x**2+2*x - 0.2的根
import numpy as np
#定義fx
def f(x):
f = x**2+2*x - 0.2
return f
#定義導數
def df(x):
df = 2*x+2
return df
# f:函數
# df:導數
# x:zip變量
# err:誤差,用來判斷是否滿足求解要求
def newtons(f, df, x, err):
loop = 1
x_i = float(x)
e_tmp = err + 1
while e_tmp > err:
#超出循環次數
if loop > 1000:
print('cycles exceeded')
break
print('######loop'+str(loop))
f_tmp = f(x_i)
df_tmp = df(x_i)
print('xi = ' + str(x_i) + ',f = ' + str(f_tmp) + ',df = ' + str(df_tmp))
x_i = x_i - (f_tmp/df_tmp)
e_tmp = abs(0 - f(x_i))
print('err = ' + str(e_tmp))
loop = loop + 1
return x_i
x = newtons(f, df, 3, 0.01)
print(x)
二、牛頓法也被用於求函數的極值。
由於函數取極值的點處的導數值爲零,故可用牛頓法求導函數的零點,其迭代式爲
具體代碼如下:
#實現f = x**2+2*x - 0.2的最小值
import numpy as np
#定義fx
def f(x):
f = x**2+2*x - 0.2
return f
#定義導數
def df(x):
df = 2*x+2
return df
#定義二階導數
def ddf(x):
df = 2
return df
# f:函數
# df:導數
# x:zip變量
# err:誤差,用來判斷是否滿足求解要求
def newtons(df, ddf, x, err):
loop = 1
x_i = float(x)
e_tmp = err + 1
while e_tmp > err:
#超出循環次數
if loop > 1000:
print('cycles exceeded')
break
print('######loop'+str(loop))
df_tmp = df(x_i)
ddf_tmp = ddf(x_i)
print('xi = ' + str(x_i) + ',df = ' + str(df_tmp) + ',ddf = ' + str(ddf_tmp))
x_i = x_i - (df_tmp/ddf_tmp)
e_tmp = abs(df(x_i) - df_tmp)
print('err = ' + str(e_tmp))
loop = loop + 1
return x_i
x = newtons(df, ddf, 3, 0.01)
print(x)
多元函數:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def Fun(x,y):#原函數
return x-y+2*x*x+2*x*y+y*y
def PxFun(x,y):#偏x導
return 1+4*x+2*y
def PyFun(x,y):#偏y導
return -1+2*x+2*y
#二次偏x導
def PPxFun(x,y):
return 4
#二次偏y導
def PPyFun(x,y):
return 2
#初始化
fig=plt.figure()#figure對象
ax=Axes3D(fig)#Axes3D對象
X,Y=np.mgrid[-2:2:40j,-2:2:40j]#取樣並作滿射聯合
Z=Fun(X,Y)#取樣點Z座標打表
ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap="rainbow")
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
#梯度下降
x=0
y=0#初始選取一個點
tag_x=[x]
tag_y=[y]
tag_z=[Fun(x,y)]#三個座標分別打入表中,該表用於繪製點
new_x=x
new_y=y
Over=False
while Over==False:
new_x-=PxFun(x,y)/PPxFun(x,y)
new_y-=PyFun(x,y)/PPyFun(x,y)#分別作梯度下降
if Fun(x,y)-Fun(new_x,new_y)<7e-9:#精度
Over=True
x=new_x
y=new_y#更新舊點
tag_x.append(x)
tag_y.append(y)
tag_z.append(Fun(x,y))#新點三個座標打入表中
#繪製點/輸出座標
ax.plot(tag_x,tag_y,tag_z,'r.')
plt.title('(x,y)~('+str(x)+","+str(y)+')')
plt.show()