深度学习之详解常见梯度算法(概念、公式、原理、算法实现过程)

目录


博主介绍:✌专注于前后端、机器学习、人工智能应用领域开发的优质创作者、秉着互联网精神开源贡献精神,答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战,深受全网粉丝喜爱与支持✌有需要可以联系作者我哦!

🍅文末三连哦🍅

👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟

前言

梯度下降(Gradient Descent)是一种优化算法,用于寻找最小化损失函数(或成本函数)的参数值。在机器学习和深度学习的背景下,损失函数衡量了模型预测值与真实值之间的差异,而梯度下降则是用于更新模型的参数(例如权重和偏置),以最小化这个差异。

梯度下降的工作原理是,通过计算损失函数关于模型参数的梯度,然后沿着梯度的反方向(即最陡峭的下降方向)更新参数。这样,每次迭代都会使损失函数值减小(至少在局部上是这样的),从而逐渐接近损失函数的最小值。

具体来说,梯度下降算法的步骤通常如下:

  1. 初始化参数:随机初始化模型的参数(例如权重和偏置)。

  2. 计算梯度:使用当前参数计算损失函数关于这些参数的梯度。梯度是一个向量,指示了损失函数在每个参数上的局部变化率。

  3. 更新参数:将每个参数沿着梯度的反方向移动一小步,步长由学习率控制。学习率是一个超参数,决定了参数更新的幅度。

  4. 重复迭代:重复步骤2和3,直到满足某个停止条件(例如达到最大迭代次数、损失函数值足够小或梯度足够小)。

常见的梯度下降算法:

  • 批量梯度下降(Batch Gradient Descent):在每次迭代中使用整个数据集来计算梯度并更新参数。这种方法计算量大,但通常能保证收敛到全局最小值(对于凸损失函数)。

  • 随机梯度下降(Stochastic Gradient Descent, SGD):在每次迭代中只使用一个样本来计算梯度并更新参数。这种方法计算量小,收敛速度快,但可能会引入噪声,导致在最小值附近震荡。

  • 小批量梯度下降(Mini-batch Gradient Descent):在每次迭代中使用一小批样本来计算梯度并更新参数。这种方法是批量梯度下降和随机梯度下降的折中,结合了它们的优点。

梯度下降是机器学习和深度学习中最常用的优化算法之一,但它也有其局限性。例如,对于非凸损失函数,梯度下降可能只能找到局部最小值而不是全局最小值。此外,学习率的选择对算法的性能至关重要,过大或过小的学习率都可能导致算法表现不佳。因此,在实践中,常常使用更先进的优化算法,如动量(Momentum)、Adam、RMSprop等,它们是对梯度下降算法的改进和扩展。

一、如何实现梯度下降?

深度学习中的自动求梯度,主要依赖于反向传播(Backpropagation)算法和计算图(Computational Graph)的概念。下面,我们将简要解释这两个概念如何共同作用以实现自动求梯度:

  1. 计算图
    深度学习模型中的计算可以看作是一系列的操作(如加法、乘法、激活函数等)的组合。这些操作可以表示为计算图中的节点,而节点之间的连接则代表数据依赖关系。每个节点都有一个或多个输入(来自其他节点的输出)和一个输出。

  2. 前向传播
    在前向传播过程中,数据从输入层流向输出层,经过计算图中的每个节点,并产生相应的输出。这些输出将作为后续节点的输入,直到最终得到模型的预测结果。

  3. 损失函数
    为了评估模型的预测结果与真实结果之间的差距,我们使用损失函数。损失函数是一个量化这种差距的指标,其目标是在训练过程中最小化。

  4. 反向传播
    反向传播是自动求梯度的关键步骤。它开始于损失函数节点,并沿着计算图反向传播。在反向传播过程中,我们计算每个节点的梯度,即损失函数对该节点输入的偏导数。这些梯度表示了如何调整节点的输入以最小化损失函数。

  5. 梯度下降
    有了每个参数的梯度后,我们就可以使用梯度下降(或其变种,如Adam、RMSprop等)来更新模型的参数。通过反复进行前向传播、计算损失、反向传播和参数更新,模型逐渐学会从输入数据中提取有用的特征,并产生准确的预测。

具体来说,反向传播利用链式法则来计算梯度。链式法则允许我们将复杂的复合函数的导数分解为更简单的子函数的导数的乘积。这样,我们可以从输出层开始,逐层计算梯度,直到达到输入层。

