前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >9种神经网络优化算法详解

9种神经网络优化算法详解

原创
作者头像
皮大大
发布于 2025-02-07 01:47:45
发布于 2025-02-07 01:47:45
49902
代码可运行
举报
文章被收录于专栏:深度学习深度学习
运行总次数:2
代码可运行

公众号:尤而小屋 编辑:Peter 作者:Peter

大家好,我是Peter~

深度学习中,有一个“损失loss”的概念,它告诉我们:模型在训练数据中表现的“多差”。

现在,我们需要利用这个损失来训练我们的网络,使其表现得更好。本质上,我们需要做的是利用损失并尝试将其最小化,因为较低的损失意味着我们的模型将会表现得更好。最小化(或最大化)任何数学表达式的这个过程被称为优化

理解全局最小化和局部最小化

  • 局部最小化:Local Minima
  • 全局最小化:Global Minima

优化器如何工作

优化器是用于改变神经网络属性(例如权重和学习率)的算法或方法,以减少损失。优化器通过最小化函数来解决优化问题。

为了更好地理解优化器的作用,可以想象一个蒙着眼睛的登山者试图走下一座山。无法确切知道他该往哪个方向走,但他能判断自己是在下山(取得进展)还是在上山(失去进展)。只要他一直朝着下山的方向前进,最终就能到达山脚。

正在上传图片...

同样,在训练神经网络时,我们无法从一开始就确定模型的权重应该是什么,但可以通过基于损失函数的不断调整(类似于判断登山者是否在下山)来逐步接近目标。

优化器的作用就在于此: 它决定了如何调整神经网络的权重和学习率以减少损失。优化算法通过不断优化损失函数,帮助模型尽可能地输出准确的结果。

9种优化器

列举9种不同类型的优化器以及它们是如何精确地工作以最小化损失函数的。

  1. Gradient Descent
  2. Stochastic Gradient Descent, SGD
  3. Mini-Batch Stochastic Gradient Descent, MB-SGD
  4. SGD with Momentum
  5. Nesterov Accelerated Gradient, NAG
  6. Adaptive Gradient, AdaGrad
  7. AdaDelta
  8. RMSprop
  9. Adam

梯度下降Gradient Descent

基本思想

梯度下降(Gradient Descent)是一种优化算法,用于寻找可微函数的局部最小值。其目标是通过迭代调整模型参数,最小化代价函数(Cost Function)。以下是梯度下降算法的基本思想:

  • 目标:找到模型参数的最优值,使得代价函数达到最小值。
  • 方法:利用函数的梯度(即导数)来确定参数调整的方向。梯度(Gradient)指的是函数在某一点的梯度是一个向量,指向函数增长最快的方向。

到底什么是梯度?

"A gradient measures how much the output of a function changes if you change the inputs a little bit." — Lex Fridman (MIT)

梯度下降的核心思想是:沿着梯度的反方向(即函数下降最快的方向)调整参数

算法步骤

  1. 初始化参数
    • 选择初始参数值(通常随机初始化或使用特定策略)。
    • 设置学习率(Learning Rate),学习率决定了每次迭代中参数更新的步长。
  2. 计算梯度: 计算代价函数对每个参数的偏导数,得到梯度向量。
  3. 更新参数: 使用梯度下降更新公式调整参数: $$

\theta = \theta - \alpha \cdot \nabla J(\theta)

$$

其中:

  • $\theta\$ 是模型参数。
  • $\alpha\$ 是学习率。
  • $\nabla J(\theta)$ 是代价函数 $J(\theta)\$ 对参数 $\theta\$ 的梯度。

重复计算梯度和更新参数的过程,直到满足终止条件(如收敛或达到最大迭代次数)。

收敛条件

  • 收敛判断:当代价函数的变化量小于某个阈值,或梯度的范数小于某个阈值时,认为算法收敛。
  • 停止条件:可以设置最大迭代次数,防止算法陷入无限循环。

学习率的作用

  • 学习率的选择
    • 如果学习率过大,可能导致参数更新过度,使代价函数无法收敛甚至发散。
    • 如果学习率过小,会使收敛速度过慢,增加训练时间。
  • 动态调整学习率:在训练过程中,可以采用动态调整学习率的策略,如学习率衰减(Learning Rate Decay),以加速收敛。

通过图像的形式描述不同学习率的过程:

可以看到学习率不能过大或过小。

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
for i in range(nb_epochs):   
    params_grad = evaluate_gradient(loss_function, data, params)           
    params = params - learning_rate * params_grad

优缺点

Advantages:

  1. 计算简单
  2. 实现容易
  3. 容易理解

Disadvantages:

  1. 可能陷入局部最小值。
  2. 权重是在计算整个数据集的梯度之后才更新的。因此,如果数据集太大,可能需要花费较长时间才能收敛到最小值。
  3. 需要大量内存来计算整个数据集的梯度。

案例

线性回归+梯度下降:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

# 生成模拟数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)  # 100个随机数据点
y = 4 + 3 * X + np.random.randn(100, 1)  #  y = 4 + 3x + 噪声

# 添加偏置项
X_b = np.c_[np.ones((100, 1)), X]  # 在X中添加一列1,作为偏置项

# 初始化参数
w = np.random.randn(2, 1)  # 随机初始化参数w和b
learning_rate = 0.01  # 学习率
n_iterations = 1000  # 迭代次数

# 梯度下降
for iteration in range(n_iterations):
    y_pred = X_b.dot(w)  # 计算预测值
    gradients = 2 / len(X_b) * X_b.T.dot(y_pred - y)  # 计算梯度
    w = w - learning_rate * gradients  # 更新参数

    # 每隔一定次数打印损失
    if iteration % 100 == 0:
        loss = np.mean((y_pred - y) ** 2)
        print(f"Iteration {iteration}: Loss = {loss}")

# 打印最终结果
print(f"Optimal parameters: w = {w[1][0]}, b = {w[0][0]}")

# 可视化结果
plt.scatter(X, y, color='blue', label='Data points')
plt.plot(X, X_b.dot(w), color='red', label='Fitted line')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.show()

每100次输出一次Loss值:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
Iteration 0: Loss = 82.6630580098186
Iteration 100: Loss = 1.03474536503957
Iteration 200: Loss = 1.0053717575274455
Iteration 300: Loss = 0.9992232039352024
Iteration 400: Loss = 0.9959987975896929
Iteration 500: Loss = 0.9943068126783625
Iteration 600: Loss = 0.9934189550799246
Iteration 700: Loss = 0.9929530578311317
Iteration 800: Loss = 0.9927085814119238
Iteration 900: Loss = 0.992580294070233
Optimal parameters: w = 2.9827303563323175, b = 4.20607718142562

随机梯度下降Stochastic Gradient Descent (SGD)

定义

随机梯度下降(SGD)是一种优化算法,用于在训练机器学习模型时最小化损失函数。它是梯度下降算法的一种扩展,通过每次只使用一个训练样本(或少量样本)来计算梯度,从而减少计算量和内存需求。

基本思想

目标:通过迭代更新模型参数,最小化损失函数 J(θ)。

方法:每次只使用一个训练样本 (x(i),y(i)) 来计算梯度,并更新参数。

