深度学习-07-反向传播的自动化

2024-06-05 02:36

本文主要是介绍深度学习-07-反向传播的自动化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

深度学习-07-反向传播的自动化


本文是《深度学习入门2-自製框架》 的学习笔记,记录自己学习心得,以及对重点知识的理解。如果内容对你有帮助,请支持正版,去购买正版书籍,支持正版书籍不仅是尊重作者的辛勤劳动,也是鼓励更多优秀作品问世。

当前笔记内容主要为:步骤7 反向传播的自动化 章节的相关理解。

书籍总共分为5个阶段,每个阶段分很多步骤,最终是一步一步实现一个深度学习框架。例如前两个阶段为:

第 1 阶段共包括 10 个步骤 。 在这个阶段,将创建自动微分的机制
第 2 阶段,从步骤11-24,该阶段的主要目标是扩展当前的 DeZero ,使它能够执行更复杂的计算 ,使它能 够处理接收多个输入的函数和返回多个输出的函数


1.为反向传播的自动化创造条件

之前我们在实现反向传播的时候,我们是手动编写进行反向传播计算的代码,这意味着我们每次都要编写这些代码。例如下面的:

    A = Square()
    B = Exp()
    C = Square()

    x = Variable(np.array(0.5))
    a = A(x)
    b = B(a)
    y = C(b)

    y.grad = np.array(1.0)
    b.grad = C.backward(y.grad)
    a.grad = B.backward(b.grad)
    x.grad = A.backward(a.grad)
    print(x.grad)

如果计算图不一样,那么我们每次就需要白那些不一样的代码来计算反向传播。

图:不同计算图的例子。

那我们就开始思考如果自动化这块内容?书中讲解了一种机制:无论普通的计算流程(正向传播)中是什么样的计算,反向传播都能 自动进行 。这里引入一个概念:Define- by-Run。
Define-by-Run;是在深度学习中进行计算时 ,在计算之间建立"连接"的机 制 。 这种机制也称为动态计算图


计算图都是流水线式的计算 。 因此,只要以列表的形式记录函数的顺序,就可以通过反向回溯自动进行反向传播
    
    
在实现反向传播的自动化之前,我们先思考一下变量和函数之间的关系。解决方案主要从这里入手。我们需要考察变量和函数的关系并且用代码表示出来。

函数的变量包括"输入变量 "(input) 和"输出变量"(output)。函数是变量的 "父母" 如果没有父母,说明这个变量是用户的输入变量。

修改Variable 定义,函数和变量之间的"连接,让这个"连接"在执行普通计算(正向传播)的那一刻创建。

class Variable:def __init__(self, data):self.data = dataself.grad = Noneself.creator = Nonedef set_creator(self,func):self.creator = func

上面代码,定义了熟悉 creator 标识是那个函数。并且定义了set 方法,来进行变量与函数之间的关联。

修改 Function 定义:

class Function:def __call__(self, input):x = input.datay = self.forward(x)output = Variable(y)output.set_creator(self)  # 输出者保存创造者对象self.input = inputself.output = output  # 保存输出者。我是创造者的信息,这是动态建立 "连接"这 一 机制的核心return outputdef forward(self, x):raise NotImplementedError()  # 使用Function  这个方法forward 方法的人 , 这个方法应该通过继承采实现def backward(self, gy):raise NotImplementedError()


在函数执行时,就设置输出变量的 creator 为”自己“。并且将输出保存起来。

经过上面的操作后,变量和函数之间建立的联系,并且这两种联系的建立时代码执行过程中创建的。

有了连接,我们手动检查下,计算下反向遍历计算图  

    A = Square()B = Exp()C = Square()x = Variable(np.array(0.5))a = A(x)b = B(a)y = C(b)assert y.creator == Cassert y.creator.input == bassert y.creator.input.creator == Bassert y.creator.input.creator.input == aassert y.creator.input.creator.input.creator == Aassert y.creator.input.creator.input.creator.input == x

没有抛出异常,这意味着 assert 语句的所有条件都得到了满足。


