最近在机器学习方便进行了一系列的学习,其中的资料参考以 https://nndl.github.io/ 的最多。人个也建议充分利用此资源,不仅知识常全、解释专业、关键还是免费的(目前来说),作者是上海交大的一名老师。其实我本人对机器学习关注已久,也觉得其能在流量、故障特别是资源高度方面有施展空间,但一直忙于研究服务网格(ServiceMesh) 相关工作,直到今日才得以对此领域有比较全面性的了解;因此想趁此机会给所学内容作一个总结,也方便大家进行学习。
发展历史
说到机器学习,大家听闻最多的就要数 “深度学习” 这么一个概念了,近几年比较火,深度学习其实就是机器学习的一新方法论合集(例如蒙特卡罗方法、时序差分、深度Q网络等)。机器学习的研究上世纪就开始了,特别是深度学习的基础 “人工神经元网络(以下简称神经网络)” 更是于 1943 年就由心理学家 Warren McCulloch 和数学家 Walter Pitts 提出了。它在经历了快速发展后陷入瓶颈期,最重要的一点便是无法有效地训练神经网络——主要是算力与算法效率上的问题——直到上世纪未才由反向传播(BP)方式得以改进。需要注意的是,虽然神经网络是当前机器学习研究方向的热门,但不等于它就是机器学习,更不要说深度学习了——机器学习还有很多方式例如知识库、SVM(支持向量机)等。
神经网络就是模拟生物大脑的信息传递结构,以计算机的视角进行了构建,参照生物神经元的特性,也分为神经元、轴突与树突,具体由计算机图数据结构来表示。例如一个简单的神经元网络如下:
这是一个典型的前馈神经元网结构,其分为三个部分:输入层、隐层与输出层。隐层可以有多层,输出层的结点数量为结果对应的量,例如我们对手写 0-9 共 10 个字母进行识别,那么输出层的结点数量便为 10。每层之前的连接可以采用全连接也可以部分连接,相对简单的模型一般是全连接,但我们也能看到采用全连接(即每个结点都与下层的所有结点相连),那么随着隐层的增加,连接的边也会剧增,其训练的复杂程度也会指数上升,这就是为什么之前说神经网络在创立后后便入到了瓶颈期。这个问题一直持续到了反向传播算法的兴起。1986年,DavidRumelhart和James McClelland全面分析了连接主义模型,并重新发明了反向传播算法。Geoffrey Hinton等人将反向传播算法引入到多层感知器,解决了多层感知器的学习问题。这时,人工神经网络才又重新引起人们的注意,并重新成为新的研究热点。
神经网络结构
神经网络是机器学习里的连接主义,这种方式不讲求模型的可解释性;与之相对的是符号主义,这里方式以推理模型或者公式及知识库进行,每步操作都是可以解释的。之所以说神经网络不讲求解释,是因为其与遗传算法类似都是演绎类的算法,这种算法自身逻辑相当复杂,很难(甚至说不能)使用一种公式或者逻辑将其讲解清楚,我们也没有必须对进行了解释,反之需要的是设法提升其效率、拟合能力及鲁棒性。接下来我们来看看单个神经元:
在这里的 (x1,x2,...,xn) 是输入向量, b 是一个常量偏置量,每条输入都上都有一个权重,在经过加权求后得到 “净输入” z,如下公式所示:
由于净输入是简单的加权求合,即线性函数,其表示能力有限(例如我们无论调整权重也不能拟合非线性例如指数函数),因此每个神经元还需要一个“激活函数”,其作为就是将其映射到非线性空间上。激活函数需要具备以下几点性质:
- 连续并可导(允许少数点上不可导)的非线性函数。可导的激活函数可以 直接利用数值优化的方法来学习网络参数。
- 激活函数及其导函数要尽可能的简单,有利于提高网络计算效率。
- 激活函数的导函数的值域要在一个合适的区间内,不能太大也不能太小, 否则会影响训练的效率和稳定性。
净输入经过一个激活函数后,输出的结果我们称为 “活性值”,层层向下作用直至输出层,每个神经元的输出即是下一层的输入,这点与生物神经元的树突与轴突概念是完全一致的。综上所述,神经网络中间的连接关系、激活函数与边中的权重共同构成了网络的决策体系,而我们指的机器学习所学到的知识就存储在各边上的权重中;因此对神经网络的训练,实质上就是对权重值向量的训练,层数越多,连接越复杂,训练计算量也就越大。
激活函数
因为净输入仅仅是权重与输入值的线性组合,为了提升神经网络的拟合能力同时将净输入的取值范围控制在一个固定的范围内,增加了激活函数。激活函主要分为两种:“Sigmoid型激活函数” 与 “修正线性单元(Rectified Linear Unit,ReLU)”
-
Sigmoid型函数是指一类S型曲线函数,为两端饱和函数。常用的Sigmoid型 函数有Logistic函数和Tanh函数。其中 Logistic函数的定义如下:
Logistic函数可以看成是一个“挤压”函数,把一个实数域的输入 “挤压” 到 (0,1)。当输入值在0附近时,Sigmoid型函数近似为线性函数;当输入值靠近两端 时,对输入进行抑制。输入越小,越接近于0;输入越大,越接近于1。这样的特点 也和生物神经元类似,对一些输入会产生兴奋(输出为1),对另一些输入产生抑 制(输出为0)。从下图我们可以看出其函数图像:
从上图可以明显看出其取值范围在[-1, 1],这样固定的聚会范围有助于对数据的判别。可以换一个角度思考,如果不引入激活函数,那么不同神经元的输出聚会范围都不一样,例如一层神经元输出范围是 [-100,10], 二层却变成了 [10, 100],这种情况下,一层的值就很难作为二层的输入了。
-
修正线性单元(Rectified Linear Unit,ReLU)是目前深层神经网络中经常使用的激活函数,它实际上是一个斜坡(ramp)函数,定义为:
采用 ReLU 的神经元只需要进行加、乘和比较的操作,计算上更加高效;并且它被认为有生物上的解释性,比如单侧抑制、宽兴奋边界(即兴奋程度 也可以非常高)——在生物神经网络中,同时处于兴奋状态的神经元非常稀疏(例如人脑 中在同一时刻大概只有 1 ∼ 4% 的神经元处于活跃状态)。不过缺点是,ReLU神经元在训练时比较容易 “死亡”。在训练时,如果参数在一次不恰当的更新后,第一个隐藏层中的某个ReLU神经元在所有的训练数据上都不能被激活,那么这个神经元自身参数的梯度永远都会是 0,在以后的训练过程中永远不能被激活。ReLU 还有很多变种,例如带泄露的 ReLU、带参数的 ReLU 等。
损失函数
在机器学习的数据中,我们使用训练集D对模型进行训练,然后使用数据集D`对其结果进行验证。一个好的模型f(x,θ∗)应该在所有(x,y)的可能取值上都与真实映射函数 y = g(x)一致,即:
损失函数 L(g(x),f(x;θ)) 就是用来量化两个变量之间的差异的,它是一个非负实函数,用来评价模型的好坏,给修正优化作一个指标。与激活函数一样,损失函数也有不少的选择,主要如下:
- 0-1损失函数最直观的损失函数是模型预测的错误率,显然也是最简单的,即如果与实际一致则取值 1,如果不一致则取值 0。
- 平方损失函数(Quadratic Loss Function)经常用在预测标签 y 为实数值的任务中,一般不用于分类问题中。其函数如下:
- Hinge损失函数 对于两类分类问题,假设y 的取值为{−1,+1},f(x;θ) ∈ R。 Hinge 函数的表达式为:
过拟合、鲁棒性、偏差与方差
想必大家都学习过泰勒公式,泰勒公式是指在知道一个连续可导函数某点及其各阶导数值的取值后,能近似地以多项式的方式将原函数表式出来,这个相似度取决于项的数量,如果取正无穷,那么就是完全一致的。我们使用神经网络来靠近目标函数也是个道理。理论上来讲,神经网络可以模拟靠近任何连续实函数,这个靠近的过程,我们就称为拟合。然而我们对神经网络的训练使用的一已知的数据集。这个时候,如果模型不当,就会以篇概全,过度靠近局部而忽略了其它部分。简单来说就是只在训练的数据集上起作为,真到预测的时候就不行了。这种现象我们称为 “过拟合”
再来谈谈鲁棒性,鲁棒是 Robust 的音译,也就是健壮和强壮的意思。具体定义,不同的场景有不同的说明。对于机器学习算法方面,可以由以下三个方面来叙述:
- 模型具有较高的精度或有效性,这也是对于机器学习中所有学习模型的基本要求
- 对于模型假设出现的较小偏差,只能对算法性能产生较小的影响
- 对于模型假设出现的较大偏差,不可对算法性能产生“灾难性”的影响
换句话来说,就是鲁棒性好的算法拥有更强的适应能力,能在训练数据噪声较在、离群点较多与采样率高低的情况下也能取得不错的效果,就是我们俗话说的好(nai)养(cao)啦!
接着我们来谈偏差与方差。在实际训练一个模型f(x)时,训练集D是从真实分布P(x,y)上独立同分 布地采样出来的有限样本集合。不同的训练集会得到不同的模型。令fD(x)表示 在训练集D学习到的模型,一个机器学习算法(包括模型以及优化算法)的能力可以用不同训练集上的模型的平均性能来评价。 对于单个样本x,不同训练集D得到模型fD(x)和最优模型f∗(x)的上的期望差距为:
其中第一个红色部分的两个公式化简是这样的:
第二部分由于所求方差中已经没有了变量经x, 因此同前一部分的原理,可以直接拿掉期望表达式 E。
我们把化简后,前面一个部分即:,称为 “方差”;后面一个部分称为,即:,称为 “偏差”。
偏差与方差以两个方面描述了算法建立的模型与真实模型的差距:“方差” 是指一个模型在不同训练集上的差异,可以用来衡量一个模型是否容易过拟合;“偏差” 是指一个模型的在不同训练集上的平均性能和最优模型的差异。我们可以通过下图比较直观地感受 “方差” 与 “偏差”。
前馈神经网络与反向传播法(BP)
前馈神经网络是神经网络的一种,因为其数据流自输入节点自前向后流向输出节点,因此称为 “前馈神经网络”。前馈网络中各个神经元按接受信息的先后分为不同的组。每一组可以看作一个神经层。每一层中的神经元接受前一层神经元的输出,并输出到下一层神经元。整个网络中的信息是朝一个方向传播,没有反向的信息传播,可以用一个有向无环路图表示。前馈网络包括全连接前馈网络和卷积神经网络等,其中全连接是比较简单的模型,即每层的神经元都与下一层的神经元进行全接连(如上面图1所示);卷积神经连接结构将在下面介绍。
前馈神经网络具有很强的拟合能力,常见的连续非线性函数都可以用前馈神经网络来近似。因此如何高效地训练前馈神经网络是一个热门研究问题,目前最广为认可的是 “反向传播” 法。对于神经网络的训练效果我们前面讲过可以使用损失函数来衡量,给定一个样本 (x,y),将其输入到神经网络模型中,得到网络输出为 y^, 假设损失函数为 L(y,y^)。假设采用随机梯度下降进行神经网络参数学习,则需要计算损失函数关于每个参数的导数。如果大家对梯度下降不了解,这里简单介绍下。递度是描述一个函数在某一点上变化速度最快的一个向量。对于二维函数来说,它就是函数的导数 dx。很明显,如果我们需要找到函数的极大或者极小值,那么在寻找的路径上其梯度必然是逐渐减小的——即梯度下降——当递度变为 0 时表示已经到达极值点。对于二维函数其梯度的表达式如下:
那么随机递度下降又是怎么回事呢?这是因为如果我们采用梯度下降法寻找最大与最小值时,递度为 0 的点不一定是最小值,甚至不一定是极小值,它可能是一个鞍点。因此为了解决局部最小值陷阱与鞍点问题,学者们陆续提出了很多梯度下降改良方法,例如 “随机梯度下降(SGD)”、“动量随机梯度下降(Momentum SGD)”、“AdaGrad”、“RMSProp” 等,下面一张图示意了各算法在处理鞍点时的效果:
现在我们回到反向传播法,它的含义是:第 l 层的一个神经元的误差项(或敏感性)是所有与该神经元相连的第 l+1 层的神经元的误差项的权重和。因此我们通过对最终结果 y^ 与 y 的差便可以从后到前从最后一层倒推到第一层将每一层的误差计算出来从而进行针对性地调整。基于误差反向传播算法(Backpropagation,BP)的前馈神经网络训练过程可以 分为以下三步:
- 前馈计算每一层的净输入 z(l) 和激活值 a(l),直到最后一层
- 反向传播计算每一层的误差项 δ(l)
- 计算每一层参数的偏导数,并更新参数
反向传播算法传播法需要计算大量的微分,显然这里不可能使用人工来计算。计算机计算微分的方式一般采用自动微分。自动微分(Automatic Differentiation,AD)是一种可以对一个(程序)函数进行计算导数的方法。符号微分的处理对象是数学表达式,而自动微分的处理对象是一个函数或一段程序。而自动微分可以直接在原始程序代码进行微分,因此自动微分成为目前大多数深度学习框架的首选。自动微分的基本原理是所有的数值计算可以分解为一些基本操作,包含 +、−、×、/ 和一些初等函数 exp、log、sin、cos 等,然后利用链式法则来自动计算一个复合函数的梯度。
所谓链式法则便是复合函数求导的基本原理,设一个复合函数为 y = f(g(k(x))),则其导数为 y` = f(g(k(x)))`· (g(k(x))` · k(x)` · x`,实例如下:
循环神经网络(Recurrent NN)
在前馈神经网络中,信息的传递是单向的,这种限制虽然使得网络变得更容易学习,但在一定程度上也减弱了神经网络模型的能力。在生物神经网络中,神经元之间的连接关系要复杂的多。前馈神经网络可以看作是一个复杂的函数,每次输入都是独立的,即网络的输出只依赖于当前的输入。但是在很多现实任务中,网络的输入不仅和当前时刻的输入相关,也和其过去一段时间的输出相关。 比如一个有限状态自动机,其下一个时刻的状态(输出)不仅仅和当前输入相关, 也和当前状态(上一个时刻的输出)相关。此外,前馈网络难以处理时序数据,比如视频、语音、文本等。时序数据的长度一般是不固定的,而前馈神经网络要求输 入和输出的维数都是固定的,不能任意改变。因此,当处理这一类和时序相关的问题时,就需要一种能力更强的模型。 循环神经网络(Recurrent Neural Network,RNN)是一类具有短期记忆能力的神经网络。在循环神经网络中,神经元不但可以接受其它神经元的信息,也可以接受自身的信息,形成具有环路的网络结构, 循环神经网络有时也被翻译成递归神经网络(不过实际上递归神经网络有另外的结构)。和前馈神经网络相比,循环神 经网络更加符合生物神经网络的结构。循环神经网络已经被广泛应用在语音识 别、语言模型以及自然语言生成等任务上。下图给出了循环神经网络的示意图:
循环神经网络的训练主要采用随时间反向传播(Backpropagation Through Time,BPTT)算法。它的的主要思想是通过类似前馈神经网络的错误反向传播算法来进行计算梯度。 BPTT 算法将循环神经网络看作是一个展开的多层前馈网络,其中 “每一层” 对应循环网络中的 “每个时刻”。这样,循环神经网络就可以按按照前馈网络中的反向传播算法进行计算参数梯度。在 “展开” 的前馈网络中,所有层的参数是共享的,因此参数的真实梯度是所有 “展开层” 的参数梯度之和。
虽然简单循环网络理论上可以建立长时间间隔的状态之间的依赖关系,但是由于梯度爆炸或消失问题,实际上只能学习到短期的依赖关系。这样,当间隔t−k比较大时(例如阅读理解的上下文理解),简单神经网络很难建模这种长距离的依赖关系,称为长程依赖问题(Long-Term Dependencies Problem)。为了改善循环神经网络的长程依赖问题,一种非常好的解决方案是引入门控机制来控制信息的累积速度,包括有选择地加入新的信息,并有选择地遗忘之前累积的信息。这一类网络可以称为基于门控的循环神经网络(Gated RNN)。
长短期记忆(Long Short-Term Memory,LSTM)网络便是基于门控的循环神经网络(Gated RNN)系列应用较多的一种。循环神经网络中的隐状态h存储了历史信息,可以看作是一种记忆(Memory)。在简单循环网络中,隐状态每个时刻都会被重写,因此可以看作是一种短期记忆(Short-Term Memory)。在神经网络中,长期记忆(Long-Term Memory) 可以看作是网络参数(包含边的权重及模型中各层的参数),隐含了从训练数据中学到的经验,其更新周期要远远慢 于短期记忆。而在LSTM网络中,记忆单元c可以在某个时刻捕捉到某个关键信息,并有能力将此关键信息保存一定的时间间隔。记忆单元c中保存信息的生命周期要长于短期记忆 h,但又远远短于长期记忆,因此称为长的短期记忆(Long Short-Term Memory)。下图给出了LSTM网络的循环单元结构
LSTM 的核心便是元胞状态(Cell State),即贯穿整个 LSTM 单元顶部的路径中的 ct,元胞状态有点像是传送带,它直接穿过整个链,同时只有一些较小的线性交互。LSTM有能力对元胞状态添加或者删除信息,这种能力便是通过一种叫门的结构来控制。其计算过程为:
- 首先利用上一时刻的外部状态 ht−1 和当前时刻的输入 xt,计算出三个门,以及候选状态 ˜ct
- 结合遗忘门 ft 和输入门 it 来更新记忆单元 ct;
- 结合输出门 ot,将内部状态的信息ct 产生外部状态 ht。
若需要对 LSTM 计算过程进行更为详细的了解,可以参考这篇博客。
目前主流的 LSTM 网络用的三个门来动态地控制内部状态的应该遗忘多少历史信息,输入多少新信息,以及输出多少信息。本质上,几乎所有的 RNN 成就都是由 LSTM 取得的。对于大部分的任务,LSTM 表现得非常好。在过去的几年里,RNN 在一系列的任务中都取得了令人惊叹的成就,比如语音识别、语言建模、翻译、图片标题等等。
卷积神经网络(CNN)
卷积神经网络(Convolutional Neural Network,CNN或ConvNet)是一种具有局部连接、权重共享等特性的深层前馈神经网络。所谓的局部连接是指,每层与下层的连接不是全连接,即当前层的每个节点与下一层部分的节点相连而不是全部,与之相对的普通神经网络是全连接。为什么会产生出这样的网络结构呢?原因在于将神经网络用于处理图像时会存在以下两个问题:
- 参数太多:如果输入图像大小为100×100×3(即图像高度为100,宽度 为100, 3个颜色通道:RGB)。在全连接前馈网络中,第一个隐藏层的每个神经元 到输入层都有100×100×3 = 30,000个互相独立的连接,每个连接都对应一个权重参数。随着隐藏层神经元数量的增多,参数的规模也会急剧增加。这会导致 整个神经网络的训练效率会非常低,也很容易出现过拟合。
- 局部不变性特征:自然图像中的物体都具有局部不变性特征,比如尺度缩放、平移、旋转等操作不影响其语义信息。而全连接前馈网络很难提取这些局部不变特征,一般需要进行数据增强来提高性能。
目前的卷积神经网络一般是由卷积层、汇聚层和全连接层交叉堆叠而成的前馈神经网络,使用反向传播算法进行训练。卷积神经网络有三个结构上的特性:局部连接、权重共享以及汇聚。和前馈神经网络相比,卷积神经网络的参数更少。卷积神经网络的重点便在于卷积,它是数学上的一种重要运算。假设一个信号发生器每个时刻 t 产生一个信号 xt,其信息的衰减率为wk,即在 k−1 个时 间步长后,信息为原来的 wk 倍。假设w1 = 1,w2 = 1/2,w3 = 1/4,那么在时刻 t 收到的信号 yt 为当前时刻产生的信息和以前时刻延迟信息的叠加。即:
其中 wk 组成的向量 <w1,w2,...,wk> 我们称为滤波器。如果上面的公式不够直观,我们可以使用图形将其演算表示出下:
神经网络里一般使用的是二维卷积,其定义为:
下图展示了二维卷积的计算:
常用的均值滤波(Mean Filter)就是当前位置的像素值设为滤波器窗口中 所有像素的平均值,也就是 wuv = 1/mn。有些同学可能会问,像边缘的元素没有前置元素,那公式应该如何计算?这里一般有几种填充策略,其中最为常见的是(Zero Padding)。
了解了卷积在数学上的意义,现在我们可以知道,卷积层有两个很重要的性质:
- 局部连接在卷积层(假设是第l层)中的每一个神经元都只和下一层(第l −1 层)中某个局部窗口内的神经元相连,构成一个局部连接网络。如下图,卷积层和下一层之间的连接数大大减少,由原来的 n(l)×nl−1 个连接变为 n(l)×m 个连接,m 为滤波器大小。
- 权重共享作为参数的滤波器wl 对于第l层的所有的神经元都是相同的。如下图,所有的同颜色连接上的权重是相同的。
卷积神经网络有两个重要概念:一、卷积层,其作用是提取一个局部区域的特征,不同的卷积核相当于不同的特征提取器;二、汇聚层,也叫子采样层(Subsampling Layer),其作用是进行特征选择,降低特征数量,并从而减少参数数量。一个典型的卷积网络是由卷积层、汇聚层、全连接层交叉堆叠而成。目前常用的卷积网络结构如下图所示。一个卷积块为连续 M 个卷积层和 b个汇聚层(M 通常设置为2∼5, b为0或1)。一个卷积网络中可以堆叠 N 个连续的卷积块,然后在后面接着 K 个全连接层(N 的取值区间比较大,比如 1 ∼ 100 或者更大;K 一般为0∼2)。
目前,整个网络结构趋向于使用更小的卷积核(比如 1×1 和 3×3)以及更 深的结构(比如层数大于 50)。此外,由于卷积的操作性越来越灵活(比如不同的 步长),汇聚层的作用变得也越来越小,因此目前比较流行的卷积网络中,汇聚层 的比例也逐渐降低,趋向于全卷积网络。
总结
机器学习是计算机科学一门独立的学科,其体系复杂庞大,这篇博客也仅是我对其概念上初略的学习总结,可以让对机器学习感兴趣的同学有个大致定性上的认识。以上所述仅仅是浅显的介绍,如有错误不足之处还请大家批评改正。
人工智能(AI)是接下来工业的爆发点,在接来的几年里,它将无处不在。
------ 文本撰写于 2019-9-12,完成于 2019-10-07
评论列表: