深度学习 - 梯度下降优化方法

梯度下降的基本概念

梯度下降(Gradient Descent)是一种用于优化机器学习模型参数的算法,其目的是最小化损失函数,从而提高模型的预测精度。梯度下降的核心思想是通过迭代地调整参数,沿着损失函数下降的方向前进,最终找到最优解。

生活中的背景例子:寻找山谷的最低点

想象你站在一个山谷中,眼睛被蒙住,只能用脚感受地面的坡度来找到山谷的最低点(即损失函数的最小值)。你每一步都想朝着坡度下降最快的方向走,直到你感觉不到坡度,也就是你到了最低点。这就好比在优化一个模型时,通过不断调整参数,使得模型的预测误差(损失函数)越来越小,最终找到最佳参数组合。

梯度下降的具体方法及其优化

1. 批量梯度下降(Batch Gradient Descent)

生活中的例子

你决定每次移动之前,都要先测量整个山谷的坡度,然后再决定移动的方向和步幅。虽然每一步的方向和步幅都很准确,但每次都要花很多时间来测量整个山谷的坡度。

公式
θ : = θ − η ⋅ ∇ θ J ( θ ) \theta := \theta - \eta \cdot \nabla_{\theta} J(\theta) θ:=θ−η⋅∇θJ(θ)

其中:

  • θ \theta θ是模型参数
  • η \eta η是学习率
  • ∇ θ J ( θ ) \nabla_{\theta} J(\theta) ∇θJ(θ)是损失函数 J ( θ ) J(\theta) J(θ)关于 θ \theta θ的梯度

API
TensorFlow

python 复制代码
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

PyTorch

python 复制代码
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

批量梯度下降过程图像python代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

# 损失函数: y = x^2
def loss(x):
    return x ** 2

# 损失函数的梯度: dy/dx = 2x
def gradient(x):
    return 2 * x

# 批量梯度下降
def batch_gradient_descent(start, learning_rate, iterations):
    x = start
    path = [x]
    for i in range(iterations):
        grad = gradient(x)
        x = x - learning_rate * grad
        path.append(x)
    return path

# 参数
start = 10
learning_rate = 0.1
iterations = 20

# 运行梯度下降
path = batch_gradient_descent(start, learning_rate, iterations)

# 绘制图像
x = np.linspace(-10, 10, 100)
y = loss(x)
plt.plot(x, y, label='Loss Function')
plt.scatter(path, [loss(p) for p in path], color='red', label='Batch Gradient Descent Path')
plt.xlabel('x')
plt.ylabel('Loss')
plt.legend()
plt.title('Batch Gradient Descent')
plt.show()
  • 从图像可知,批量梯度下降每次使用整个训练集计算梯度并更新参数,适用于小规模数据集,收敛稳定,但计算开销大。
2. 随机梯度下降(Stochastic Gradient Descent, SGD)

生活中的例子

你决定每一步都只根据当前所在位置的坡度来移动。虽然这样可以快速决定下一步怎么走,但由于只考虑当前点,可能会导致路径不稳定,有时候会走过头。

公式
θ : = θ − η ⋅ ∇ θ J ( θ ; x ( i ) , y ( i ) ) \theta := \theta - \eta \cdot \nabla_{\theta} J(\theta; x^{(i)}, y^{(i)}) θ:=θ−η⋅∇θJ(θ;x(i),y(i))

其中 ( x ( i ) , y ( i ) ) (x^{(i)}, y^{(i)}) (x(i),y(i))是当前样本的数据

API
TensorFlowPyTorch 中的API与批量梯度下降相同,具体行为取决于数据的加载方式。例如在训练时可以一批数据包含一个样本。

随机梯度下降过程图像python代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

# 损失函数: y = x^2
def loss(x):
    return x ** 2

# 损失函数的梯度: dy/dx = 2x
def gradient(x):
    return 2 * x

# 随机梯度下降
def stochastic_gradient_descent(start, learning_rate, iterations):
    x = start
    path = [x]
    for i in range(iterations):
        grad = gradient(x)
        x = x - learning_rate * grad * np.random.uniform(0.5, 1.5)  # 模拟随机样本的影响
        path.append(x)
    return path

# 参数
start = 10
learning_rate = 0.1
iterations = 20

# 运行梯度下降
path = stochastic_gradient_descent(start, learning_rate, iterations)