二、梯度计算

梯度下降的核心思想是通过迭代地调整模型参数的值,使得损失函数逐渐减小。具体来说,它的步骤如下:

  1. 初始化参数:选择一个初始的模型参数向量。
  2. 计算梯度:计算损失函数对参数的梯度(或者称为导数),表示损失函数在当前参数值处的变化率。
  3. 更新参数:沿着梯度的反方向,以一定的步长(学习率)更新参数的值,使得损失函数逐渐减小。
  4. 迭代:重复步骤2和步骤3,直到满足终止条件(如达到最大迭代次数、损失函数收敛等)。

公式:

假设损失函数为$J(\theta)$$\theta$是待优化的模型参数向量。梯度下降的更新规则如下:

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

其中,$\alpha$是学习率,用来控制参数更新的步长;$\nabla J(\theta)$是损失函数$J(\theta)$对参数$\theta$的梯度。

实现过程:

下面是梯度下降的实现过程的伪代码:

1. 初始化参数 theta
2. 设置学习率 alpha,最大迭代次数 num_iters,终止条件 threshold
3. 初始化损失函数值列表 J_history
4. for iter in range(num_iters):
5.     计算损失函数值 J
6.     计算损失函数对参数的梯度 gradient
7.     更新参数 theta:theta = theta – alpha * gradient
8.     将损失函数值 J 加入 J_history
9.     if 损失函数变化小于 threshold:
10.        结束迭代
11. 返回优化后的参数 theta 和损失函数值列表 J_history

三、常见的梯度公式及梯度算法

常见的梯度公式:

1.标量对向量的梯度:

假设有一个标量函数 $f(\mathbf{x})$$\mathbf{x}$是一个向量,梯度的公式为:

\nabla f(\mathbf{x}) = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, ..., \frac{\partial f}{\partial x_n} \right)

其中,$\frac{\partial f}{\partial x_i}$表示函数 $f$$\mathbf{x}$的第 $i$个元素 $x_i$的偏导数。

2. 标量对矩阵的梯度:

假设有一个标量函数 $f(\mathbf{X})$$\mathbf{X}$是一个矩阵,梯度的公式为:

\nabla f(\mathbf{X}) = \begin{pmatrix} \frac{\partial f}{\partial X_{11}} & \frac{\partial f}{\partial X_{12}} & \cdots & \frac{\partial f}{\partial X_{1m}} \\ \frac{\partial f}{\partial X_{21}} & \frac{\partial f}{\partial X_{22}} & \cdots & \frac{\partial f}{\partial X_{2m}} \\ \vdots & \vdots & \ddots & \vdots \\ \frac{\partial f}{\partial X_{n1}} & \frac{\partial f}{\partial X_{n2}} & \cdots & \frac{\partial f}{\partial X_{nm}} \end{pmatrix}

其中,$X_{ij}$表示矩阵 $\mathbf{X}$中的元素。

3. 向量对标量的梯度:

假设有一个向量函数$\mathbf{f}(x)$$x$是一个标量,梯度的公式为:

\nabla \mathbf{f}(x) = \left( \frac{\partial f_1}{\partial x}, \frac{\partial f_2}{\partial x}, ..., \frac{\partial f_n}{\partial x} \right)

其中$\frac{\partial f_i}{\partial x}$表示函数$\mathbf{f}$ 的第$i$个分量对$x$ 的偏导数。

