【一起撸个DL框架】2 节点与计算图的搭建

news2024/11/25 18:44:23

CSDN个人主页:清风莫追
欢迎关注本专栏:《一起撸个DL框架》


文章目录

  • 2 节点与计算图的搭建 🍒
    • 2.1 简介
    • 2.2 设计节点类
    • 2.3 节点类的具体实现
    • 2.4 搭建计算图进行计算
    • 2.5 小结
    • 2.6 题外话——节点存储的值

2 节点与计算图的搭建 🍒

2.1 简介

这一节将动手搭建一个简单的“计算图”,并在其上进行计算。

计算图这个术语大家可能感到陌生,它是图论中“图”的一种,由节点有向边组成,用来表示数据的流动。计算时则根据变量节点的输入得到输出。

在这里插入图片描述

2.2 设计节点类

我们将定义一个抽象的节点类。计算图中有两种节点,一种是“变量节点”,是计算图接受外部输入的地方,如上图中x1、x2节点;另一种是“计算节点”,从父节点获取输入,并进行某种运算后得到本节点的值,运算过程与具体的节点有关,如上图中add结点。所有的节点都将从抽象的节点类中派生得到。

(你当然也可以独立地实现每个节点类。但在抽象的节点类实现各种节点共有的性质,比如每个节点都会有自身的值、会有父节点,这样可以减少一些冗余的代码。)

我们将抽象的节点类命名为Node,那么Node类中应该有哪些成员呢?在搭建计算图时,需要将新建立的节点与之前的节点进行连接,因此可以有一个__init__()方法;变量节点需要接受外部输入,可以有个set_value()方法;计算节点需要知道自身具体的计算过程,可以有个compute()方法。那么,Node类的大致结构如下:

(这里为了简化设计,我们假定计算图中的每个节点都至多拥有两个父节点。即使是3个数相加,也可以拆解成两次2个数相加的运算。)

class Node:
    def __init__(self, parent1=None, parent2=None) -> None:
    	pass
    def set_value(self, value):
		pass
    def compute(self):
    	pass

接着,我们就可以通过继承Node类,实现各种具体的节点。比如“变量节点类(Varrible)”和“加法节点类(Add)”。其中变量节点什么也不用做,只需要原样继承Node类就好了。那么我可以直接将Node类作为变量节点吗?当然可以!这里主打的就是一个整整齐齐(继承关系更加统一和清晰)。同时,变量节点没有父节点,而是从外部接受输入,因此父节点直接初始化为None就好。

加法节点还需要具体实现计算本节点值的compute()方法。

class Varrible(Node):
    def __init__(self) -> None:
        super().__init__()

class Add(Node):
    def __init__(self, parent1=None, parent2=None) -> None:
        super().__init__(parent1, parent2)
    def compute(self):
        pass

2.3 节点类的具体实现

实现代码如下:

(在Node类中定义copute()有什么意义呢,在具体的计算节点类中再定义不就可以了吗?没错,但这里我们的目的主要是作为一个提醒:在计算节点中不用忘记了实现具体的计算方法,同时保证统一的方法名,不要在加法节点中是compute,在以后的乘法节点中又变成了calculate)

class Node:
    def __init__(self, parent1=None, parent2=None) -> None:
        self.parent1 = parent1
        self.parent2 = parent2
        self.value = None
    def set_value(self, value):
        self.value = value
    def compute(self):
        '''本节点值的计算逻辑。是抽象方法,需在具体的节点类中重写'''
        pass

class Varrible(Node):
    def __init__(self) -> None:
        super().__init__()

class Add(Node):
    def __init__(self, parent1=None, parent2=None) -> None:
        super().__init__(parent1, parent2)
    def compute(self):
        self.value = self.parent1.value + self.parent2.value

2.4 搭建计算图进行计算

完成节点类的定义之后,利用计算图进行计算的过程大致是个三步走的过程:

  • 1 搭建计算图。节点本身是孤立的,将节点连接起来才是具有逻辑结构的计算图。
  • 2 输入。
  • 3 计算结果节点的值。
if __name__ == '__main__':

    # 搭建计算图
    x1 = Varrible()
    x2 = Varrible()
    add = Add(x1, x2)  # 结果节点
    
    # 输入
    x1.set_value(int(input('请输入x1:')))
    x2.set_value(int(input('请输入x2:')))

    # 进行前向计算
    add.compute()  # 计算add节点的值并保存在该节点的value属性中
    print(add.value)

运行结果:

请输入x1:3
请输入x2:4
7

2.5 小结

本节以一个不到40行代码的简单例子,向搭建介绍了计算图的搭建与运算的大致过程,实现了将两个变量x1、x2作为输入,计算它们的和add的功能。