# 绘制图像
x = np.linspace(-10, 10, 100)
y = loss(x)
plt.plot(x, y, label='Loss Function')
plt.scatter(path, [loss(p) for p in path], color='red', label='SGD Path')
plt.xlabel('x')
plt.ylabel('Loss')
plt.legend()
plt.title('Stochastic Gradient Descent')
plt.show()
  • 随机梯度下降每次使用一个样本计算梯度并更新参数,计算效率高,适用于大规模数据集,但收敛不稳定,容易出现抖动。
3. 小批量梯度下降(Mini-Batch Gradient Descent)

生活中的例子

你决定每次移动之前,只测量周围一小部分区域的坡度,然后根据这小部分区域的平均坡度来决定方向和步幅。这样既不需要花太多时间测量整个山谷,也不会因为只看一个点而导致路径不稳定。

公式
θ : = θ − η ⋅ ∇ θ J ( θ ; B ) \theta := \theta - \eta \cdot \nabla_{\theta} J(\theta; \mathcal{B}) θ:=θ−η⋅∇θJ(θ;B)

其中 B \mathcal{B} B是当前小批量的数据

API
TensorFlowPyTorch 中的API与批量梯度下降相同,但在数据加载时使用小批量。

小批量梯度下降过程图像python代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

# 损失函数: y = x^2
def loss(x):
    return x ** 2

# 损失函数的梯度: dy/dx = 2x
def gradient(x):
    return 2 * x

# 小批量梯度下降
def mini_batch_gradient_descent(start, learning_rate, iterations, batch_size=5):
    x = start
    path = [x]
    for i in range(iterations):
        grad = gradient(x)
        x = x - learning_rate * grad * np.random.uniform(0.8, 1.2)  # 模拟小批量样本的影响
        path.append(x)
    return path

# 参数
start = 10
learning_rate = 0.1
iterations = 20

# 运行梯度下降
path = mini_batch_gradient_descent(start, learning_rate, iterations)

# 绘制图像
x = np.linspace(-10, 10, 100)
y = loss(x)
plt.plot(x, y, label='Loss Function')
plt.scatter(path, [loss(p) for p in path], color='red', label='Mini-Batch Gradient Descent Path')
plt.xlabel('x')
plt.ylabel('Loss')
plt.legend()
plt.title('Mini-Batch Gradient Descent')
plt.show()
  • 小批量梯度下降每次使用一个小批量样本计算梯度并更新参数,平衡了计算效率和稳定性。
4. 动量法(Momentum)

生活中的例子

你在移动时,不仅考虑当前的坡度,还考虑之前几步的移动方向,就像带着惯性一样。如果前几步一直往一个方向走,那么你会倾向于继续往这个方向走,减少来回震荡。

公式
v : = β v + ( 1 − β ) ∇ θ J ( θ ) v := \beta v + (1 - \beta) \nabla_{\theta} J(\theta) v:=βv+(1−β)∇θJ(θ)
θ : = θ − η v \theta := \theta - \eta v θ:=θ−ηv

其中:

  • v v v是动量项
  • β \beta β是动量系数(通常接近1,如0.9)

API
TensorFlow

python 复制代码
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01, momentum=0.9)

PyTorch

python 复制代码
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

动量法图像python代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

# 损失函数: y = x^2
def loss(x):
    return x ** 2

# 损失函数的梯度: dy/dx = 2x
def gradient(x):
    return 2 * x

# 动量法
def momentum_gradient_descent(start, learning_rate, iterations, beta=0.9):
    x = start
    v = 0
    path = [x]
    for i in range(iterations):
        grad = gradient(x)
        v = beta * v + (1 - beta) * grad
        x = x - learning_rate * v
        path.append(x)
    return path

# 参数
start = 10
learning_rate = 0.1
iterations = 20

# 运行梯度下降
path = momentum_gradient_descent(start, learning_rate, iterations)

# 绘制图像
x = np.linspace(-10, 10, 100)
y = loss(x)
plt.plot(x, y, label='Loss Function')
plt.scatter(path, [loss(p) for p in path], color='red', label='Momentum Path')
plt.xlabel('x')
plt.ylabel('Loss')
plt.legend()
plt.title('Momentum Gradient Descent')
plt.show()
  • 动量法通过引入动量项加速收敛并减少震荡,适用于深度神经网络训练。
5. RMSProp

生活中的例子

你在移动时,会根据最近一段时间内每一步的坡度情况,动态调整步幅。比如,当坡度变化剧烈时,你会迈小步,当坡度变化平缓时,你会迈大步。

