深度学习框架太抽象?其实不外乎这五大核心组件

timlong timlong     2023-05-06     554

关键词:

许多初学者觉得深度学习框架抽象,虽然调用了几个函数/方法,计算了几个数学难题,但始终不能理解这些框架的全貌。

 

为了更好地认识深度学习框架,也为了给一些想要自己亲手搭建深度学习框架的朋友提供一些基础性的指导,日前来自苏黎世联邦理工学院计算机科学系的硕士研究生Gokula Krishnan Santhanam在博客上撰文,概括了大部分深度学习框架都会包含的五大核心组件,为我们详细剖析了深度学习框架一般性的内部组织结构。以下由AI科技评论编译。

 

Gokula Krishnan Santhanam认为,大部分深度学习框架都包含以下五个核心组件:

 

1. 张量(Tensor)

2. 基于张量的各种操作

3. 计算图(Computation Graph)

4. 自动微分(Automatic Differentiation)工具

5. BLAS、cuBLAS、cuDNN等拓展包

 

1. 张量(Tensor)

 

张量是所有深度学习框架中最核心的组件,因为后续的所有运算和优化算法都是基于张量进行的。几何代数中定义的张量是基于向量和矩阵的推广,通俗一点理解的话,我们可以将标量视为零阶张量,矢量视为一阶张量,那么矩阵就是二阶张量。

 

举例来说,我们可以将任意一张RGB彩色图片表示成一个三阶张量(三个维度分别是图片的高度、宽度和色彩数据)。如下图所示是一张普通的水果图片,按照RGB三原色表示,其可以拆分为三张红色、绿色和蓝色的灰度图片,如果将这种表示方法用张量的形式写出来,就是图中最下方的那张表格。

 

技术图片

 

技术图片

 

技术图片

 

图中只显示了前5行、320列的数据,每个方格代表一个像素点,其中的数据[1.0, 1.0, 1.0]即为颜色。假设用[1.0, 0, 0]表示红色,[0, 1.0, 0]表示绿色,[0, 0, 1.0]表示蓝色,那么如图所示,前面5行的数据则全是白色。

 

将这一定义进行扩展,我们也可以用四阶张量表示一个包含多张图片的数据集,其中的四个维度分别是:图片在数据集中的编号,图片高度、宽度,以及色彩数据。

 

将各种各样的数据抽象成张量表示,然后再输入神经网络模型进行后续处理是一种非常必要且高效的策略。因为如果没有这一步骤,我们就需要根据各种不同类型的数据组织形式定义各种不同类型的数据操作,这会浪费大量的开发者精力。更关键的是,当数据处理完成后,我们还可以方便地将张量再转换回想要的格式。例如Python NumPy包中numpy.imread和numpy.imsave两个方法,分别用来将图片转换成张量对象(即代码中的Tensor对象),和将张量再转换成图片保存起来。

 

2. 基于张量的各种操作

 

有了张量对象之后,下面一步就是一系列针对这一对象的数学运算和处理过程。

 

技术图片

 

其实,整个神经网络都可以简单视为为了达到某种目的,针对输入张量进行的一系列操作过程。而所谓的“学习”就是不断纠正神经网络的实际输出结果和预期结果之间误差的过程。这里的一系列操作包含的范围很宽,可以是简单的矩阵乘法,也可以是卷积、池化和LSTM等稍复杂的运算。而且各框架支持的张量操作通常也不尽相同,详细情况可以查看其官方文档(如下为NumPy、Theano和TensorFlow的说明文档)。

 

NumPy: http://www.scipy-lectures.org/intro/numpy/operations.html

 

Theano: http://deeplearning.net/software/theano/library/tensor/basic.html

 

TensorFlow: https://www.tensorflow.org/api_docs/python/math_ops/

 

需要指出的是,大部分的张量操作都是基于类实现的(而且是抽象类),而并不是函数(这一点可能要归功于大部分的深度学习框架都是用面向对象的编程语言实现的)。这种实现思路一方面允许开发者将各种类似的操作汇总在一起,方便组织管理。另一方面也保证了整个代码的复用性、扩展性和对外接口的统一。总体上让整个框架更灵活和易于扩展,为将来的发展预留了空间。

 

3. 计算图(Computation Graph)

 

有了张量和基于张量的各种操作之后,下一步就是将各种操作整合起来,输出我们需要的结果。

 