有同学可能就疑惑了,40行的简单例子?那它和我这四行代码有什么区别吗?嗯,从实现的功能上来看,几乎可以说是没有区别。不过,这是为了给后面的内容做铺垫的啦!我们想要实现一个简单的框架,图的结构可以比较灵活的进行调整,而一个函数def add(x1, x2)直接就写定了。

def add(x1, x2):
    return x1 + x2
y = add(int(input('请输入x1:')), int(input('请输入x2:')))
print(y)

本节实现的计算图只有三个节点,后面我们将继续对代码进行扩展,以支撑更加复杂的计算图的实现,一步步前进,最终尝试用我们的框架去实现一些简单的深度学习任务。

2.6 题外话——节点存储的值

我们与实际深度学习框架相比,虽然都是基于计算图的思想,但基本的实现上却有所区别。因为多个节点的运算在实现上,可以通过矩阵乘法来打包进行,效率更高,代码编写也更简单,但也更加抽象和难以理解。

小批量梯度下降法”(MBGD)是一个基本的神经网络优化算法,每次用一小批样本来更新网络的参数,而不是一个样本(SGD),也不是所有样本(BGD)。框架通常还将“批机制”集成到了计算图中,可以在计算图的一次运算中批量处理多个样本,于是计算图需要再加一个维度。而对于三维的图像输入数据(高,宽,通道数),图的节点中存储的将是四维的张量

注:有时我们谈到SGD,其实指的是MBGD。

在这里插入图片描述

我主要参考的书籍是张觉非和陈震的《用Python实现深度学习框架》,书中实现的MatrixSlow框架为了概念的清晰,将批机制放在了计算图之外,以将它与计算图在原理上区分开。在MatixSlow的实现中,每个节点存储的值都是二维矩阵

然而目前我们的实现中,每个节点存储的都是单个数值,也就是“标量”。这将导致更糟糕的计算效率,但好处是可以屏蔽之后反向传播时的矩阵乘法运算的求导问题。我感觉这样在概念上对深度学习框架的理解可能会更简单一些。


上一篇:【一起撸个DL框架】1 绪论

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/459281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据湖Iceberg-存储结构(2)

文章目录 存储结构数据文件 data files表快照 Snapshot清单列表 Manifest list清单文件 Manifest file 数据湖Iceberg-简介(1) 数据湖Iceberg-存储结构(2) 数据湖Iceberg-Hive集成Iceberg(3) 数据湖Iceberg-SparkSQL集成(4) 数据湖Iceberg-FlinkSQL集成(5) 数据湖Iceberg-Flink…

Redis入门到入土(day01)

NoSQL概述 为什么用NoSQL 1、单机MySQL的美好年代 在90年代,一个网站的访问量一般不大,用单个数据库完全可以轻松应付! 在那个时候,更多的都是静态网页,动态交互类型的网站不多。 上述架构下,我们来看看…

一文详细介绍查看和启用nginx日志(access.log和error.log),nginx错误日志的安全级别,自定义访问日志中的格式

文章目录 1. 文章引言2. Nginx访问日志(access.log)2.1 简述访问日志2.2 启用Nginx访问日志2.3 自定义访问日志中的格式 3. Nginx错误日志(error.log)3.1 简述错误日志3.2 启用错误日志3.3 Nginx错误日志的安全级别 4. 文末总结 1. 文章引言 我们在实际工作中,经常使…

vue3中如何引入element-icon并使用

简单来说,步骤就是: 安装——注册——按需引入——使用 安装 # NPM $ npm install element-plus/icons-vue # Yarn $ yarn add element-plus/icons-vue # pnpm $ pnpm install element-plus/icons-vue注册 您需要从 element-plus/icons-vue 中导入所有…

【BI软件】零编程构建财务分析模型(行计算模型)

上一讲和大家讲到,自定义SQL是用个性化的开发去满足个性化的需求,而分析模型则是用共性的开发去满足个性化的需求。而分析模型的好处显而易见,通过分析模型来开发报表,更灵活、更高效,而且开发及运维的成本非常低。同时…

C++中引用的基本内容

个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C之路】 引用,其实没啥特别的,就是起外号,或者说起小名。就比如说孙悟空就有很多外号,如…

基于Python实现个人手机定位分析

TransBigData是一个为交通时空大数据处理、分析和可视化而开发的Python包。本文就来用它实现个人手机定位分析,感兴趣的小伙伴可以了解一下 但其实交通时空大数据并不仅仅局限于交通工具产生的数据,我们的日常生活中也会产生大量的数据。比如我们的手机…

前端 百度地图绘制路线加上图片

