当前位置: 首页 > article >正文

Python 梯度下降法(二):RMSProp Optimize

文章目录

  • Python 梯度下降法(二):RMSProp Optimize
    • 一、数学原理
      • 1.1 介绍
      • 1.2 公式
    • 二、代码实现
      • 2.1 函数代码
      • 2.2 总代码
    • 三、代码优化
      • 3.1 存在问题
      • 3.2 收敛判断
      • 3.3 函数代码
      • 3.4 总代码
    • 四、优缺点
      • 4.1 优点
      • 4.2 缺点

Python 梯度下降法(二):RMSProp Optimize

结合第一篇文章一起看:Python 梯度下降法(一):Gradient Descent-CSDN博客

一、数学原理

1.1 介绍

RMSProp(Root Mean Square Propagation)是一种自适应学习率优化算法,广泛用于深度学习中的梯度下降优化。它通过调整每个参数的学习率来解决传统梯度下降法中学习率固定的问题,从而加速收敛并提高性能。

RMSProp 的核心思想是对每个参数的学习率进行自适应调整。它通过维护一个指数加权移动平均(Exponential Moving Average, EMA)的梯度平方值来调整学习率:

  • 对于梯度较大的参数,降低其学习率。
  • 对于梯度较小的参数,增加其学习率。
    这种方法可以有效缓解梯度下降中的震荡问题,尤其是在非凸优化问题中。

1.2 公式

符号说明:

θ : 需要优化的参数向量 J ( θ ) : 损失函数 g t : 在第 t 次迭代时损失函数关于 θ 的梯度, ∇ θ J ( θ t ) ρ : 衰减率,常用值为 0.9 η : 学习率,需要手动设置 ϵ : 一个及小的参数,无限趋近于零,避免不会出现零 ( 1 0 − 8 ) s t : 指数加权移动平均 \begin{array}{l} \theta&:需要优化的参数向量 \\ J(\theta)&: 损失函数 \\ g_{t}&:在第t次迭代时损失函数关于\theta的梯度,\nabla_{\theta}J(\theta_{t}) \\ \rho &: 衰减率,常用值为0.9\\ \eta&:学习率,需要手动设置 \\ \epsilon&: 一个及小的参数,无限趋近于零,避免不会出现零(10^{-8}) \\ s_{t}&:指数加权移动平均 \end{array} θJ(θ)gtρηϵst:需要优化的参数向量:损失函数:在第t次迭代时损失函数关于θ的梯度,θJ(θt):衰减率,常用值为0.9:学习率,需要手动设置:一个及小的参数,无限趋近于零,避免不会出现零(108):指数加权移动平均

  1. 初始化参数为: θ 0 , s 0 = 0 \theta_{0},s_{0}=0 θ0,s0=0

  2. 迭代更新,每次迭代 t t t中,更新指数加权移动平均:
    s t = ρ s t − 1 + ( 1 − ρ ) g t ⊙ g t s_{t}=\rho s_{t-1}+(1-\rho)g_{t}\odot g_{t} st=ρst1+(1ρ)gtgt s t s_{t} st可以理解为对梯度平方的一个平滑估计,它更关注近期的梯度信息, ρ \rho ρ控制了历史信息的衰减程度。

  3. 计算自适应学习率,公式为 η s t + ϵ \frac{\eta}{\sqrt{ s_{t}+\epsilon }} st+ϵ η,其中,分母 s t + ϵ \sqrt{ s_{t}+\epsilon} st+ϵ 起到了归一化梯度的作用,使得学习率可以更具梯度的尺寸进行自适应的调整。

  4. 更新参数: θ t + 1 = θ t − η s t + ϵ g t \theta_{t+1}=\theta_{t}- \frac{\eta}{\sqrt{ s_{t}+\epsilon }}g_{t} θt+1=θtst+ϵ ηgt

二、代码实现

2.1 函数代码

RMSProp优化算法实现:

# 定义RMSProp优化算法
def rmsprop_optimizer(X, y, eta, num_iter=1000, epsilon=1e-5, rho=0.9):
    """
    X: 数据 x  mxn
    y: 数据 y  nx1
    eta: 学习率  
    num_iter: 迭代次数
    epsilon: 无穷小
    rho: 衰减率
    """
    m, n = X.shape 
    theta, s = np.zeros((n, 1)), np.zeros((n, 1))  # 初始参数 nx1,以及指数加权移动平均 nx1
    loss_ = []  # 存储损失率的变化,便于绘图
    for _ in range(num_iter):
        # 计算预测值
        h = np.dot(X, theta)
        # 计算误差
        error = h - y
        loss_.append(np.mean(error**2) / 2)
        # 计算梯度
        gradient = (1/m) * np.dot(X.T, error)
        s = rho * s + (1 - rho) * np.pow(gradient, 2)  # 利用广播机制来进行运算每个维度上的平滑估计
        theta = theta - np.multiply(eta / np.sqrt(s + epsilon), gradient)  # Hadamar product
    return theta, loss_