但不幸的是,随着操作种类和数量的增多,有可能引发各种意想不到的问题,包括多个操作之间应该并行还是顺次执行,如何协同各种不同的底层设备,以及如何避免各种类型的冗余操作等等。这些问题有可能拉低整个深度学习网络的运行效率或者引入不必要的Bug,而计算图正是为解决这一问题产生的。

 

据AI科技评论了解,计算图首次被引入人工智能领域是在2009年的论文《Learning Deep Architectures for AI》。当时的图片如下所示,作者用不同的占位符(*,+,sin)构成操作结点,以字母x、a、b构成变量结点,再以有向线段将这些结点连接起来,组成一个表征运算逻辑关系的清晰明了的“图”型数据结构,这就是最初的计算图。

 

技术图片

 

后来随着技术的不断演进,加上脚本语言和低级语言各自不同的特点(概括地说,脚本语言建模方便但执行缓慢,低级语言则正好相反),因此业界逐渐形成了这样的一种开发框架:前端用Python等脚本语言建模,后端用C++等低级语言执行(这里低级是就应用层而言),以此综合了两者的优点。可以看到,这种开发框架大大降低了传统框架做跨设备计算时的代码耦合度,也避免了每次后端变动都需要修改前端的维护开销。而这里,在前端和后端之间起到关键耦合作用的就是计算图。

 

将计算图作为前后端之间的中间表示(Intermediate Representations)可以带来良好的交互性,开发者可以将Tensor对象作为数据结构,函数/方法作为操作类型,将特定的操作类型应用于特定的数据结构,从而定义出类似MATLAB的强大建模语言。

 

需要注意的是,通常情况下开发者不会将用于中间表示得到的计算图直接用于模型构造,因为这样的计算图通常包含了大量的冗余求解目标,也没有提取共享变量,因而通常都会经过依赖性剪枝、符号融合、内存共享等方法对计算图进行优化。

 

目前,各个框架对于计算图的实现机制和侧重点各不相同。例如Theano和MXNet都是以隐式处理的方式在编译中由表达式向计算图过渡。而Caffe则比较直接,可以创建一个Graph对象,然后以类似Graph.Operator(xxx)的方式显示调用。

 

因为计算图的引入,开发者得以从宏观上俯瞰整个神经网络的内部结构,就好像编译器可以从整个代码的角度决定如何分配寄存器那样,计算图也可以从宏观上决定代码运行时的GPU内存分配,以及分布式环境中不同底层设备间的相互协作方式。除此之外,现在也有许多深度学习框架将计算图应用于模型调试,可以实时输出当前某一操作类型的文本描述。

 

4. 自动微分(Automatic Differentiation)工具

 

计算图带来的另一个好处是让模型训练阶段的梯度计算变得模块化且更为便捷,也就是自动微分法。

 

正如前面提到的,因为我们可以将神经网络视为由许多非线性过程组成的一个复杂的函数体,而计算图则以模块化的方式完整表征了这一函数体的内部逻辑关系,因此微分这一复杂函数体,即求取模型梯度的方法就变成了在计算图中简单地从输入到输出进行一次完整遍历的过程。与自动微分对应,业内更传统的做法是符号微分。

 

符号微分即常见的求导分析。针对一些非线性过程(如修正线性单元ReLU)或者大规模的问题,使用符号微分法的成本往往非常高昂,有时甚至不可行(即不可微)。因此,以上述迭代式的自动微分法求解模型梯度已经被广泛采用。并且由于自动微分可以成功应对一些符号微分不适用的场景,目前许多计算图程序包(例如Computation Graph Toolkit)都已经预先实现了自动微分。

 

另外,由于每个节点处的导数只能相对于其相邻节点计算,因此实现了自动微分的模块一般都可以直接加入任意的操作类中,当然也可以被上层的微分大模块直接调用。

 

5. BLAS、cuBLAS、cuDNN等拓展包

 

现在,通过上述所有模块,我们已经可以搭建一个全功能的深度学习框架:将待处理数据转换为张量,针对张量施加各种需要的操作,通过自动微分对模型展开训练,然后得到输出结果开始测试。这时还缺什么呢?答案是运算效率。

 

由于此前的大部分实现都是基于高级语言的(如Java、Python、Lua等),而即使是执行最简单的操作,高级语言也会比低级语言消耗更多的CPU周期,更何况是结构复杂的深度神经网络,因此运算缓慢就成了高级语言的一个天然的缺陷。

 

