深度学习笔记之优化算法(六)RMSprop算法的简单认识

2023-10-11 10:52

本文主要是介绍深度学习笔记之优化算法(六)RMSprop算法的简单认识,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

深度学习笔记之优化算法——RMSProp算法的简单认识

  • 引言
    • 回顾:AdaGrad算法
      • AdaGrad算法与动量法的优化方式区别
      • AdaGrad算法的缺陷
    • RMProp算法
      • 关于AdaGrad问题的优化方式
      • RMSProp的算法过程描述
    • RMSProp示例代码

引言

上一节对 AdaGrad \text{AdaGrad} AdaGrad算法进行了简单认识,本节将介绍 RMSProp \text{RMSProp} RMSProp方法。

回顾:AdaGrad算法

AdaGrad算法与动量法的优化方式区别

动量法、 Nesterov \text{Nesterov} Nesterov动量法在迭代过程中对梯度方向进行优化不同, AdaGrad \text{AdaGrad} AdaGrad算法在迭代过程中对梯度大小(学习率)进行优化,两者优化的思路本质上存在区别。其迭代过程对比表示如下:

  • 关于动量法在计算当前迭代步骤的梯度 m t m_t mt时,使用了 m t − 1 , ∇ θ ; t − 1 J ( θ t − 1 ) m_{t-1},\nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) mt1,θ;t1J(θt1)加权和(向量加法)的方式来优化 m t m_t mt的方向;当方向固定后,在判断沿着 m t m_t mt方向前进的步长时,仅使用了固定的学习率 η \eta η作为前进步长。
  • AdaGrad \text{AdaGrad} AdaGrad算法对当前时刻的梯度信息 G t \mathcal G_t Gt并没有执行任何方向上的优化;在判断步长时使用 η R t + ϵ ⇒ η \begin{aligned}\frac{\eta}{\sqrt{\mathcal R_t} + \epsilon} \Rightarrow \eta\end{aligned} Rt +ϵηη执行更新操作,其本质上是向量与标量之间的乘法操作
    Momentum :  { m t = β ⋅ m t − 1 + ( 1 − β ) ⋅ ∇ θ ; t − 1 J ( θ t − 1 ) θ t = θ t − 1 − η ⋅ m t AdaGrad :  { G t = ∇ θ ; t − 1 J ( θ t − 1 ) R t = R t − 1 + G t ⊙ G t θ t = θ t − 1 − η R t + ϵ ⊙ G t \begin{aligned} & \text{Momentum : } \begin{cases} m_t = \beta \cdot m_{t-1} + (1 - \beta) \cdot \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) \\ \theta_t = \theta_{t-1} - \eta \cdot m_t \end{cases} \\ & \text{AdaGrad : } \quad \begin{cases} \mathcal G_t = \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) \\ \mathcal R_t = \mathcal R_{t-1} + \mathcal G_t \odot \mathcal G_t \\ \begin{aligned} \theta_t = \theta_{t-1} - \frac{\eta}{\sqrt{\mathcal R_t} + \epsilon} \odot \mathcal G_t \end{aligned} \end{cases} \end{aligned} Momentum : {mt=βmt1+(1β)θ;t1J(θt1)θt=θt1ηmtAdaGrad :  Gt=θ;t1J(θt1)Rt=Rt1+GtGtθt=θt1Rt +ϵηGt

AdaGrad算法的缺陷

引入上一节使用 AdaGrad \text{AdaGrad} AdaGrad算法对目标函数 f ( x ) = x T Q x ; x = ( x 1 , x 2 ) T ; Q = ( 0.5 0 0 20 ) f(x) = x^T \mathcal Q x;x = (x_1,x_2)^T;\mathcal Q = \begin{pmatrix}0.5 \quad 0 \\ 0 \quad 20\end{pmatrix} f(x)=xTQx;x=(x1,x2)T;Q=(0.50020)迭代过程:Adagrad算法图像示例
我们能够观察到:虽然该算法在梯度较小的、平缓的倾斜方向能够稳定的前进,但是同样也会观察到:在迭代算法的中后段,算法消耗了相当多的迭代步骤,原因也很明显:此时的学习率 η \eta η太小了,并且还会无限的小下去

上述示例中的目标函数是一个强凸函数,它存在全局最优解;因此迭代的最终结果也只会趋近最优解;但如果目标函数是一个复杂函数 ? ? ?就像这样:
画的不太好,凑合着看~
非凸复杂函数示例
观察上图,黄色点描述的是使用 AdaGrad \text{AdaGrad} AdaGrad算法,权重不同迭代步骤下的更新位置;如果该目标函数是一个简单的凸函数,它可能最终会收敛至某一点,例如红色点;但如果该函数比较复杂,在本段迭代过程之后,梯度又重新增加(图中最左侧黄点位置)那么此时的收敛速度又是什么样的呢 ? ? ?

上一节提到过: AdaGrade \text{AdaGrade} AdaGrade的学习率只会减小,不会增加,即便后续的梯度又重新增大,但它的学习率不会增加,只会更加缓慢地继续更新
对应《深度学习(花书)》P188 8.5.1中的原文:从训练开始时累积梯度平方会导致有效学习率过早地、过量地减小

之所以 AdaGrad \text{AdaGrad} AdaGrad算法的学习率只减不增,究其原因还是:在累积平方梯度的过程中,平方梯度 G t ⊙ G t \mathcal G_t \odot \mathcal G_t GtGt完整地保存在累积梯度变量 R \mathcal R R。这种现象在 Nesterov \text{Nesterov} Nesterov动量法中也提到过:在迭代步骤较深时,初始迭代步骤的历史平方梯度对当前步骤没有参考价值

RMProp算法

关于AdaGrad问题的优化方式

针对上述问题,同样可以按照动量法的思路:通过指数加权移动平均法适当地丢弃遥远过去的历史平方梯度。优化后的公式表示如下:
视频中的描述(文章下方链接) 33:14 \text{33:14} 33:14与《深度学习(花书)》中的公式关于 ϵ \epsilon ϵ的位置存在稍许不同,对比如下:
AdaGrad :  { G t = ∇ θ ; t − 1 J ( θ t − 1 ) R t = R t − 1 + G t ⊙ G t θ t = θ t − 1 − η R t + ϵ ⊙ G t Video(RMProp) :  { G t = ∇ θ ; t − 1 J ( θ t − 1 ) R t = β ⋅ R t − 1 + ( 1 − β ) ⋅ G t ⊙ G t θ t = θ t − 1 − η R t + ϵ ⊙ G t DeepLearning(RMProp) :  { G t = ∇ θ ; t − 1 J ( θ t − 1 ) R t = β ⋅ R t − 1 + ( 1 − β ) ⋅ G t ⊙ G t θ t = θ t − 1 − η R t + ϵ ⊙ G t \begin{aligned} \text{AdaGrad : } & \begin{cases} \mathcal G_t = \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) \\ \mathcal R_t = \mathcal R_{t-1} + \mathcal G_t \odot \mathcal G_t \\ \begin{aligned} \theta_t = \theta_{t-1} - \frac{\eta}{\sqrt{\mathcal R_t} + \epsilon} \odot \mathcal G_t \end{aligned} \end{cases} \\ \text{Video(RMProp) : } & \begin{cases} \mathcal G_t = \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) \\ \mathcal R_t = \beta \cdot \mathcal R_{t-1} + (1 - \beta) \cdot \mathcal G_t \odot \mathcal G_t \\ \begin{aligned} \theta_t = \theta_{t - 1} - \frac{\eta}{\sqrt{\mathcal R_t} + \epsilon} \odot \mathcal G_t \end{aligned} \end{cases} \\ \text{DeepLearning(RMProp) : } & \begin{cases} \mathcal G_t = \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) \\ \mathcal R_t = \beta \cdot \mathcal R_{t-1} + (1 - \beta) \cdot \mathcal G_t \odot \mathcal G_t \\ \begin{aligned} \theta_t = \theta_{t-1} - \frac{\eta}{\sqrt{\mathcal R_t + \epsilon}} \odot \mathcal G_t \end{aligned} \end{cases} \end{aligned} AdaGrad : Video(RMProp) : DeepLearning(RMProp) :  Gt=θ;t1J(θt1)Rt=Rt1+GtGtθt=θt1Rt +ϵηGt Gt=θ;t1J(θt1)Rt=βRt1+(1β)GtGtθt=θt1Rt +ϵηGt Gt=θ;t1J(θt1)Rt=βRt1+(1β)GtGtθt=θt1Rt+ϵ ηGt
这种操作旨在:当执行迭代步骤时,只有之前的若干次迭代步骤对当前步骤产生影响

RMSProp的算法过程描述

基于 RMSProp \text{RMSProp} RMSProp算法步骤表示如下:
初始化操作

  • 学习率 η \eta η; 衰减因子 β \beta β
  • 初始化参数 θ \theta θ;梯度累积信息 R = 0 \mathcal R = 0 R=0;超参数 ϵ = 1 0 − 7 \epsilon = 10^{-7} ϵ=107

算法过程

  • While \text{While} While没有达到停止准则 do \text{do} do
  • 从训练集 D \mathcal D D中采集出包含 k k k个样本的小批量 { ( x ( i ) , y ( i ) ) } i = 1 k \{(x^{(i)},y^{(i)})\}_{i=1}^k {(x(i),y(i))}i=1k
  • 计算当前步骤参数 θ \theta θ梯度信息 G \mathcal G G
    G ⇐ 1 k ∑ i = 1 k ∇ θ L [ f ( x ( i ) ; θ ) , y ( i ) ] \mathcal G \Leftarrow \frac{1}{k} \sum_{i=1}^k \nabla_{\theta} \mathcal L[f(x^{(i)};\theta),y^{(i)}] Gk1i=1kθL[f(x(i);θ),y(i)]
  • 使用 R \mathcal R R通过指数加权移动平均法梯度内积 G ⊙ G \mathcal G \odot \mathcal G GG进行累积
    R ⇐ β ⋅ R + ( 1 − β ) ⋅ G ⊙ G \mathcal R \Leftarrow \beta \cdot \mathcal R + (1 - \beta) \cdot \mathcal G \odot \mathcal G RβR+(1β)GG
  • 计算参数 θ \theta θ更新信息 Δ θ \Delta \theta Δθ
    这里暂时使用《深度学习(花书)》中的描述。
    Δ θ = − η R t + ϵ ⋅ G \Delta \theta = - \frac{\eta}{\sqrt{\mathcal R_t + \epsilon}} \cdot \mathcal G Δθ=Rt+ϵ ηG
  • 应用更新:
    θ ⇐ θ + Δ θ \theta \Leftarrow \theta + \Delta \theta θθ+Δθ
  • End While \text{End While} End While

RMSProp示例代码

RMSProp \text{RMSProp} RMSProp算法 AdaGrad \text{AdaGrad} AdaGrad算法进行对比,对应代码表示如下:

import numpy as np
import math
import matplotlib.pyplot as plt
from tqdm import tqdmdef f(x, y):return 0.5 * (x ** 2) + 20 * (y ** 2)def ConTourFunction(x, Contour):return math.sqrt(0.05 * (Contour - (0.5 * (x ** 2))))def Derfx(x):return xdef Derfy(y):return 40 * ydef DrawBackGround(ax,Idx):ContourList = [0.2, 1.0, 4.0, 8.0, 16.0, 32.0]LimitParameter = 0.0001for Contour in ContourList:# 设置范围时,需要满足x的定义域描述。x = np.linspace(-1 * math.sqrt(2 * Contour) + LimitParameter, math.sqrt(2 * Contour) - LimitParameter, 200)y1 = [ConTourFunction(i, Contour) for i in x]y2 = [-1 * j for j in y1]ax[Idx].plot(x, y1, '--', c="tab:blue")ax[Idx].plot(x, y2, '--', c="tab:blue")def Process(mode):assert mode in ["AdaGrad","RMSProp"]Start = (8.0, 1.0)LocList = list()LocList.append(Start)Eta = 0.2Beta = 0.8Epsilon = 0.0000001R = 0.0Delta = 0.1while True:DerStart = (Derfx(Start[0]), Derfy(Start[1]))InnerProduct = (DerStart[0] ** 2) + (DerStart[1] ** 2)if mode == "AdaGrad":R += InnerProductelse:DecayR = R * BetaR = DecayR + ((1.0 - Beta) * InnerProduct)UpdateEta = -1 * (Eta / (Epsilon + math.sqrt(R)))UpdateMessage = (UpdateEta * DerStart[0], UpdateEta * DerStart[1])Next = (Start[0] + UpdateMessage[0], Start[1] + UpdateMessage[1])DerNext = (Derfx(Next[0]), Derfy(Next[1]))# 这里终止条件使用梯度向量的模接近于Delta,一个很小的正值;if math.sqrt((DerNext[0] ** 2) + (DerNext[1] ** 2)) < Delta:breakelse:LocList.append(Next)Start = Nextreturn LocListdef DrawPicture():AdaGradLocList = Process(mode="AdaGrad")RMSPropLocList = Process(mode="RMSProp")fig, ax = plt.subplots(2, 1, figsize=(8, 6))AdaGradplotList = list()ax[0].set_title("AdaGrad")DrawBackGround(ax,Idx=0)for (x, y) in tqdm(AdaGradLocList):AdaGradplotList.append((x, y))ax[0].scatter(x, y, s=30, facecolor="none", edgecolors="tab:orange", marker='o')if len(AdaGradplotList) < 2:continueelse:ax[0].plot([AdaGradplotList[0][0], AdaGradplotList[1][0]], [AdaGradplotList[0][1], AdaGradplotList[1][1]], c="tab:orange")AdaGradplotList.pop(0)RMSPropplotList = list()ax[1].set_title("RMSProp")DrawBackGround(ax, Idx=1)for (x, y) in tqdm(RMSPropLocList):RMSPropplotList.append((x, y))ax[1].scatter(x, y, s=30, facecolor="none", edgecolors="tab:red", marker='o')if len(RMSPropplotList) < 2:continueelse:ax[1].plot([RMSPropplotList[0][0], RMSPropplotList[1][0]], [RMSPropplotList[0][1], RMSPropplotList[1][1]], c="tab:red")RMSPropplotList.pop(0)plt.show()if __name__ == '__main__':DrawPicture()

对应图像结果表示如下:
AdaGradVSRMSProp
对比图像可以看出:关于 RMSProp \text{RMSProp} RMSProp的迭代步骤明显少于 AdaGrad \text{AdaGrad} AdaGrad
回头再次观察 RMSProp \text{RMSProp} RMSProp迭代公式,可以发现:虽然 RMSprop \text{RMSprop} RMSprop算法对 AdaGrad \text{AdaGrad} AdaGrad进行了改进,但其本质上依然是对梯度的大小(学习率)进行优化。下一节我们将对 RMSProp \text{RMSProp} RMSProp进行延伸——从梯度方向、梯度大小(学习率)两个角度同时对梯度进行优化。
使用 Nesterov \text{Nesterov} Nesterov动量的 RMSProp \text{RMSProp} RMSProp算法

Reference \text{Reference} Reference
“随机梯度下降、牛顿法、动量法、Nesterov、AdaGrad、RMSprop、Adam”,打包理解对梯度下降的优化
《深度学习(花书)》 P188 8.5.2 RMSProp \text{P188 8.5.2 RMSProp} P188 8.5.2 RMSProp

这篇关于深度学习笔记之优化算法(六)RMSprop算法的简单认识的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/187546

相关文章

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

Python实现简单封装网络请求的示例详解

《Python实现简单封装网络请求的示例详解》这篇文章主要为大家详细介绍了Python实现简单封装网络请求的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录安装依赖核心功能说明1. 类与方法概览2.NetHelper类初始化参数3.ApiResponse类属性与方法使用实

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置