採用數值計算極值的基礎思想:
選擇一個初始點,計算該點的導數,然後通過導數和步長推進到下一個點,直到兩個點之差很小爲止(達到收斂條件)。
以函數 y = x**2 + x 爲例:
- 選定一個初始值,例如X0=2
- 計算在該點的導數,f’(X0)=6
- 按照下列公式調整 x 的新值: X1 = X0 - αf’(X0)
▪ α稱爲步進係數,用來控制步長大小。例如設置爲0.1, 0.001等
▪ f’(X0)主要用來控制步長的方向。在本例中是通過正負號來控制
▪ 注意,要與導數的方向相反(所以用減號),否則將會離極值點越來越遠
4)計算f(X1),並且與f(X1) 對比,根據某個規則來判斷是否已經收斂,例如:二者的差值小於某個臨界誤差,例如0.000001。如果尚未收
斂,則繼續進行上述循環 - 如果在指定循環次數(例如1000次)之後仍然沒有收斂,則可以認爲該函數沒有極值
注意:如果函數本身有多個極值點,那麼逼近法找到的是其中的一個,未必是最低的極值點
整體圖形樣式:
運行結果圖:
詳細代碼:
import numpy as np
import matplotlib.pyplot as plt
def targetFunc(x):
return x**2 + x
def gradientFunc(x):
return 2*x+1
listx = []
def gradientCal(guessX,targetFunc,gradientFunc,rating=0.1,tolent=0.000001):
'''
:param initX:猜測的點
:param targetFunc: 目標函數
:param gradientFunc: 導函數,梯度函數
:param rating: 步進係數
:param tolent: 收斂條件
:return: 返回極值點x的值
'''
newguessX = targetFunc(guessX) # 猜測點的實際值
gradientX = gradientFunc(guessX) # 猜測點的導數
newX = guessX - rating*gradientX # 獲取新的x值
newResult = targetFunc(newX) # 獲取新的x的值的實際值
subResult = np.abs( newResult - newguessX)
while subResult>tolent:
guessX = newX
newguessX=newResult
listx.append(guessX)
newX = newX - rating*targetFunc(newX)
newResult = targetFunc(newX)
subResult = np.abs(newguessX-newResult)
return guessX
if __name__ =='__main__':
print(gradientCal(2, targetFunc, gradientFunc))
x = np.arange(-10, 11, 1)
y = x**2+x
plt.plot(x, y)
plt.grid(linestyle='--')
plt.scatter(np.array(listx),np.array(listx)**2,s=20)
plt.show()
print(listx)
9.174537253959678e-06
[3.9, 1.9889999999999999, 1.3944879, 1.0605794596753588, 0.8420386346792953, 0.6869318649821086, 0.5710511397711179, 0.4813360853706168, 0.41003403412556416, 0.35221783979887933,
0.3045903151517325, 0.26485375762813607, 0.23135363057234812, 0.20286581727721265, 0.17846378156753623, 0.15743247127764406, 0.13921072584862104, 0.12335169064462895,
0.10949495762167723, 0.09734654728505221, 0.0866642575297149, 0.07724676242342574, 0.06892537995059304, 0.06155777115540038, 0.05502305812089828, 0.049217998616310876, 0.04405395761590027,
0.03945448673614789, 0.035353372410171814, 0.031693049075077404, 0.028423299231602136,
0.025500180914521, 0.02288513690040157, 0.0205442502612664, 0.018447618613260008, 0.01656882528868398, 0.014884490162670887, 0.013373886341663534, 0.012018611623909208, 0.01080230575898165,
0.009710406202112432, 0.008729936383040187, 0.007849321565810976, 0.0070582282243255275,
0.006347423543326308, 0.00570865221042984, 0.005134528118380891,
0.004618438968642957, 0.004154462073927953, 0.0037372899110227876, 0.0033621641863326055, 0.003024817352897759, 0.002721420665606144, 0.002448537986001611, 0.0022030846535745605,
0.001982290830018023, 0.0017836687993227432, 0.0016049837719519012, 0.0014442277974658882, 0.001299596438326202, 0.0011694678994033309, 0.0010523843439462243, 0.0009470351582708636,
0.0008522419548846771, 0.0007669451277612428, 0.0006901917945022188, 0.0006211249785806771, 0.0005589739010987077, 0.000503045265806626, 0.0004527154337720183,
0.000407423395268419, 0.0003666644563592759, 0.0003299845664409926, 0.00029697522081548444, 0.0002672688793057582, 0.00024053484810979782, 0.0002164755775975025, 0.00019482333367018263,
0.00017533720469003014, 0.00015780040990749227, 0.00014201787881980635, 0.00012781407403003527,
0.00011503103298327973, 0.00010352660647109684, 9.317287404816241e-05, 8.385471852490033e-05, 7.546854351102841e-05, 6.79211196098196e-05, 6.112854632098873e-05, 5.501531801897233e-05,
4.9513483548553424e-05, 4.456189003519277e-05, 4.010550245546914e-05, 3.6094791364789505e-05, 3.2485181944914184e-05, 2.9236558221718168e-05, 2.6312816921912686e-05,
2.3681465993287983e-05, 2.1313263312776027e-05, 1.918189155597912e-05, 1.7263665605884842e-05, 1.5537269241881344e-05, 1.3983518177019659e-05, 1.2585146805439633e-05, 1.1326616286303658e-05,
1.0193941828449642e-05, 9.174537253959678e-06]