在SGD算法中,每次只取一个数据点来计算导数

SGD(随机梯度下降)针对每个训练样本 x(i) 和对应的标签 y(i) 进行参数更新。

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
θ = θ − α⋅∂(J(θ;x(i),y(i)))/∂θ

对比随机梯度下降SGD和梯度下降GD:

在左边,随机梯度下降(SGD,其中每步 m=1)为每个样本进行一次梯度下降步骤;而在右边是完整的梯度下降(每整个训练集进行1次步骤)。

观察结果表明,在SGD中,更新需要比梯度下降更多的迭代次数才能到达最小值。在右边,梯度下降到达最小值的步数更少,但SGD算法更“嘈杂”,需要更多的迭代次数。

在TensorFlow中的使用:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from tensorflow.keras.optimizers import SGD 
optimizer = SGD(learning_rate=0.01, momentum=0.0, nesterov=False

算法步骤

  • 初始化参数:
    • 随机初始化模型参数 θ。
    • 设置学习率 α。
  • 迭代更新:
    • 对于每个训练样本 (x(i),y(i)):
    • 计算损失函数 J(θ) 关于参数 θ 的梯度 ∇J(θ)。
  • 更新参数:
    • θ=θ−α⋅∇J(θ)
  • 重复步骤:

重复上述过程,直到满足终止条件(如收敛或达到最大迭代次数)。

SGD的代码片段只是在训练样本上增加了一个循环,并针对每个样本计算梯度

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
for i in range(nb_epochs):
    np.random.shuffle(data)
    for example in data:
        params_grad = evaluate_gradient(loss_function, example, params)
        params = params - learning_rate * params_grad

优缺点

Advantages:

  • 计算效率高:每次只处理一个样本,计算量小,适合大规模数据集。
  • 内存需求低:不需要一次性加载整个数据集,节省内存。
  • 实时更新:参数在每个样本后更新,能够快速响应数据的变化。

Disadvantages:

  • 噪声大:每次更新基于单个样本,梯度估计可能不准确,导致更新过程“嘈杂”。
  • 收敛速度慢:可能需要更多迭代次数才能收敛到最小值。
  • 易陷入局部最小值:由于更新的随机性,可能在局部最小值附近徘徊。

随机梯度下降(SGD)通过每次只处理一个样本,减少了计算量和内存需求,同时保持了快速的参数更新能力。

虽然存在一定的噪声和收敛速度较慢的问题,但通过适当的调整学习率和优化策略,SGD在许多实际应用中表现出色。

案例

线性回归+随机梯度下降:

代码语言:python
代码运行次数:1
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)
X = 2 * np.random.rand(100, 1)  # 生成100个随机数据点
y = 4 + 3 * X + np.random.randn(100, 1)  # 真实关系 y = 4 + 3x + 噪声

# 偏置
X_b = np.c_[np.ones((100, 1)), X]  # 在X中添加一列1,作为偏置项

# 初始化参数
w = np.random.randn(2, 1)  # 随机初始化参数w和b
learning_rate = 0.01  # 学习率
n_iterations = 1000  # 迭代次数
m = len(X_b)  # 样本数量

# 随机梯度下降
for iteration in range(n_iterations):
    # 重点:随机选择一个样本
    random_index = np.random.randint(m)
    xi = X_b[random_index:random_index + 1]
    yi = y[random_index:random_index + 1]
    
    # 计算梯度
    gradients = 2 * xi.T.dot(xi.dot(w) - yi)
    # 更新参数
    w = w - learning_rate * gradients
    
    # 每隔100次数打印损失
    if iteration % 100 == 0:
        y_pred = X_b.dot(w)
        loss = np.mean((y_pred - y) ** 2)
        print(f"Iteration {iteration}: Loss = {loss}")

print(f"Optimal parameters: w = {w[1][0]}, b = {w[0][0]}")

plt.scatter(X, y, color='blue', label='Data points')
plt.plot(X, X_b.dot(w), color='red', label='Fitted line')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.show()

# 结果
Iteration 0: Loss = 69.02554947814826
Iteration 100: Loss = 1.0436708721159689
Iteration 200: Loss = 1.041294923577367
Iteration 300: Loss = 1.010387875806174
Iteration 400: Loss = 1.0070132665208844
Iteration 500: Loss = 1.091486693566191
Iteration 600: Loss = 0.9986328028787116
Iteration 700: Loss = 1.0340118681106303
Iteration 800: Loss = 0.9984103484305885
Iteration 900: Loss = 1.0082506511215945
Optimal parameters: w = 3.052173302887621, b = 4.352670551847081

小批量随机梯度下降(Mini Batch Stochastic Gradient Descent, MB-SGD)

小批量随机梯度下降(Mini Batch Stochastic Gradient Descent, MB-SGD)是梯度下降算法的一种改进,结合了批量梯度下降(Batch Gradient Descent)和随机梯度下降(Stochastic Gradient Descent, SGD)的优点。

它通过每次使用一个小批量(Mini-Batch)的数据来计算梯度,从而在计算效率和稳定性之间取得平衡。

基本思想

目标:通过迭代更新模型参数,最小化损失函数 J(θ)。

方法:每次从训练集中随机抽取一个小批量的数据(通常包含几十个样本),计算该小批量数据的梯度,并更新参数。

算法步骤

  • 初始化参数:
    • 随机初始化模型参数θ。
    • 设置学习率α。
    • 定义小批量的大小m(通常为2的幂,如32、64、128等)。
  • 划分数据集:

将整个训练集划分为若干个小批量,每个小批量包含 m 个样本。

  • 迭代更新: $$ \nabla J(\theta) = \frac{1}{m} \sum_{i=1}^{m} \nabla J(\theta; x^{(i)}, y^{(i)}) $$
  • 更新参数: $$ \theta = \theta - \alpha \cdot \nabla J(\theta) $$ 重复步骤: 重复上述过程,直到满足终止条件(如收敛或达到最大迭代次数)。

使用mini-batches参数:

代码语言:python
代码运行次数:1
运行
AI代码解释
复制
for i in range(nb_epochs):
    np.random.shuffle(data)
    for batch in get_batches(data, batch_size=50):
        params_grad = evaluate_gradient(loss_function, batch, params)
        params = params - learning_rate * params_grad

Advantages:

  • 相比于标准的随机梯度下降(SGD)算法,收敛的时间复杂度更低。

Disadvantages::

  • 与梯度下降(GD)算法相比,小批量随机梯度下降(MB-SGD)的更新过程更加“嘈杂”。
  • 比梯度下降(GD)算法需要更长时间才能收敛。
  • 可能会陷入局部最小值。

案例

逻辑回归+小批量随机梯度下降:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

# 生成一些简单的二分类数据
np.random.seed(42)
X = np.random.randn(100, 2)  # 100个样本,每个样本有2个特征
y = (X[:, 0] + X[:, 1] > 0).astype(int)  # 标签,根据两个特征之和是否大于0来分类

# 添加偏置项
X_b = np.c_[np.ones((100, 1)), X]

# 初始化参数
theta = np.random.randn(3)

# 定义sigmoid函数
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

