02c 梯度下降法2 - cccbook/py2gpt GitHub Wiki
本文為 ChatGPT 寫的,但有點不好懂,我有寫一個簡單的《梯度下降法》程式,然後利用 ChatGPT 來解說,請參考下文。
在深度學習中,我們通常會遇到最優化問題,即尋找一組參數,使得模型的預測結果與真實值之間的誤差最小化。這種問題可以表示為以下形式:
其中,
在深度學習中,常用的最優化方法是梯度下降法。
梯度下降法是一種常用的最優化方法,其核心思想是:將目標函數的參數沿著負梯度方向進行微小調整,使得目標函數的值不斷減小,最終收斂到局部最優解或全局最優解。
具體而言,梯度下降法的更新公式如下:
其中,
梯度下降法有多種變體,如批量梯度下降法(Batch Gradient Descent,BGD)、隨機梯度下降法(Stochastic Gradient Descent,SGD)和小批量梯度下降法(Mini-batch Gradient Descent,MGD)等。
梯度下降法在更新參數時只考慮當前的梯度,因此容易受到噪聲和局部極小值的影響,導致收斂速度較慢。Momentum是一種基於梯度下降法的改進方法,可以加速模型的收斂速度。
Momentum的基本思想是累積之前的梯度信息,並在更新參數時將其考慮進去。具體來說,Momentum引入了一個動量項(momentum term)$v$,用來記錄之前的梯度信息,並在當前的梯度上加上動量項,進行更新。Momentum的更新公式為:
其中,
Adagrad是一種自適應學習率的梯度下降法,可以根據每個參數的歷史梯度信息調整學習率,有效地避免了學習率的手動調整。
Adagrad的基本思想是對每個參數維度調整學習率,使得在梯度變化較大的維度上使用較小的學習率,在梯度變化較小的維度上使用較大的學習率。具體來說,Adagrad引入了一個參數累加項(accumulator),用來記錄每個參數的歷史梯度平方和。在更新參數時,將學習率除以累加項的平方根,進行調整。Adagrad的更新公式為:
其中,
在深度學習中,梯度下降法是最常用的最優化算法之一。PyTorch是一個非常流行的深度學習框架,它提供了一系列內置的最優化算法,包括梯度下降法。在本節中,我們將使用Python和PyTorch來實現梯度下降法。
首先,我們需要定義一個模型和一個損失函數。這裡我們以線性回歸模型為例,並使用均方差(MSE)作為損失函數。
import torch
import torch.nn as nn
class LinearRegression(nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(input_dim, output_dim)
def forward(self, x):
out = self.linear(x)
return out
model = LinearRegression(input_dim=1, output_dim=1)
criterion = nn.MSELoss()接下來,我們需要定義一個優化器。PyTorch提供了一個名為torch.optim的優化器模組,其中包含了多種最優化算法,例如梯度下降法、Adam、Adagrad等等。在這裡,我們使用梯度下降法作為最優化算法。
learning_rate = 0.01
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)最後,我們可以開始訓練模型。在每個epoch中,我們需要進行以下步驟:
- 計算模型輸出。
- 計算損失函數值。
- 計算梯度。
- 更新模型參數
num_epochs = 1000
for epoch in range(num_epochs):
# Forward pass
y_pred = model(x_train)
# Compute loss
loss = criterion(y_pred, y_train)
# Compute gradients
loss.backward()
# Update parameters
optimizer.step()
# Zero gradients
optimizer.zero_grad()
# Print loss
if (epoch+1) % 100 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))在上述代碼中,x_train和y_train是訓練集的特徵和標籤。在每個epoch中,我們首先計算模型的輸出,然後計算損失函數的值。接著,我們使用loss.backward()計算梯度,並使用optimizer.step()更新模型參數。最後,我們使用optimizer.zero_grad()來清除之前的梯度。
接下來我們將使用PyTorch實現Adagrad。我們使用之前的簡單線性回歸模型來演示Adagrad的運作。假設我們有以下的訓練數據:
x_train = torch.tensor([[1.0], [2.0], [3.0], [4.0], [5.0]])
y_train = torch.tensor([[2.0], [4.0], [6.0], [8.0], [10.0]])首先,我們需要定義模型和損失函數:
class LinearRegression(torch.nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegression, self).__init__()
self.linear = torch.nn.Linear(input_dim, output_dim)
def forward(self, x):
out = self.linear(x)
return out
model = LinearRegression(1, 1)
criterion = torch.nn.MSELoss()接下來,我們定義優化器並設置超參數。在這個例子中,我們將初始學習率設置為 0.1 ,並將 eps 設置為 1e-8。
optimizer = torch.optim.Adagrad(model.parameters(), lr=0.1, eps=1e-8)最後,我們開始進行訓練:
num_epochs = 1000
for epoch in range(num_epochs):
# Forward pass
y_pred = model(x_train)
loss = criterion(y_pred, y_train)
# Backward pass
optimizer.zero_grad()
loss.backward()
# Update parameters
optimizer.step()
# Print progress
if (epoch+1) % 100 == 0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))在這個例子中,我們訓練了1000個epoch。每100個epoch,我們輸出當前的損失值。由於Adagrad自適應地調整每個權重的學習率,因此不需要手動調整學習率,可以看到,即使在較高的學習率下,Adagrad也能夠成功地訓練模型,並得到與SGD相當的結果。