常见梯度算法:

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

    批量梯度下降是最基本的梯度下降算法之一,它在每一次迭代中使用整个训练数据集来计算梯度,并更新模型参数。虽然计算梯度的效率较低,但是可以得到全局最优解。批量梯度下降的缺点是可能陷入局部最优解,同时对内存要求较高。

  2. 随机梯度下降(Stochastic Gradient Descent)

    随机梯度下降是批量梯度下降的一种改进方法,它在每一次迭代中随机选择一个样本来计算梯度,并更新模型参数。虽然计算梯度的效率较高,但是由于参数更新的方向波动较大,因此收敛过程不稳定。随机梯度下降通常用于大规模数据集和在线学习。

  3. 小批量梯度下降(Mini-batch Gradient Descent)

    小批量梯度下降是批量梯度下降和随机梯度下降的结合,每次迭代使用一个小批量的样本来计算梯度,并更新模型参数。这种方法在计算效率和收敛稳定性之间取得了平衡,是实际应用中最常用的梯度下降算法之一。

  4. Adam优化算法

    Adam(Adaptive Moment Estimation)是一种自适应学习率的优化算法,结合了动量梯度下降和自适应学习率的优点。它通过计算梯度的一阶矩估计和二阶矩估计来自适应地调整学习率,从而在不同维度上具有不同的学习率。Adam算法在实践中表现良好,被广泛应用于深度学习中。

  5. RMSProp优化算法

    RMSProp(Root Mean Square Propagation)是一种自适应学习率的优化算法,它在Adam算法之前提出,通过计算梯度的平方的移动平均来调整学习率,从而加速收敛过程。RMSProp算法通常用于优化神经网络的训练。

  6. Adagrad优化算法

    Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,它通过将学习率分别应用于每个参数的梯度的平方来调整学习率,从而使得稀疏梯度的参数得到更大的更新,稠密梯度的参数得到较小的更新。Adagrad算法通常用于处理稀疏数据集和非凸优化问题。

四、常见梯度算法实现 

1、批量梯度下降算法实现函数

def batch_gradient_descent(X, y, theta, alpha, num_iters):
    """
    批量梯度下降算法实现函数
    
    参数:
    X:特征矩阵,每一行代表一个训练样本的特征,每一列代表一个特征
    y:目标值,向量,每个元素对应一个训练样本的目标值
    theta:模型参数,向量,初始值
    alpha:学习率,控制参数更新步长
    num_iters:迭代次数,控制优化的迭代次数
    
    返回:
    theta:优化后的模型参数
    J_history:损失函数值的历史记录
    """
    m = len(y)
    J_history = []  # 记录损失函数值的历史记录
    
    for iter in range(num_iters):
        # 计算损失函数值
        h = np.dot(X, theta)
        loss = h - y
        J = np.sum(loss ** 2) / (2 * m)
        J_history.append(J)
        
        # 计算梯度
        gradient = np.dot(X.T, loss) / m
        
        # 更新参数
        theta = theta - alpha * gradient
    
    return theta, J_history

2、随机梯度下降算法实现函数

def stochastic_gradient_descent(X, y, theta, alpha, num_iters):
    """
    随机梯度下降算法实现函数
    
    参数:
    X:特征矩阵,每一行代表一个训练样本的特征,每一列代表一个特征
    y:目标值,向量,每个元素对应一个训练样本的目标值
    theta:模型参数,向量,初始值
    alpha:学习率,控制参数更新步长
    num_iters:迭代次数,控制优化的迭代次数
    
    返回:
    theta:优化后的模型参数
    J_history:损失函数值的历史记录
    """
    m = len(y)
    J_history = []  # 记录损失函数值的历史记录
    
    for iter in range(num_iters):
        for i in range(m):
            # 随机选择一个样本
            random_index = np.random.randint(m)
            X_i = X[random_index:random_index+1]
            y_i = y[random_index:random_index+1]
            
            # 计算损失函数值
            h = np.dot(X_i, theta)
            loss = h - y_i
            J = np.sum(loss ** 2) / 2
            J_history.append(J)
            
            # 计算梯度
            gradient = np.dot(X_i.T, loss)
            
            # 更新参数
            theta = theta - alpha * gradient
    
    return theta, J_history

 3、小批量梯度下降算法实现函数

def mini_batch_gradient_descent(X, y, theta, alpha, num_iters, batch_size):
    """
    小批量梯度下降算法实现函数
    
    参数:
    X:特征矩阵,每一行代表一个训练样本的特征,每一列代表一个特征
    y:目标值,向量,每个元素对应一个训练样本的目标值
    theta:模型参数,向量,初始值
    alpha:学习率,控制参数更新步长
    num_iters:迭代次数,控制优化的迭代次数
    batch_size:小批量大小,控制每次迭代使用的样本数量
    
    返回:
    theta:优化后的模型参数
    J_history:损失函数值的历史记录
    """
    m = len(y)
    J_history = []  # 记录损失函数值的历史记录
    
    for iter in range(num_iters):
        for i in range(0, m, batch_size):
            # 选择一个小批量样本
            X_batch = X[i:i+batch_size]
            y_batch = y[i:i+batch_size]
            
            # 计算损失函数值
            h = np.dot(X_batch, theta)
            loss = h - y_batch
            J

 4、Adam优化算法实现函数

