深度学习与硬件GPU,软件框架关系及相关概念解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/piaoxuezhong/article/details/78596276

套用:人工智能,深度学习,机器学习……不管你在从事什么工作,都需要了解这些概念。否则的话,三年之内你就会变成一只恐龙。 —— 马克·库班

本篇主要是为了在学习机器学习和深度学习之前进行一些扫雷性质的工作,毕竟要入门一个新的领域,前期了解性质的工作必不可少,针对我自己的一些疑惑,例如:深度学习需要哪些知识储备,深度学习与英伟达GPU的关系,深度学习是否一定要懂CUDA等等问题,我查阅了相关网址并整理成本篇,主要参考有:

  • http://www.fast.ai/2017/11/16/what-you-need/?spm=5176.100239.blogcont255175.51.QKCA5A
  • http://www.sohu.com/a/205254401_642762
  • http://www.360doc.com/content/17/0529/15/29942112_658222283.shtml
  • https://www.zhihu.com/question/31785984
  • http://www.sohu.com/a/203682858_642762

第一部分:深度学习与硬件、软件的关系

硬件GPU与深度学习关系解析

在过去的20年里,视频游戏产业推动了GPU(图形处理单元)的巨大进步,其绘制图形所需的矩阵数学正是深度学习所需的计算类型。GPU技术的进步是推动了神经网络的发展,没有GPU的情况下训练深度学习模型在大多数情况下将会非常缓慢。

GPU分类与选择

大多数深度学习从业者并不直接进行GPU编程,而是使用处理这个问题的软件库(如PyTorch,TensorFlow等)。有效使用这些库则需要访问正确类型的GPU。
CUDAOpenCL是GPU编程的两种主要方式。CUDA是迄今为止最发达,最广泛的生态系统,也是深度学习库最有力的支持。CUDA是由Nvidia创建的专有语言,不被其他公司的GPU所使用。fast.ai推荐使用Nvidia GPU并不是对Nvidia有特别的亲近或信任,只是说这是迄今深度学习的最佳选择。
Nvidia在GPU市场占据主导地位,其次是竞争对手AMD公司。AMD发布一个名为ROCm的平台,为深度学习提供更多的支持。 PyTorch,TensorFlow,MxNet和CNTK等主要深度学习库的ROCm状态仍在开发中。
NVIDIA的标准库使得基于CUDA来建立第一个深度学习库变得非常容易,而AMD的OpenCL则没有这样强大的标准库。现在,AMD卡没有像这样好的深度学习库,所以就只有NVIDIA。即使未来有一些OpenCL库可能也可用,但我也会坚持使用NVIDIA,因为GPU计算能力或GPGPU社区非常强大,可以持续促进CUDA的发展,而OpenCL则相对有限。因此,在CUDA社区中,很容易获得不错的开源解决方案和可靠的建议。
此外,即使深度学习刚刚起步,NVIDIA仍然在持续深入的发展。其他公司现在把钱和精力放在深度学习上,由于起步较晚,现在还是相对落后。目前,除NVIDIA-CUDA之外,其他很多软硬件结合的深度学习方案都会遇到或多或少的问题。
至于英特尔的Xeon Phi处理方案,官方广告宣称编程者可以使用标准的C代码进行开发,并很容易将代码轻松转换为经过加速的Xeon Phi代码。这个特性听起来很有趣,因为我们可以依靠丰富的C代码资源。但是,实际上只有很小部分的C代码是被支持的,所以这个特性目前并不是很有用,而且能够运行的大部分C代码都很慢。

给定预算下如何选择最快的GPU

