要训练一个好的 CNN 模型,通常需要很多训练数据,尤其是模型结构比较复杂的时候, 比如 ImageNet 数据集上训练的模型。虽然深度学习在 ImageNet 上取得了巨大成功,但是一个 现实的问题是,很多应用的训练集是较小的,如何在这种情况下应用深度学习呢?有三种方法 可供读者参考。
(1)可以将 ImageNet 上训练得到的模型做为起点,利用目标训练集和反向传播对其进 行继续训练,将模型适应到特定的应用。ImageNet 起到预训练的作用。
(2)如果目标训练集不够大,也可以将低层的网络参数固定,沿用 ImageNet 上的训练集 结果,只对上层进行更新。这是因为底层的网络参数是最难更新的,而从 ImageNet 学习得到 的底层滤波器往往描述了各种不同的局部边缘和纹理信息,而这些滤波器对一般的图像有较好 的普适性。
(3)直接采用 ImageNet 上训练得到的模型,把最高的隐含层的输出作为特征表达,代 替常用的手工设计的特征。
1)数据集太小,数据样本不足时,深度学习相对其它机器学习算法,没有明显优势。
(2)数据集没有局部相关特性,目前深度学习表现比较好的领域主要是图像/语音 /自然语言处理等领域,这些领域的一个共性是局部相关性。图像中像素组成物体,语音 信号中音位组合成单词,文本数据中单词组合成句子,这些特征元素的组合一旦被打乱, 表示的含义同时也被改变。对于没有这样的局部相关性的数据集,不适于使用深度学习算 法进行处理。举个例子:预测一个人的健康状况,相关的参数会有年龄、职业、收入、家 庭状况等各种元素,将这些元素打乱,并不会影响相关的结果。
对于训练样本(黑点),不同的算法 A/B 在不同的测试样本(白点)中有不同的表现,这表示:对于一个学习算法A,若它在某些问题上比学习算法B更好,则必然存在一些问题, 在那里B比A好。
也就是说:对于所有问题,无论学习算法 A 多聪明,学习算法 B 多笨拙,它们的期望性 能相同。
但是:没有免费午餐定力假设所有问题出现几率相同,实际应用中,不同的场景,会有不 同的问题分布,所以,在优化算法时,针对具体问题进行分析,是算法优化的核心所在。
共线性:多变量线性回归中,变量之间由于存在高度相关关系而使回归估计不准确。
产生问题:共线性会造成冗余,导致过拟合。
解决方法:排除变量的相关性、加入权重正则。
深度学习从统计学角度,可以看做递归的广义线性模型。
广义线性模型相对于经典的线性模型 ( y = w x + b ) (y=wx+b) (y=wx+b),核心在于引入了连接函数 g ( ⋅ ) g(\cdot) g(⋅),形式变为: y = g − 1 ( w x + b ) y=g-1(wx+b) y=g−1(wx+b)。
深度学习时递归的广义线性模型,神经元的激活函数,即为广义线性模型的链接函数。逻 辑回归(广义线性模型的一种)的 Logistic 函数即为神经元激活函数中的 Sigmoid 函数,很多 类似的方法在统计学和神经网络中的名称不一样,容易引起困惑。
神经网络的训练中,通过改变神经元的权重,使网络的输出值尽可能逼近标签以降低误差 值,训练普遍使用 BP 算法,核心思想是,计算出输出与标签间的损失函数值,然后计算其相 对于每个神经元的梯度,进行权值的迭代。
梯度消失会造成权值更新缓慢,模型训练难度增加。造成梯度消失的一个原因是,许多激 活函数将输出值挤压在很小的区间内,在激活函数两端较大范围的定义域内梯度为 0 0 0。造成学 习停止。
权值初始化的方法主要有:常量初始化(constant)、高斯分布初始化(gaussian)、 positive_unitball 初始化、均匀分布初始化(uniform)、xavier 初始化、msra 初始化、双线性初 始化(bilinear)。
1. 常量初始化(constant)
把权值或者偏置初始化为一个常数,具体是什么常数,可以自己定义。
2. 高斯分布初始化(gaussian)
需要给定高斯函数的均值与标准差。
3. positive_unitball 初始化
让每一个神经元的输入的权值和为 1 1 1,例如:一个神经元有 100 100 100 个输入,让这 100 100 100 个输入
的权值和为 1 1 1. 首先给这 100 100 100 个权值赋值为在 ( 0 , 1 ) (0,1) (0,1)之间的均匀分布,然后,每一个权值再 除以它们的和就可以啦。这么做,可以有助于防止权值初始化过大,从而防止激活函数(sigmoid 函数)进入饱和区。所以,它应该比较适合 simgmoid 形的激活函数。
4. 均匀分布初始化(uniform)
将权值与偏置进行均匀分布的初始化,用 min 与 max 控制它们的的上下限,默认为 ( 0 , 1 ) (0,1) (0,1)。
5. xavier 初始化
对于权值的分布:均值为 0 0 0,方差为( 1 1 1 / 输入的个数)的均匀分布。如果我们更注重前
向传播的话,我们可以选择 fan_in,即正向传播的输入个数;如果更注重后向传播的话,我们选择 fan_out, 因为在反向传播的时候,fan_out 就是神经元的输入个数;如果两者都考虑的话, 就选 average = (fan_in + fan_out) / 2 2 2。对于 ReLU 激活函数来说,XavierFiller 初始化也是很适合。关于该初始化方法,具体可以参考文章1、文章2,该方法假定激活函数是线性的。
6. msra 初始化
对于权值的分布:基于均值为 0 0 0,方差为( 2 2 2/输入的个数)的高斯分布;它特别适合 ReLU 激活函数,该方法主要是基于 Relu 函数提出的,推导过程类似于 xavier。
7. 双线性初始化(bilinear)
常用在反卷积神经网络里的权值初始化
启发式算法中,局部最优值的陷入无法避免。启发式,本质上是一种贪心策略,这也在客 观上决定了不符合贪心规则的更好(或者最优)解会错过。
简单来说,避免陷入局部最优就是两个字:随机。
具体实现手段上,可以根据所采用的启发式框架来灵活地加入随机性。比如遗传里面,可 以在交叉变异时,可以在控制人口策略中,也可以在选择父本母本样本时;禁忌里面,可以在 禁忌表的长度上体现,也可以在解禁策略中使用,等等。这些都要结合具体问题特定的算例集, 需要反复尝试摸索才行。参数的敏感性是一个问题,建议不要超过 3 3 3 个参数,参数越不敏感越好。不同算例集用不同种子运行多次( 100 100 100 次左右才有统计意义),统计平均性能即可。需注 意全局的随机重启通常来说不是一个好办法,因为等于主动放弃之前搜索结果,万不得已不要 用,或者就是不用。
三个原则应该把握:越随机越好;越不随机越好;二者平衡最好。
1. 越随机越好
没有随机性,一定会陷入局部最优。为了获得更大的找到最优解的期望,算法中一定要有
足够的随机性。具体体现为鲁棒性较好,搜索时多样性较好。算法的每一步选择都可以考虑加入随机性,但要控制好概率。比如,某个贪心策略下,是以概率 $1 $做某一动作,可以考虑将其 改为以概率 0.999 0.999 0.999 做之前的操作,以剩余概率做其他操作。具体参数设置需调试。
2. 越不随机越好
随机性往往是对问题内在规律的一种妥协。即没有找到其内在规律,又不知道如何是好, 为了获得更好的多样性,逼不得已加入随机。因此,对给定问题的深入研究才是根本:分辨出 哪些时候,某个动作就是客观上能严格保证最优的——这点至关重要,直接决定了算法性能。 最好的算法一定是和问题结构紧密相连的,范范地套用某个启发式的框架不会有出色的性能。 当然,如果不是追求性能至上,而是考虑到开发效率实现成本这些额外因素,则另当别论。
3. 二者平衡最好
通常情况下,做好第一点,可以略微改善算法性能;做好第二点,有希望给算法带来质的提高。而二者调和后的平衡则会带来质的飞跃。
贪心是“自强不息”的精进,不放过任何改进算法的机会;多样性的随机是“厚德载物”的一分包 容,给那些目前看似不那么好的解一些机会。调和好二者,不偏颇任何一方才能使算法有出色 的性能。要把握这种平衡,非一朝一夕之功,只能在反复试验反思中去细细品味。
要结合具体问题而言,范范空谈无太大用。
在对函数进行凸优化时,如果使用导数的方法(如:梯度下降法/GD,牛顿法等)来寻找最优解,有可能陷入到局部最优解而非全局最优解。
为了防止得到局部最优,可以对梯度下降法进行一些改进,防止陷入局部最优。
但是请注意,这些方法只能保证以最大的可能找到全局最优,无法保证 100 % 100\% 100%得到全局最优。
(1)incremental GD/stochastic GD
在 GD 中,是需要遍历所有的点之后才计算 w w w 的变化的;但是,在 stochastic GD 中,每输入一个点,就根据该点计算下一步的 w w w,这样,不仅可以从 batch training 变成 online training 方法,而且每次是按照单点的最优方向而不是整体的最优方向前进,从而相当于在朝目标前进的路上多拐了好多弯,有可能逃出局部最优。
(2)momentum 方法
momentum 相当与记忆住上一次的更新。在每次的更新中,都要加一个 k k k 倍的上一次更新 量。这样,也不再是按照标准路线前进,每次的步骤都容易受到上一次的影响,从而可能会逃 出局部最优。另外,也会加大步长,从而加快收敛。
机器学习通过对算法中的目标函数进行不断求解优化,得到最终想要的结果。分类和回归 问题中,通常使用损失函数或代价函数作为目标函数。
损失函数用来评价预测值和真实值不一样的程度。通常损失函数越好,模型的性能也越好。
损失函数可分为经验风险损失函数和结构风险损失函数。经验风险损失函数指预测结果和 实际结果的差别,结构风险损失函数是在经验风险损失函数上加上正则项。
下面介绍常用的损失函数:
1) 0 − 1 0-1 0−1 损失函数
如果预测值和目标值相等,值为 0 0 0,如果不相等,值为 1 1 1:
L ( Y , f ( x ) ) = { 1 , Y ≠ f ( x ) , 0 , Y = f ( x ) . L(Y,f(x))= \left\{ \begin{array}{} 1\;\;\;,\;\;Y\ne f(x), \\ 0\;\;\;,\;\;Y=f(x). \end{array} \right. L(Y,f(x))={1,Y=f(x),0,Y=f(x).
一般的在实际使用中,相等的条件过于严格,可适当放宽条件:
L ( Y , f ( x ) ) = { 1 , ∣ Y − f ( x ) ∣ ≥ T , 0 , ∣ Y − f ( x ) ∣ < T . L(Y,f(x))= \left\{ \begin{array}{} 1\;\;\;,\;\;|Y - f(x)| \ge T, \\ 0\;\;\;,\;\;|Y-f(x)| < T. \end{array} \right. L(Y,f(x))={1,∣Y−f(x)∣≥T,0,∣Y−f(x)∣<T.
2)绝对值损失函数
和 0 − 1 0-1 0−1 损失函数相似,绝对值损失函数表示为:
L ( Y , f ( x ) ) = ∣ Y − f ( x ) ∣ . L(Y,f(x))=|Y-f(x)|. L(Y,f(x))=∣Y−f(x)∣.
3)平方损失函数
L ( Y ∣ f ( x ) ) = ∑ N ( Y − f ( x ) ) 2 . L(Y|f(x))=\sum_{N}(Y-f(x))^2. L(Y∣f(x))=N∑(Y−f(x))2.
这点可从最小二乘法和欧几里得距离角度理解。最小二乘法的原理是,最优拟合曲线应该 使所有点到回归直线的距离和最小。
4) l o g log log 对数损失函数
L ( Y , P ( Y ∣ X ) ) = − l o g P ( Y ∣ X ) . L(Y,P(Y|X))=-logP(Y|X). L(Y,P(Y∣X))=−logP(Y∣X).
常见的逻辑回归使用的就是对数损失函数,有很多人认为逻辑回归的损失函数式平方损失, 其实不然。逻辑回归它假设样本服从伯努利分布,进而求得满足该分布的似然函数,接着取对 数求极值等。逻辑回归推导出的经验风险函数是最小化负的似然函数,从损失函数的角度看, 就是 l o g log log 损失函数。
5)指数损失函数
指数损失函数的标准形式为:
L ( Y ∣ f ( x ) ) = e x p [ − y f ( x ) ] . L(Y|f(x))=exp[-yf(x)]. L(Y∣f(x))=exp[−yf(x)].
例如 AdaBoost 就是以指数损失函数为损失函数。
6)Hinge 损失函数
Hinge 损失函数的标准形式如下:
L ( y ) = m a x ( 0 , 1 − t y ) . L(y)=max(0, 1-ty). L(y)=max(0,1−ty).
其中 y y y 是预测值,范围为 ( − 1 , 1 ) (-1,1) (−1,1), t t t 为目标值,其为 − 1 -1 −1 或 1 1 1。
在线性支持向量机中,最优化问题可等价于:
m i n w , b ∑ i = 1 N ( 1 − y i ( w x i + b ) ) + λ ∥ w 2 ∥ \underset{w,b}{min}\sum_{i=1}^{N}(1-y_i(wx_i+b))+\lambda \lVert w^2 \rVert w,bmini=1∑N(1−yi(wxi+b))+λ∥w2∥
当数据预处理完成后,我们需要选择有意义的特征输入机器学习的算法和模型进行训练。通常来说,从两个方面考虑来选择特征:
(1)特征是否发散:如果一个特征不发散,例如方差接近于 0 0 0,也就是说样本在这个特 征上基本上没有差异,这个特征对于样本的区分并没有什么用。
(2)特征与目标的相关性:这点比较显见,与目标相关性高的特征,应当优选选择。除移除低方差法外,本文介绍的其他方法均从相关性考虑。
根据特征选择的形式又可以将特征选择方法分为 3 3 3 种:
(1)Filter:过滤法,按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择
阈值的个数,选择特征。
(2)Wrapper:包装法,根据目标函数(通常是预测效果评分),每次选择若干特征,或
者排除若干特征。
(3)Embedded:嵌入法,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于 Filter 方法,但是是通过训练来确定特征的优劣。
(1)减少特征数量、降维,使模型泛化能力更强,减少过拟合;
(2)增强对特征和特征值之间的理解。拿到数据集,一个特征选择方法,往往很难同时完成这两个目的。通常情况下,选择一种自己最熟悉或者最方便的特征选择方法(往往目的是降维,而忽略了对特征和数据理解的目的)。 本文将结合 Scikit-learn 提供的例子介绍几种常用的特征选择方法,它们各自的优缺点和问题。
1 为什么要使用梯度更新规则?
在介绍梯度消失以及爆炸之前,先简单说一说梯度消失的根源—–深度神经网络和反向传 播。目前深度学习方法中,深度神经网络的发展造就了我们可以构建更深层的网络完成更复杂 的任务,深层网络比如深度卷积网络,LSTM 等等,而且最终结果表明,在处理复杂任务上, 深度网络比浅层的网络具有更好的效果。但是,目前优化神经网络的方法都是基于反向传播的 思想,即根据损失函数计算的误差通过梯度反向传播的方式,指导深度网络权值的更新优化。 这样做是有一定原因的,首先,深层网络由许多非线性层堆叠而来,每一层非线性层都可以视 为是一个非线性函数 f ( x ) f(x) f(x)( f ( x ) f(x) f(x)非线性来自于非线性激活函数),因此整个深度网络可以视为是一个复合的非线性多元函数:
F ( x ) = f n ( ⋯ f 3 ( f 2 ( f 1 ( x ) ∗ θ 1 + b ) ∗ θ 2 + b ) ⋯ ) F(x)=f_n(\cdots f_3(f_2(f_1(x)*\theta_1+b)*\theta_2+b)\cdots) F(x)=fn(⋯f3(f2(f1(x)∗θ1+b)∗θ2+b)⋯)
我们最终的目的是希望这个多元函数可以很好的完成输入到输出之间的映射,假设不同的输入,输出的最优解是 g ( x ) g(x) g(x) ,那么,优化深度网络就是为了寻找到合适的权值,满足 L o s s = L ( g ( x ) , F ( x ) ) Loss=L(g(x),F(x)) Loss=L(g(x),F(x))取得极小值点,比如最简单的损失函数:
L o s s = ∥ g ( x ) − f ( x ) ∥ 2 2 . Loss = \lVert g(x)-f(x) \rVert^2_2. Loss=∥g(x)−f(x)∥22.
假设损失函数的数据空间是下图这样的,我们最优的权值就是为了寻找下图中的最小值点, 对于这种数学寻找最小值问题,采用梯度下降的方法再适合不过了。
2 梯度消失、爆炸原因?
梯度消失与梯度爆炸其实是一种情况,看接下来的文章就知道了。两种情况下梯度消失经 常出现,一是在深层网络中,二是采用了不合适的损失函数,比如 sigmoid。梯度爆炸一般出 现在深层网络和权值初始化值太大的情况下,下面分别从这两个角度分析梯度消失和爆炸的原因。
(1)深层网络角度
对激活函数进行求导,如果此部分大于 1 1 1,那么层数增多的时候,最终的求出的梯度更新 将以指数形式增加,即发生梯度爆炸,如果此部分小于 1 1 1,那么随着层数增多,求出的梯度更 新信息将会以指数形式衰减,即发生了梯度消失。
从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的 情况很好,靠近输入的层学习的很慢,有时甚至训练了很久,前几层的权值和刚开始随机初始 化的值差不多。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足, 另外多说一句,Hinton 提出 capsule 的原因就是为了彻底抛弃反向传播,如果真能大范围普及, 那真是一个革命。
(2)激活函数角度
计算权值更新信息的时候需要计算前层偏导信息,因此如果激活函数选择不合适,比如使用 sigmoid,梯度消失就会很明显了,原因看下图,左图是sigmoid的损失函数图,右边是其倒数的图像,如果使用 sigmoid 作为损失函数,其梯度是不可能超过 0.25 0.25 0.25 的,这样经过链式求导之后,很容易发生梯度消失。
3 梯度消失、爆炸的解决方案
方案1-预训练加微调
此方法来自Hinton在2006年发表的一篇论文,Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。
方案2-梯度剪切、正则
梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。
另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization)比较常见的是l1l1正则,和l2l2正则,在各个深度框架中都有相应的API可以使用正则化。
方案3-relu、leakrelu、elu等激活函数
Relu
思想也很简单,如果激活函数的导数为1,那么就不存在梯度消失爆炸的问题了,每层的网络都可以得到相同的更新速度,relu就这样应运而生。
relu函数的导数在正数部分是恒等于1的,因此在深层网络中使用relu激活函数就不会导致梯度消失和爆炸的问题。
relu的主要贡献在于:
(1)解决了梯度消失、爆炸的问题
(2)计算方便,计算速度快
(3)加速了网络的训练
同时也存在一些缺点:
(1)由于负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决);
(2)输出不是以0为中心的。
leakrelu
leakrelu就是为了解决relu的0区间带来的影响,其数学表达为:leakrelu = m a x ( k ∗ x , 0 ) =max(k*x,0) =max(k∗x,0)其中 k k k是leak系数,一般选择 0.01 0.01 0.01或者 0.02 0.02 0.02,或者通过学习而来。
方案4-batchnorm
Batchnorm是深度学习发展以来提出的最重要的成果之一了,目前已经被广泛的应用到了各大网络中,具有加速网络收敛速度,提升训练稳定性的效果,Batchnorm本质上是解决反向传播过程中的梯度问题。Batchnorm全名是Batch Normalization,简称BN,即批规范化,通过规范化操作将输出信号 x x x规范化到均值为 0 0 0,方差为 1 1 1保证网络的稳定性。
方案5-残差结构
事实上,就是残差网络的出现导致了Imagenet比赛的终结,自从残差提出后,几乎所有的深度网络都离不开残差的身影,相比较之前的几层,几十层的深度网络,在残差网络面前都不值一提,残差可以很轻松的构建几百层,一千多层的网络而不用担心梯度消失过快的问题,原因就在于残差的捷径(shortcut)部分。
方案6-LSTM
LSTM全称是长短期记忆网络(long-short term memory networks),是不那么容易发生梯度消失的,主要原因在于LSTM内部复杂的“门”(gates)。