《动手学深度学习 Pytorch版》 8.7 通过时间反向传播

2023-10-18 04:52

本文主要是介绍《动手学深度学习 Pytorch版》 8.7 通过时间反向传播,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

8.7.1 循环神经网络的梯度分析

本节主要探讨梯度相关问题,因此对模型及其表达式进行了简化,进行如下表示:

h t = f ( x t , h t − 1 , w h ) o t = g ( h t , w o ) \begin{align} h_t&=f(x_t,h_{t-1},w_h)\\ o_t&=g(h_t,w_o) \end{align} htot=f(xt,ht1,wh)=g(ht,wo)

参数字典:

  • t t t 表示时间步

  • h t h_t ht 表示时间步 t t t 的隐状态

  • x t x_t xt 表示输入

  • o t o_t ot 表示输出

  • w h w_h wh 表示隐藏层权重

  • w o w_o wo 表示输出层权重

  • f f f 表示隐藏层变换

  • g g g 表示输出层权重

前向传播相当简单,一次一个时间步的遍历三元组 ( x t , h t , o t ) (x_t,h_t,o_t) (xt,ht,ot),然后通过一个目标函数在所有 T T T 个时间步内评估输出 o t o_t ot 和对应的标签 y t y_t yt 之间的差异:

L ( x 1 , … , x T , y 1 , … , y T , w h , w o ) = 1 T ∑ t = 1 T l ( y t , o t ) L(x_1,\dots,x_T,y_1,\dots,y_T,w_h,w_o)=\frac{1}{T}\sum^T_{t=1}l(y_t,o_t) L(x1,,xT,y1,,yT,wh,wo)=T1t=1Tl(yt,ot)

对于反向传播,就很棘手了,特别是计算目标函数 L L L 关于参数 w h w_h wh 的梯度时,按照链式法则:

∂ L ∂ w h = 1 T ∑ t = 1 T ∂ l ( y t , o t ) ∂ w h = 1 T ∑ t = 1 T ∂ l ( y t , o t ) ∂ o t ∂ g ( h t , w o ) ∂ h t ∂ h t ∂ w h \begin{align} \frac{\partial L}{\partial w_h}&=\frac{1}{T}\sum^T_{t=1}\frac{\partial l(y_t,o_t)}{\partial w_h}\\ &=\frac{1}{T}\sum^T_{t=1}\frac{\partial l(y_t,o_t)}{\partial o_t}\frac{\partial g(h_t,w_o)}{\partial h_t}\frac{\partial h_t}{\partial w_h} \end{align} whL=T1t=1Twhl(yt,ot)=T1t=1Totl(yt,ot)htg(ht,wo)whht

乘积的第一项和第二项很容易计算, 而第三项 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh 是使事情变得棘手的地方,因为我们需要循环地计算参数 w h w_h wh h t h_t ht 的影响。根据定义式中的递归计算, h t h_t ht 既依赖于 h t − 1 h_{t-1} ht1 又依赖于 w h w_h wh,其中 h t − 1 h_{t-1} ht1 的计算也依赖于 w h w_h wh。因此,使用链式法则产生:

∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 ∂ h t − 1 ∂ w h \frac{\partial h_t}{\partial w_h}=\frac{\partial f(x_t,h_{t-1},w_h)}{\partial w_h}+\frac{\partial f(x_t,h_{t-1},w_h)}{\partial h_{t-1}}\frac{\partial h_{t-1}}{\partial w_h} whht=whf(xt,ht1,wh)+ht1f(xt,ht1,wh)whht1

消掉递归计算得

∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∑ i = 1 t − 1 ( ∏ j = i + 1 t ∂ f ( x t , h j − 1 , w h ) ∂ h j − 1 ) ∂ f ( x i , h i − 1 , w h ) ∂ w h \frac{\partial h_t}{\partial w_h}=\frac{\partial f(x_t,h_{t-1},w_h)}{\partial w_h}+\sum^{t-1}_{i=1}(\prod^t_{j=i+1}\frac{\partial f(x_t,h_{j-1},w_h)}{\partial h_{j-1}})\frac{\partial f(x_i,h_{i-1},w_h)}{\partial w_h} whht=whf(xt,ht1,wh)+i=1t1(j=i+1thj1f(xt,hj1,wh))whf(xi,hi1,wh)