2.2 总代码

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] 

# 定义RMSProp优化算法
def rmsprop_optimizer(X, y, eta, num_iter=1000, epsilon=1e-5, rho=0.9):
    """
    X: 数据 x  mxn
    y: 数据 y  nx1
    eta: 学习率  
    num_iter: 迭代次数
    epsilon: 无穷小
    rho: 衰减率
    """
    m, n = X.shape 
    theta, s = np.zeros((n, 1)), np.zeros((n, 1))  # 初始参数 nx1,以及指数加权移动平均 nx1
    loss_ = []  # 存储损失率的变化,便于绘图
    for _ in range(num_iter):
        # 计算预测值
        h = np.dot(X, theta)
        # 计算误差
        error = h - y
        loss_.append(np.mean(error**2) / 2)
        # 计算梯度
        gradient = (1/m) * np.dot(X.T, error)
        s = rho * s + (1 - rho) * np.pow(gradient, 2)  # 利用广播机制来进行运算每个维度上的平滑估计
        theta = theta - np.multiply(eta / np.sqrt(s + epsilon), gradient)  # Hadamar product
    return theta, loss_

    
# 生成一些示例数据
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
# 添加偏置项
X_b = np.c_[np.ones((100, 1)), X]

# 设置超参数
eta = 0.1

# RMSProp优化算法
theta, loss_ = rmsprop_optimizer(X_b, y, eta)

print("最优参数 theta:")
print(theta)
plt.plot(range(len(loss_)), loss_, label="损失函数图像")
plt.title("损失函数图像")
plt.xlabel("迭代次数")
plt.ylabel("损失值")
plt.show()

1738222496_l1dhye0o4j.png1738222495967.png

可以发现,其对于损失值的下降性能也较好,损失率也较为稳定。

三、代码优化

3.1 存在问题

  • 未使用小批量数据:该代码在每次迭代时使用了全部的训练数据 Xy 来计算梯度,这相当于批量梯度下降的方式。在处理大规模数据集时,这种方式可能会导致计算效率低下,并且可能会陷入局部最优解。可以参考之前小批量梯度下降的代码,引入小批量数据的处理,以提高算法的效率和泛化能力。
  • 缺乏数据预处理:在实际应用中,输入数据 X 可能需要进行预处理,例如归一化或标准化,以确保不同特征具有相似的尺度,从而加快算法的收敛速度。(这里不进行解决,参考特征缩放:数据归一化-CSDN博客)
  • 缺乏收敛判断:代码只是简单地进行了固定次数的迭代,没有设置收敛条件。在实际应用中,可以添加收敛判断,例如当损失值的变化小于某个阈值时提前停止迭代,以节省计算资源。

这里引入Mini-batch Gradient Descent,以及收敛判断,减少计算资源

3.2 收敛判断

# 收敛判断,设定阈值,进行收敛判断
# 满足条件即停止,减少系统资源的使用
if len(loss_) > 1 and abs(loss_[-1] - loss_[-2]) < threshold:
	print(f"Converged at iteration {_ + 1}")
	break  # 注意,这里不能使用return

3.3 函数代码

# 定义RMSProp优化算法
def rmsprop_optimizer(X, y, eta, batch_size=32, num_iter=1000, epsilon=1e-5, rho=0.9, threshold=1e-3):
    """
    X: 数据 x  mxn,可以在传入数据之前进行数据的归一化
    y: 数据 y  nx1
    eta: 学习率  
    batch_size: 批量数据的大小
    num_iter: 迭代次数
    epsilon: 无穷小
    rho: 衰减率
    threshold: 收敛阈值
    """
    m, n = X.shape 
    theta, s = np.zeros((n, 1)), np.zeros((n, 1))  # 初始参数 nx1,以及指数加权移动平均 nx1
    loss_ = []  # 存储损失率的变化,便于绘图
    num_batchs = m // batch_size
    for _ in range(num_iter):
        # 打乱数据集
        shuffled_indices = np.random.permutation(m)
        X_shuffled = X[shuffled_indices]
        y_shuffled = y[shuffled_indices]
        loss_temp = []  # 存储每次小批量样本生成的值
        for batch in range(num_batchs):
            
            # 选取小批量样本
            start_index = batch * batch_size
            end_index = start_index + batch_size
            xi = X_shuffled[start_index:end_index]
            yi = y_shuffled[start_index:end_index]
            # 计算预测值
            h = np.dot(xi, theta)
            # 计算误差
            error = h - yi
            loss_temp.append(np.mean(error**2) / 2)
            # 计算梯度
            gradient = (1/m) * np.dot(xi.T, error)
            s = rho * s + (1 - rho) * np.pow(gradient, 2)  # 利用广播机制来进行运算每个维度上的平滑估计
            theta = theta - np.multiply(eta / np.sqrt(s + epsilon), gradient)  # Hadamar product
        loss_.append(np.mean(loss_temp))
        # 收敛判断
        if len(loss_) > 1 and abs(loss_[-1] - loss_[-2]) < threshold:
            print(f"Converged at iteration {_ + 1}")
            break
            
    return theta, loss_

3.4 总代码

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] 

# 定义RMSProp优化算法
def rmsprop_optimizer(X, y, eta, batch_size=32, num_iter=1000, epsilon=1e-5, rho=0.9, threshold=1e-3):
    """
    X: 数据 x  mxn,可以在传入数据之前进行数据的归一化
    y: 数据 y  nx1
    eta: 学习率  
    batch_size: 批量数据的大小
    num_iter: 迭代次数
    epsilon: 无穷小
    rho: 衰减率
    threshold: 收敛阈值
    """
    m, n = X.shape 
    theta, s = np.zeros((n, 1)), np.zeros((n, 1))  # 初始参数 nx1,以及指数加权移动平均 nx1
    loss_ = []  # 存储损失率的变化,便于绘图
    num_batchs = m // batch_size
    for _ in range(num_iter):
        # 打乱数据集
        shuffled_indices = np.random.permutation(m)
        X_shuffled = X[shuffled_indices]
        y_shuffled = y[shuffled_indices]
        loss_temp = []  # 存储每次小批量样本生成的值
        for batch in range(num_batchs):
            
            # 选取小批量样本
            start_index = batch * batch_size
            end_index = start_index + batch_size
            xi = X_shuffled[start_index:end_index]
            yi = y_shuffled[start_index:end_index]
            # 计算预测值
            h = np.dot(xi, theta)
            # 计算误差
            error = h - yi
            loss_temp.append(np.mean(error**2) / 2)
            # 计算梯度
            gradient = (1/m) * np.dot(xi.T, error)
            s = rho * s + (1 - rho) * np.pow(gradient, 2)  # 利用广播机制来进行运算每个维度上的平滑估计
            theta = theta - np.multiply(eta / np.sqrt(s + epsilon), gradient)  # Hadamar product
        loss_.append(np.mean(loss_temp))  # 使用平均值作为参考
        # 收敛判断
        if len(loss_) > 1 and abs(loss_[-1] - loss_[-2]) < threshold:
            print(f"Converged at iteration {_ + 1}")
            break
            
    return theta, loss_

    
# 生成一些示例数据
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
# 添加偏置项
X_b = np.c_[np.ones((100, 1)), X]

# 设置超参数
eta = 0.1

# RMSProp优化算法
theta, loss_ = rmsprop_optimizer(X_b, y, eta)

print("最优参数 theta:")
print(theta)
plt.plot(range(len(loss_)), loss_, label="损失函数图像")
plt.title("损失函数图像")
plt.xlabel("迭代次数")
plt.ylabel("损失值")
plt.show()

1738223819_x4hrij0zgr.png1738223818170.png

四、优缺点

4.1 优点

  • 自适应学习率:RMSProp 能够根据参数的梯度变化情况自适应地调整学习率。对于梯度较大的参数,学习率会自动减小;对于梯度较小的参数,学习率会相对增大。这使得算法在处理不同尺度的梯度时更加稳定,有助于加快收敛速度。
  • 缓解 Adagrad 学习率衰减过快问题:与 Adagrad 算法不同,RMSProp 使用指数加权移动平均来计算梯度平方的累积值,避免了 Adagrad 中学习率单调递减且后期学习率过小的问题,使得算法在训练后期仍然能够继续更新参数。

4.2 缺点

  • 对超参数敏感:RMSProp 的性能依赖于超参数 η \eta η ρ \rho ρ的选择。如果超参数设置不当,可能会导致算法收敛速度慢或者无法收敛到最优解。
  • 可能陷入局部最优:和其他基于梯度的优化算法一样,RMSProp 仍然有可能陷入局部最优解,尤其是在损失函数具有复杂的地形时。

http://www.kler.cn/a/526045.html

相关文章:

  • 2022 年 6 月大学英语四级考试真题(第 2 套)——纯享题目版
  • Big Bird:适用于更长序列的Transformer模型
  • Android 启动流程
  • 新版231普通阿里滑块 自动化和逆向实现 分析
  • 【25考研】考研366是否能进北航计算机复试?该怎么准备?
  • Ubuntu全面卸载mysql
  • unity使用内置videoplayer打包到安卓手机进行视频播放
  • linux asio网络编程理论及实现
  • 8.线程的同步和互斥
  • 大数据相关职位介绍之三(数据挖掘,数据安全 ,数据合规师,首席数据官,数据科学家 )
  • 解析静态链接
  • 我的毕设之路:(2)系统类型的论文写法
  • C++并发编程指南07
  • CMAKE工程编译好后自动把可执行文件传输到远程开发板
  • 深度学习探索:ChatGPT数据分析精髓 梯度下降优化方法深度剖析
  • 微软官方工具箱 PowerToys,提升工作效率
  • Conditional DETR for Fast Training Convergence论文学习
  • 负荷预测算法模型
  • 新月智能护甲系统CMIA--未来战场的守护者
  • 从巫师求雨说起