公式
s : = β s + ( 1 − β ) ( ∇ θ J ( θ ) ) 2 s := \beta s + (1 - \beta) (\nabla_{\theta} J(\theta))^2 s:=βs+(1−β)(∇θJ(θ))2
θ : = θ − η s + ϵ ∇ θ J ( θ ) \theta := \theta - \frac{\eta}{\sqrt{s + \epsilon}} \nabla_{\theta} J(\theta) θ:=θ−s+ϵ η∇θJ(θ)

其中:

  • s s s是梯度平方的加权平均值
  • ϵ \epsilon ϵ是一个小常数,防止除零错误

API
TensorFlow

python 复制代码
optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.001)

PyTorch

python 复制代码
optimizer = torch.optim.RMSprop(model.parameters(), lr=0.001)

RMSProp图像python代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

# 损失函数: y = x^2
def loss(x):
    return x ** 2

# 损失函数的梯度: dy/dx = 2x
def gradient(x):
    return 2 * x

# RMSProp
def rmsprop_gradient_descent(start, learning_rate, iterations, beta=0.9, epsilon=1e-8):
    x = start
    s = 0
    path = [x]
    for i in range(iterations):
        grad = gradient(x)
        s = beta * s + (1 - beta) * grad**2
        x = x - learning_rate * grad / (np.sqrt(s) + epsilon)
        path.append(x)
    return path

# 参数
start = 10
learning_rate = 0.1
iterations = 20

# 运行梯度下降
path = rmsprop_gradient_descent(start, learning_rate, iterations)

# 绘制图像
x = np.linspace(-10, 10, 100)
y = loss(x)
plt.plot(x, y, label='Loss Function')
plt.scatter(path, [loss(p) for p in path], color='red', label='RMSProp Path')
plt.xlabel('x')
plt.ylabel('Loss')
plt.legend()
plt.title('RMSProp Gradient Descent')
plt.show()
  • RMSProp动态调整学习率,通过对梯度平方的加权平均值进行调整,适用于处理非平稳目标。
6. Adam(Adaptive Moment Estimation)

生活中的例子

你在移动时,结合动量法和RMSProp的优点,不仅考虑之前的移动方向(动量),还根据最近一段时间内的坡度变化情况(调整步幅),从而使移动更加平稳和高效。

公式
m : = β 1 m + ( 1 − β 1 ) ∇ θ J ( θ ) m := \beta_1 m + (1 - \beta_1) \nabla_{\theta} J(\theta) m:=β1m+(1−β1)∇θJ(θ)
v : = β 2 v + ( 1 − β 2 ) ( ∇ θ J ( θ ) ) 2 v := \beta_2 v + (1 - \beta_2) (\nabla_{\theta} J(\theta))^2 v:=β2v+(1−β2)(∇θJ(θ))2
m ^ : = m 1 − β 1 t \hat{m} := \frac{m}{1 - \beta_1^t} m^:=1−β1tm
v ^ : = v 1 − β 2 t \hat{v} := \frac{v}{1 - \beta_2^t} v^:=1−β2tv
θ : = θ − η m ^ v ^ + ϵ \theta := \theta - \eta \frac{\hat{m}}{\sqrt{\hat{v}} + \epsilon} θ:=θ−ηv^ +ϵm^

其中:

  • m m m和 v v v分别是梯度的一阶和二阶动量
  • β 1 \beta_1 β1和 β 2 \beta_2 β2是动量系数(通常分别取0.9和0.999)
  • m ^ \hat{m} m^和 v ^ \hat{v} v^是偏差校正后的动量项
  • t t t是时间步

API
TensorFlow

python 复制代码
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)

PyTorch

python 复制代码
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

Adam图像python代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

# 损失函数: y = x^2
def loss(x):
    return x ** 2

# 损失函数的梯度: dy/dx = 2x
def gradient(x):
    return 2 * x

# Adam
def adam_gradient_descent(start, learning_rate, iterations, beta1=0.9, beta2=0.999, epsilon=1e-8):
    x = start
    m = 0
    v = 0
    path = [x]
    for t in range(1, iterations + 1):
        grad = gradient(x)
        m = beta1 * m + (1 - beta1) * grad
        v = beta2 * v + (1 - beta2) * grad**2
        m_hat = m / (1 - beta1**t)
        v_hat = v / (1 - beta2**t)
        x = x - learning_rate * m_hat / (np.sqrt(v_hat) + epsilon)
        path.append(x)
    return path

# 参数
start = 10
learning_rate = 0.1
iterations = 20

# 运行梯度下降
path = adam_gradient_descent(start, learning_rate, iterations)

