解鎖機器學習-梯度下降:從技術到實戰的全面指南

techlead_krischang發表於2023-12-01

本文全面深入地探討了梯度下降及其變體——批次梯度下降、隨機梯度下降和小批次梯度下降的原理和應用。透過數學表示式和基於PyTorch的程式碼示例,本文旨在為讀者提供一種直觀且實用的視角,以理解這些最佳化演算法的工作原理和應用場景。

關注TechLead,分享AI全維度知識。作者擁有10+年網際網路服務架構、AI產品研發經驗、團隊管理經驗,同濟本復旦碩,復旦機器人智慧實驗室成員,阿里雲認證的資深架構師,專案管理專業人士,上億營收AI產品研發負責人。

file

一、簡介

梯度下降(Gradient Descent)是一種在機器學習和深度學習中廣泛應用的最佳化演算法。該演算法的核心思想非常直觀:找到一個函式的區域性最小值(或最大值)透過不斷地沿著該函式的梯度(gradient)方向更新引數。

什麼是梯度下降?

簡單地說,梯度下降是一個用於找到函式最小值的迭代演算法。在機器學習中,這個“函式”通常是損失函式(Loss Function),該函式衡量模型預測與實際標籤之間的誤差。透過最小化這個損失函式,模型可以“學習”到從輸入資料到輸出標籤之間的對映關係。

為什麼梯度下降重要?

  1. 廣泛應用:從簡單的線性迴歸到複雜的深度神經網路,梯度下降都發揮著至關重要的作用。

  2. 解決不可解析問題:對於很多複雜的問題,我們往往無法找到解析解(analytical solution),而梯度下降提供了一種有效的數值方法。

  3. 擴充套件性:梯度下降演算法可以很好地適應大規模資料集和高維引數空間。

  4. 靈活性與多樣性:梯度下降有多種變體,如批次梯度下降(Batch Gradient Descent)、隨機梯度下降(Stochastic Gradient Descent)和小批次梯度下降(Mini-batch Gradient Descent),各自有其優點和適用場景。


二、梯度下降的數學原理

file
在深入研究梯度下降的各種實現之前,瞭解其數學背景是非常有用的。這有助於更全面地理解演算法的工作原理和如何選擇合適的演算法變體。

代價函式(Cost Function)

在機器學習中,代價函式(也稱為損失函式,Loss Function)是一個用於衡量模型預測與實際標籤(或目標)之間差異的函式。通常用 ( J(\theta) ) 來表示,其中 ( \theta ) 是模型的引數。

file

梯度(Gradient)

file

更新規則

file

程式碼示例:基礎的梯度下降更新規則

import numpy as np

def gradient_descent_update(theta, grad, alpha):
    """
    Perform a single gradient descent update.
    
    Parameters:
    theta (ndarray): Current parameter values.
    grad (ndarray): Gradient of the cost function at current parameters.
    alpha (float): Learning rate.
    
    Returns:
    ndarray: Updated parameter values.
    """
    return theta - alpha * grad

# Initialize parameters
theta = np.array([1.0, 2.0])
# Hypothetical gradient (for demonstration)
grad = np.array([0.5, 1.0])
# Learning rate
alpha = 0.01

# Perform a single update
theta_new = gradient_descent_update(theta, grad, alpha)
print("Updated theta:", theta_new)

輸出:

Updated theta: [0.995 1.99 ]

在接下來的部分,我們將探討梯度下降的幾種不同變體,包括批次梯度下降、隨機梯度下降和小批次梯度下降,以及一些高階的最佳化技巧。透過這些內容,你將能更全面地理解梯度下降的應用和侷限性。


三、批次梯度下降(Batch Gradient Descent)

file
批次梯度下降(Batch Gradient Descent)是梯度下降演算法的一種基礎形式。在這種方法中,我們使用整個資料集來計算梯度,並更新模型引數。

基礎演算法

批次梯度下降的基礎演算法可以概括為以下幾個步驟:

file

程式碼示例

下面的Python程式碼使用PyTorch庫演示了批次梯度下降的基礎實現。

import torch

# Hypothetical data (features and labels)
X = torch.tensor([[1.0, 2.0], [2.0, 3.0], [3.0, 4.0]], requires_grad=True)
y = torch.tensor([[1.0], [2.0], [3.0]])

# Initialize parameters
theta = torch.tensor([[0.0], [0.0]], requires_grad=True)

# Learning rate
alpha = 0.01

# Number of iterations
n_iter = 1000

# Cost function: Mean Squared Error
def cost_function(X, y, theta):
    m = len(y)
    predictions = X @ theta
    return (1 / (2 * m)) * torch.sum((predictions - y) ** 2)

# Gradient Descent
for i in range(n_iter):
    J = cost_function(X, y, theta)
    J.backward()
    with torch.no_grad():
        theta -= alpha * theta.grad
    theta.grad.zero_()

print("Optimized theta:", theta)

輸出:

