機器學習
梯度下降法
基本概念
梯度下降法(gradient descent),又名最速下降法(steepest descent)是求解無約束最優化問題最常用的方法,它是一種迭代方法,每一步主要的操作是求解目標函式的梯度向量,將當前位置的負梯度方向作為搜尋方向(因為在該方向上目標函式下降最快,這也是最速下降法名稱的由來)。
梯度下降,其實就是一個公式:
公式推導
![img](file:///E:\qq聊天記錄\1713176942\Image\C2C\2D65DC80FB67F846BD86FE94D6FF8215.jpg)
基本梯度下降步驟
步驟:
η為學習率,ε為收斂條件。梯度下降法屬於機器學習,本質為:不斷迭代判斷是否滿足條件,會用到迴圈語句。
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
批量梯度下降(BGD)
Batch gradient descent::批量梯度下降演算法(BGD),其需要計算整個訓練集的梯度,即:
其中η為學習率,用來控制更新的“力度”/"步長"。
- 優點:
對於凸目標函式,可以保證全域性最優; 對於非凸目標函式,可以保證一個區域性最優。
- 缺點:
速度慢; 資料量大時不可行; 無法線上優化(即無法處理動態產生的新樣本)。
程式碼實現
#引庫
#引入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()
執行結果
隨機梯度下降(SGD)
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()
執行結果
小批量梯度下降(MBGD)
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()
執行結果