參考連接python
梯度降低法(gradient descent),又名最速降低法(steepest descent)是求解無約束最優化問題最經常使用的方法,它是一種迭代方法,每一步主要的操做是求解目標函數的梯度向量,將當前位置的負梯度方向做爲搜索方向(由於在該方向上目標函數降低最快,這也是最速降低法名稱的由來)。算法
梯度降低,其實就是一個公式:網絡
![img](file:///E:\qq聊天記錄\1713176942\Image\C2C\2D65DC80FB67F846BD86FE94D6FF8215.jpg)app
步驟:dom
η爲學習率,ε爲收斂條件。梯度降低法屬於機器學習,本質爲:不斷迭代判斷是否知足條件,會用到循環語句。機器學習
st=>start: 首先設定一個較小的正數m,n; op=>operation: 求當前位置處的各個偏導數; 修改當前函數的參數值; cond=>condition: 參數變化量小於n sub1=>subroutine: 回退迭代 io=>inputoutput: 求得極小值 e=>end: 結束框 st->op->cond cond(yes)->io->e cond(no)->sub1(right)->op
Batch gradient descent::批量梯度降低算法(BGD),其須要計算整個訓練集的梯度,即:函數
其中η爲學習率,用來控制更新的「力度」/"步長"。學習
對於凸目標函數,能夠保證全局最優; 對於非凸目標函數,能夠保證一個局部最優。優化
速度慢; 數據量大時不可行; 沒法在線優化(即沒法處理動態產生的新樣本)。code
代碼實現
#引庫 #引入matplotlib庫,用於畫圖 import matplotlib.pyplot as plt from math import pow #圖片嵌入jupyter #matplotlib inline #爲了便於取用數據,咱們將數據分爲x,y,在直角座標系中(x,y)是點 x = [1,2,3,4,5,6] y = [13,14,20,21,25,30] print("打印初始數據圖...") plt.scatter(x,y) plt.xlabel("X") plt.ylabel("Y") plt.show() #超參數設定 alpha = 0.01#學習率/步長 theta0 = 0#θ0 theta1 = 0#θ1 epsilon = 0.001#偏差 m = len(x) count = 0 loss = [] for time in range(1000): count += 1 #求偏導theta0和theta1的結果 temp0 = 0#J(θ)對θ0求導的結果 temp1 = 0#J(θ)對θ1求導的結果 diss = 0 for i in range(m): temp0 += (theta0+theta1*x[i]-y[i])/m temp1 += ((theta0+theta1*x[i]-y[i])/m)*x[i] #更新theta0和theta1 for i in range(m): theta0 = theta0 - alpha*((theta0+theta1*x[i]-y[i])/m) theta1 = theta1 - alpha*((theta0+theta1*x[i]-y[i])/m)*x[i] #求損失函數J(θ) for i in range(m): diss = diss + 0.5*(1/m)*pow((theta0+theta1*x[i]-y[i]),2) loss.append(diss) #看是否知足條件 ''' if diss<=epsilon: break else: continue ''' print("最終的結果爲:") print("這次迭代次數爲:{}次,最終theta0的結果爲:{},最終theta1的結果爲:{}".format(count,theta0,theta1)) print("預測的最終迴歸函數爲:y={}+{}x\n".format(theta0,theta1)) print("迭代圖像繪製...") plt.scatter(range(count),loss) plt.show()
運行結果
Stochastic gradient descent:隨機梯度降低算法(SGD),僅計算某個樣本的梯度,即針對某一個訓練樣本 xi及其label yi更新參數:
逐步減少學習率,SGD表現得同BGD很類似,最後均可以有不錯的收斂。
更新頻次快,優化速度更快; 能夠在線優化(能夠沒法處理動態產生的新樣本);必定的隨機性致使有概率跳出局部最優(隨機性來自於用一個樣本的梯度去代替總體樣本的梯度)。
隨機性可能致使收斂複雜化,即便到達最優勢仍然會進行過分優化,所以SGD得優化過程相比BGD充滿動盪。
代碼實現
#引庫 #引入matplotlib庫,用於畫圖 import matplotlib.pyplot as plt from math import pow import numpy as np #圖片嵌入jupyter #matplotlib inline #爲了便於取用數據,咱們將數據分爲x,y,在直角座標系中(x,y)是點 x = [1,2,3,4,5,6] y = [13,14,20,21,25,30] print("打印初始數據圖...") plt.scatter(x,y) plt.xlabel("X") plt.ylabel("Y") plt.show() #超參數設定 alpha = 0.01#學習率/步長 theta0 = 0#θ0 theta1 = 0#θ1 epsilon = 0.001#偏差 m = len(x) count = 0 loss = [] for time in range(1000): count += 1 diss = 0 #求偏導theta0和theta1的結果 temp0 = 0#J(θ)對θ0求導的結果 temp1 = 0#J(θ)對θ1求導的結果 for i in range(m): temp0 += (theta0+theta1*x[i]-y[i])/m temp1 += ((theta0+theta1*x[i]-y[i])/m)*x[i] #更新theta0和theta1 for i in range(m): theta0 = theta0 - alpha*((theta0+theta1*x[i]-y[i])/m) theta1 = theta1 - alpha*((theta0+theta1*x[i]-y[i])/m)*x[i] #求損失函數J(θ) rand_i = np.random.randint(0,m) diss += 0.5*(1/m)*pow((theta0+theta1*x[rand_i]-y[rand_i]),2) loss.append(diss) #看是否知足條件 ''' if diss<=epsilon: break else: continue ''' print("最終的結果爲:") print("這次迭代次數爲:{}次,最終theta0的結果爲:{},最終theta1的結果爲:{}".format(count,theta0,theta1)) print("預測的最終迴歸函數爲:y={}+{}x\n".format(theta0,theta1)) print("迭代圖像繪製...") plt.scatter(range(count),loss) plt.show()
運行結果
Mini-batch gradient descent:小批量梯度降低算法(MBGD),計算包含n個樣本的mini-batch的梯度:
MBGD是訓練神經網絡最經常使用的優化方法。
參數更新時的動盪變小,收斂過程更穩定,下降收斂難度;能夠利用現有的線性代數庫高效的計算多個樣本的梯度。
代碼實現
#引庫 #引入matplotlib庫,用於畫圖 import matplotlib.pyplot as plt from math import pow import numpy as np #圖片嵌入jupyter #matplotlib inline #爲了便於取用數據,咱們將數據分爲x,y,在直角座標系中(x,y)是點 x = [1,2,3,4,5,6] y = [13,14,20,21,25,30] print("打印初始數據圖...") plt.scatter(x,y) plt.xlabel("X") plt.ylabel("Y") plt.show() #超參數設定 alpha = 0.01#學習率/步長 theta0 = 0#θ0 theta1 = 0#θ1 epsilon = 0.001#偏差 diss = 0#損失函數 m = len(x) count = 0 loss = [] for time in range(1000): count += 1 diss = 0 #求偏導theta0和theta1的結果 temp0 = 0#J(θ)對θ0求導的結果 temp1 = 0#J(θ)對θ1求導的結果 for i in range(m): temp0 += (theta0+theta1*x[i]-y[i])/m temp1 += ((theta0+theta1*x[i]-y[i])/m)*x[i] #更新theta0和theta1 for i in range(m): theta0 = theta0 - alpha*((theta0+theta1*x[i]-y[i])/m) theta1 = theta1 - alpha*((theta0+theta1*x[i]-y[i])/m)*x[i] #求損失函數J(θ) result = [] for i in range(3): rand_i = np.random.randint(0,m) result.append(rand_i) for j in result: diss += 0.5*(1/m)*pow((theta0+theta1*x[j]-y[j]),2) loss.append(diss) #看是否知足條件 ''' if diss<=epsilon: break else: continue ''' print("最終的結果爲:") print("這次迭代次數爲:{}次,最終theta0的結果爲:{},最終theta1的結果爲:{}".format(count,theta0,theta1)) print("預測的最終迴歸函數爲:y={}+{}x\n".format(theta0,theta1)) print("迭代圖像繪製...") plt.scatter(range(count),loss) plt.show()
運行結果