在选择GPU时,首先要考虑的第一个GPU性能问题是什么呢:是否为cuda核心?时钟速度多大?内存大小多少?
这些都不是,对于深度学习性能而言,最重要的特征是内存带宽(memory bandwidth)。简而言之:GPU针对内存带宽进行了优化,但同时牺牲了内存访问时间(延迟)。CPU的设计恰恰相反:如果涉及少量内存(例如几个数字相乘(3 * 6 * 9)),CPU可以快速计算,但是对于大量内存(如矩阵乘法(A * B * C)则很慢。由于内存带宽的限制,当涉及大量内存的问题时,GPU快速计算的优势往往会受到限制。所以如果你想购买一个快速的GPU,首先要关注的是GPU的带宽(bandwidth)。通过内存带宽评估GPU的性能。

一般的GPU选择建议

一般来说,推荐GTX 1080 Ti,GTX 1080或GTX 1070.他们都是优秀的显卡,如果你有钱,应该购买GTX 1080 Ti。GTX 1070比普通的GTX Titan X(Maxwell)便宜一些。GTX 1080的性价比比GTX 1070低一些,但是自GTX 1080 Ti推出以来,价格大幅下滑,现在GTX 1080的性价比已经能够与GTX 1070比拟。所有这三款显卡应该比GTX 980 Ti要好,因为它们具有11GB和8GB(而不是6GB)的内存。
8GB的内存可能看起来有点小,但是对于许多任务来说这已经足够了。例如对于Kaggle比赛,大多数图像数据,deep style和自然语言理解任务,这些你可能会遇到几个问题。
对于入门级的人来或是偶尔想用GPU来参加类似Kaggle比赛的人,GTX 1060是一个不错的选择。我不推荐内存只有3GB的GTX 1060 variant产品,因为6G的内存就已经很有限了。但是,对于许多应用来说,6GB就足够了。GTX 1060比普通的Titan X慢,但与GTX 980具有可比的性价比。
就综合性价比而言,10系列设计得非常好。GTX 1050 Ti,GTX 1060,GTX 1070,GTX 1080和GTX 1080 Ti都非常出色。GTX 1060和GTX 1050 Ti适用于初学者,GTX 1070和GTX 1080是适合于初创公司,部分研究和工业部门,而性能突出的GTX 1080 Ti,对于以上应用都合适。

假如电脑没有GPU 

在学习深度学习时,可能会遇到的问题:如果电脑没有GPU或者没有Nvidia GPU怎么办呢?下面给出了几种选择:
(1)
使用Crestle。Crestle是一项服务(由fast.ai学生Anurag Goel开发),为你提供在云上的已经预先安装并配置为在GPU上运行的所有流行的科学和深度学习框架的云服务。它很容易通过你的浏览器访问,新用户可免费获得10小时和1 GB的存储空间。之后,GPU使用率是每小时59美分。(网址:https://www.crestle.com/
(2)通过控制台设置AWS云实例。可以按照fast.ai设置课程中的步骤创建一个AWS实例(远程提供Nvidia GPU)。AWS每小时收取90美分。另外还有一位fast.ai学生创建了一个设置Azure虚拟机进行深度学习的指南(没法给出,网址不翻墙貌似打不开~~)。
(3)建立自己的框架。在论坛里人们可以提出问题,分享他们正在使用的组件,并发布其他有用的链接和提示。最便宜的新型Nvidia GPU是300美元左右,一些学生在eBay或Craigslist上发现了更便宜的旧版GPU,而另外一些则是为了更强大的GPU支付更多的费用。下面几篇博客文章记录了建立机器的过程:
深度困惑:建立深度学习机的不幸事件(Mariya Yao)
建立一个便捷的深度学习机器(Sravya Tirukkovalur)  (汗,无法翻墙的痛楚)
建立你自己的深度学习框(Brendan Fortuner)

深度学习与软件的关系解析

深度学习是一个相对年轻的领域,库和工具正在迅速改变。 例如,Theano已经退休,PyTorch在2017年发布。 你应该假定你今天学到的任何特定的库和软件都会在一两年内被淘汰,重要的是理解底层概念。
Python是深度学习中最常用的语言。有许多深度学习库可供选择,几乎所有主要科技公司都支持不同的库,深度学习库包括TensorFlow(谷歌),PyTorch(Facebook),MxNet(华盛顿大学,由亚马逊改编),CNTK(微软),DeepLearning4j(Skymind),Caffe2(也是Facebook),Nnabla(索尼),PaddlePaddle(百度),以及Keras(在此列表中的其他几个库之上运行的高级API)。所有这些都有可用的Python选项。

动态与静态图计算

深度学习库之间的一个区别是它们使用的计算是动态还是静态计算或是同时允许(如MxNet和最新的TensorFlow,两个都允许)。动态计算意味着程序按照你编写的顺序执行。这通常使得调试更容易,并且更容易将你的想法转换成代码。静态计算意味着你预先为你的神经网络构建一个结构,然后对其执行操作。从理论上讲,这允许编译器进行更大的优化,尽管这也意味着在你的程序和编译器执行的程序之间可能存在更多的断开。这也意味着,错误可能会更多地从导致错误的代码中移除(例如,如果你在构建图形时存在错误,那么直到你稍后执行操作时,你才可能意识到)。尽管理论上有静态计算图的语言比具有动态计算的语言具有更好的性能,但我们常常发现,在实际中,这种情况并非如此。

谷歌的TensorFlow大多使用静态计算图,Facebook的PyTorch使用动态计算。fast.ai课程中选择使用PyTorch,并用于开发自己的库(PyTorch的高级包装器,用于编码最佳实践)。谷歌投入了更多的资源来营销TensorFlow,TensorFlow几周前发布了一个动态计算选项,但还不太成熟。

生产所需要的东西:不是GPU

许多人把生产中深度学习的想法过于复杂。我们可以在生产中使用CPU和选择的网络服务器进行深入学习。
生产中进行训练是非常罕见的。即使你想每天更新你的模型权重,也不需要在生产中进行训练。这意味着你只是在生产过程中进行推理(通过你的模型向前传递),比培训更快更容易。
你可以使用任何你喜欢的Web服务器(例如Flask),并将其设置为简单的API调用。
如果能够有效地批量处理数据,GPU只会提供更快的速度。 即使你每秒获得32个请求,使用GPU也可能会使你减慢速度,因为从第一次到达收集全部32个时,你必须等待一秒钟,然后执行计算,然后返回结果。所以建议在生产中使用CPU,并且可以根据需要添加更多的CPU(比使用多个GPU更容易)。
对于大公司来说,在生产中使用GPU可能是有意义的——然而,当你达到这个规模的时候,这将会是明确的。过早地尝试在需要之前进行扩展只会增加不必要的复杂性,并会使你放慢速度。

需要的数据:远远低于你的想象

迁移学习的力量(结合数据增强等技术)可以将预先训练的模型应用于更小的数据集。 例如医疗初创企业Enlitic,Jeremy Howard领导的一个团队只使用了1000例肺癌CT扫描与癌症相比,建立了一个比一组4位专家放射科医师更准确的诊断肺癌的算法。C ++库Dlib有一个例子,其中一个人脸检测器只使用4个图像进行精确训练,只包含18个人脸!

第二部分:基础概念:

(1) 神经元(Neuron)

神经元是组成神经网络的基础结构。在神经网络中,在收到输入的信号之后,神经元通过处理,然后把结果输出给其它的神经元或者直接作为最终的输出。

(2) 加权/权重(Weights)

当输入信号进入到神经元后,会被乘以相应的权重因子。举例来说,假设一个神经元有两个输入信号,那么每个输入将会存在着一个与之相应的权重因子。在初始化网络的时候,这些权重会被随机设置,然后在训练模型的过程中再不断地发生更改。

经过训练后的神经网络,输入的权重越高,意味着它的重要性更高,对输出的影响越大。当权重因子为0时意味着这个输入是无价值的。如下图所示,假设输入为a,相应的权重为W1。那么通过赋权节点后相应的输入应变为a*W1。

(3) 偏置/偏倚(Bias)

除了权重,输入还需要经过另外一种线性处理,叫做偏置。通过把偏置b与加权后的输入信号a*W1直接相加,以此作为激活函数的输入信号。

(4) 激活函数

之前线性处理之后的输入信号通过激活函数进行非线性变换,从而得到输出信号。即最后输出的信号具有f(a*W1 b)的形式,其中f为激活函数。在下面的示意图中, 设X1…Xn等n个输入分别对应着权重因子Wk1…Wkn以及相应的偏置b1…bn。我们把输入Xi乘以对应的权重因子Wki再加上bi的结果称为u。

u=∑w*x b

激活函数f是作用在u上的,也就是说这个神经元最终的输出结果为yk = f(u)

常用的激活函数:Sigmoid函数, 线性整流函数(ReLU) 和 softmax函数

(a) Sigmoid函数

作为最常用的激活函数之一,它的定义如下:

sigmoid函数为值域在0到1之间的光滑函数,当需要观察输入信号数值上微小的变化时,与阶梯函数相比,平滑函数(比如Sigmoid函数)的表现更好。

(b) 线性整流函数(ReLU-Rectified Linear Units)

近来的神经网络倾向于使用ReLU替代掉sigmoid函数作为隐层的激活函数,它的定义如下:

f(x) = max(x,0).

当x大于0时,函数输出x,其余的情况输出为0。函数的图像是:

使用ReLU函数的好处是,对于所有大于0的输入,导数是恒定的,这能够加快训练网络的速度。

(c) softmax函数

softmax激活函数通常应用在分类问题的输出层上。它与Sigmoid函数相似,唯一的不同是softmax函数输出结果是归一化的。sigmoid函数能在双输出的时候奏效,对多分类问题,softmax函数可以方便地将各个分类出现的概率算出。

(5) 神经网络

神经网络是构成深度学习系统的框架。神经网络的任务是找到一个未知函数的近似表达方式,它是由彼此相连的神经元所组成,这些神经元会在训练网络的过程中根据误差来更改它们的权重和偏置。激活函数将非线性变化用线性变化的组合来表示,最终产生输出。关于神经网络最好的定义:

神经网络是由大量彼此相连、概念化的人造神经元组成的,这些神经元彼此之间传递着数据,相应的权重也会随着神经网络的经历而进行调整。神经元们有着激活的阈值,当它们遇到相应的数据以及权重时会被激活,这些被激活的神经元组合起来导致了“学习”行为的产生。

(6) 输入层/输出层/隐藏层

输入层代表接受输入数据的一层,基本上是网络的第一层;输出层是产生输出的一层,或者是网络的最后一层,而网络中间的处理层叫做隐藏层。隐藏层对输入的数据进行特定的处理,再将其输入到下一层。输入层和输出层是可见的,而中间层通常是被隐藏起来的。

(7) 多层感知器(MLP-Multi Layer Perceptron)

一个单一的神经元不能完成复杂的任务,需要将它们堆叠起来工作。最简单的神经网络包括一个输入层、一个隐藏层和一个输出层。每一层都由多个神经元组成,每一层的每个神经元都与下一层中的所有神经元相连。这样的网络可以被称为是全连接网络

(8) 正向传播(forward propagation)

正向传播是指信号从输入层经过隐藏层到输出层的传输过程。在正向传播中,信号是沿着单一方向进行传播,即输入层给隐藏层提供输入,进而最终产生相应的输出。

(9) 成本函数(cost function)

在神经网络的建造过程中,建造者们希望输出的结果能够尽可能地接近实际值,成本函数用来描述网络的这种准确性。

神经网络的目标是增加预测的准确性从而减少误差,即最小化成本函数。通常情况下,最优化的输出结果往往对应着成本函数的最小值。如果采用均方误差作为成本误差,模型学习的过程就是围绕着最小化成本而进行的。

(10) 梯度下降(gradient descent)

梯度下降是一种最小化成本函数的优化算法。在梯度下降中,从起始点x开始,一次移动一点,比如说移动delta h,然后将位置信息更换为x-delta h,如此重复下去,直到达到局部的极小值,此时认为极小值就是成本最小的地方。

数学上说,沿着函数的负梯度运动就能得到函数的局域最小值。

(11) 学习速率(learning rate)

学习速率定义为在每次迭代过程中对成本函数的最小化次数。简单来说,学习速率就是指朝着成本函数最小值的下降速率。选择学习速率需要很谨慎,过大会导致可能越过最优解,过小会导致收敛花费太多的时间。

(12) 反向传播(back propagation)

在定义一个神经网络的过程中, 每个节点会被随机地分配权重和偏置。一次迭代后,我们可以根据产生的结果计算出整个网络的偏差,然后用偏差结合成本函数的梯度,对权重因子进行相应的调整,使得下次迭代的过程中偏差变小。这样一个结合成本函数的梯度来调整权重因子的过程就叫做反向传播。在反向传播中,信号的传递方向是朝后的,误差连同成本函数的梯度从输出层沿着隐藏层传播,同时伴随着对权重因子的调整。

(13) 分批(Batches)

当在训练一个神经网络的时候,相对于一次性将所有的数据全输入进去,有一个更好的方法:先将数据随机地分为几个大小一致的数据块,再分批次输入。跟一次性训练出来的模型相比,分批训练能够使模型的适用性更好 。

(14) 周期(epochs)

一个周期表示对所有的数据批次都进行了一次迭代,包括一次正向传播和一次反向传播,所以一个周期/纪元就意味着对所有的输入数据分别进行一次正向传播和反向传播。

训练网络周期的次数是可以选择的,往往周期数越高,模型的准确性就越高,但是,耗时往往就越长。同样你还需要考虑如果周期/纪元的次数过高,那么可能会出现过拟合的情况。

(15) Dropout方法

Dropout是一个可以阻止网络过拟合的规则化方法。在训练过程中隐藏的某些特定神经元会被忽略掉(drop)。这意味着网络的训练是在几个不同的结构上完成的。dropout就像是一场合奏,多个不同结构网络的输出组合产生最终的输出结果。

(16) 分批标准化(Batch Normalization)

分批标准化就像是人们在河流中用以监测水位的监察站一样。这是为了保证下一层网络得到的数据拥有合适的分布。在训练神经网络的过程中,每一次梯度下降后权重因子都会得到改变,从而会改变相应的数据结构。

但是下一层网络希望能够得到与之前分布相似的数据,因此在每一次数据传递前都需要对数据进行一次正则化处理。

(17) 过滤器/滤波器(Filter)

CNN中的滤波器,具体是指将一个权重矩阵,我们用它乘以输入图像的一部分,产生相应的卷积输出。

比方说,对于一个28×28的图片,将一个3×3的滤波器与图片中3×3的矩阵依次相乘,从而得到相应的卷积输出。滤波器的尺寸通常比原始图片要小,与权重相似,在最小化成本的反向传播中,滤波器也会被更新。

就像下面这张图片一样,通过一个过滤器,依次乘以图片中每个3×3的分块,从而产生卷积的结果。

(18) CNN(卷积神经网络)

卷积神经网络通常用来处理图像数据,假设输入数据的形状为28×28×3(28pixels×28pixels×RGB Value),那么对于传统的神经网络来说就会有2352(28×28×3)个变量。随着图像尺寸的增加,那么变量的数量就会急剧增加。

因此,通过对图片进行卷积,可以减少变量的数目。随着过滤器沿着图像上宽和高的两个方向滑动,就会产生一个相应的2维激活映射,最后再沿纵向将所有的激活映射堆叠在一起,就产生了最后的输出。

(19) 池化(pooling)

为了进一步减少变量的数目同时防止过拟合,一种常见的做法是在卷积层中引入池化层(pooling layer)。如下图所示,最常用的池化层的操作是将原始图片中每个4×4分块取最大值形成一个新的矩阵,这叫做最大值池化(max pooling)。

当然也有人尝试诸如平均池化(average pooling)之类的方式,但在实际情况中最大化池化拥有更好的效果。

(20) 补白(padding)

如下图所示,补白(padding)通常是指给图像的边缘增加额外的空白,从而使得卷积后输出的图像跟输入图像在尺寸上一致,这也被称作相同补白(Same Padding)。

有效补白(Valid Padding)指的是保持图片上每个真实的像素点,不增加空白,因此在经历卷积后数据的尺寸会不断变小。(译者注:具体是指有效补白每次会丢弃最后不满足于一次卷积的像素点,比如说filter是3*3的,那么对于一行有32个pixel的数据,经历一次卷积后就会丢掉最后2个pixel;而通过相同补白,增加一个空白位,使每行有33个pixel,卷积后数据的尺寸不会变小。

(21) 数据增强(Data Augmentation)

数据增强(Data Augmentation)指的是从已有数据中创造出新的数据,通过增加训练量以期望能够提高预测的准确率。

比如在说数字识别中,我们遇到的数字可能是倾斜或旋转的,因此如果将训练的图片进行适度的旋转,增大训练量,那么模型的准确性就可能会得到提高。通过“旋转”的操作,训练数据的品质得到了提升,这种过程被称作数据增强。

(22) 递归神经元(Recurrent Neural Network)

对于递归神经元来说,经由它自己处理过的数据会变成自身下一次的输入,这个过程总共会进行t次。如下图所示,将递归神经元展开就相当于t个不同的神经元串联起来,这种神经元的长处是能够产生一个更全面的输出结果。

第三部分:再次推荐几个学习的网址

最后,附一张照片结束本篇,希望可以认识更多通道中人,一起进步。


展开阅读全文

没有更多推荐了,返回首页