# 小批量随机梯度下降
def mini_batch_gradient_descent(X, y, theta, learning_rate=0.01, batch_size=10, epochs=100):
    m = len(y)
    for epoch in range(epochs):
        indices = np.random.permutation(m)
        X_shuffled = X[indices]
        y_shuffled = y[indices]
        for i in range(0, m, batch_size):
            xi = X_shuffled[i:i+batch_size]
            yi = y_shuffled[i:i+batch_size]
            gradients = xi.T.dot(sigmoid(xi.dot(theta)) - yi) / len(yi)
            theta -= learning_rate * gradients
        if epoch % 10 == 0:
            loss = -np.mean(yi * np.log(sigmoid(xi.dot(theta))) + (1 - yi) * np.log(1 - sigmoid(xi.dot(theta))))
            print(f'Epoch {epoch}, Loss: {loss}')
    return theta

# 训练模型
learning_rate = 0.1
batch_size = 10
epochs = 100
theta = mini_batch_gradient_descent(X_b, y, theta, learning_rate, batch_size, epochs)

print("Trained parameters:", theta)

# 预测函数
def predict(X, theta):
    probabilities = sigmoid(X.dot(theta))
    return probabilities >= 0.5

# 测试模型
predictions = predict(X_b, theta)
accuracy = np.mean(predictions == y)
print(f"Accuracy: {accuracy * 100:.2f}%")

# 可视化模型和预测效果
def plot_decision_boundary(X, y, theta):
    plt.figure(figsize=(10, 6))
    plt.scatter(X[:, 1], X[:, 2], c=y, marker='o', cmap='winter')
    x1_min, x1_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    x2_min, x2_max = X[:, 2].min() - 1, X[:, 2].max() + 1
    xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max, 100), np.linspace(x2_min, x2_max, 100))
    grid = np.c_[np.ones((xx1.ravel().shape[0], 1)), xx1.ravel(), xx2.ravel()]
    Z = sigmoid(grid.dot(theta)).reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.3, cmap='winter')
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    plt.title('Decision Boundary and Data Points')
    plt.show()

# 调用绘图函数
plot_decision_boundary(X_b, y, theta)

# 结果
Epoch 0, Loss: 0.424476004585312
Epoch 10, Loss: 0.2950600705690528
Epoch 20, Loss: 0.19517955198064607
Epoch 30, Loss: 0.07305972705615815
Epoch 40, Loss: 0.15634434000393793
Epoch 50, Loss: 0.09763985480946141
Epoch 60, Loss: 0.22901934823973308
Epoch 70, Loss: 0.06952644778550963
Epoch 80, Loss: 0.12401363486230814
Epoch 90, Loss: 0.05268405861771795
Trained parameters: [-0.17306619  3.80492488  3.80846526]
Accuracy: 99.00%

SGD with Momentum

基本原理

小批量随机梯度下降(MB-SGD)算法的一个主要缺点是权重更新非常“嘈杂”。带动量的随机梯度下降(SGD with Momentum)通过降噪梯度克服了这一缺点,它在传统的随机梯度下降(SGD)的基础上引入了动量Momentum机制,在每次更新时,通过考虑历史梯度信息来加速收敛并减少噪声。

算法步骤

  1. 初始化参数
  2. 随机初始化模型参数 $\theta$
  3. 初始化动量参数 v (通常初始化为零向量)。
  4. 设置学习率 $\alpha$ 和动量系数$\gamma $(通常取值为0.9或0.99)。
  5. 迭代更新
  6. 对于每个训练样本$(x^{(i)}, y^{(i)}) $ 或小批量数据: 1. 计算当前梯度$\nabla J(\theta)$: $$ \nabla J(\theta) = \frac{\partial J(\theta; x^{(i)}, y^{(i)})}{\partial \theta} $$ 2. 更新动量参数 $ v $: $$ v = \gamma \cdot v - \alpha \cdot \nabla J(\theta) $$ 其中: - $\gamma\$ 是动量系数,控制历史梯度的衰减速度。 - $\alpha\$ 是学习率,控制更新步长。 1. 更新参数$ \theta $: $$ \theta = \theta + v $$
  7. 重复步骤
  8. 重复上述过程,直到满足终止条件(如收敛或达到最大迭代次数)。

优缺点

Advantages:

  • 减少噪声:通过考虑历史梯度信息,减少了更新过程中的噪声。
  • 加速收敛:动量机制帮助模型更快地收敛到最小值,特别是在损失函数的“山谷”中。
  • 减少振荡:在接近最小值时,动量机制可以减少参数更新的振荡。

Disadvantages:

  • 超参数选择:需要选择合适的动量系数 $\gamma\$ 和学习率 $\alpha$,这可能需要一些实验和调整。
  • 计算复杂度:虽然每次更新的计算量与SGD相当,但引入动量机制会增加一些额外的计算开销。

在TensorFlow中的使用:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from tensorflow.keras.optimizers import SGD 
optimizer = SGD(learning_rate=0.01, momentum=0.9, nesterov=False)

案例

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

# 生成一些随机数据
np.random.seed(42)
X = np.random.randn(200, 2)
y = np.logical_xor(X[:, 0] > 0, X[:, 1] > 0)
y = y.astype(int)

# 定义激活函数和其导数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return x * (1 - x)

# 定义网络结构
input_size = 2
hidden_size = 4
output_size = 1

# 初始化参数
W1 = np.random.randn(input_size, hidden_size)
b1 = np.zeros((1, hidden_size))
W2 = np.random.randn(hidden_size, output_size)
b2 = np.zeros((1, output_size))

# 超参数
learning_rate = 0.01
momentum = 0.9
n_iterations = 10000

# 动量初始化
velocity_W1 = np.zeros_like(W1)
velocity_b1 = np.zeros_like(b1)
velocity_W2 = np.zeros_like(W2)
velocity_b2 = np.zeros_like(b2)

# SGD with Momentum
for iteration in range(n_iterations):
    # 前向传播
    hidden_input = np.dot(X, W1) + b1
    hidden_output = sigmoid(hidden_input)
    output_input = np.dot(hidden_output, W2) + b2
    output = sigmoid(output_input)
    
    # 计算损失
    loss = np.mean((output - y.reshape(-1, 1)) ** 2)
    
    # 反向传播
    d_output = (output - y.reshape(-1, 1)) * sigmoid_derivative(output)
    d_hidden = np.dot(d_output, W2.T) * sigmoid_derivative(hidden_output)
    
    # 计算梯度
    dW2 = np.dot(hidden_output.T, d_output)
    db2 = np.sum(d_output, axis=0, keepdims=True)
    dW1 = np.dot(X.T, d_hidden)
    db1 = np.sum(d_hidden, axis=0, keepdims=True)
    
    # 更新动量
    velocity_W2 = momentum * velocity_W2 + learning_rate * dW2
    velocity_b2 = momentum * velocity_b2 + learning_rate * db2
    velocity_W1 = momentum * velocity_W1 + learning_rate * dW1
    velocity_b1 = momentum * velocity_b1 + learning_rate * db1
    
    # 更新参数
    W2 = W2 - velocity_W2
    b2 = b2 - velocity_b2
    W1 = W1 - velocity_W1
    b1 = b1 - velocity_b1
    
    # 打印损失
    if iteration % 1000 == 0:
        print(f"Iteration {iteration}, Loss: {loss}")