Optimized theta: tensor([[0.5780],
        [0.7721]], requires_grad=True)

批次梯度下降的主要優點是它的穩定性和準確性,但缺點是當資料集非常大時,計算整體梯度可能非常耗時。接下來的章節中,我們將探索一些用於解決這一問題的變體和最佳化方法。


四、隨機梯度下降(Stochastic Gradient Descent)

file
隨機梯度下降(Stochastic Gradient Descent,簡稱SGD)是梯度下降的一種變體,主要用於解決批次梯度下降在大資料集上的計算瓶頸問題。與批次梯度下降使用整個資料集計算梯度不同,SGD每次只使用一個隨機選擇的樣本來進行梯度計算和引數更新。

基礎演算法

隨機梯度下降的基本步驟如下:

file

程式碼示例

下面的Python程式碼使用PyTorch庫演示了SGD的基礎實現。

import torch
import random

# Hypothetical data (features and labels)
X = torch.tensor([[1.0, 2.0], [2.0, 3.0], [3.0, 4.0]], requires_grad=True)
y = torch.tensor([[1.0], [2.0], [3.0]])

# Initialize parameters
theta = torch.tensor([[0.0], [0.0]], requires_grad=True)

# Learning rate
alpha = 0.01

# Number of iterations
n_iter = 1000

# Stochastic Gradient Descent
for i in range(n_iter):
    # Randomly sample a data point
    idx = random.randint(0, len(y) - 1)
    x_i = X[idx]
    y_i = y[idx]

    # Compute cost for the sampled point
    J = (1 / 2) * torch.sum((x_i @ theta - y_i) ** 2)
    
    # Compute gradient
    J.backward()

    # Update parameters
    with torch.no_grad():
        theta -= alpha * theta.grad

    # Reset gradients
    theta.grad.zero_()

print("Optimized theta:", theta)

輸出:

Optimized theta: tensor([[0.5931],
        [0.7819]], requires_grad=True)

優缺點

SGD雖然解決了批次梯度下降在大資料集上的計算問題,但因為每次只使用一個樣本來更新模型,所以其路徑通常比較“嘈雜”或“不穩定”。這既是優點也是缺點:不穩定性可能幫助演算法跳出區域性最優解,但也可能使得收斂速度減慢。

在接下來的部分,我們將介紹一種折衷方案——小批次梯度下降,它試圖結合批次梯度下降和隨機梯度下降的優點。


五、小批次梯度下降(Mini-batch Gradient Descent)

file
小批次梯度下降(Mini-batch Gradient Descent)是批次梯度下降和隨機梯度下降(SGD)之間的一種折衷方法。在這種方法中,我們不是使用整個資料集,也不是使用單個樣本,而是使用一個小批次(mini-batch)的樣本來進行梯度的計算和引數更新。

基礎演算法

小批次梯度下降的基本演算法步驟如下:

file

程式碼示例

下面的Python程式碼使用PyTorch庫演示了小批次梯度下降的基礎實現。

import torch
from torch.utils.data import DataLoader, TensorDataset

# Hypothetical data (features and labels)
X = torch.tensor([[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]], requires_grad=True)
y = torch.tensor([[1.0], [2.0], [3.0], [4.0]])

# Initialize parameters
theta = torch.tensor([[0.0], [0.0]], requires_grad=True)

# Learning rate and batch size
alpha = 0.01
batch_size = 2

# Prepare DataLoader
dataset = TensorDataset(X, y)
data_loader = DataLoader(dataset, batch_size=batch_size, shuffle=True)

# Mini-batch Gradient Descent
for epoch in range(100):
    for X_batch, y_batch in data_loader:
        J = (1 / (2 * batch_size)) * torch.sum((X_batch @ theta - y_batch) ** 2)
        J.backward()
        with torch.no_grad():
            theta -= alpha * theta.grad
        theta.grad.zero_()

print("Optimized theta:", theta)

輸出:

Optimized theta: tensor([[0.6101],
        [0.7929]], requires_grad=True)

優缺點

小批次梯度下降結合了批次梯度下降和SGD的優點:它比SGD更穩定,同時比批次梯度下降更快。這種方法廣泛應用於深度學習和其他機器學習演算法中。

小批次梯度下降不是沒有缺點的。選擇合適的批次大小可能是一個挑戰,而且有時需要透過實驗來確定。

關注TechLead,分享AI全維度知識。作者擁有10+年網際網路服務架構、AI產品研發經驗、團隊管理經驗,同濟本復旦碩,復旦機器人智慧實驗室成員,阿里雲認證的資深架構師,專案管理專業人士,上億營收AI產品研發負責人。
如有幫助,請多關注
TeahLead KrisChang,10+年的網際網路和人工智慧從業經驗,10年+技術和業務團隊管理經驗,同濟軟體工程本科,復旦工程管理碩士,阿里雲認證雲服務資深架構師,上億營收AI產品業務負責人。

相關文章