最全總結(jié)!機(jī)器學(xué)習(xí)優(yōu)化算法!
機(jī)器學(xué)習(xí)的最優(yōu)化算法是用于找到最佳模型參數(shù),以最小化預(yù)測誤差的算法。這些算法通過迭代地調(diào)整模型參數(shù),以不斷改進(jìn)模型的性能。
本文系統(tǒng)地介紹了優(yōu)化算法,基本脈絡(luò)是從優(yōu)化的基礎(chǔ)知識(shí),到各種優(yōu)化算法原理的介紹及代碼示例,最后放上各種算法的對比及實(shí)踐經(jīng)驗(yàn)總結(jié)!
一、基礎(chǔ)知識(shí)
1.1 梯度(一階導(dǎo)數(shù))
考慮一座在 (x1, x2) 點(diǎn)高度是 f(x1, x2) 的山。那么,某一點(diǎn)的梯度方向是在該點(diǎn)坡度最陡的方向,而梯度的大小告訴我們坡度到底有多陡。注意,梯度也可以告訴我們不在最快變化方向的其他方向的變化速度(二維情況下,按照梯度方向傾斜的圓在平面上投影成一個(gè)橢圓)。對于一個(gè)含有 n 個(gè)變量的標(biāo)量函數(shù),即函數(shù)輸入一個(gè) n 維 的向量,輸出一個(gè)數(shù)值,梯度可以定義為:
1.2 Hesse 矩陣(二階導(dǎo)數(shù))
Hesse 矩陣常被應(yīng)用于牛頓法解決的大規(guī)模優(yōu)化問題(后面會(huì)介紹),主要形式如下:
當(dāng) f(x) 為二次函數(shù)時(shí),梯度以及 Hesse 矩陣很容易求得。二次函數(shù)可以寫成下列形式:
其中 A 是 n 階對稱矩陣,b 是 n 維列向量, c 是常數(shù)。f(x) 梯度是 Ax+b, Hesse 矩陣等于 A。
1.3 Jacobi 矩陣
Jacobi 矩陣實(shí)際上是向量值函數(shù)的梯度矩陣,假設(shè)F:Rn→Rm 是一個(gè)從n維歐氏空間轉(zhuǎn)換到m維歐氏空間的函數(shù)。這個(gè)函數(shù)由m個(gè)實(shí)函數(shù)組成:
。這些函數(shù)的偏導(dǎo)數(shù)(如果存在)可以組成一個(gè)m行n列的矩陣(m by n),這就是所謂的雅可比矩陣:
二、機(jī)器學(xué)習(xí)的優(yōu)化算法
2.1 梯度下降法(Gradient Descent)
梯度下降法是最常用的一種優(yōu)化算法,通過迭代地沿著梯度的負(fù)方向來尋找最優(yōu)解。
在機(jī)器學(xué)習(xí)中,梯度下降法通常用于求解損失函數(shù)的最小值,通過不斷更新模型的參數(shù)來逐漸減小損失函數(shù)的值。
梯度下降法的優(yōu)點(diǎn)是簡單、穩(wěn)定且容易實(shí)現(xiàn),適用于大規(guī)模數(shù)據(jù)集和復(fù)雜的模型。
梯度下降是一個(gè)大類,常見的梯度下降類算法如下圖:
2.2 隨機(jī)梯度下降法(Stochastic Gradient Descent, SGD)
隨機(jī)梯度下降是在梯度下降算法效率上做了優(yōu)化,不使用全量樣本計(jì)算當(dāng)前的梯度,而是使用小批量(mini-batch)樣本來估計(jì)梯度,大大提高了效率。
原因在于使用更多樣本來估計(jì)梯度的方法的收益是低于線性的,對于大多數(shù)優(yōu)化算法基于梯度下降,如果每一步中計(jì)算梯度的時(shí)間大大縮短,則它們會(huì)更快收斂。且訓(xùn)練集通常存在冗余,大量樣本都對梯度做出了非常相似的貢獻(xiàn)。此時(shí)基于小批量樣本估計(jì)梯度的策略也能夠計(jì)算正確的梯度,但是節(jié)省了大量時(shí)間。
SGD具有快速收斂的特點(diǎn),適用于處理大規(guī)模數(shù)據(jù)集和分布式計(jì)算環(huán)境。
SGD的缺點(diǎn)是容易陷入局部最優(yōu)解,可結(jié)合其他優(yōu)化算法如動(dòng)量法或Adam等來提高收斂效果。
import numpy as np
# 定義損失函數(shù)
def loss_function(w, X, y):
return np.sum(np.square(X.dot(w) - y)) / len(y)
# 定義梯度函數(shù)
def gradient(w, X, y):
return X.T.dot((X.dot(w) - y)) / len(y)
# 定義SGD優(yōu)化器
def sgd(X, y, learning_rate=0.01, epochs=100):
n_features = X.shape[1]
w = np.zeros(n_features)
for epoch in range(epochs):
for i in range(len(X)):
grad = gradient(w, X[i], y[i])
w -= learning_rate * grad
print("Epoch %d loss: %f" % (epoch+1, loss_function(w, X, y)))
return w
2.3 動(dòng)量法(Momentum)和Nesterov 動(dòng)量法
動(dòng)量法通過引入一個(gè)動(dòng)量項(xiàng)來加速梯度下降法的收斂速度。
Nesterov 動(dòng)量法是對動(dòng)量法的改進(jìn),在每一步迭代中考慮了未來的信息,從而更好地指導(dǎo)參數(shù)的更新方向。
動(dòng)量法和Nesterov 動(dòng)量法適用于非凸優(yōu)化問題,能夠跳出局部最優(yōu)解并加速收斂。
2.4 Adam(Adaptive Moment Estimation)
Adam是最常用的優(yōu)化算法之一,是一種自適應(yīng)學(xué)習(xí)率的優(yōu)化算法,結(jié)合了動(dòng)量法和RMSprop的思想。
Adam能夠自動(dòng)調(diào)整學(xué)習(xí)率,并且在不同的數(shù)據(jù)分布和模型結(jié)構(gòu)下具有良好的收斂效果。(雖然說已經(jīng)簡化了調(diào)參,但是并沒有一勞永逸地解決問題,默認(rèn)的參數(shù)雖然好,但也不是放之四海而皆準(zhǔn)。因此,在充分理解數(shù)據(jù)的基礎(chǔ)上,依然需要根據(jù)數(shù)據(jù)特性、算法特性進(jìn)行充分的調(diào)參實(shí)驗(yàn)。)
Adam適用于處理高維特征和稀疏數(shù)據(jù)集,非常適用于深度學(xué)習(xí)模型中的參數(shù)優(yōu)化。在使用大型模型和數(shù)據(jù)集的情況下,Adam 優(yōu)化算法在解決局部深度學(xué)習(xí)問題上是很高效的。
import torch
import torch.optim as optim
import numpy as np
# 定義損失函數(shù)和梯度函數(shù)(這里使用PyTorch的自動(dòng)梯度計(jì)算)
loss_function = torch.nn.MSELoss() # 均方誤差損失函數(shù)
gradient = torch.autograd.grad # 自動(dòng)梯度計(jì)算函數(shù)
# 定義Adam優(yōu)化器(這里使用了PyTorch的Adam類)
optimizer = optim.Adam([torch.Tensor([0.])], lr=0.01) # 學(xué)習(xí)率設(shè)置為0.01,初始權(quán)重為0向量(注意:PyTorch中優(yōu)化器的權(quán)重參數(shù)需要是tensor對象)
optimizer.zero_grad() # 清除歷史梯度信息(如果使用其他優(yōu)化器,可能需要手動(dòng)清除梯度)
output = loss_function(torch.Tensor([1]), torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[2], [4]])) # 計(jì)算損失函數(shù)值(這里使用了PyTorch的Tensor類,模擬了線性回歸問題的數(shù)據(jù)和目標(biāo))
output.backward() # 反向傳播計(jì)算梯度(這里使用了PyTorch的backward方法)
optimizer.step() # 更新權(quán)重(這里使用了PyTorch的step方法)
2.5 AdaGrad(Adaptive Gradient Algorithm)和RMSprop
AdaGrad是一種自適應(yīng)學(xué)習(xí)率的優(yōu)化算法,能夠根據(jù)參數(shù)的歷史梯度來動(dòng)態(tài)調(diào)整學(xué)習(xí)率。
RMSprop則是對AdaGrad的改進(jìn),通過引入一個(gè)指數(shù)衰減的平均來平滑歷史梯度的方差。
AdaGrad和RMSprop適用于處理稀疏數(shù)據(jù)集和具有非平穩(wěn)目標(biāo)函數(shù)的優(yōu)化問題。
2.6 牛頓法(Newton's Method)和擬牛頓法(Quasi-Newton Methods)
牛頓法是一種基于目標(biāo)函數(shù)的二階導(dǎo)數(shù)信息的優(yōu)化算法,通過構(gòu)建二階導(dǎo)數(shù)矩陣并對其進(jìn)行求解來逼近最優(yōu)解。
擬牛頓法是牛頓法的改進(jìn),通過構(gòu)造一個(gè)對稱正定的矩陣來逼近目標(biāo)函數(shù)的二階導(dǎo)數(shù)矩陣的逆矩陣,從而避免了直接計(jì)算二階導(dǎo)數(shù)矩陣的逆矩陣。
牛頓法和擬牛頓法適用于二階可導(dǎo)的目標(biāo)函數(shù),具有較快的收斂速度,但在計(jì)算二階導(dǎo)數(shù)矩陣時(shí)需要較大的存儲(chǔ)空間。
import numpy as np
from scipy.linalg import inv
# 定義損失函數(shù)和Hessian矩陣
def loss_function(w, X, y):
return np.sum(np.square(X.dot(w) - y)) / len(y)
def hessian(w, X, y):
return X.T.dot(X) / len(y)
# 定義牛頓法優(yōu)化器
def newton(X, y, learning_rate=0.01, epochs=100):
n_features = X.shape[1]
w = np.zeros(n_features)
for epoch in range(epochs):
H = hessian(w, X, y)
w -= inv(H).dot(gradient(w, X, y))
print("Epoch %d loss: %f" % (epoch+1, loss_function(w, X, y)))
return w
2.7 共軛梯度法(Conjugate Gradient)
共軛梯度法是介于梯度下降法和牛頓法之間的一種方法,利用共軛方向進(jìn)行搜索。
共軛梯度法的優(yōu)點(diǎn)是在每一步迭代中不需要計(jì)算完整的梯度向量,而是通過迭代的方式逐步逼近最優(yōu)解。
該方法適用于大規(guī)模問題,尤其是稀疏矩陣和對稱正定的問題。
2.8 LBFGS(Limited-memory Broyden–Fletcher–Goldfarb–Shanno)
一種有限內(nèi)存的Broyden-Fletcher-Goldfarb-Shanno(BFGS)算法,主要用于解決大規(guī)模優(yōu)化問題。由于它只需要有限數(shù)量的計(jì)算機(jī)內(nèi)存,因此特別適合處理大規(guī)模問題。LBFGS算法的目標(biāo)是最小化一個(gè)給定的函數(shù),通常用于機(jī)器學(xué)習(xí)中的參數(shù)估計(jì)。
import numpy as np
from scipy.optimize import minimize
# 目標(biāo)函數(shù)
def objective_function(x):
return x**2 - 4*x + 4
# L-BFGS算法求解最小值
result = minimize(objective_function, x0=1, method='L-BFGS-B')
x_min = result.x
print(f"L-BFGS的最小值為:{objective_function(x_min)}")
2.9 SA(Simulated Annealing)
一種隨機(jī)搜索算法,其靈感來源于物理退火過程。該算法通過接受或拒絕解的移動(dòng)來模擬退火過程,以避免陷入局部最優(yōu)解并尋找全局最優(yōu)解。在模擬退火算法中,接受概率通?;诮獾囊苿?dòng)的優(yōu)劣和溫度的降低,允許在搜索過程中暫時(shí)接受較差的解,這有助于跳出局部最優(yōu),從而有可能找到全局最優(yōu)解。
import numpy as np
from scipy.optimize import anneal
# 目標(biāo)函數(shù)
def objective_function(x):
return (x - 2)**2
# SA算法求解最小值
result = anneal(objective_function, x0=0, lower=-10, upper=10, maxiter=1000)
x_min = result.x
print(f"SA的最小值為:{objective_function(x_min)}")
2.10 AC-SA(Adaptive Clustering-based Simulated Annealing)
一種基于自適應(yīng)聚類的模擬退火算法。通過模擬物理退火過程,利用聚類技術(shù)來組織解空間并控制解的移動(dòng)。該方法適用于處理大規(guī)模、高維度的優(yōu)化問題,尤其適用于那些具有多個(gè)局部最優(yōu)解的問題。
遺傳算法是一種基于自然選擇和遺傳學(xué)機(jī)理的生物進(jìn)化過程的模擬算法,適用于解決優(yōu)化問題,特別是組合優(yōu)化問題。該算法通過數(shù)學(xué)的方式,利用計(jì)算機(jī)仿真運(yùn)算,將問題的求解過程轉(zhuǎn)換成類似生物進(jìn)化中的染色體基因的交叉、變異等過程。在求解較為復(fù)雜的組合優(yōu)化問題時(shí),相對一些常規(guī)的優(yōu)化算法,通常能夠較快地獲得較好的優(yōu)化結(jié)果。
2.11 PSO(Particle Swarm Optimization)
PSO是一種基于種群的隨機(jī)優(yōu)化技術(shù),模擬了鳥群覓食的行為(吐槽下,智能優(yōu)化算法的領(lǐng)域真是卷麻了!!!)。粒子群算法模仿昆蟲、獸群、鳥群和魚群等的群集行為,這些群體按照一種合作的方式尋找食物,群體中的每個(gè)成員通過學(xué)習(xí)它自身的經(jīng)驗(yàn)和其他成員的經(jīng)驗(yàn)來不斷改變其搜索模式。PSO算法適用于處理多峰函數(shù)和離散優(yōu)化問題,具有簡單、靈活和容易實(shí)現(xiàn)的特點(diǎn)。
回顧下各類算法的優(yōu)缺點(diǎn):
- 梯度下降類的優(yōu)化算法:優(yōu)點(diǎn)是簡單、快速,常用于深度神經(jīng)網(wǎng)絡(luò)模型;缺點(diǎn)是可能得到的是局部最優(yōu)解。
- 牛頓法:優(yōu)點(diǎn)是二階收斂,收斂速度快;缺點(diǎn)是需要計(jì)算目標(biāo)函數(shù)的Hessian矩陣,計(jì)算復(fù)雜度高。
- 模擬退火算法:優(yōu)點(diǎn)是避免陷入局部最優(yōu)解,能夠找到全局最優(yōu)解;缺點(diǎn)是收斂速度慢,需要大量時(shí)間。
- 遺傳算法:優(yōu)點(diǎn)是通過變異機(jī)制避免陷入局部最優(yōu)解,搜索能力強(qiáng);缺點(diǎn)是編程復(fù)雜,需要設(shè)置多個(gè)參數(shù),實(shí)現(xiàn)較為復(fù)雜。
- 粒子群優(yōu)化算法:優(yōu)點(diǎn)是簡單、收斂快、計(jì)算復(fù)雜度低;缺點(diǎn)是多樣性丟失、容易陷入局部最優(yōu),實(shí)現(xiàn)較為復(fù)雜。
三、優(yōu)化算法的小結(jié)
本文介紹了梯度下降類、牛頓法、模擬退火、遺傳算法和粒子群優(yōu)化等常用的機(jī)器學(xué)習(xí)優(yōu)化算法。這些算法各有特點(diǎn)和適用范圍,選擇合適的算法需要根據(jù)具體的問題、數(shù)據(jù)集和模型來進(jìn)行權(quán)衡的。
最后,結(jié)合經(jīng)驗(yàn)分享一些常用梯度下降類優(yōu)化算法的選擇和使用技巧:
首先,沒有一種算法是普遍適用于所有情況的。如果你是初學(xué)者,建議從SGD+Nesterov Momentum或Adam開始。
選擇你熟悉的算法,這樣你可以更熟練地調(diào)整參數(shù)并利用經(jīng)驗(yàn)。
充分了解你的數(shù)據(jù)。如果模型非常稀疏,優(yōu)先考慮使用自適應(yīng)學(xué)習(xí)率的算法。
根據(jù)你的需求選擇算法。在模型設(shè)計(jì)實(shí)驗(yàn)階段,為了快速驗(yàn)證新模型的效果,可以使用Adam進(jìn)行快速實(shí)驗(yàn)優(yōu)化。在模型上線或發(fā)布之前,使用經(jīng)過微調(diào)的SGD進(jìn)行模型的精細(xì)優(yōu)化。
先用小數(shù)據(jù)集進(jìn)行實(shí)驗(yàn)。有研究指出,隨機(jī)梯度下降算法的收斂速度與數(shù)據(jù)集的大小關(guān)系不大。因此,可以使用具有代表性的小數(shù)據(jù)集進(jìn)行實(shí)驗(yàn),測試最佳優(yōu)化算法,并通過參數(shù)搜索找到最優(yōu)的訓(xùn)練參數(shù)。
考慮不同算法的組合。先用Adam進(jìn)行快速下降,然后再切換到SGD進(jìn)行充分調(diào)優(yōu)。切換策略可以參考本文介紹的方法。
確保數(shù)據(jù)集充分打散(shuffle)。這樣在使用自適應(yīng)學(xué)習(xí)率算法時(shí),可以避免某些特征集中出現(xiàn),導(dǎo)致學(xué)習(xí)過度或不足,使下降方向出現(xiàn)偏差。
在訓(xùn)練過程中持續(xù)監(jiān)控訓(xùn)練數(shù)據(jù)和驗(yàn)證數(shù)據(jù)上的目標(biāo)函數(shù)值以及精度或AUC等指標(biāo)的變化情況。對訓(xùn)練數(shù)據(jù)的監(jiān)控是為了確保模型進(jìn)行了充分訓(xùn)練——下降方向正確且學(xué)習(xí)率足夠高。對驗(yàn)證數(shù)據(jù)的監(jiān)控是為了避免過擬合。
制定合適的學(xué)習(xí)率衰減策略。可以使用定期衰減策略,例如每過幾個(gè)epoch就衰減一次;或者利用精度或AUC等性能指標(biāo)進(jìn)行監(jiān)控。當(dāng)測試集上的指標(biāo)不再改善或下降時(shí),降低學(xué)習(xí)率。