目前针对这一问题有两种解决方案。

 

第一种方法是模拟传统的编译器。就好像传统编译器会把高级语言编译成特定平台的汇编语言实现高效运行一样,这种方法将高级语言转换为C语言,然后在C语言基础上编译、执行。为了实现这种转换,每一种张量操作的实现代码都会预先加入C语言的转换部分,然后由编译器在编译阶段将这些由C语言实现的张量操作综合在一起。目前pyCUDA和Cython等编译器都已经实现了这一功能。

 

第二种方法就是前文提到的,利用脚本语言实现前端建模,用低级语言如C++实现后端运行,这意味着高级语言和低级语言之间的交互都发生在框架内部,因此每次的后端变动都不需要修改前端,也不需要完整编译(只需要通过修改编译参数进行部分编译),因此整体速度也就更快。

 

除此之外,由于低级语言的最优化编程难度很高,而且大部分的基础操作其实也都有公开的最优解决方案,因此另一个显著的加速手段就是利用现成的扩展包。例如最初用Fortran实现的BLAS(基础线性代数子程序),就是一个非常优秀的基本矩阵(张量)运算库,此外还有英特尔的MKL(Math Kernel Library)等,开发者可以根据个人喜好灵活选择。

 

技术图片

 

值得一提的是,一般的BLAS库只是针对普通的CPU场景进行了优化,但目前大部分的深度学习模型都已经开始采用并行GPU的运算模式,因此利用诸如NVIDIA推出的针对GPU优化的cuBLAS和cuDNN等更据针对性的库可能是更好的选择。

 

运算速度对于深度学习框架来说至关重要,例如同样训练一个神经网络,不加速需要4天的时间,加速的话可能只要4小时。在快速发展的人工智能领域,特别是对那些成立不久的人工智能初创公司而言,这种差别可能就会决定谁是先驱者,而谁是追随者。

 

总结

 

原文作者在文末指出:为了向开发者提供尽量简单的接口,大部分深度学习框架通常都会将普通的概念抽象化,这可能是造成许多用户感知不到上述五点核心组件的重要原因。

 

而这也正是作者写本文的初衷:他希望开发者能够通过了解不同框架之间的一些相似特性,更好地认识和使用一个深度学习框架。另一方面,对于那些不仅对学会使用深度学习框架感兴趣,还打算亲手搭建一个深度框架的朋友,作者认为了解各框架的内部组成和一些共性的特征也是迈向成功的重要一步。他真诚地相信,一个优秀的工程师不仅应该“知其然”,更应该“知其所以然”。

 

来源:medium

scrapy五大核心组件工作流程(代码片段)

...组件#引擎(Scrapy)对整个系统的数据流进行处理,触发事务(框架核心).#调度器(Scheduler)用来接受引擎发过来的请求.由过滤器过滤重复的url并将其压入队列中,在引擎再次请求的时候返回.可以想像成一个URL(抓取网页的网址或者说是... 查看详情

深度学习及机器学习框架对比摘要

对比深度学习十大框架:TensorFlow并非最好?TensorFlow与主流深度学习框架对比五大主流深度学习框架对比:MXNET是最好选择主流开源深度学习框架对比分析主流深度学习框架对比深度学习框架的评估与比较几种机器学习框架的对... 查看详情

springcloud五大核心组件(转载)

转载:https://blog.csdn.net/weixin_51130354/article/details/123336336springCloud五大核心组件五大核心组件如下:服务发现——NetflixEureka客服端负载均衡——NetflixRibbon断路器——Netfli 查看详情

爬虫框架scrapy五大核心组件

scrapy五大核心组件的工作流程当执行爬虫文件时,5大核心组件就在工作了spiders 引擎(ScrapyEngine)管道(itemPipeline)调度器(Scheduler)下载器(Downloader)首先执行爬虫文件spider,spider的作用是 (1)解析(2)发请求,原始的url... 查看详情

vue.js学习笔记:什么是mvvm框架,vue.js的核心思想

  一:MVVM框架MVVM框架的应用场景: 1、针对具有复杂交互逻辑的前端应用            2、提供基础的架构抽象            3、提供ajax数据持久化,保证前端用户体验 二:vue.js的核心思... 查看详情

