梯度下降法和牛頓迭代法的Python實現原理及比較

2021-10-04 19:22:28 字數 3766 閱讀 5667

偏導數:就是對函式的兩個未知數求微分

然後得到的函式

例如乙個函式為y=x12+x22+2x1x2

d(y)/d(x1)=2x1+2x2

d(y)/d(x2)=2x2+2x1

學習率:

也稱為迭代的步長,優化函式的梯度是不斷變化的,有時候變化很大,有時候變化很小,所以需要將每次的梯度變化控制在乙個合適的範圍內。

梯度:梯度其實就是函式的變化率,在多元函式中,梯度變為了向量,有了變化的方向。

梯度的方向表示的是函式增加最快的方向。

梯度下降法求解,首先就要求得所給定函式的偏導數,即y對x1和x2的微分函式,規定學習率,給定一組初始值,然後計算梯度函式,使用迭代公式更新迭代一次後的函式未知數的值,然後計算出迭代後的梯度函式,將原梯度函式的值與迭代後的梯度函式的值的差值進行判斷,判斷差值是否收斂,若收斂,就停止演算法,否則,就重複之前的迭代。

1、首先匯入需要的庫並設定字符集

import numpy as np

import matplotlib as mpl

import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import axes3d

# 設定字符集,防止中文亂碼

mpl.rcparams['font.sans-serif'] = [u'simhei']

mpl.rcparams['axes.unicode_minus'] = false

2、對函式用matlab進行顯示

#定義要求極值的函式表示式

def f2(x1,x2):

return x1**2+2*x2**2-4*x1-2*x1*x2

x1 = np.arange(0,5,0.1)

x2 = np.arange(0,5,0.1)

x1, x2 = np.meshgrid(x1, x2) # 生成xv、yv,將x1、x2變成n*m的矩陣,方便後面繪圖

y = np.array(list(map(lambda t : f2(t[0],t[1]),zip(x1.flatten(),x2.flatten()))))

y.shape = x1.shape

%matplotlib inline

#作圖fig = plt.figure(facecolor='w')

ax = axes3d(fig)

ax.plot_su***ce(x1,x2,y,rstride=1,cstride=1,cmap=plt.cm.jet)

ax.set_title(u'$ y = x1^2 +2x2^2-4x1-2x1x2 $')

plt.show()

顯示為:

3、用梯度下降法求解函式極值,要求對應x1和x2的偏導數

#函式

def f2(x, y):

return x**2+2*y**2-4*x-2*x*y

## 求兩個未知數對於函式的偏導數

def hx1(x, y):

return 2*x-2*y-4

def hx2(x, y):

return -2*x+4*y

4、定義初值和學習率,然後運用陣列儲存梯度下降後所經過的點

#學習率

alpha = 0.1

#儲存梯度下降經過的點

gd_x1 =

gd_x2 =

gd_y =

# 定義y的變化量和迭代次數

y_change = 0-f2(x1,x2)

iter_num = 0

5、判斷前後兩次迭代的y值的差值,如果很小表明函式已經收斂了,就可以得出最後的極小值了,然後用matlab顯示出所經過的點,我的圖上經過的點在背面有點兒看不清晰

while(y_change > 1e-10) :

tmp_x1 = x1 - alpha * hx1(x1,x2)

tmp_x2 = x2 - alpha * hx2(x1,x2)

tmp_y = f2(tmp_x1,tmp_x2)

y_change =f2(x1,x2)-tmp_y

x1 = tmp_x1

x2 = tmp_x2

iter_num =iter_num+1

print(u"最終結果為:(%.5f, %.5f, %.5f)" % (x1, x2, f2(x1,x2)))

print(u"迭代過程中x的取值,迭代次數:%d" % iter_num)

print(gd_x1)#列印出迭代的x1的值

# 作圖

fig = plt.figure(facecolor='w',figsize=(20,18))

ax = axes3d(fig)

ax.plot_su***ce(x1,x2,y,rstride=1,cstride=1,cmap=plt.cm.jet)

ax.plot(gd_x1,gd_x2,gd_y,'ko-')

ax.set_xlabel('x')

ax.set_ylabel('y')

ax.set_zlabel('z')

ax.set_title(u'函式;\n學習率:%.3f; 最終解:(%.3f, %.3f, %.3f);迭代次數:%d' % (alpha, x1, x2, f2(x1,x2), iter_num))

plt.show()

牛頓迭代法是一種線性化方法,基本思想就是將非線性方程f(x)=0逐步歸結為某種線性方程來求解。假設f(x)=0有乙個近似根為xk,那麼f(x)就近似等於f(xk)+f』(xk)(x-xk),令該函式為0,就可以求的迭代公式為

xk+1=xk-f(xk)/f』(xk) (k=0,1,2,…)

然後迭代到前後兩個值的差值非常小時,就可以得到f(x)=0的根。

通俗來講就是,給函式乙個x值,然後求得函式在這個點上的切線與x軸的交點,然後將這個交點的x值做為乙個新的初始值再求切線與x軸的交點,直至前後兩個x值的差值非常小,就可以判斷為這個值為函式等於0時的解。

所以用牛頓法解方程時,要先求得函式的微分方程,寫出迭代公式,然後給定乙個初值,將值帶入到迭代公式中,一直求解,直到達到我們所想要的精度。

牛頓迭代法的python實現**:

方程為y=2x3+5x2-x+6

求解y=0的解

#方程為2*x^3+5*x^2-x+6=0

#設初值

x0=-2.5

#為迭代公式

x1=x0-(2*x0*x0*x0+5*x0*x0-x0+6)/(6*x0*x0+10*x0-1)

while abs(x1-x0)>1e-5:

x0=x1

x1=x0-(2*x0*x0*x0+5*x0*x0-x0+6)/(6*x0*x0+10*x0-1)

print(x1)

梯度下降法和牛頓迭代法都要用到迭代公式,並更新x的值,不同的是牛頓迭代法是只有乙個未知數,而梯度下降法中未知數的個數不止乙個。兩種方法都要求這個函式可以微分。牛頓迭代法,有乙個很大的缺陷就是你得大概清楚方程為0的解在哪個範圍,不然隨便乙個初值,可能要成千上萬次迭代,才能得到最終的值,太過於麻煩。所以可以設定一最大個迭代次數,超過了最大迭代次數,判定牛頓迭代法不可應用於該方程的求解,換為其他的方法。

參考部落格:

梯度下降法和牛頓下降法

泰勒公式可以表示為 f boldsymbol boldsymbol f boldsymbol boldsymbol boldsymbol frac boldsymbol boldsymbol boldsymbol o boldsymbol tag 在 2 中 boldsymbol x 1,x n b...

梯度下降法與牛頓法

梯度下降法,是迭代演算法。在求最值時,常常用到。bp網路中,最小化 誤差cost function,求解對應網路中的weights,即可用梯度下降法來更新weights.梯度下降法基本思想 給定乙個函式 f 假設求 f 最大值 最小值 初始化函式上的乙個點,對該點求導,該點往導數的方向 反方向 移動...

梯度下降法與牛頓法

梯度 f 在 0 處的梯度表示f 在點 0 處函式值變化最快的方向。對於凸函式f 來說,沿著負梯度方向尋找可以找到函式的極小值 k 1 k f k k 表示第 k步迭代,表示修正因子 步長 因為梯度方向變化最快,只在區域性有效 如果對於多維情形,表示為 k 1 k f k 其中 k k1,k2,kn...