# 绘制决策边界
def plot_decision_boundary(X, y, model):
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),
                         np.arange(y_min, y_max, 0.01))
    Z = model(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    plt.contourf(xx, yy, Z, alpha=0.8)
    plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', marker='o')
    plt.xlabel("X1")
    plt.ylabel("X2")
    plt.title("Decision Boundary")
    plt.show()

# 定义模型预测函数
def predict(X):
    hidden_input = np.dot(X, W1) + b1
    hidden_output = sigmoid(hidden_input)
    output_input = np.dot(hidden_output, W2) + b2
    output = sigmoid(output_input)
    return (output > 0.5).astype(int)

# 绘制决策边界
plot_decision_boundary(X, y, predict)

# 结果
Iteration 0, Loss: 0.24866396311697422
Iteration 1000, Loss: 0.059649335744367704
Iteration 2000, Loss: 0.05161391737798015
Iteration 3000, Loss: 0.047237416656551276
Iteration 4000, Loss: 0.043973210315089856
Iteration 5000, Loss: 0.041256973919964544
Iteration 6000, Loss: 0.03895073389030161
Iteration 7000, Loss: 0.037002859681704706
Iteration 8000, Loss: 0.035360650108840486
Iteration 9000, Loss: 0.03396667708959878

Nesterov Accelerated Gradient, NAG

基本原理

动量法每下降一步都是由前面下降方向的一个累积和当前点的梯度方向组合而成。于是一位大神(Nesterov)就开始思考,既然每一步都要将两个梯度方向(历史梯度、当前梯度)做一个合并再下降,那为什么不先按照历史梯度往前走那么一小步,按照前面一小步位置的“超前梯度”来做梯度合并呢?

如此一来,小球就可以先不管三七二十一先往前走一步,在靠前一点的位置看到梯度,然后按照那个位置再来修正这一步的梯度方向。如此一来,有了超前的眼光,小球就会更加”聪明“, 这种方法被命名为Nesterov accelerated gradient 简称 NAG

Nesterov Accelerated Gradient(NAG)是一种改进的梯度下降优化算法,它在传统的动量优化算法的基础上引入了“前瞻性”更新机制,从而提高了收敛速度并减少了震荡

NAG的核心思想是在计算梯度时:

  • 先根据之前的动量方向进行一个预期的更新
  • 然后再根据这个预期位置计算梯度。

这种方法使得参数更新更加“前瞻”,避免了传统动量方法中可能出现的过冲问题。

数学公式

记$vt$为第t次迭代梯度的累积:

  1. 初始化:$ v_0 = 0 $
  2. 第一次迭代: $v1 = \eta \nabla\theta J(\theta) $
  3. 第二次迭代:$ v2 = \gamma v_1 + \eta \nabla\theta J(\theta - \gamma v_1) $
  4. 一般迭代规则(第 ( t ) 次迭代):$ vt = \gamma v{t-1} + \eta \nabla\theta J(\theta - \gamma v{t-1}) $

其中:

  • $ \eta $ 是学习率
  • $ \gamma $ 是动量系数
  • $ \nabla_\theta J(\theta) $是损失函数$J$关于参数$ \theta $的梯度

在TensorFlow中的使用:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
from tensorflow.keras.optimizers import SGD 
optimizer = SGD(learning_rate=0.01, momentum=0.9, nesterov=True)

案例

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

class LogisticRegressionNAG:
    def __init__(self, learning_rate=0.01, momentum=0.9, n_iters=1000):
        self.learning_rate = learning_rate
        self.momentum = momentum
        self.n_iters = n_iters
        self.weights = None
        self.bias = None
        self.v_w = None
        self.v_b = None

    def sigmoid(self, z):
        return 1 / (1 + np.exp(-z))

    def fit(self, X, y):
        n_samples, n_features = X.shape
        self.weights = np.zeros(n_features)
        self.bias = 0
        self.v_w = np.zeros(n_features)
        self.v_b = 0
        losses = []  # 用于记录损失值

        for _ in range(self.n_iters):
            # 临时更新
            temp_weights = self.weights - self.momentum * self.v_w
            temp_bias = self.bias - self.momentum * self.v_b
            # 计算梯度
            linear_model = np.dot(X, temp_weights) + temp_bias
            y_pred = self.sigmoid(linear_model)
            dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
            db = (1 / n_samples) * np.sum(y_pred - y)
            # 更新动量项
            self.v_w = self.momentum * self.v_w + self.learning_rate * dw
            self.v_b = self.momentum * self.v_b + self.learning_rate * db
            # 更新参数
            self.weights = self.weights - self.v_w
            self.bias -= self.v_b
            # 记录损失值
            loss = np.mean(-y * np.log(y_pred) - (1 - y) * np.log(1 - y_pred))
            losses.append(loss)
        
        # 绘制损失曲线
        plt.figure()
        plt.plot(range(self.n_iters), losses, label="Loss")
        plt.title("Loss Curve for Logistic Regression with NAG")
        plt.xlabel("Iterations")
        plt.ylabel("Loss")
        plt.legend()
        plt.show()

    def predict(self, X):
        linear_model = np.dot(X, self.weights) + self.bias
        y_pred = self.sigmoid(linear_model)
        return np.where(y_pred > 0.5, 1, 0)

# 生成数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = (X > 1).astype(int).ravel()  # 生成二分类标签

# 训练模型
model = LogisticRegressionNAG(learning_rate=0.1, momentum=0.9, n_iters=1000)
model.fit(X, y)

# 预测
X_new = np.array([[0], [2]])
y_pred = model.predict(X_new)

# 绘制预测结果
plt.figure()
plt.scatter(X, y, color='blue', label="Actual")
plt.scatter(X_new, y_pred, color='red', label="Predicted")
plt.title("Logistic Regression with NAG")
plt.xlabel("X")
plt.ylabel("y")
plt.legend()
plt.show()

不同迭代次数下的模型损失loss

经过NAG优化后的模型的预测效果(红点)

Adaptive Gradient, AdaGrad

对于之前讨论的所有算法,学习率都是固定的

Adaptive Gradient(AdaGrad)算法是一种自适应学习的优化算法,于2011年由Duchi等人提出,它能够根据参数的历史梯度自适应地调整学习率

核心思想

AdaGrad的核心思想是对每个参数的学习率进行适应性调整,从而实现对参数的不同历史梯度的平方和进行自适应调整。

具体来说,AdaGrad通过累积过去所有梯度的平方和来为每个参数动态调整学习率,使得较少更新频繁出现的特征参数具有更大的学习率,而较频繁更新的特征参数则具有更小的学习率。

数学原理

  1. 梯度计算: $$ g = \nabla{\theta{k-1}} L(\theta) $$ 计算损失函数 $ L(\theta)$ 关于参数 $\theta $ 在第 $k-1$ 次迭代时的梯度 $g $ ;其中$\nabla{\theta}$表示梯度运算符,$\theta{k-1}$表示上一步的参数值。
  2. 累积梯度平方和更新:

$$

rk = r{k-1} + g \odot g

$$

在第 k 次迭代时,将当前梯度 g 的平方(逐元素相乘)累加到之前的累积梯度平方和 $ r_{k-1} $ 上,得到新的累积梯度平方和 $ r_k $ 。其中,$\odot$表示元素乘法(即Hadamard乘积)。

  1. 自适应学习率计算: $$ \eta = \frac{\eta_0}{\sqrt{r_k + \epsilon}} $$ 计算自适应学习率,其中 $ \eta_0 $ 是初始学习率, $ r_k $ 是当前的累积梯度平方和, $ \epsilon $ 是一个小的正数(防止除零错误)。通过累积梯度平方和$r_k$来调整学习率$\epsilon$;这样的调整使得学习率对于出现频繁的特征会更小,而对于稀疏特征会更大,有助于提高模型在稀疏数据上的性能
  2. 参数更新: $$ \theta_k = \theta - \eta g $$

完整形式:

$$

\thetak = \theta - \frac{\eta_0}{\sqrt{r_k + \epsilon}} * \nabla{\theta_{k-1}} L(\theta)

$$

使用计算出的自适应学习率 $ \eta $ 和梯度 $ g $ 来更新参数 $ \theta $ 到新值 $ \theta_k $ ,目的是减少损失函数 $ L(\theta) $ 的值。

优缺点

Advantage: 不需要手动更新学习率

Disadvantage:

  • 学习率持续衰减:由于累积的平方梯度持续增加,学习率会持续衰减,最终导致学习率过小,从而使得训练后期模型难以收敛。
  • 存储梯度平方和:需要为每个参数存储一个累积的梯度平方和,这在参数很多时会增加额外的内存开销。

案例

以下是一个基于Adaptive Gradient(AdaGrad)优化算法的Python代码示例,并附带了优化过程的可视化效果。我们将使用一个简单的二维函数 $f(x)=x_1^2+x_2^2$ 来展示优化过程,并通过Matplotlib绘制优化路径。

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

# 定义目标函数
def f(x):
    return x[0]**2 + x[1]**2  # 示例函数:f(x) = x1^2 + x2^2

# 定义目标函数的梯度
def grad_f(x):
    return np.array([2*x[0], 2*x[1]])  # 示例函数的梯度

# AdaGrad优化算法
def Adagrad(x_init, step_size, n_iters):
    eta = step_size
    G_t = 0  # 累积梯度的平方
    eps = 1e-8  # 防止分母为零的小常数
    theta = np.tile(x_init, (n_iters, 1))  # 初始化参数
    z = np.tile([f(x_init)], n_iters)  # 初始化目标函数值

    for k in range(1, n_iters):
        # 计算梯度
        g_t = grad_f(theta[k-1])
        # 累积梯度的平方
        G_t += g_t**2
        # 更新参数
        theta[k] = theta[k-1] - eta * g_t / (np.sqrt(G_t) + eps)
        # 计算目标函数值
        z[k] = f(theta[k])

    # 返回优化过程中的参数和目标函数值
    return theta, z

# 初始化参数
x_init = np.array([1.0, 1.0])  # 初始参数
step_size = 0.1  # 学习率
n_iters = 50  # 迭代次数

# 运行AdaGrad优化算法
theta, z = Adagrad(x_init, step_size, n_iters)

# 可视化优化过程
# 绘制目标函数的等高线图
x1 = np.linspace(-2, 2, 400)
x2 = np.linspace(-2, 2, 400)
X1, X2 = np.meshgrid(x1, x2)
Z = X1**2 + X2**2

plt.figure(figsize=(10, 6))
contour = plt.contour(X1, X2, Z, levels=50, cmap='viridis')
plt.clabel(contour, inline=True, fontsize=8)
plt.title("AdaGrad Optimization Path")
plt.xlabel("x1")
plt.ylabel("x2")

# 绘制优化路径
plt.plot(theta[:, 0], theta[:, 1], 'r-', linewidth=2, label="AdaGrad Path")
plt.scatter(theta[:, 0], theta[:, 1], c='r', s=50, zorder=5)
plt.scatter([0], [0], c='g', s=100, label="Global Minimum")

plt.legend()
plt.show()

AdaDelta

基本原理

AdaGrad存在的问题是,随着迭代次数的增加,学习率会变得非常小,这导致收敛速度变慢。为了避免这个问题,AdaDelta算法采用了一种想法,即取梯度的指数衰减平均值

AdaDelta是Adagrad的一个更稳健的扩展,它根据梯度更新的移动窗口来调整学习率,而不是累积所有过去的梯度。这样,即使进行了很多次更新,AdaDelta也能够继续学习。

AdaDelta算法并没有低效地存储过去的平方梯度,而是将梯度的累积和递归地定义为所有过去平方梯度的衰减平均值。

在时间步 $t$ 的运行平均$Eg^2_t$仅依赖于先前的累积平均值和当前的梯度:

在AdaDelta算法中不需要设置默认的学习率:

优缺点

Advantage:

  1. AdaDelta不需要手动设置学习率,因为它会根据迭代过程中的梯度信息来自适应地调整学习率。
  2. 对稀疏数据表现良好:在处理稀疏数据时,AdaDelta能够动态调整学习率,防止学习率过快减小,从而避免收敛速度变慢的问题。
  3. 减少对初始条件的敏感性:AdaDelta对初始化条件的敏感性较低,因为它会根据训练过程中的情况进行自适应调整。

Disadvantage:

收敛速度:与一些更新的优化方法(如Adam)相比,AdaDelta可能不会那么快地收敛。

案例

对经典的Rosenbrock函数进行优化:

$$f(x,y)=(1-x)^2+100(y-x^2)^2$$

这个函数只有一个全部最小值点$f(x,y)=(1,1)$,并且在 $(0,0) $附近有一个较深的山谷

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

# 定义Rosenbrock函数
def f(x):
    return (1 - x[0])**2 + 100 * (x[1] - x[0]**2)**2

# 定义Rosenbrock函数的梯度
def grad_f(x):
    return np.array([
        -2 * (1 - x[0]) - 400 * x[0] * (x[1] - x[0]**2),
        200 * (x[1] - x[0]**2)
    ])

# AdaDelta优化算法
def adadelta_optimizer(x_init, num_iter=100, rho=0.9, epsilon=1e-8):
    """
    x_init: 初始参数
    num_iter: 迭代次数
    rho: 衰减率
    epsilon: 无穷小量
    """
    # 初始化参数
    x = x_init
    E_g2 = np.zeros_like(x)  # 梯度平方的指数加权移动平均
    E_delta_x2 = np.zeros_like(x)  # 参数更新量平方的指数加权移动平均
    x_history = [x.copy()]  # 保存优化路径
    f_history = [f(x)]  # 保存目标函数值

    for i in range(num_iter):
        # 计算梯度
        g = grad_f(x)
        # 更新梯度平方的指数加权移动平均
        E_g2 = rho * E_g2 + (1 - rho) * g**2
        # 计算参数更新量
        delta_x = -np.sqrt(E_delta_x2 + epsilon) / np.sqrt(E_g2 + epsilon) * g
        # 更新参数
        x += delta_x
        # 更新参数更新量平方的指数加权移动平均
        E_delta_x2 = rho * E_delta_x2 + (1 - rho) * delta_x**2
        # 保存优化路径和目标函数值
        x_history.append(x.copy())
        f_history.append(f(x))

    return np.array(x_history), np.array(f_history)

# 初始化参数
x_init = np.array([-1.5, 1.5])  # 初始参数
num_iter = 100  # 迭代次数

# 运行AdaDelta优化算法
x_history, f_history = adadelta_optimizer(x_init, num_iter=num_iter)

# 可视化优化过程
# 绘制Rosenbrock函数的等高线图
x1 = np.linspace(-2, 2, 400)
x2 = np.linspace(-1, 3, 400)
X1, X2 = np.meshgrid(x1, x2)
Z = (1 - X1)**2 + 100 * (X2 - X1**2)**2

plt.figure(figsize=(10, 6))
contour = plt.contour(X1, X2, Z, levels=50, cmap='viridis')
plt.clabel(contour, inline=True, fontsize=8)
plt.title("AdaDelta Optimization Path for Rosenbrock Function")
plt.xlabel("x1")
plt.ylabel("x2")

# 绘制优化路径
plt.plot(x_history[:, 0], x_history[:, 1], 'r-', linewidth=2, label="AdaDelta Path")
plt.scatter(x_history[:, 0], x_history[:, 1], c='r', s=50, zorder=5)
plt.scatter([1], [1], c='g', s=100, label="Global Minimum")

plt.legend()
plt.show()

RMSprop(Root Mean Square Propagation)

基本原理

RMSprop(Root Mean Square Propagation)算法是一种自适应学习率的优化算法,由 Geoffrey Hinton 提出,旨在解决梯度下降及其变体在优化过程中学习率固定不变时可能导致的收敛速度慢或不收敛的问题。

RMSprop通过为每个参数动态调整学习率来改进这一点,特别适用于处理非平稳目标函数。

基本原理:

  1. 初始化:
  2. 参数$\theta$
  3. 梯度平方的指数加权平均值$Eg^2$为0
  4. 设置学习率$ η $(比如0.001)
  5. 设置衰减率 ρ(比如0.9)
  6. 梯度计算

在每次迭代中,计算损失函数 $L(θ)$关于参数$θ$的梯度$g$

  1. 更新梯度平方的指数加权平均值$Eg^2$:
  1. 参数更新

使用下面的参数更新参数$\theta$

其中,$ϵ$ 是一个小的正数(例如$10^{−8}$),用于防止除零错误。

优缺点

Advantage:

  1. 自适应学习率:RMSprop为每个参数动态调整学习率,使得学习率与梯度的平方的指数加权平均值的平方根成反比。这有助于处理稀疏数据和非平稳目标函数。
  2. 防止梯度爆炸:通过限制梯度更新的幅度,RMSprop有助于防止梯度爆炸问题。
  3. 无需手动调整学习率:RMSprop自动调整学习率,减少了手动调整学习率的需求。

Disadvantage:

  1. 可能需要调整超参数:尽管RMSprop自动调整学习率,但仍然需要选择合适的衰减率 ρ 和学习率 η。
  2. 在某些情况下可能不稳定:在某些情况下,RMSprop可能不如其他优化算法(如Adam)稳定。

案例

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

# 定义Himmelblau函数
def f(x):
    return (x[0]**2 + x[1] - 11)**2 + (x[0] + x[1]**2 - 7)**2

# 定义Himmelblau函数的梯度
def grad_f(x):
    return np.array([
        4 * x[0] * (x[0]**2 + x[1] - 11) + 2 * (x[0] + x[1]**2 - 7),
        2 * (x[0]**2 + x[1] - 11) + 4 * x[1] * (x[0] + x[1]**2 - 7)
    ])

# RMSprop优化算法
def rmsprop_optimizer(x_init, num_iter=100, learning_rate=0.001, rho=0.9, epsilon=1e-8):
    """
    x_init: 初始参数
    num_iter: 迭代次数
    learning_rate: 学习率
    rho: 衰减率
    epsilon: 无穷小量
    """
    # 初始化参数
    x = x_init
    v = np.zeros_like(x)  # 梯度平方的累积
    x_history = [x.copy()]  # 保存优化路径
    f_history = [f(x)]  # 保存目标函数值

    for i in range(num_iter):
        # 计算梯度
        g = grad_f(x)
        # 更新梯度平方的累积
        v = rho * v + (1 - rho) * g**2
        # 更新参数
        x -= learning_rate * g / (np.sqrt(v) + epsilon)
        # 保存优化路径和目标函数值
        x_history.append(x.copy())
        f_history.append(f(x))

    return np.array(x_history), np.array(f_history)

# 初始化参数
x_init = np.array([0.0, 0.0])  # 初始参数
num_iter = 100  # 迭代次数

# 运行RMSprop优化算法
x_history, f_history = rmsprop_optimizer(x_init, num_iter=num_iter)

# 可视化优化过程
# 绘制Himmelblau函数的等高线图
x1 = np.linspace(-5, 5, 400)
x2 = np.linspace(-5, 5, 400)
X1, X2 = np.meshgrid(x1, x2)
Z = (X1**2 + X2 - 11)**2 + (X1 + X2**2 - 7)**2

plt.figure(figsize=(10, 6))
contour = plt.contour(X1, X2, Z, levels=50, cmap='viridis')
plt.clabel(contour, inline=True, fontsize=8)
plt.title("RMSprop Optimization Path for Himmelblau Function")
plt.xlabel("x1")
plt.ylabel("x2")

# 绘制优化路径
plt.plot(x_history[:, 0], x_history[:, 1], 'r-', linewidth=2, label="RMSprop Path")
plt.scatter(x_history[:, 0], x_history[:, 1], c='r', s=50, zorder=5)
plt.scatter([3], [2], c='g', s=100, label="Global Minimum")
plt.scatter([-2.8051, -3.7793, 3.5844], [3.1313, -3.2832, -1.8481], c='b', s=100, label="Local Minima")

plt.legend()
plt.show()

优化器9:Adaptive Moment Estimation(Adam)

在机器学习中,Adam(Adaptive Moment Estimation,自适应矩估计)作为一种高效的优化算法脱颖而出。它旨在调整每个参数的学习率。

基本原理

Adam可以看作是结合了RMSprop和带动量的随机梯度下降(SGD with Momentum)的优化算法。

Adam为每个参数计算自适应学习率。除了像AdaDelta和RMSprop那样存储过去梯度平方的指数衰减平均值$v_t$之外,Adam还维护了一个过去梯度的指数衰减平均值$m_t$,这与动量方法类似。

如果说动量可以被看作是一个在斜坡上滚动的球,那么Adam的行为则像是一个带有摩擦的重球,因此它更倾向于在误差曲面的平坦最小值处停留。

数学公式

核心:Adam通过考虑梯度的一阶矩二阶矩的移动平均值,改进了梯度下降的方法,使得它能够智能地适应每个参数的学习率。

其中,$m_k和v_k$分别是梯度的一阶矩和二阶矩的估计,$\beta_1和\beta_2$是控制两个矩估计得指数衰减率,范围在0到1之间,通常设置为0.9和0.999。$\epsilon$是个非常小的数(例如1e-8),防止除数为零。k是当前迭代的次数,用于做偏差校正。

Adam代码的核心代码:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
def adam_update(parameters, gradients, m, v, t, lr=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):
    for param, grad in zip(parameters, gradients):
        m[param] = beta1 * m[param] + (1 - beta1) * grad
        v[param] = beta2 * v[param] + (1 - beta2) * (grad ** 2)
        m_corrected = m[param] / (1 - beta1 ** t)
        v_corrected = v[param] / (1 - beta2 ** t)
        param_update = lr * m_corrected / (np.sqrt(v_corrected) + epsilon)
        param -= param_update

案例

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt

# 目标函数
def func(X):
    return 5 * X[0, 0]**2 + 2 * X[1, 0]**2 + 3 * X[0, 0] - 10 * X[1, 0] + 4

# 目标函数的梯度
def grad(X):
    grad_x1 = 10 * X[0, 0] + 3
    grad_x2 = 4 * X[1, 0] - 10
    return np.array([[grad_x1], [grad_x2]])

# Adam优化器类
class Adam:
    def __init__(self, func, grad, seed):
        self.func = func
        self.grad = grad
        self.seed = seed
        self.xPath = []
        self.JPath = []

    def get_solu(self, alpha=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8, zeta=1e-6, maxIter=1000):
        self.xPath = []
        self.JPath = []
        x = self.seed
        JVal = self.func(x)
        self.xPath.append(x)
        self.JPath.append(JVal)
        grad = self.grad(x)
        m, v = np.zeros(x.shape), np.zeros(x.shape)
        for k in range(1, maxIter + 1):
            m = beta1 * m + (1 - beta1) * grad
            v = beta2 * v + (1 - beta2) * (grad ** 2)
            m_hat = m / (1 - beta1 ** k)
            v_hat = v / (1 - beta2 ** k)
            x = x - alpha * m_hat / (np.sqrt(v_hat) + epsilon)
            JVal = self.func(x)
            self.xPath.append(x)
            self.JPath.append(JVal)
            grad = self.grad(x)
            if np.linalg.norm(grad) < zeta:
                break
        return x, JVal

# 可视化类
class AdamPlot:
    @staticmethod
    def plot_fig(adamObj):
        x, JVal = adamObj.get_solu(alpha=0.1)
        xPath = np.array(adamObj.xPath)
        JPath = adamObj.JPath
        fig = plt.figure(figsize=(12, 6))
        ax1 = plt.subplot(1, 2, 1)
        ax2 = plt.subplot(1, 2, 2)

        # 绘制损失值变化
        ax1.plot(JPath, "k.", markersize=5)
        ax1.plot(0, JPath[0], "go", label="Starting Point")
        ax1.plot(len(JPath) - 1, JPath[-1], "r*", label="Solution")
        ax1.set_xlabel("Iteration")
        ax1.set_ylabel("Loss")
        ax1.legend()

        # 绘制优化路径
        x1 = np.linspace(-10, 10, 300)
        x2 = np.linspace(-10, 10, 300)
        x1, x2 = np.meshgrid(x1, x2)
        f = 5 * x1**2 + 2 * x2**2 + 3 * x1 - 10 * x2 + 4
        ax2.contour(x1, x2, f, levels=50)
        ax2.plot(xPath[:, 0, 0], xPath[:, 1, 0], "k--", lw=2)
        ax2.plot(xPath[0, 0, 0], xPath[0, 1, 0], "go", label="Starting Point")
        ax2.plot(xPath[-1, 0, 0], xPath[-1, 1, 0], "r*", label="Solution")
        ax2.set_xlabel("$x_1$")
        ax2.set_ylabel("$x_2$")
        ax2.legend()

        plt.tight_layout()
        plt.show()

# 主程序
if __name__ == "__main__":
    seed = np.array([[1.0], [1.0]])  # 初始点
    adamObj = Adam(func, grad, seed)
    AdamPlot.plot_fig(adamObj)

参考

1、https://www.kdnuggets.com/2020/12/optimization-algorithms-neural-networks.html

2、https://blog.csdn.net/qq_38156104/article/details/106739700

3、https://medium.com/@piyushkashyap045/understanding-nesterov-accelerated-gradient-nag-340c53d64597

4、https://blog.csdn.net/m0_48923489/article/details/136854257

5、https://blog.csdn.net/m0_48923489/article/details/136863726

6、Adam: A Method for Stochastic Optimization

Diederik P. Kingma, Jimmy Ba

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
深度学习:神经网络优化技巧
在深度学习中,有一个“损失loss”的概念,它告诉我们:模型在训练数据中表现的“多差”。
皮大大
2025/05/09
770
不愧是京东,面试超开心。。。
这几天看到以为同学面试京东,给她的感觉非常不错,如果加入面试官的团队,一定会超开心。
Python编程爱好者
2024/01/20
1640
不愧是京东,面试超开心。。。
深度学习——优化器算法Optimizer详解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)
在机器学习、深度学习中使用的优化算法除了常见的梯度下降,还有 Adadelta,Adagrad,RMSProp 等几种优化器,都是什么呢,又该怎么选择呢? 在 Sebastian Ruder 的这篇论文中给出了常用优化器的比较,今天来学习一下: https://arxiv.org/pdf/1609.04747.pdf 本文将梳理: 每个算法的梯度更新规则和缺点 为了应对这个不足而提出的下一个算法 超参数的一般设定值 几种算法的效果比较 选择哪种算法 ---- 0.梯度下降法深入理解 以下为个人总结,如有错误
10JQKA
2018/05/09
8.3K0
深度学习——优化器算法Optimizer详解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)
由浅入深了解 深度神经网络优化算法
在最简单的情况下,优化问题包括通过系统地从允许集合中选择输入值并计算函数值来最大化或最小化实函数。
AiCharm
2023/06/07
4490
由浅入深了解 深度神经网络优化算法
从梯度下降到 Adam!一文看懂各种神经网络优化算法
每天给你送来NLP技术干货! ---- 编译:王小新,来源:量子位 在调整模型更新权重和偏差参数的方式时,你是否考虑过哪种优化算法能使模型产生更好且更快的效果?应该用梯度下降,随机梯度下降,还是Adam方法? 这篇文章介绍了不同优化算法之间的主要区别,以及如何选择最佳的优化方法。 什么是优化算法? 优化算法的功能,是通过改善训练方式,来最小化(或最大化)损失函数E(x)。 模型内部有些参数,是用来计算测试集中目标值Y的真实值和预测值的偏差程度的,基于这些参数,就形成了损失函数E(x)。 比如说,权重(W)
zenRRan
2022/05/06
9460
从梯度下降到 Adam!一文看懂各种神经网络优化算法
神经网络优化算法综述
算法检查 gradient check sanity check other check 一阶算法 Adagrad momentum nag rmsprop 总结 二阶算法 牛顿法 拟牛顿法 参考 神
用户1147754
2018/01/02
1.3K0
神经网络优化算法综述
【PyTorch入门】 PyTorch不同优化器的比较
在 PyTorch 中,torch.optim 提供了多种优化器用于神经网络训练。每种优化器背后有不同的更新规则和机制,旨在适应不同的训练需求。以下是五种常见优化器(SGD、Momentum、AdaGrad、RMSprop、Adam)的原理、作用、优缺点及应用场景。
机器学习司猫白
2025/01/21
2540
【PyTorch入门】 PyTorch不同优化器的比较
如何选择优化器 optimizer
在很多机器学习和深度学习的应用中,我们发现用的最多的优化器是 Adam,为什么呢? 下面是 TensorFlow 中的优化器, https://www.tensorflow.org/api_guid
杨熹
2018/04/03
3.7K0
如何选择优化器 optimizer
02.改善深层神经网络:超参数调试、正则化以及优化 W2.优化算法(作业:优化方法)
调好参数的 mini-batch 梯度下降,通常优于梯度下降或随机梯度下降(特别是当训练集很大时)
Michael阿明
2021/02/19
3780
斯坦福CS231n - CNN for Visual Recognition(7)-lecture6梯度检查、参数更新
  梯度检查是非常重要的一个环节,就是将解析梯度和数值计算梯度进行比较。数值计算梯度时,使用中心化公式