虽然我们可以使用链式法则递归地计算 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh,但当 t t t 很大时这个链就会变得很长。需要想办法来处理这一问题.

8.7.1.1 完全计算

最简单粗暴的方法,可以直接计算,然而,这样的计算非常缓慢,并且可能会发生梯度爆炸,因为初始条件的微小变化就可能会对结果产生巨大的影响。也就是说类似于蝴蝶效应,即初始条件的很小变化就会导致结果发生不成比例的变化。而我们正在寻找的是能够很好地泛化高稳定性模型的估计器。因此,在实践中,这种方法几乎从未使用过。

8.7.1.2 随即截断

可以用一个随机变量替换 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh,该随机变量在预期中是正确的,但是会截断序列。 这个随机变量是通过使用序列 ξ t \xi_t ξt 来实现的,序列预定义了 0 < π t < 1 0<\pi_t<1 0<πt<1,其中 P ( ξ t = 0 ) = 1 − π t P(\xi_t=0)=1-\pi_t P(ξt=0)=1πt P ( ξ t = π t − 1 = π t ) P(\xi_t=\pi_t^{-1}=\pi_t) P(ξt=πt1=πt),因此 E ∣ ξ t ∣ = 1 E|\xi_t|=1 Eξt=1。 我们使用它来替换梯度 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh 得到:

(8.7.8)

z t = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ξ t ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 ∂ h t − 1 ∂ w h z_t=\frac{\partial f(x_t,h_{t-1},w_h)}{\partial w_h}+\xi_t\frac{\partial f(x_t,h_{t-1},w_h)}{\partial h_{t-1}}\frac{\partial h_{t-1}}{\partial w_h} zt=whf(xt,ht1,wh)+ξtht1f(xt,ht1,wh)whht1

ξ t \xi_t ξt 的定义中推导出来 E ∣ ξ t ∣ = ∂ h t / ∂ w h E|\xi_t|=\partial h_t/\partial w_h Eξt=ht/wh。每当 ξ t = 0 \xi_t=0 ξt=0 时,递归计算终止在这个 t t t 时间步。这导致了不同长度序列的加权和,其中长序列出现的很少,所以将适当地加大权重。

8.7.1.3 比较策略

在这里插入图片描述

行自上而下分别为:

  • 第一行采用随机截断,方法是将文本划分为不同长度的片断;

  • 第二行采用常规截断,方法是将文本分解为相同长度的子序列。这也是我们在循环神经网络实验中一直在做的;

  • 第三行采用通过时间的完全反向传播,结果是产生了在计算上不可行的表达式。

虽然随机截断在理论上具有吸引力,但很可能是由于多种因素在实践中并不比常规截断更好:

  • 首先,在对过去若干个时间步经过反向传播后,观测结果足以捕获实际的依赖关系。

  • 其次,增加的方差抵消了时间步数越多梯度越精确的事实。

  • 第三,我们真正想要的是只有短范围交互的模型。因此,模型需要的正是截断的通过时间反向传播方法所具备的轻度正则化效果。

8.7.2 通过时间反向传播

在这里插入图片描述

  • “通过时间反向传播”仅仅适用于反向传播在具有隐状态的序列模型。

  • 截断是计算方便性和数值稳定性的需要。截断包括:规则截断和随机截断。

  • 矩阵的高次幂可能导致神经网络特征值的发散或消失,将以梯度爆炸或梯度消失的形式表现。

  • 为了计算的效率,“通过时间反向传播”在计算期间会缓存中间值。

这篇关于《动手学深度学习 Pytorch版》 8.7 通过时间反向传播的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例

《PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例》词嵌入解决NLP维度灾难,捕捉语义关系,PyTorch的nn.Embedding模块提供灵活实现,支持参数配置、预训练及变长... 目录一、词嵌入(Word Embedding)简介为什么需要词嵌入?二、PyTorch中的nn.Em

go中的时间处理过程

《go中的时间处理过程》:本文主要介绍go中的时间处理过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 获取当前时间2 获取当前时间戳3 获取当前时间的字符串格式4 相互转化4.1 时间戳转时间字符串 (int64 > string)4.2 时间字符串转时间

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加