使用百度官方示例的方法根据起终点经纬度查询驾车路线但是只是一个线路 <template><div class"transportInfo"><div id"mapcontainer" class"map">11</div><div class"collapse"><el-collapse v-mo…

CA(证书颁发机构)

CA 根证书路径/csk-rootca/csk-ca.pem&#xff1b; ~ 签发数字证书&#xff0c;颁发者信息&#xff1a;(仅包含如下信息) C CN ST China L BeiJing O skills OU Operations Departments CN CSK Global Root CA 1.修改证书的路径以及相关配置 vi /etc/pki/tls/op…

el-upload文件上传组件的封装

样式1 样式2 上传的格式 // annexUrl 数据格式如下[{"uid": 1682329534561,"name": "2023/04/24/273f36b860a74e79be3faed3ce20236f.pdf","suffix": ".pdf","url": "http://192.168.0.254:19000/annex/2023/…

JVM系列(十) 垃圾收集器之 Parallel Scavenge/Old

上篇文章我们讲解了单线程垃圾收集器 Serial/SerialOld &#xff0c;与之相对应的多线程垃圾收集器就是 Parallel Scavenge/Old&#xff0c; 本文我们讲解下多线程垃圾收集器 Parallel Scavenge/Old 垃圾收集器 新生代收集器&#xff1a; Serial、ParNew、Parallel Scavenge&…

数据库 | 什么是视图?怎么使用?什么是索引?

目录 一、视图 1 、视图概念 2、为什么要使用视图 3 、性能问题 4 、定义视图 5、查看视图 6、删除视图 二、索引 1、引入索引的问题 2、索引是什么 3、索引为什么选择b树 一、视图 1 、视图概念 视图&#xff08;View&#xff09;是一种虚拟存在的表&#xff0c;对…

【DRF配置管理】如何建立完善的DRF自带接口docs文档

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 DRF应用和管理 【DRF配置管理】Django使用DRF框架 【DRF配置管理】如何实现JWT认证 【DRF配置管理】如何在视图函数配置参数(一) 【DRF配置管理】如何…

okcc呼叫问题的解决方法(建议收藏)

很多客户开始使用OKCC呼叫中心系统&#xff0c;运营经常遇到的问题是呼叫打不通&#xff0c;无话单&#xff0c;呼叫秒挂&#xff0c;语音提示"您没有使用业务的权限"等等异常情况&#xff0c;而且反馈线路正常&#xff0c;使用呼叫系统拨打就是呼不通。 OKCC系统…

史上最烂 spring aop 原理分析

盗引中篇spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点、区别、使用方式、原理及各自对反射的优化、二者在 spring 中的统一、通知顺序、从 Aspect 到 Advisior、静态通知调用、动态通知调用。 版本 jdk&#xff1a;8spring&#xff1a;5.3.20spring boot&…

华为OD机试(20222023)真题目录 + 考点 + 复盘思路

大家好&#xff0c;我是哪吒。 本专栏包含了最新最全的华为OD机试真题&#xff0c;有详细的分析和Java代码解答。已帮助1000同学顺利通过OD机考&#xff0c;发现新题目&#xff0c;随时更新。 以下为华为OD机试真题题库。 1、华为OD机试真题&#xff08;Java&#xff09;&am…

创建型模式-原型模式

原型模式 介绍 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象 结构 原型模式包含如下角色&#xff1a; 抽象原型类&#xff1a;规定了具体原型对象必须实现的的 clone() 方法。具体原型类&#xff1a;实现抽象原型类的 cl…

Linux文本处理三大利器Grep、AWK、Sed

写在前面 Linux三剑客是文本处理工具&#xff0c;它们可以帮助我们快速、高效地对文本进行处理。其中包括了grep、awk、以及sed这三个强大的命令行工具。 Linux 三剑客主要作用: grep&#xff0c;它可以根据正则表达式查找相关内容并打印对应的数据。awk&#xff0c;它可以根…

redhat8配置vsftpd服务

目录 一、匿名访问模式 1.1、ftp服务器端修改配置&#xff08;配置文件&#xff1a;/etc/vsftpd/vsftpd.conf&#xff09; 1.2 修改ftp目录的权限 1.3 设置selinux服务对ftp服务的访问规则策略为允许 1.4 防火墙添加ftp服务 1.5 测试 二、本地用户模式 2.1 服务端修改配…

6、什么是类型断言?

虽然 TypeScript 很强大&#xff0c;但有时还不如我们了解一个值的类型方便&#xff0c;这时候我们更希望 TypeScript 不要帮我们进行类型检查&#xff0c;而是交给我们自己来&#xff0c;所以就用到了类型断言。类型断言有点像是一种类型转换&#xff0c;它把某个值强行指定为…