def adam(X, y, theta, alpha, beta1, beta2, epsilon, num_iters):
    """
    Adam优化算法实现函数
    
    参数:
    X:特征矩阵,每一行代表一个训练样本的特征,每一列代表一个特征
    y:目标值,向量,每个元素对应一个训练样本的目标值
    theta:模型参数,向量,初始值
    alpha:学习率,控制参数更新步长
    beta1:动量参数,控制历史梯度的影响程度
    beta2:动量参数,控制历史梯度平方的影响程度
    epsilon:数值稳定性参数,防止除零错误
    num_iters:迭代次数,控制优化的迭代次数
    
    返回:
    theta:优化后的模型参数
    J_history:损失函数值的历史记录
    """
    m = len(y)
    J_history = []  # 记录损失函数值的历史记录
    mt = np.zeros_like(theta)  # 一阶矩估计
    vt = np.zeros_like(theta)  # 二阶矩估计
    t = 0  # 迭代次数
    
    for iter in range(num_iters):
        t += 1
        # 计算梯度
        h = np.dot(X, theta)
        loss = h - y
        gradient = np.dot(X.T, loss) / m
        
        # 更新一阶矩估计
        mt = beta1 * mt + (1 - beta1) * gradient
        
        # 更新二阶矩估计
        vt = beta2 * vt + (1 - beta2) * (gradient ** 2)
        
        # 纠正偏差
        mt_hat = mt / (1 - beta1 ** t)
        vt_hat = vt / (1 - beta2 ** t)
        
        # 更新参数
        theta = theta - alpha * mt_hat / (np.sqrt(vt_hat) + epsilon)
        
        # 计算损失函数值
        J = np.sum((np.dot(X, theta) - y) ** 2) / (2 * m)
        J_history.append(J)
    
    return theta, J_history

5、简单应用案列demo

基于线性回归神经网络模型,并使用批量梯度下降算法进行训练。最后,使用matplotlib库将损失函数值随迭代次数的变化可视化输出。

import numpy as np
import matplotlib.pyplot as plt

# 生成示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

# 在特征矩阵 X 中添加偏置列
X_b = np.c_[np.ones((100, 1)), X]

# 定义激活函数(这里使用恒等函数)
def identity_activation(z):
    return z

# 定义损失函数(均方误差)
def mse_loss(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 定义批量梯度下降算法
def batch_gradient_descent(X, y, theta, alpha, num_iters):
    m = len(y)
    J_history = []  # 记录损失函数值的历史记录
    
    for iter in range(num_iters):
        # 计算模型预测值
        y_pred = identity_activation(np.dot(X, theta))
        
        # 计算损失函数值
        J = mse_loss(y, y_pred)
        J_history.append(J)
        
        # 计算梯度
        gradient = np.dot(X.T, (y_pred - y)) / m
        
        # 更新参数
        theta = theta - alpha * gradient
    
    return theta, J_history

# 初始化模型参数
theta = np.random.randn(2, 1)

# 设置超参数
alpha = 0.01  # 学习率
num_iters = 1000  # 迭代次数

# 调用批量梯度下降算法训练模型
theta_bgd, J_history_bgd = batch_gradient_descent(X_b, y, theta, alpha, num_iters)

# 输出优化后的模型参数
print("优化后的模型参数 theta:", theta_bgd)

# 可视化损失函数值的变化
plt.plot(range(num_iters), J_history_bgd)
plt.xlabel('Iterations')
plt.ylabel('Cost Function (MSE)')
plt.title('Batch Gradient Descent')
plt.show()

执行结果:

 

 

五、总结 

通过今天的学习,我们对梯度下降算法及其在神经网络训练中的应用有了更深入的理解,也了解了一些常见的梯度优化算法的原理和特点。总之,我们深入探讨了梯度下降法,这是一种常用的优化算法。它的核心思想是根据目标函数的梯度方向,逐步向最陡峭的下降方向移动,以最小化目标函数。我们学习了批量梯度下降法、随机梯度下降法和小批量梯度下降法三种形式,并了解了它们各自的优缺点和应用场景。

最后,创作不易!非常感谢大家的关注、点赞、收藏、评论啦!谢谢四连哦!好人好运连连,学习进步!工作顺利哦! 

版权声明:本文为博主作者:程序小勇原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/a910247/article/details/137354786

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2024年4月16日
下一篇 2024年4月16日

相关推荐