李智
2018/08/03
7410
斯坦福CS231n - CNN for Visual Recognition(7)-lecture6梯度检查、参数更新
【深度学习实验】网络优化与正则化(一):优化算法:使用动量优化的随机梯度下降算法(Stochastic Gradient Descent with Momentum)
  目前,研究人员通过大量实践总结了一些经验方法,以在神经网络的表示能力、复杂度、学习效率和泛化能力之间取得良好的平衡,从而得到良好的网络模型。本系列文章将从网络优化和网络正则化两个方面来介绍如下方法:
Qomolangma
2024/07/30
2790
【深度学习实验】网络优化与正则化(一):优化算法:使用动量优化的随机梯度下降算法(Stochastic Gradient Descent with Momentum)
入门 | 目标函数的经典优化算法介绍
选自3dbabove 机器之心编译 参与:乾树、刘晓坤 本文使用通俗的语言和形象的图示,介绍了随机梯度下降算法和它的三种经典变体,并提供了完整的实现代码。 GitHub 链接:https://github.com/ManuelGonzalezRivero/3dbabove 代价函数的多种优化方法 目标函数是衡量预测值和实际值的相似程度的指标。通常,我们希望得到使代价尽可能小的参数集,而这意味着你的算法性能不错。函数的最小可能代价被称为最小值。有时一个代价函数可以有多个局部极小值。幸运的是,在参数空间的维数
机器之心
2018/05/10
2K0
神经网络中的优化方法
在传统的梯度下降优化算法中,如果碰到平缓区域,梯度值较小,参数优化变慢 ,遇到鞍点(是指在某些方向上梯度为零而在其他方向上梯度非零的点。),梯度为 0,参数无法优化,碰到局部最小值。实践中使用的小批量梯度下降法(mini-batch SGD)因其梯度估计的噪声性质,有时能够使模型脱离这些点。
@小森
2024/05/06
1180
神经网络中的优化方法
caffe详解之优化算法
前面我们介绍了卷积神经网络中主流的数据层,卷积层,全连接层,池化层,激活函数层,归一化层,dropout层,softmax层。分析每一层的配置及意义的目的主要是为了便于设计出适合自己的网络。然后根据自己的任务需要定义合适的损失函数。当搭建出自己的网络并确定网络的损失函数后,下一个关键问题便是训练网络,训练网络的前提需要确定优化算法。下面我们针对常见的深度学习优化算法进行梳理:
AI异构
2020/07/29
5110
caffe详解之优化算法
深度|梯度下降优化算法综述
该文翻译自An overview of gradient descent optimization algorithms。 总所周知,梯度下降算法是机器学习中使用非常广泛的优化算法,也是众多机器学习算法中最常用的优化方法。几乎当前每一个先进的(state-of-the-art)机器学习库或者深度学习库都会包括梯度下降算法的不同变种实现。但是,它们就像一个黑盒优化器,很难得到它们优缺点的实际解释。 这篇文章旨在提供梯度下降算法中的不同变种的介绍,帮助使用者根据具体需要进行使用。 这篇文章首先介绍梯度下降算法的
智能算法
2018/04/02
7050
深度|梯度下降优化算法综述
深度学习中的优化算法与实现
通过这么长时间的学习,我们应该对于通过深度学习解决问题的大体流程有个宏观的概念了吧?
BBuf
2020/10/10
1.1K0
深度学习中的优化算法与实现
梯度下降优化算法概述
本文介绍了自适应学习率算法的发展历程、常用算法、以及若干优化策略。通过实际案例分析了自适应学习率算法在深度学习中的重要性,并探讨了未来研究方向。
Alan Lee
2018/01/03
2.8K0
梯度下降优化算法概述
【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现
RMSProp(Root Mean Square Propagation)算法是由Geoffrey Hinton在2012年提出的,是对传统的梯度下降算法的改进。它是一种常用的优化算法,用于在深度学习中更新神经网络的参数。
SarPro
2024/04/10
4600
【动手学深度学习】深入浅出深度学习之RMSProp算法的设计与实现
深度学习与CV教程(7) | 神经网络训练技巧 (下)
本系列为 斯坦福CS231n 《深度学习与计算机视觉(Deep Learning for Computer Vision)》的全套学习笔记,对应的课程视频可以在 这里 查看。更多资料获取方式见文末。
ShowMeAI
2022/06/01
5260
深度学习与CV教程(7) | 神经网络训练技巧 (下)
动手学深度学习(八) 优化算法进阶
在 Section 11.4 中,我们提到,目标函数有关自变量的梯度代表了目标函数在自变量当前位置下降最快的方向。因此,梯度下降也叫作最陡下降(steepest descent)。在每次迭代中,梯度下降根据自变量当前位置,沿着当前位置的梯度更新自变量。然而,如果自变量的迭代方向仅仅取决于自变量当前位置,这可能会带来一些问题。对于noisy gradient,我们需要谨慎的选取学习率和batch size, 来控制梯度方差和收敛的结果。
致Great
2020/02/25
1.4K0
动手学深度学习(八) 优化算法进阶
推荐阅读
相关推荐
深度学习:神经网络优化技巧
更多 >
目录
  • 理解全局最小化和局部最小化
    • 优化器如何工作
  • 9种优化器
  • 梯度下降Gradient Descent
    • 基本思想
    • 算法步骤
    • 收敛条件
    • 学习率的作用
    • 优缺点
    • 案例
  • 随机梯度下降Stochastic Gradient Descent (SGD)
    • 定义
    • 基本思想
    • 算法步骤
    • 优缺点
    • 案例
  • 小批量随机梯度下降(Mini Batch Stochastic Gradient Descent, MB-SGD)
    • 基本思想
    • 算法步骤
    • 案例
  • SGD with Momentum
    • 基本原理
    • 算法步骤
    • 优缺点
    • 案例
  • Nesterov Accelerated Gradient, NAG
    • 基本原理
    • 数学公式
  • 案例
  • Adaptive Gradient, AdaGrad
    • 核心思想
    • 数学原理
    • 优缺点
    • 案例
  • AdaDelta
    • 基本原理
    • 优缺点
    • 案例
  • RMSprop(Root Mean Square Propagation)
    • 基本原理
    • 优缺点
    • 案例
    • 优化器9:Adaptive Moment Estimation(Adam)
    • 基本原理
    • 数学公式
    • 案例
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档