1.深度学习花书前言
机器学习早期的时候十分依赖于已有的知识库和人为的逻辑规则,需要人们花大量的时间去制定合理的逻辑判定,可以说是有多少人工,就有多少智能。后来逐渐发展出一些简单的机器学习方法例如logistic regression、naive bayes等,机器可以通过一些特征来学习一定的模式出来,但这非常依赖于可靠的特征,比如对于logistic regression用来辅助医疗诊断,我们无法将核磁共振图像直接输入机器来作出诊断,而是医生需要先做一份报告总结一些特征,而机器通过报告中提供的表征再来进行机器学习,这就对如何提取有效表征提出了很大的要求,仍是一个需要花费很多人力的过程。鉴于这些简单模型只能从专家提供的表征映射到结果,而不能自己提取出特征的局限性,人们发展出了表征学习(representation learning),希望机器自己能够提取出有意义的特征而无需人为干预。经典的例子就是Autoencoder,主要就是由加码器encoder从原始数据提取特征,然后可以通过解码器decoder利用新的表征来重塑原始数据。
这些表征很有可能是隐含的、抽象的,比如图像识别中单个像素可能没有有效的信息,更有意义的是若干像素组成的边,由边组成的轮廓,进而由轮廓组成的物体。深度学习就是通过一层层的表征学习,每层可能逻辑很简单,但之后的层可以通过对前面简单的层的组合来构建更复杂的表征。经典的例子如多层感知机(multilayer perceptron),就是每个感知机的数理逻辑都很简单,层内可以并行执行,层间顺序执行,通过层层叠加实现更复杂的逻辑。深度学习的“深”可以理解为通过更多层来结合出更复杂的逻辑,这就完成了从输入到内在层层表征再由内在表征到输出的映射。
花书可以大致分为三大部分:
- 机器学习基础知识:涵盖线性代数,概率论,数值计算和传统机器学习基础等知识。如果之前学过Andrew Ng的CS229的话基本可以跳过。
- 深度神经网络核心知识:属于本书必读部分,涵盖前馈神经网络,卷积神经网络(CNN),递归神经网络(RNN) 等。
- 深度学习前沿:有一些前沿研究领域的介绍,如线性因子模型,表征学习,生成模型等。
在1940-1960年间,人们更多的是从神经科学找灵感,希望能够搭建能够模拟人脑工作模式的神经网络,这个时期的名字是人工神经网络(Artificial Neural Network) 或神经机械学(cybernetics)。感知机模型(perceptron)也是这个时期的产物。这个时期的模型大部分都是线性模型,对于非线性的关系不能进行很好的模拟所以有很大的局限性,深度学习研究就逐渐降温了。不过,这个时期为后来的深度学习打下基础,我们现在训练常用的随机梯度下降算法(stochastic gradient descent)就是源自处理这个时期的一种线性模型——自适应线性单元(Adaptive Linear Neuron)。虽然现在仍有媒体经常将深度学习与神经科学类比,但是由于我们对大脑工作机制的研究进展缓慢,所以实际上现在深度学习从业者已很少从神经科学中寻找灵感。
第二个阶段是1980-1990年代,这个时候更多的称为联结主义(connectionism)或并行分布式计算(parallel distributed computing),主要是强调很多的简单的计算单位可以通过互联进行更复杂的计算。这个时期成果很多,比如现在常用的反向传播算法(back propagation)还有自然语言处理中常用的LSTM(第十章讲递归神经网络时详谈)都来自与这个时期。之后由于很多AI产品期望过高而又无法落地,研究热潮逐渐退去。
第三个阶段就是2006年至今,由于软硬件性能的提高,深度学习逐渐应用在各个领域,深度学习研究重整旗鼓。“深度”学习的名字成为主流,意在强调可以训练更多层次更复杂的神经网络,“深”帮助我们开发更复杂的模型,解决更复杂的问题。
先说数据大小,如果自己动手训练过深度学习模型的话就会体验到数据集大小对预测准确率影响很大,即使是同一个模型,训练量的大小不同会造成最终效果天差地别,统计学上,通过小量数据训练延展到新数据是很困难的。随着世界数字化的趋势大数据的发展,我们有更多被标注的数据集,深度学习模型的准确度也因此受益。
随着模型准确度的提高,深度学习也逐渐得到更广泛的实际应用,比如图像识别,语音识别,机器翻译等领域。像DeepMind AlphaGo这种强化学习方面的应用更是掀起了全民AI热潮。与此同时,各种深度学习框架的出现如Caffe,Torch,Tensorflow等也方便更多人学习或利用深度学习模型。这些反过来又促进了深度学习行业的发展。
在一片繁荣下,深度学习的可解释性又常受诟病,对抗样本等的出现也让人思考深度学习的有效性,这都需要更多从业者去深入思考,而不能满足于黑箱成果,“路漫漫其修远兮,吾将上下而求索。”
2.三要素
2.1任务
在机器学习系统中,任务常常是通过已有的一些例子(example)来总结出一些统计规律。而每个例子又常常由很多通过测量得到的特征(feature)构成,我们常常将各个特征用特征向量来代表一个特征。机器学习任务可以大致分为以下的几类问题:
分类问题(classification): 指的是假如我们研究对象有k种不同的类别,我们希望程序能够知道每个数据属于哪一类,即学习的映射。比如图像识别里,我们希望推断一个图片是小汽车还是飞机,还有人脸识别中我们希望知道这些脸部图像属于谁。
回归问题(regression):我们有的时候想用机器预测某一具体数值,即学习的映射。这个定义和分类问题有些类似,但是输出格式不同。例子有我们想预测将来股票的价格的等。
结构化输出(structured output): 这是一个比较广的类别,主要指输出格式可能具有多个元素,并且各元素之间有较强关联。比如字符识别问题(Optical Character Recognition,简称OCR),即通过程序将图片中包含文字的部分识别出来并转换成字符串;语音识别问题(speech recognition)输入音频通过程序转化成相应的文字表示;机器翻译(machine translation)将某种语言翻译成另一种语言;图像描述(image captioning)即输入图像输出描述图像的文字等。
机器合成(synthesis):指机器通过已有的训练数据集可以生成一些与数据集类似的数据,比如图像合成语音合成等。
这些分类并不是很严格的定义,对于同一个问题我们常常可以把它当做不同种类的问题而采取不同方法解决,比如推荐系统预测用户是否会购买某种商品,我们既可以把它当做回归问题,也可以当做二元分类问题。
2.2性能指标
为了研究机器学习模型的有效性,我们需要可以定量的测量它的性能。比方说对于分类问题,我们可以定义准确率(accuracy)即在所有数据中模型做出正确分类的百分比,我们也可以测量错误率(error rate)即模型做出错误判断的百分比,而模型的目的就是提高正确率或减小错误率。这里我们要引出测试集(test set)的概念,通常我们希望我们的模型不仅仅能描述已有的数据,而是对于新数据也能做出很好的预测,所以我们通常要利用一个独立于训练集的测试数据集来实测模型的性能指标。
当然,对于某一研究对象找到合适的性能指标不一定是显而易见的。比方说对于翻译问题,我们的目标是整个句子都需正确,还是对于翻译正确句子的某一部分也给部分奖励?对于回归问题,我们是更多惩罚很少出错,但每次错误都是重大错误的系统,还是更多惩罚经常出错但是都是中等程度错误的系统?这些都需要视应用而定。
2.3经验
依赖于我们提供给机器的数据集格式,我们可以大致将机器学习问题分为监督学习(supervised learning)和无监督学习(unsupervised learning)问题。
监督学习:数据集不仅仅有特征,每个数据还有标签(label)。比方说图像识别数据里我们不仅提供原始图像每个像素值,我们还标注每个图像的类型,比如图像是飞机还是汽车。
无监督学习:相应地,在无监督学习里,数据只有特征,没有标注的标签,我们需要机器学习这个研究对象的概率分布,比如说聚类(clustering)问题,我们希望机器可以通过这些特征而把数据集分成不同的类似的群,比如通过用户之前的购买记录分析用户的年龄段等。
强化学习(reinforcement learning): 还有一类问题不一定有固定的静态的数据集,而是通过与环境的不断交互,形成机器学习系统与环境的反馈,从而不断的改进模型,经典例子如DeepMind的AlphaGo。
3.欠拟合与过拟合的本质
训练机器学习模型的目的不仅仅是可以描述已有的数据,而且是对未知的新数据也可以做出较好的推测,这种推广到新数据的能力称作泛化(generalization)。我们称在训练集上的误差为训练误差(training error),而在新的数据上的误差的期望称为泛化误差(generalization error)或测试误差(test error)。通常我们用测试集上的数据对模型进行测试,将其结果近似为泛化误差。
为什么我们只观测了训练集却可以影响测试集上的效果呢?如果他们是完全随机的无关的分布我们是无法做出这样的推测的,我们通常需要做出对于训练集和测试集的采样过程的假设。训练集和测试集是由某种数据生成分布产生的,通常我们假设其满足独立同分布(independent and identically distributed, 简称i.i.d),即每个数据是相互独立的,而训练集和测试集是又从同一个概率分布中取样出来的。
假设参数固定,那么我们的训练误差和测试误差就应相同。但是实际上,在机器学习模型中,我们的参数不是事先固定的,而是我们通过采样训练集选取了一个仅优化训练集的参数,然后再对测试集采样,所以测试误差常常会大于训练误差。
我们的机器学习模型因此有两个主要目的:
尽量减小训练误差。
尽量减小训练误差和测试误差间的间距
模型是欠拟合还是过拟合是由模型的容量(capacity)决定的。低容量由于对训练集描述不足造成欠拟合,高容量由于记忆过多训练集信息而不一定对于测试集适用导致过拟合。比如对于线性回归,它仅适合数据都在一条直线附近的情形,容量较小,为提高容量,我们可以引入多次项,比如二次项,可以描述二次曲线,容量较一次多项式要高。对如下图的数据点,一次式容量偏小造成欠拟合,二次式容量适中拟合较好,而九次式容量偏大造成过拟合。
训练误差,测试误差和模型容量的关系可以由下图表示,在容量较小时我们处在欠拟合区,训练误差和测试误差均较大,随着容量增大,训练误差会逐渐减小,但测试误差与训练误差的间距也会逐渐加大,当模型容量超过最适容量后,测试误差不降反增,进入过拟合区
4.正则化方法
为了减小测试误差与训练误差的差距过大防止过拟合,我们需要正则化方法(regularization),这一方法的主要目的是给模型进行一些修改使其倾向于减小测试误差。
假如我们引入一项对权重参数矢量w的正则项使得损失函数变为
J
(
w
)
=
M
S
E
t
r
a
i
n
+
λ
w
T
w
J(w)=MSE_{train}+{\lambda}w^Tw
J(w)=MSEtrain+λwTw。
λ
{\lambda}
λ等于零时它和原来的损失函数相同,当
λ
{\lambda}
λ越大时第二项造成的影响越大,为了使误差函数更小,则需要使
w
w
w更小,如使每一个
w
w
w坐标更小或使
w
w
w更集中在某些特征上而其他特征上趋于零,我们需要通过调节
λ
{\lambda}
λ大小来找到过拟合与欠拟合间合适的平衡点。例如对于九次多项式拟合,如下图所示,在最左图中当
λ
{\lambda}
λ过大时,每一个多次项的
w
w
w都趋于零,曲线是一条近似直线,造成欠拟合,在最右图中,当
λ
{\lambda}
λ趋于零时正则项约为零,对多项式没有造成任何限制,造成过拟合。只有如中间图中选取一个适中的
λ
{\lambda}
λ才可使某些项的权重减小,进行比较合适的曲线拟合。
5.超参数与验证集
初学者可能对参数与超参数(hyperparameter)的区别不是很清晰。用多次项拟合例子来说,参数就是指其中每项的权重
w
w
w的值,合适的
w
w
w是通过机器学习得到的,而超参数是我们选取用几次多项式来描述,也可以看做模型容量超参数,另外还有正则项系数
λ
{\lambda}
λ取什么值,这些通常是人为设定的。有些超参数是无法用训练集习得的,例如模型容量超参数,如果仅对训练集来说总会选取更大的模型容量,使得训练误差减小,但会造成过拟合,同样的,对于正则项,仅对训练集学习会使得正则项为零而使训练误差更小,也造成过拟合。
为了解决这个问题,我们需要一个区别于训练集的验证集(validation set)。我们可以将训练集分成两部分,一部分对于固定的超参数得到合适的参数w,而另一部分作为验证集来测试该模型的泛化误差,然后对超参数进行适宜的调整。简单概括就是训练集是为了选取合适的参数,而验证集是为了选取合适的超参数。
6. 前馈神经网络
前馈神经网络(Deep feedforward network) 可以说是深度学习最核心的模型之一。前馈神经网络的目的是对于输入
x
x
x,假设我们要模拟从输入到输出的真实函数
f
∗
f*
f∗,神经网络想要找到这样的映射
y
=
f
(
x
;
θ
)
y=f(x;{\theta})
y=f(x;θ)和合适的参数
θ
{\theta}
θ使得其预测尽量接近真实函数
f
∗
f*
f∗。
其中,前馈代表了所有的信息都从输入经过某些中间的计算而最终输出到 ,而不存在从模型的输出到输入的反馈(feedback),对于有反馈的情况即为循环神经网络(recurrent neural network)。前馈网络已经广泛应用在工业界,其重要性不言而喻,而且它也是理解在自然语言处理中应用广泛的循环神经网络的基础。
而网络则代表了该模型是将不同的基本函数组合在一起形成的模型。例如通过将三个函数
f
(
1
)
f^{(1)}
f(1),
f
(
2
)
f^{(2)}
f(2),
f
(
3
)
f^{(3)}
f(3)串联起来构成最终的函数
f
(
x
)
=
f
(
3
)
(
f
(
2
)
(
f
(
1
)
(
x
)
)
)
f(x)=f^{(3)}(f^{(2)}(f^{(1)}(x)))
f(x)=f(3)(f(2)(f(1)(x))),
f
(
1
)
f^{(1)}
f(1)就是网络的第一层,
f
(
2
)
f^{(2)}
f(2)就是网络的第二层,以此类推。这个链的长度又被称作网络的深度(depth),深度学习也因此得名。而前馈网络的最后一层被称作输出层(output layer),对于我们的训练数据,每一个输入
x
x
x都有相应的标记
y
=
f
∗
(
x
)
y=f^{*}(x)
y=f∗(x),而网络的输出层的结果需要尽量接近 y。但对于其它层来说,和训练数据没有这样的直接对应关系,即我们的算法只要求最后的输出接近于真实的标记,而对于中间每层的目的并没有明确定义,所以这些层又被称作隐藏层(hidden layer)。
最后,神经代表了它的灵感部分受到了神经科学的影响。每一隐藏层通常是矢量值,而这些隐藏层的维度定义了网络的宽度。我们可以将每层看做从一个大的从矢量到矢量的函数映射,但从另一方面也可以将矢量的每个元素看做一个小的神经元,每个神经元进行了矢量到标量的映射操作(这一操作又被称作激活函数,activation function),而每一层是不同的神经元并行运算的综合。
前馈神经网络的提出是为了解决传统线性模型的一些限制。线性模型如逻辑回归或者线性回归的优势是我们有的可以快速求出解析解,有的可以利用convex optimization来解决。但同时,线性模型也受限于只能模拟线性关系,而很难学习不同输入参数间的关系。为了将线性模型扩展到非线性函数,我们可以对于输入
x
x
x做非线性变换,再利用对于的线性模型解决该问题。
6.1如何选取映射
选取一个比较通用的
f
∗
f^{*}
f∗,例如kernel trick中的RBF kernel(也称作Gaussian kernel),如果的维度足够高,我们总能够使其匹配训练集,但很难推广到测试集。因为这种模型只是假设了局域变化不大的前提,而并没有包含任何有价值的先验信息。
人工选取合适的
f
∗
f^{*}
f∗,实际上这是在深度学习流行之前普遍采用的方法,但是这需要大量的相关经验与人力资源,而且不同领域间的知识很难迁移。
深度学习的策略是利用神经网络学习合适的用隐藏层代表的映射
f
∗
f^{*}
f∗,即模拟
y
=
f
(
x
;
θ
;
w
)
=
f
∗
(
x
;
θ
)
T
w
y=f(x;{\theta};w)=f^*(x;{\theta})^Tw
y=f(x;θ;w)=f∗(x;θ)Tw,其中
θ
{\theta}
θ是
f
∗
f^*
f∗的模拟参数,而
w
w
w是从
f
∗
f^*
f∗到最终输出的映射参数。它结合了第一和第二种方法,我们可以从比较通用的函数家族中学习
f
∗
f^*
f∗,同时也可以利用经验对函数家族的选择进行一些限制。与第二种方法比较,其优势在于我们只需要找到一个比较合适的函数家族,而不需要知道确切的函数。
6.2用神经网络模拟XOR
从图中可以看出,我们无法对该空间进行线性分割,使得两个输出为1的点落在分割线同一侧,而两个输出为0的点落在分割线另一侧。所以,传统的线性模型无法解决这一问题。为了解决这个问题,我们需要找到一个新的特征空间,使得在新空间中能用线性模型来解决。
我们引入一个如下图所示的简单的具有一层隐藏层的前馈网络模型:注意图中两种方式表示是等价的,左图是具体画出每个节点,而右图是简化为层。
假设我们用
h
=
f
(
1
)
(
x
;
W
;
c
)
h=f^{(1)}(x;W;c)
h=f(1)(x;W;c)模拟从输入到到隐藏层的映射,而用
y
=
f
(
2
)
(
h
;
w
,
b
)
y=f^{(2)}(h;w,b)
y=f(2)(h;w,b)模拟从隐藏层到输出的线性映射,则整个模型可以表示为
f
(
x
;
W
,
c
,
w
,
b
)
=
f
(
2
)
(
f
(
1
)
(
x
)
)
f(x;W,c,w,b)=f^{(2)}(f^{(1)}(x))
f(x;W,c,w,b)=f(2)(f(1)(x)), 那我们如何选取
f
(
1
)
f^{(1)}
f(1)呢,通常在神经网络中我们选称作rectified linear unit,简称为RELU的激活函数,其形式为
g
(
z
)
=
m
a
x
0
,
z
g(z)=max{0,z}
g(z)=max0,z
同时选取
h
=
f
(
2
)
h=f^{(2)}
h=f(2) 为线性函数,我们的模型转化为
f
(
x
;
W
,
c
,
w
,
b
)
=
w
T
m
a
x
(
0
,
W
T
x
+
c
)
+
b
f(x;W,c,w,b)=w^Tmax(0,W^Tx+c)+b
f(x;W,c,w,b)=wTmax(0,WTx+c)+b,我们的输入用矩阵表示为
而希望模拟的对应的输出是
对于我们的模型,我们可以找到如下的解
即我们已经从原空间映射到隐藏层所代表的空间
可以看到在新空间中,原来的输出为1的两个点已经汇聚在同一点 h=[1,0]
,因此我们可以找到该空间的线性分割,使得两个输出为1的点落在分割线同一侧,而两个输出为0的点落在分割线另一侧。我们继续将h,w,b代入可得最终输出
7.损失函数
神经网络的设计主要包含两方面:1)损失函数的选择 2)模型的具体架构。对于损失函数,我们通常选择的是减小模型的概率分布与真实的概率分布之间的差异,即交叉熵(cross-entropy):损失函数的具体形式依赖于模型的概率分布
J
(
θ
)
=
−
E
x
,
y
p
l
o
g
p
m
o
d
e
l
(
y
∣
x
)
J({\theta})=-E_{x,y~p}logp_{model}(y|x)
J(θ)=−Ex,y plogpmodel(y∣x)
需要注意的是,由于神经网络的非线性的特征,我们通常需要用梯度下降的方法逐渐逼近其极值,而且不能保证损失一定会收敛。假如损失函数很容易饱和即在某些区间趋于不变的话,则其梯度很小,梯度下降算法很难更新,所以我们希望损失函数在我们所研究的区间内尽量不饱和。这也是为什么我们通常选取交叉熵的形式,因为很多概率分布函数都会出现指数形式(如sigmoid函数)而在某些区间饱和,交叉熵中的log函数正好可以抵消其饱和,使得模型可以较快更新纠正错误预测。
损失函数的具体形式依赖于神经网络输出层的选择,假设我们的神经网络已经得到了一系列隐藏特征
h
=
f
(
x
;
θ
)
h=f(x;{\theta})
h=f(x;θ) ,输出层就是从隐藏特征向我们的预测目标的映射。对于不同的输出分布,我们会有不同的输出函数及损失函数,常见的有如下几种:
对于输出是Bernoulli Distribution的二元分布
如果我们需要描述目标是多个class的概率分布,我们需要将处理二元分类问题的sigmoid函数扩展,即对于多元分类问题常用的Softmax函数。
对于输出是高斯分布的情况之前已经总结过,由于线性输出不存在饱和区间,所以能较好的应用梯度下降算法。
万能近似定理证明:仅有一层隐藏层的前馈网络就足够表示任何函数的近似到任意的精度,那我们为什么还经常要构建更深层次的网络呢?原因是如果深度较浅,我们就需要每层有更多的节点即更大的宽度,为达到相同准确度所需要的总节点数更多。另外一方面,浅的网络也更易过拟合,泛化误差较大,例如Ian研究了对于图片地址数字识别的问题,测试准确度会随着层数的增大而提高:所以通常我们会选取更深的网络来解决更复杂的问题。总结一下,这部分主要讲了神经网络的损失函数通常用交叉熵,隐藏层通常用ReLU,而更深的模型能有效减少总节点数且减少泛化误差。
8.反向传播
正向传播就是对于前馈神经网络来说,信息从输入到隐藏层再到输出的正向流动过程,最终会得到损失函数的值。而反向传播就是从损失函数反向流入网络以计算梯度(gradient)的过程。要注意,有个普遍的误解是反向传播就是神经网络的全部学习算法,实际上,反向传播仅指计算梯度的过程,实际上的学习过程是诸如随机梯度下降(stochastic gradient descent,SGD)更新网络的算法。
反向传播的原理很简单,就是利用了导数的链式法则。我们利用链式法则,就可以不断的从最终的损失函数不断的反向推导出每层的梯度,而反向传播就是一种特殊的进行链式法则运算的执行过程,即结合了动态规划(dynammic programming)避免了某些操作的重复性运算,利用较小的存储代价换取速度的提升。
9.提升模型泛化能力的方法
总体来说,一部分正则化方法使给模型施加额外的限制条件,例如限制参数值范围,有些会在目标函数中添加一些额外惩罚项,本质上也是希望限制参数值。有的时候,这些限制条件或惩罚项代表了特定的先验经验,有的时候是希望避免模型过于复杂。Parameter Norm Penalties即在目标函数中添加对于参数的惩罚项以减小模型的capacity,
使机器学习模型效果更好的很自然的一种办法就是给它提供更多的训练数据,当然实际操作中,有时候训练集是有限的,我们可以制造一些假数据并添加入训练集中,当然这仅对某些机器学习问题适用,例如对于图像识别,我们可以平移图像,添加噪声,旋转,色调偏移等等,我们希望模型能够在这些变换或干扰不受影响保持预测的准确性,从而减小泛化误差。
与Dataset augmentation类似,多任务学习也是希望令模型的参数能够进行很好的泛化,其原理是对多个目标共享模型的一部分(输入及某些中间的表示层),使其对于多个有关联的目标均有较好的效果,保证模型可以更好的推广。
通常对于较大的模型,我们会观察到训练集上的误差不断减小,但验证集上的误差会在某个点之后反而逐渐增大,这意味着为了减小泛化误差,我们可以在训练过程中不断的记录验证集上的误差及对应的模型参数,最终返回验证集上误差最小所对应的模型参数,这个简单直观的方法就是early stopping,由于其简单高效,在深度学习中得到了广泛应用。
Sparse Representations使参数更稀疏,同样的我们也可以通过增加对于表征层的norm penalty项使表征(隐藏层)更稀疏。
Bagging(全称是bootstrap aggregating)通过整合多个模型来减小泛化误差,其基本思想是多个模型对于训练集做出同样错误预测的概率较小,Bagging是ensemble methods(集成算法)的一种方法。
Dropout可以理解做是将ensemble应用到大型神经网络的一种更为实际有效的方法。由于ensemble需要训练多个模型,对于大型神经网络,其训练和评估所需时间和存储资源较大,这种方法常常不太实际,Dropout就提供了一个更便宜的解决方案:即通过随机去掉一些节点的方法训练多个子网络,并最终将这些子网络ensemble起来。其具体方法是当我们利用minibatch的算法如随机梯度下降算法来学习时,我们可以随机的选取一个binary mask(0表示节点输出为零,1表示正常输出该节点)决定哪些输入和隐藏层节点保留,每次的mask的选择是独立的。而mask为1的概率是我们可以调控的超参数。和bagging方法相比,bagging中每个模型是完全独立的,而dropout中,模型间由于继承了父网络中的参数的子集会共享一些参数,这使得在有限的存储空间中我们可以表示多个模型。以上是训练过程,而在做inference预测时,我们需要取所有模型的预测的均值,但是这往往计算量过多,Hinton提出inference时我们实际可以只用一个模型但其中每个节点的权重需要乘以包含这个节点的概率,这种方法称作weight scaling inference rule。实际中,我们常常把weight scaling过程放在训练过程中,即训练中每个节点输出就乘以包含该节点的概率的倒数,则inference时只需要正常的通过一遍前馈过程即可,不需要在进行weight scaling。Dropout的优势在于其计算资源占用小,并且对于模型或训练算法的限制较小,基本上可以适用于各种前馈网络,循环网络或概率模型,所以实际工业模型中应用很多。
Adversarial Training对抗训练很有意思,它让人们深入思考机器学习究竟学到了什么有效信息。这方面的工作主要是由谷歌的Szegedy和本书作者Ian Goodfellow进行的。他们可以制造一些对抗样本迷惑神经网络,如下图中所示,他们对于熊猫图片加了一些人眼不可见的干扰,形成新样本,而新的人眼仍可鉴定为熊猫的图片却会被机器以较大置信率鉴定为长臂猿。
为什么在人类看来类似的样本机器会得到大相径庭的结论呢?Ian认为这是由于神经网络中的大部分组成还是线性的(如ReLU可以看成是分段线性),而对于不同的输入,线性函数会受到较大的扰动,产生较大的改变。为了解决这一问题,他们会将这些对抗样本重新加到训练集中,使得神经网络倾向于对于数据集保持局部稳定而不至干扰过大,从而学习到更有效的信息。
10.优化方法归纳
随着样本的增多,计算梯度的准确度的回报是小于线性的。例如我们有两种方法:1. 利用100个样本计算梯度 2.利用10000个样本计算梯度。 第二种方法是第一种的100倍的计算量,但只将均值的标准差减少了10倍,我们通常希望我们能更快的达到我们的优化目标,所以不需要每次计算梯度都严格的利用全部样本,而是进行多次iteration,而每次估算的梯度有合适的准确度即可。在优化算法里,我们通常把一次仅利用一个样本来更新的方式叫做stochastic或online 方法。但对于深度学习来讲,我们通常所说的stochastic gradient descent指的是minibatch stochastic methods,即每次计算梯度时利用一部分样本,其样本量是新引入的超参数batch size。注意到,我们引入了另一个超参数学习率 ,可以说学习率是深度学习中最重要的需要调节的参数,如果学习率过大,我们可能会一次就跳过极小点而到山谷的另一侧,那么训练的loss可能会有较大波动而不是一致的向极小点步进,另一方面,如果学习率过小,训练更新过小,需要较长时间才能达到较好效果。通常我们需要经过不断的试验来选取合适的学习率,另外也可以在初始时使用稍大一些的学习率,随着训练的进行我们可以逐步的降低学习率从而避免波动,而之后保持学习率恒定。
Momentum,顾名思义,来自物理学中的动量概念,即我们用一个新的变量(可以看做是速度,在质量为单位质量时大小等于Momentum)来记录之前的梯度变化的速度,其优势在于对于局域极小值或鞍点的情况,由于保持了原有的速度,模型可以继续更新。
而对于不同方向的曲率不同的问题,由于其保持一定原有方向的速度,不会在曲率较大的山峰间进行剧烈波动,如下图蓝线所示:
AdaGrad没有引入速度变量 ,而是记录每个参数方向上的梯度的值的平方和,在该参数方向上步进时除以这个平方和的平方根,则对于原梯度较小学习进展较慢的方向相较于原梯度较大的方向rescale的程度较小,从而加速在该方向上的学习进程。Adagrad虽然可以较好的解决不同方向曲率差异过大的情况,但是我们可以看到随着训练的进行,习率衰减依赖于所有之前的梯度的历史结果,可能在我们未达到极值点前学习率已经减至过低从而无法有效的更新模型。所以RMSProp方法在其上做了改进,计算的是一个带有指数权重的moving average。
Adam 可以看做是RMSProp 与Momentum方法的一种结合,其得名于Adaptive moments,意在结合两者的优点。它引入两个moment, 第一个即为速度的Momentum,第二个moment则是如RMSProp中的梯度的平方和,并分别对两个moment进行一些随时间变化的修正。实际应用中,选择Adam和合适的参数能够适用于大部分深度学习优化问题。
11.卷积神经网络
继续深度学习花书的读书笔记总结,这一章主要介绍了卷积神经网络(convolutional neural network, 简称CNN), 它通常适用于具有网格状结构的数据,例如时序数据可看做是在特定时间间隔上的一维网格,图像可以看做是像素构成的二维网格,医学成像如CT等为三维网格数据。
卷积神经网络,顾名思义,利用了数学上的卷积操作(convolution)。和前面总结的基本的前馈神经网络相比,CNN只不过是将某层或某几层中的矩阵乘法运算替换为卷积运算,其他的比如说最大似然法则,反向传播算法等等都保持不变。
对于传统的神经网络来说,由于其操作是矩阵乘法,每一个输入与输出元之间都需要一个独立的参数来表示,这代表每个输出元与每个输入元之间都有连接,我们就需要很大的空间来存储这些参数,而对于CNN来说,通常其kernel的大小远小于其输入的大小,例如对于图像数据,输入常常有成千上万的像素,而对于检测图像中边的结构的kernel可能只需要利用十至百个像素即可,这极大的减小了存储所需空间,而且减小了计算输出时的计算量。对于m个输入和n个输出,矩阵乘法需要 个参数,其运算时间为 ,而假如我们限制每个输入到输出的连接为k个,则我们仅需要 个参数,且运算时间为 。如图中所示,上图为卷积操作,下图为矩阵乘法,可见卷积操作总的连接数大大减小.
另外,对于传统神经网络来说,每一个输入至输出的元素都是独立的,只对于输入的一个元素起作用,而对于CNN来说,kernel的矩阵元素对于输入的每一个元素都起作用,实现了参数的共享,如图中所示,上图是一个kernel大小为3的卷积神经网络,其中深黑色箭头代表的kernel中间的元素对于每一个 到 的运算都起作用,而对于下图矩阵乘法来讲,黑色箭头代表的权重矩阵中的元素仅对 到 的运算起作用。
除了卷积层之外,CNN中还有常用的操作是pooling function,其作用是利用附近元素的统计信息来代替其原有的值,其目的是可以使结果在对于输入的小量改变的干扰下保持稳定。例如,一个经典的pooling function是max pooling,即将周围小方格中的最大值作为输出值,当某一输入值改变时,对最大值影响较小,保持了输出的稳定。加入pooling后,卷积的基本单元包括卷积层(convolution layer),激活函数的非线性Detector layer,以及pooling layer
12.循环神经网络
循环神经网络(Recurrent neural network, 简称RNN),主要用来处理序列数据,比如一些文字序列或时序数据。对于这类数据,基本的前馈神经网络会对每一个输入的特征都训练一个单独的参数,而不能很好的进行参数的共享,而RNN就可以通过对不同时间点的特征共享参数而更容易的进行训练,泛化效果也更好。RNN与CNN不同的地方在于其每一点的输出还依赖于之前的结果。
13.对抗神经网络
GAN的全称是Generative adversarial network,中文翻译过来就是对抗式神经网络。对抗神经网络其实是两个网络的组合,可以理解为一个网络生成模拟数据(生成网络Generator),另一个网络判断生成的数据是真实的还是模拟的(判别网络Discriminator)。生成网络要不断优化自己生成的数据让判别网络判断不出来,判别网络也要优化自己让自己判断得更准确。二者关系形成对抗,因此叫对抗神经网络。
GAN网络最强大的地方就是可以帮助我们建立模型,而不像传统的网络那样是在已有模型上帮我们更新参数而已。同时,GAN网络是一种无监督的学习方式,它的泛化性非常好。