2.尝试反向传播

利用上面的变量与函数之间的关系。进行反向传播计算。

先 y ---> b 

    y.grad = np.array(1.0)C = y.creator  # 获取函数b = C.input     # 获取函数的输入b.grad = C.backward(y.grad)    # 调用函数的backward 方法

然后  b ---> a
    
 

    B = b.creatorb = B.inputa.grad = B.backward(b.grad)

最后  a----> x 

    A = a.creatorx = A.inputx.grad = A.backward(a.grad)print(x.grad)


    
其实每一步的规律是:
1 获取函数 
2 获取函数的输入 
3 调用函数的 backward 方法


最后执行的结果为  
3.29744

3.增加backward 方法

前面这些反向传播的代码可以看山,它们有着相同的处理流程准确 来说,是从一个变量到前一个变量的反向传播逻辑相同。

修改Variable 类,增加一个新的方法-backward 


class Variable:def __init__(self, data):self.data = dataself.grad = Noneself.creator = Nonedef set_creator(self,func):self.creator = funcdef backward(self):f = self.creator  # 获取函数if f is not None:x = f.input # 获取函数的输入x.grad =f.backward(self.grad) # 调用函数的backward() 方法x.backward()  # 调用自己前面的那个变量的 backward()方法
4.项目代码
'''
step07.py
自动实现反向传播'''import numpy as npclass Variable:def __init__(self, data):self.data = dataself.grad = Noneself.creator = Nonedef set_creator(self,func):self.creator = funcdef backward(self):f = self.creator  # 获取函数if f is not None:x = f.input # 获取函数的输入x.grad =f.backward(self.grad) # 调用函数的backward() 方法x.backward()  # 调用自己前面的那个变量的 backward()方法class Function:def __call__(self, input):x = input.datay = self.forward(x)output = Variable(y)output.set_creator(self)  # 输出者保存创造者对象self.input = inputself.output = output  # 保存输出者。我是创造者的信息,这是动态建立 "连接"这 一 机制的核心return outputdef forward(self, x):raise NotImplementedError()  # 使用Function  这个方法forward 方法的人 , 这个方法应该通过继承采实现def backward(self, gy):raise NotImplementedError()class Square(Function):def forward(self, x):y = x ** 2return ydef backward(self, gy):x= self.input.datagx = 2 * x * gy     #方法的参数 gy 是 一个 ndarray 实例 , 它是从输出传播而来的导数 。return gxclass Exp(Function):def forward(self, x):y = np.exp(x)return ydef backward(self, gy):x = self.input.datagx = np.exp(x) * gyreturn gxif __name__ == '__main__':A = Square()B = Exp()C = Square()x = Variable(np.array(0.5))a = A(x)b = B(a)y = C(b)assert y.creator == Cassert y.creator.input == bassert y.creator.input.creator == Bassert y.creator.input.creator.input == aassert y.creator.input.creator.input.creator == Aassert y.creator.input.creator.input.creator.input == x# 反向传播y.grad = np.array(1.0)C = y.creator  # 获取函数b = C.input     # 获取函数的输入b.grad = C.backward(y.grad)    # 调用函数的backward 方法B = b.creatorb = B.inputa.grad = B.backward(b.grad)A = a.creatorx = A.inputx.grad = A.backward(a.grad)print(x.grad)# 自动反向传播x = Variable(np.array(0.5))a = A(x)b = B(a)y = C(b)y.grad = np.array(1.0)y.back()print(x.grad)
5.总结

经过此小节的代码丰富,目前我们可以执行自动反向传播计算。

这篇关于深度学习-07-反向传播的自动化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方

深度解析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 配置

Python自动化处理PDF文档的操作完整指南

《Python自动化处理PDF文档的操作完整指南》在办公自动化中,PDF文档处理是一项常见需求,本文将介绍如何使用Python实现PDF文档的自动化处理,感兴趣的小伙伴可以跟随小编一起学习一下... 目录使用pymupdf读写PDF文件基本概念安装pymupdf提取文本内容提取图像添加水印使用pdfplum

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程