tensorflow学习路径

...Flow本身仅仅是一个分布式的高性能计算框架,想要用TF做深度学习,仅仅学习这个框架本身是没有太大意义的。因此应该将TF看作技术路线中的一个核心点,去掌握整个开发所需要的必 查看详情

ai框架核心技术系列来啦!从入门到放弃!

...术】这个系列,主要是跟大家一起探讨和学习人工智能、深度学习的计算机系统设计,而整个系统是围绕着我在工作之余所积累、梳理、构建关于AI框架的一些核心技术内容。【AI框架核心技术】这个系列,主要是跟大家一起探... 查看详情

4.validator校验器的五大核心组件,一个都不能少(代码片段)

...pring技术栈、MyBatis、JVM、中间件等小而美的专栏供以免费学习。关注公众号【BAT的乌托邦】逐个击破,深入掌握,拒绝浅尝辄止。?前言你好,我是YourBatman。[上篇文章]()介绍了校验器上下文ValidatorContext,知道它可以对校验器Valid... 查看详情

唐宇迪-人工智能学习路线(下篇)

...工智能的学习可以拆分为7步,此为4-7步:下篇。第4步:深度学习1)深度学习概述终于说到深度学习了,都需要学什么呢?深度学习可以说是当下最好用的算法了,各个领域都能吃得开。其实最核心的还是在计算机视觉和自然语... 查看详情

spark之rdd编程

...实就是分布式的元素集合。在Spark中,对数据的所有操作不外乎创建RDD、转化已有RDD以及调用RDD操作进行求值。而在这背后,Spark会自动将RDD中的数据分发到集群中,并行化执行。一、创建RDD将程序中已有的集合传给SparkContext 查看详情

图解springmvc五大组件

...Servlet这个控件是SpringMVC最核心的一个控件,顾名思义其实他就是一个Servlet,是Spring写好的一个Servlet2.HandleMapping控件标明了路径与Controller的对应关系,不同的路径访问不同的Controller3.Controller用来处理业务逻辑的Java类... 查看详情

图解springmvc五大组件

...Servlet这个控件是SpringMVC最核心的一个控件,顾名思义其实他就是一个Servlet,是Spring写好的一个Servlet2.HandleMapping控件标明了路径与Controller的对应关系,不同的路径访问不同的Controller3.Controller用来处理业务逻辑的Java类... 查看详情

阿里pai深度学习组件:tensorflow实现图片智能分类实验

...平台,包含数据预处理、特征工程、常规机器学习算法、深度学习框架、模型的评估以及预测这一整套机器学习相关服务。由于目前PAI还属于公测阶段,所以是不收费的。但是PAI底层依赖于maxcompute(计算)和oss(存储),所以... 查看详情

现代深度学习为监督学习提供了一个强大的框架

...习不同的是,通过添加更多层以及向层内添加更多单元,深度网络可以表示复杂性不断增加的函数。给定足够大的模型(层数设计)和足够大的标注训练数据集,我们可以通过深度学习将输入向量映射到输出向量,完成大多数对... 查看详情

java数组合并的写法,深度好文

一、概述对Spring高级框架做一定了解,做好前期的预习,后续的学习更容易理解和上手。二、核心思想理解了核心思想,围绕这个思想去学习Spring源码就变得事半功倍了。其实,IOC和AOP不是spring提出的,但是sp... 查看详情

深度学习小白的学习笔记——机器学习框架

机器学习用来干嘛?在李宏毅老师的描述中,机器学习其实就是在为很多问题寻找一个方程式从而得到一个机器预测的答案。而这些方程式中又对应两大类不同的问题。第一种:Regression(回归):这一类... 查看详情

spark之rdd编程(代码片段)

...实就是分布式的元素集合。在Spark中,对数据的所有操作不外乎创建RDD、转化已有RDD以及调用RDD操作进行求值。而在这背后,Spark会自动将RDD中的数据分发到集群中,并行化执行。一、创建RDD将程序中已有的集合传给SparkContext 查看详情

rdd编程上(自学三)

...RDD其实就是分布式的元素集合。在Spark中,对数据的操作不外乎创建RDD、转化已有RDD以及调用RDD操作进行求值。而在这一切背后,Spark会自动将RDD中的数据分发到集群上,并将操作并行化执行。3.1RDD基础  Spark中的RDD就是一个不... 查看详情