# 绘制图像
x = np.linspace(-10, 10, 100)
y = loss(x)
plt.plot(x, y, label='Loss Function')
plt.scatter(path, [loss(p) for p in path], color='red', label='Adam Path')
plt.xlabel('x')
plt.ylabel('Loss')
plt.legend()
plt.title('Adam Gradient Descent')
plt.show()
  • Adam结合动量法和RMSProp的优点,自适应调整学习率,适用于各种优化问题。

综合应用示例

假设我们在使用TensorFlow和PyTorch训练一个简单的神经网络,以下是如何应用这些优化方法的示例代码。

TensorFlow 示例

python 复制代码
import tensorflow as tf

# 定义模型
model = tf.keras.Sequential([
    tf.keras.layers.Dense(128, activation='relu', input_shape=(784,)),
    tf.keras.layers.Dense(10, activation='softmax')
])

# 编译模型并选择优化器
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# 准备数据
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# 训练模型
model.fit(x_train, y_train, epochs=10, batch_size=32)

PyTorch 示例

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 定义模型
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(784, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

model = SimpleNN()

# 选择优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

# 准备数据
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)

# 训练模型
for epoch in range(10):
    for batch in train_loader:
        x_train, y_train = batch
        x_train = x_train.view(x_train.size(0), -1)  # Flatten the images

        optimizer.zero_grad()
        outputs = model(x_train)
        loss = criterion(outputs, y_train)
        loss.backward()
        optimizer.step()

综合对比

优化方法 优点 缺点 可能出现的问题 适用场景
批量梯度下降(Batch GD) 收敛稳定,适用于小规模数据集 每次迭代计算开销大,速度慢 难以处理大规模数据,容易陷入局部最优 小规模数据集,适合精确收敛
随机梯度下降(SGD) 计算效率高,适用于大规模数据集 路径不稳定,波动较大 收敛路径抖动大,不稳定 大规模数据集,在线学习,快速迭代
小批量梯度下降(Mini-Batch GD) 平衡了计算效率和收敛稳定性 需要选择合适的小批量大小,计算量仍然较大 小批量大小选择不当可能影响收敛效果 大规模数据集,适合批量计算
动量法(Momentum) 加速收敛,减少震荡 需要调整动量系数,增加了参数选择的复杂性 动量系数选择不当可能导致过冲 深度神经网络训练,加速收敛
RMSProp 动态调整学习率,适应非平稳目标 需要调整参数β和ε,参数选择复杂 参数选择不当可能影响收敛效果 非平稳目标,复杂优化问题
Adam 结合动量法和RMSProp优点,自适应调整学习率,收敛快 需要调整多个参数,计算复杂性高 参数选择不当可能影响收敛效果 各种优化问题,特别是深度学习模型训练

更多问题咨询

CosAI

相关推荐
这个男人是小帅30 分钟前
【GAT】 代码详解 (1) 运行方法【pytorch】可运行版本
人工智能·pytorch·python·深度学习·分类
__基本操作__31 分钟前
边缘提取函数 [OPENCV--2]
人工智能·opencv·计算机视觉
Doctor老王36 分钟前
TR3:Pytorch复现Transformer
人工智能·pytorch·transformer
热爱生活的五柒36 分钟前
pytorch中数据和模型都要部署在cuda上面
人工智能·pytorch·深度学习
HyperAI超神经3 小时前
【TVM 教程】使用 Tensorize 来利用硬件内联函数
人工智能·深度学习·自然语言处理·tvm·计算机技术·编程开发·编译框架
扫地的小何尚4 小时前
NVIDIA RTX 系统上使用 llama.cpp 加速 LLM
人工智能·aigc·llama·gpu·nvidia·cuda·英伟达
埃菲尔铁塔_CV算法7 小时前
深度学习神经网络创新点方向
人工智能·深度学习·神经网络
艾思科蓝-何老师【H8053】7 小时前
【ACM出版】第四届信号处理与通信技术国际学术会议(SPCT 2024)
人工智能·信号处理·论文发表·香港中文大学
weixin_452600697 小时前
《青牛科技 GC6125:驱动芯片中的璀璨之星,点亮 IPcamera 和云台控制(替代 BU24025/ROHM)》
人工智能·科技·单片机·嵌入式硬件·新能源充电桩·智能充电枪
学术搬运工7 小时前
【珠海科技学院主办,暨南大学协办 | IEEE出版 | EI检索稳定 】2024年健康大数据与智能医疗国际会议(ICHIH 2024)
大数据·图像处理·人工智能·科技·机器学习·自然语言处理