图像分类
图像分类:在已有固定分类标签的集合下,对输入的图像,从分类标签集合中找出一个分类标签,最后把分类标签分配给该输入图像的过程。综上,其主要任务是对于一个给定的图像,预测它属于哪个分类标签或者给出属于一系列不同标签的可能性。
计算机视觉算法在图像识别方面的一些难点:
1)视角变化:同一物体,摄像头可以从多个角度来展现;
2)大小变化:物体可视的大小通常是会变化的(不仅是在图片中,在真实世界中大小也是由变化的);
3)形变:很多东西的形状并非一成不变,会有很大变化;
4)遮挡:目标物体可能被遮挡。有时候只有物体的一部分(可以小到几个像素)是可见的;
5)光照条件:在像素层面上,光照的影响非常大;
6)背景干扰:物体可能混入背景之中,使之难以被辨认;
7)类内差异:一类物体的个体之间的外形差异很大,如椅子。这一类物体有许多不同的对象,每个都有自己的外形
面对以上难题,好的图像分类此模型是能够在维持分类结论稳定的同时,保持对类间差异足够敏感。
识别图像分类的方法:
数据驱动方法:给计算机很多数据,然后实现学习算法,让计算机学习到每个类的外形。此方法第一步为收集已经做好分类标注的图片来作为训练集。
图像分类就是输入一个元素为像素值的数组,然后给它分配一个分类标签。其流程如下:
1)输入:输入是包含N个图像的集合,每个图像的标签是K中分类标签中的一种。这个集合称为训练集;
2)学习:使用训练集来学习每个类到底长什么样,即训练分类器或学习一个模型;
3)评价:利用分类来预测其未曾见过的图像分类标签,并以此来评价分类器的质量。然后把分类器预测的标签和图像真正的分类标签对比。分类器预测的分类标签与图像真正的分类标签一致的数目越多,则分类效果越好。
K-NN分类器需要设定k值,那么选择哪个k值最合适?此外,可以选择不同的距离函数,如L1范数和L2范数等,那么选择哪个好?所有这些选择,被称为超参数(hyperparameter)。在基于数据进行学习的机器学习算法设计中,超参数是很常见的。一般来说,这些超参数具体怎么设置或取值并不是显而易见的。
可以尝试使用不同的值,看哪个值最好,就选用哪个。但是要特别注意:绝不能使用训练集来进行调优。在设计机器学习算法的时候,应该把测试集看做非常珍贵的资源,不到最后一步,决不使用它。如果使用测试集来调优,而且算法看起来效果不错,则真正的危险在于:算法实际部署后,性能可能会远低于预期。这种情况,称之为算法对测试集过拟合。从另一个角度说,如果使用测试集来调优,实际上就是把测试集当做训练集,由测试集训练出来的算法再跑测试集,自然性能看起来会很好。这其实过于乐观了,实际部署起来效果就会差很多。所以最终测试的时候再使用测试,可以很好地近似度量你设计的分类器的泛化性能。
测试数据集只使用一次,即训练完成后评价最终的模型时使用。
不使用测试集调优的方法:从训练集中取出一部分数据用来调优,这部分数据称为验证集。
把训练集分成训练集和验证集。使用验证集来对所有超参数调优。最后只在测试集上跑一次并报告结果。
交叉验证:有时候,训练集数据量小(因此验证集的数量更小),故会使用交叉验证的方法进行调参。交叉验证集,就是对所有的训练样本,平均分成k分,用k-1份训练,1份用来验证。然后循环去k-1份来训练,其中1份来验证,最后将k此实验结果的平均值作为算法验证结果。
实际应用中,人们不是很喜欢交叉验证,主要是因为它会耗费较多的计算资源。一般直接把训练集按照50%~90%的比例分成训练集和验证集。不过还要看具体情况来,如果超参数数量多,可能就想用更大的验证集,而验证集的数量不够,此时最好使用交叉验证。
NN(最近邻)分类器的优缺点:
1)NN分类器易于理解,实现简单;
2)算法的训练不需要花时间,因为其训练过程只是将训练集数据存储起来;
3)测试则需要花费大量时间计算,因为每个测试集都要与所有的训练集进行比较,而实际中更关注测试效率,其对比就是卷积神经网络,其训练花费很多时间,但一旦训练完成,对新的测试数据进行分类非常快。
ANN(近似最近邻)算法可以提升NN分类器在数据上的计算速度。不过这些算法需要在准确率和时空复杂度之间进行权衡,并通常依赖一个预处理/索引过程,这个过程中一般包含kd树的创建和k-means算法的运用。
NN分类器在某些特定情况(如数据维度较低)下,可能是不错的选择。但是在高维数据上,很少使用。
总结:
1)图像分类问题。在该问题中,给出一个由被标注了分类标签的图像组成的集合,要求算法能预测没有标签的图像的分类标签,并根据算法预测准确率进行评价;
2)最近邻分类器(Nearest Neighbor classifier):分类器中存在不同的超参数(比如k值或距离类型的选取),要想选取好的超参数不是一件轻而易举的事;
3)选取超参数的正确方法是:将原始训练集分为训练集和验证集,在验证集上尝试不同的超参数,最后保留表现最好那个;
4)一旦找到最优的超参数,就让算法以该参数在测试集跑且只跑一次,并根据测试结果评价算法;
5)最近邻分类器简单易实现,但需要存储所有训练数据,并且在测试的时候过于耗费计算能力;
K-NN使用需按照以下流程:
1)预处理数据:对数据中的特征进行归一化,让其具有零平均值和单位方差;
2)如果数据是高位数据,考虑使用降维方法,如PCA或随机投影;
3)将数据随机分入训练集和验证集。按照一般规律,70%~90%数据作为训练集。这个比例根据算法中有多少超参数,以及这些超参数对于算法的预期影响来决定。如果需要预测的超参数很多,则就应该使用更大的验证集来有效地估计它们。如果担心验证集数量不够,则可以尝试使用交叉验证方法。如果计算资源足够,使用交叉验证总是更加安全(分数越多,效果越好,同时耗费计算资源越多);
4)在验证集上调优,尝试足够多的k值,尝试L1和L2两种范数计算方式;
5)如果分类器跑得太慢,尝试使用Approximate Nearest Neighbor来加速这个过程,其代价是降低一些准确率;
6)对最优的超参数做记录。记录最优参数后,是否应该让使用最优参数的算法在完整的训练集上进行并再次训练呢?因为如果把验证集重新放回到训练集中(自然训练集的数据量就又变大了),有可能最优参数又会有所变化。实践中,不要这样做。千万不要在最终的分类器中使用验证集数据,这样做会破坏对于最优参数的估计。直接使用测试集来测试用最优参数设置好的最优模型,得到测试集数据的分类器准确率,并依次作为KNN分类器在该数据上的性能的表现。
KNN分类器不足:
1)分类器必须记住所有训练数据并将其存储起来,以便于未来测试数据用于比较。这在存储空间上是低效的,数据集的大小很容易就以GB计算;
2)对一个测试图像进行分类器需要和所有训练图像作为比较,算法的资源耗费高。
评分函数:它是原始图像数据到类别分支的映射;
损失函数:它是用来量化预测分类标签的得分与真实标签之间的一致性。
最优化过程:通过更新评分函数的参数来最小化损失函数值。
从图像到标签分值的参数化映射
该方法的第一部分就是定义一个评分函数,这个函数将图像的像素值映射为各个分类类别的得分,得分高低代表图像属于该类别的可能性高低。
图像中的零均值中心化很重要。
直观地:当评分函数输出结果与真实结果之间的差异越大,损色函数输出越大,反之越小。
SVM的损失函数想要正确分类类别的分数比不正确类别的分数高,而且至少要高一定值。
max(0,-) 函数被称为折叶损失(hinge loss);而当max(0,-)^2函数为平方折叶损失SVM(L2-SVM)它更强烈地惩罚过边界的边界值。不使用平方是更标准的版本,但是在某些数据集中,平方折叶损失工作得更好。可以通过交叉验证来决定到底使用哪个。
正则化:正则化函数不是数据的函数,仅基于权重。包含正则化惩罚后,就能够给出完整的多类SVM损失函数,它由两部分组成:数据损失(data loss),即所有样例的平均损失Li,以及正则化损失(regularization loss)。
引入正则化惩罚能够带来很多的良好性质。如引入L2惩罚后,SVM就有了最大边界。其中最好的性质就是对大数值权重进行惩罚,可以提升其泛化能力,因为这意味着没有哪个维度能够独自于整体分值有过大的影响。
对训练集中数据做出准确分类预测和让损失值最小化这两件事是等价的。
Softmax分类器
SVM是最常用的两个分类器之一,另一个就是Softmax分类器,它的损失函数与SVM的损失函数不同。对于学习过二元逻辑回归分类器的读者来说,Softmax分类器就可以理解为逻辑回归分类器面对多个分类的一般化归纳。Softmax分类器中使用交叉熵损失函数。Softmax函数:其输入值是一个向量,向量中元素为任意实数的评分值(z中的),函数对其进行压缩,输出一个向量,其中每个元素值都在0到1之间,且所有元素之和为1。
Softmax分类器所做的就是最小化在估计分类概率和真实分布之间的交叉熵。交叉熵损失函数“想要”预测分布的所有概率密度都在正确分类上。
精确地说,SVM分类器使用的是折叶损失(hinge loss),有时候又被称为最大边界损失(max-margin loss)。Softmax分类器使用的是交叉熵损失(cross-entropy loss)。Softmax分类器函数是从softmax函数得来,softmax函数将原始分类评分变成正的归一化数值,所有数值和为1,这样处理后交叉熵损失才能应用。注意:从技术上说,softmax损失没有意义,因为softmax只是一个压缩数值的函数。
SVM分类器将计算的结果看成是分类评分,它的损失函数鼓励正确的分类的分值比其它分类的分值高出至少一个边界值。Softmax分类器将这些数值看做是每个分类没有归一化的对数概率,鼓励正确的归一化的对数概率变高,其余的变低。
相对于Softmax分类器,SVM更加局部目标化,这可以看做是一个特性,也可以看做是一个优势。
总结:
1)定义了从图像像素映射到不同类别的分类评分函数。评分函数是一个基于权重W和偏差b的线性函数;
2)与KNN分类器不同,参数方法的优势在于一旦通过训练学习到了参数,就可以将训练数据丢弃。同时该方法对于新的测试数据的预测非常快,因为只需要与权重w进行一个矩阵乘法运算。
3)介绍偏差技巧,让我们能够将偏差向量和权重矩阵合二为一,然后就可以只跟踪一个矩阵;
4)定义了损失函数(SVM和Softmax线性分类器)。损失函数能够衡量给出的参数集和训练数据集真实类别情况之间的一致性。在损失函数的定义中可以看到,对训练数据做出良好预测与得到一个足够低的损失函数是等价的。
图像分类任务中的两个关键部分:
1)基于参数的评分函数。该函数将原始图像像素映射为分类评分值(如一个线性函数);
2)损失函数。该函数能够根据分配评分和训练集图像数据实际分类的一致性,衡量某个具体参数集的质量好坏。损失函数有多种版本和不同的实现方式。(如Softmax和SVM)
最优化:寻找能够使得损失函数值最小化的参数过程。
实现最优化策略:
1)随机搜索,其核心思想是迭代优化。核心思路是:找到最优化的权重W非常困难,甚至是不可能的(尤其是W中存的是整个神经网络的权重的时候),但如果问题转化为对一个权重矩阵W取优,使其损失值稍微减少。那么问题的难度就大大降低了。即从一个随机的W开始,然后对其迭代取优,每次让它的损失值变得更小一点。整体策略:从随机权重开始,然后迭代取优,从而获得更低的损失值。
2)随机本地搜索:此策略为从一个随机W开始,然后生成一个随机的扰动,直到当权重与扰动的和使得损失值减少,才进行更新。
3)跟随梯度:前两个策略中,是尝试在权重空间找到一个方向,沿着该方向能降低损失函数的损失值。其实,不需要随机寻找方向,因为可以直接计算出最好的方向,在数学上计算出最陡峭的方面,此方向即为损失函数的梯度。此方向就像是感受一下脚下山体的倾斜程度,然后向着最陡峭的下降方向下山。在一维函数中,斜率是函数在某一点的瞬时变化率。梯度是函数的斜率的一般化表达,它不是一个值,而是一个向量。在输入空间中,梯度是各个维度的斜率组成的向量(或者称为导数)。当函数有多个参数的时候,称导数为偏导数。而梯度就是在各个维度上偏导数所形成的向量。
梯度计算
计算梯度有两种方法:一个是缓慢的近似方法(数值梯度法),但实现相对简单。另一个方法(分析梯度法)计算迅速,结果精确,但是实现时容易出错,且需要使用微分。
在梯度负方向上更新:当向着梯度df的负方向去更新时,损失函数值是降低而不是升高。
步长影响:梯度指明了函数在哪个方向是变化率最大的,但是没有指明在这个方向上应该走多远。选择步长(即学习率)将会是神经网络训练中最重要(也是最头痛)的超参数设定之一。就好比蒙眼下上,可以感觉到脚朝向的不同方向上,地形的倾斜程度不同。但是该跨出多少步长?不确定。如果谨慎地小步走,情况可能比较稳定但是进展较慢(这就是步长较小的情况)。相反,如果想尽快下山,那就大步走吧,但结果也不一定尽如人意。在某些点如果步长过大,反而可能越过最低点导致更高的损失值。
小步长下降稳定但进度慢,大步长进展快但是分险更大。采取大步长可能导致错过最优点,然损失值上升。步长(学习率)将会是调参中最重要的超参数之一。
效率问题:计算数值梯度的复杂度和参数的量线性相关。此策略不适合大规模数据。
微分分析计算梯度:使用有限差值近似计算梯度比较简单,但缺点在于终究只是近似(因为对于h值只是选取了一个很小的数值,但真正的梯度定义中h趋向0的基线),且耗费计算资源太多。第二个梯度计算方法是利用微分来分析,能得到计算梯度的公式(不是近似),用公式计算梯度速度很快,唯一不好的就是实现的时候容易出错。为了解决这个问题,在实际操作时常常将分析梯度法的结果和数值梯度法的结果作比较,一次来检查其实现的正确性。此步骤为梯度检查。
梯度下降
计算损失函数的梯度,即程序重复的计算梯度然后对参数进行更新,此过程为梯度下降。梯度下降是对神经网络的损失函数最优化中最常用的方法。
小批量数据梯度下降(Mini-batch gradient descent):在大规模的应用中,训练数据可以达到百万级量级。如果像这样计算整个训练集,来获得仅仅一个参数的更新就太浪费了。一个常用的方法是计算训练集中的小批量数据。实际情况中,数据集不会包含重复,则小批量数据的梯度就是对整个数据集梯度的一个近似。在实践中通过计算小批量数据的梯度可以实现更快速地收敛,并以此来进行更频繁的参数更新。小批量数据策略中有个极端情况,就是每个批量中只有1个数据样本,这种策略称为随机梯度下降(SGD)。向量化操作的代码一次计算100个数据比100此计算1个数据要高效得多。即使SGD在技术上是指每次使用1个数据来计算梯度,但可能有人会使用SGD来指代小批量数据梯度下降(或用MGD指代小批量数据梯度下降,而BGD指代较少)。小批量数据的大小是一个超参数,但是一般并不需要通过交叉验证来调参。它一般由存储器的限制来决定,或者干脆设置为同样大小,如32,64,128等。之所以使用2的指数,是因为在实际中许多向量化操作实现的时候,如果输入数据量是2的倍数,那么运算更快。
总结:
信息流的总结如上图,数据集中的 (x, y) 是给定的。权重从一个随机数字开始,且可以改变。在前向传播时,评分函数计算出类别的分类评分并存储在向量f中。损失函数包含两个部分:数据损失和正则化损失。其中数据损失计算的是分类评分f和实际标签y之间的差异,正则化损失只是一个关于权重的函数。在梯度下降过程中,计算权重的梯度,然后使用它们来实现参数的更新。
总结:
1)将损失函数比作了一个高纬度的最优化地形,并尝试到达它的最底部。最优化的工作工程可以看做一个蒙着眼睛的徒步者希望摸索着走到山的底部。在例子中,可见SVM的损失函数是分段线性的,并且是碗状的。
2)提出了迭代优化的思想,从一个随机的权重开始,然后一步步地让损失值变小,直到最小。
3)函数的梯度给出了该函数最陡峭的上升方向。介绍了利用有限的差值来近似计算梯度的方法,该方法实现简单但是效率较低(有限差值就是h,用来计算数值梯度)。
4)参数更新需要有技巧地设置步长,也叫学习率。如果步长太小,进度稳定但是缓慢,如果步长太大,进度快但是可能有风险。
5)讨论权衡了数值梯度法和分析梯度法。数值梯度法计算简单,但结果只是近似耗费计算资源。分析梯度法计算准确迅速但是实现容易出错,而且需要对梯度公式进行推导的数学基本功。因此,在实际中使用分析梯度法,然后使用梯度检查来检查其实现正确与否,其本质就是将分析梯度法的结果与数值梯度法的计算结果对比。
6)介绍了梯度下降方法,它在循环中迭代地计算梯度并更新参数。
反向传播
反向传播是利用链式法则递归计算表达式的梯度的方法。
导数意义:函数变量在某个点周围的极小区域内变化,而导数就是变量变化导致的函数在该方向上的变化率。
函数关于每个变量的导数指明了整个表达式对于该变量的敏感程度。
使用链式方法计算复合表达式
链式法则指出将这些梯度表达式链起来的正确方式是相乘。在实际操作中,知识简单地将两个梯度数值相乘。
前向传播:从输入计算到输出,方向传播:从尾部开始,根据链式法则递归地向前计算梯度,一直到网络的输入端。可以认为,梯度是从计算链路中回流。
反向传播是一个优美的局部过程。在整个计算线路图中,每个门单元都会得到一些输入并立即计算两个东西:1)这个门的输出值;2)其输出值关于输入值的局部梯度。前向传播完毕,在反向传播过程中,门单元门将最终获得整个网络的最终输出值在自己的输出值上的梯度。链式法则指出,门单元应该将回传的梯度乘以它对其他的输入的局部梯度,从而得到整个网络的输出对该门单元的每个输入值的梯度。这里对于每个输入的乘法操作是基于链式法则的。该操作让一个相对独立的门单元变成复杂计算线路中不可或缺的一部分,这个复杂计算线路可以是神经网络。
对前向传播变量进行缓存:在计算反向传播时,前向传播过程中得到的一些中间变量非常有用。在实际操作中,最好代码实现对于这些中间变量的缓存,这样在反向传播的时候也能用上他们。如果这样做过于困难,也可以(但是浪费计算资源)重新计算他们。
在不同分支的梯度要相加:如果变量x,y在前向传播的表达式中出现多次,那么进行反向传播的时候就要非常小心,使用+=而不是=来累计这些变量的梯度(不然就会造成覆写)。此为遵循了在微积分中的多元链式法则,该法则指出如果变量在线路中分支走向不同的部分,那么梯度在回传的时候就应该进行累加。
可以使用向量化操作计算梯度。
总结:
1)对梯度的含义有了直观理解,直到了梯度是如何在网络中反向传播的,知道了它们是如何与网络的不同部分通信并控制其升高或者降低,并使得最终输出值更高的;
2)讨论了分段计算在反向传播的实现中的重要性。应该将函数分成不同的模块,这样计算局部梯度相对容易,然后基于链式法则将其链起来。重要的是,不需要把这些表达式写在之上然后演算它的完整求导公式,因为实际上并不需要关于输入变量的梯度的数学公式。只需要将表达式分成不同的可以求导的模块(模块可以是矩阵向量的乘法操作,或者取最大值操作,或者加法操作等),然后在反向传播中一步一步地计算梯度。
一个单独的神经元可以用来实现一个二分类分类器,比如二分类的Softmax或者SVM分类器
常用的激活函数:Sigmoid非线性函数,tanh函数等。
Sigmod函数非常常用,其原因是它对于神经元的激活频率有良好的解释:从完全不激活(0)到在求和后的最大频率处的完全饱和的激活。但现在Sigmod函数已经不太受欢迎,原因是它存在以下两点缺点:
1)Sigmoid函数饱和使梯度消失;2)Sigmod函数的输出不是零中心的。
Tanh函数与Sigmoid神经元一样,也存在饱和问题,但是它的输出是零中心的,故tanh非线性函数比sigmoid非线性函数更受欢迎。
ReLUctant。它的函数公式是f(x)=max(0,x)。即这个激活函数就是一个关于0阈值的。它存在以下优缺点:
1)优点:相较于sigmoid和tanh函数,ReLUctant对于随机梯度下降的收敛有巨大的加速作用。这是由它的线性,非饱和的公式导致的。
2)优点:sigmoid和tanh神经元含有指数运算等耗费计算资源的操作,而ReLUctant可以简单地通过一个矩阵进行阈值计算得到。
3)缺点:在训练的时候,ReLU单元比较脆弱并且可能死掉。
Leaky ReLU:是为了解决“ReLUctant死亡”问题。其在x小于0时,给出一个很小的负数梯度值,如0.01。
Maxout:它是对ReLU和Leaky ReLU的一般化归纳,它拥有ReLU单元的所有优点(线性操作和不饱和),而没有它的缺点(死亡的ReLU单元)。然后和ReLU对比,它每个神经元的参数数量增加了一倍,这就导致整体参数的数量激增。
总结:使用ReLU非线性函数时,注意设置好学习率,或许可以监控网络中死亡的神经元占的比例。如果单元死亡问题出现,可以尝试Leaky ReLU或者Maxout,不建议使用sigmoid,可以尝试tanh,其效果可能不如ReLU或者Maxout。
全连接层的前向传播一般就是先进行一个矩阵乘法,然后加上偏置并运用激活函数。
神经网络在实践中非常好用,是因为他们表达出的函数不仅平滑,而且对于数据的统计特性有很好的拟合。同时,网络通过最优化算法(梯度下降)能比较容易地学习到这个函数。类似的,虽然在理论上深层网络(使用了多个隐层)和单层网络的表达能力是一样的,但是就实践经验而言,深度网络效果比单层网络好。
在卷积神经网络中,对于一个良好的识别系统来说,深度是一个极端重要的因此(比如数十(以10为量级)个可学习的层)。对于该现象的一种解释观点是:因为图像拥有层次化结构(比如脸是由眼睛等组成,眼睛又是由边缘组成),所以多层处理对于这种数据有直观意义。
设置层的数量和尺寸
首先,要知道当增加层的数量和尺寸时,网络的容量上升了。即神经元可以合作表达许多复杂函数,所以表达函数的空间增加。更多神经元的神经网络可以表达更复杂的函数。然而这既是优势也是不足,优势是可以分类更复杂的数据,不足是可能造成对训练数据的过拟合。过拟合是网络对数据中的噪声有很强的拟合能力,而没有重视数据间(假设)的潜在基本关系。防止神经网络过拟合的方法有很多中(如L2正则化,dropout和输出噪音等)。在实践中,使用这些方法来控制过拟合比减少网络神经元数目要好得多。
不要减少网络神经元数目的主要原因在于小网络更难使用梯度下降等局部方法来进行训练:虽然小型网络的损失函数的局部极小值更少,也比较容易收敛到这些局部极小值,但是这些最小值一般都很差,损失值很高。相反,大网络拥有更多的局部极小值,但就实际损失值来看,这些局部极小值表现更好,损失更小。在实际中,将发现如果训练的是一个小网络,那么最终的损失值将展现出多变性:某些情况下运气好会收敛到一个好的地方,某些情况下就收敛到一个不好的极值。从另一方面来说,如果训练一个大的网络,将会发现许多不同的解决方法,但是最终损失值的差异将会小很多。即所有解决办法差不多,而且对于随机初始化参数好坏的依赖也会小很多。
注意:正则化强度是控制神经网络过拟合的好方法。不同正则化强度的效果:每个神经网络都有20个隐层单元,但是随着正则化强度增加,它的决策边界变得更加平滑。故不应该因害怕出现过拟合而使用小网络。相反,应该进尽可能使用大网络,然后使用正则化技巧来控制过拟合。
总结:
1)不同类型的激活函数中,ReLU是最佳推荐;
2)神经网络,神经元通过全连接层连接,层间神经元两两相连,但是层内神经元不连接;
3)分层的结构能够让神经网络高效地进行矩阵乘法和激活函数运算;
4)神经网络是一个通用函数近似器,但是该性质与其广泛使用无太大关系。之所以使用神经网络,是因为它们对于实际问题中的函数的公式能够在某种程度上做出“正确”假设。
5)更大的网络一般会更好一些。更大容量的模型一定要和更强的正则化(更高的权重衰减)配合,否则它们就会过拟合。
神经网络就是进行一系列的线性映射与非线性激活函数交织的运算。
数据预处理
1)均值减去法:是预处理最常用的形式。它对数据中每个独立特征减去平均值,从几何上可以理解为在每个维度上都将数据云的中心都迁移到原点。
2)归一化:是指将数据的所有维度都归一化,使其数值范围都近似相等。有两种常用方法可以实现归一化。第一种是先对数据做零中心化处理,然后每个维度都除以其标准差。第二种方法是对每个维度都做归一化,使其每个维度的最大和最小值是1和-1。
注意:预处理操作只有在确性不同的输入特征有不同的数值范围(或计量单位)时才有意义,但要注意预处理操作的重要性几乎等同于学习算法本身。
3)PCA和白化是另一种预处理形式。在这种处理中,先对数据进行零中心化处理,然后计算协方差矩阵,它展示了数据中的相关性质。通常使用PCA降维过的数据训练线性分类器和神经网络会达到非常好的性能效果,同时还能节省时间和存储空间。
白化操作的输入是特征基准上的数据,然后对每个维度除以其特征值来对数值范围进行归一化。此变换的几何解释是:如果数据服从多变量的高斯分布,那么经过白化后,数据的分布将会是一个均值为零,且协方差相等的矩阵。
注意:该变换的一个缺陷是在变换的过程中可能会夸大数据中的噪声,因为它将所有维度都拉伸到相同的数值范围,这些维度中也包含了那些只有极少差异性(方差小)而大多是噪声的维度。实际操作中,此问题可以用更强的平滑来解决。
实践操作:实际在卷积神经网络中并不会采用PCA和白化。然后对数据进行零中心化操作还是非常重要的,对每个像素进行归一化也很常见。
常见错误:进行预处理很重要的一点是任何预处理策略(如数据均值)都只能在训练集数据上进行,算法训练完毕后再应用到验证集或者测试集。具体做法应如下:应该先分成训练、验证、测试集,只是从训练集中求图片平均值,然后各个集(训练、验证、测试集)中的图像再减去这个平均值。
权重初始化
1)错误:全零初始化。在训练完毕后,虽然不知道网络中每个权重的最终值应该是多少,但如果数据经过了恰当的归一化的话,可以假设所有权重数值中大约一半为正数,一半为负数。但不要全零进行初始化,因为如果权重被初始化为同样的值,神经元之间就失去了不对称的源头。
2)小随机数初始化:权重初始值非常接近0又不能等于0。解决方法是将权重初始化为很小的数值,以此来打破对称性。其思路是:如果神经元刚开始的时候是随机且不相等的,那么它们将计算出不同的更新,并将自身变成整个网络的不同部分。
警告:并不是小数值一定会得到好的结果。一个神经网络的层中的权重值很小,那么在反向传播的时候就会计算出非常小的梯度(因为梯度与权重是成比例的)。这就会很大程度上减小反向传播中的“梯度信号”,在深度网络中,就会出现问题。
3)使用1/sqrt(n)校准方差。随着输入数据量的增长,随机初始化的神经元的输出数据的分布中的方差也在增大。可以处以输入数据量的平方根来调整其数值范围,这样神经元输出的方差就归一化到1。建议是用1/sqrt(n)来初始化神经元的权重向量。其中n是输入数据的数量。这样就保证了网络中所有神经元起始时有近似同样的输出分布。这样做可以提高收敛的速度。
4)系数初始化:另一个处理非标定方差的方法是将所有权重矩阵设为0,但是为了打破对称性,每个神经元都同下一层固定数目的神经元随机连接(其权重数值由一个小的高斯分布生成)。
5)偏置的初始化:通常将偏置初始化为0,这是因为随机小数值权重矩阵已经打破了对称性。
6)批量归一化:该方法减轻了如何合理初始化神经网络这个棘手问题,其做法是让激活数据在训练开始前通过一个网络,网络处理数据使其服从标准高斯分布。在神经网络中使用批量归一化变得非常常见。在实践中,使用批量归一化的网络对于不好的初始值有更强的鲁棒性。总结:批量归一化可以理解为在网络的每一层之前都做预处理,只是这种操作以另一种方式与网络集成在一起。
正则化
有不少方法是通过控制神经网络的容量来防止其过拟合的:
L2正则化可能是最常用的正则化方法。可以通过惩罚目标函数中所有参数的平法将其实现。L2正则化可以直观理解为对它大于大数值的权重向量进行严厉惩罚,倾向于更加分散的权重向量。
L1正则化:它会让权重向量在最优化的过程中变得稀疏(即非常接近0)。即使用L1正则化的神经元最后使用的是它们最重要的输入数据的系数子集,同时对于噪音输入则几乎是不变的。相较L1正则化,L2正则化中的权重向量大多是分散的小数字。在实践中,如果不是特别关注某些明确的特征选择,一般说来L2正则化都会比L1正则化效果好。
最大范式约束:是指给每个神经元中权重向量的量级设定上限,并使用投影梯度下降来确保这一约束。
随机失活:是一个简单又极其有效的正则化方法。它与L1正则化,L2正则化,最大范式约束等方法互为补充。在训练的时候,随机失活的实现方法是让神经元以超参数p的概率被激活或者被设置为0。在训练过程中,随机失活可以被认为是对完整的神经网络抽样出一些子集,每次基于输入数据只更新子网络的参数。(数量巨大的子网络们并不是相互独立,因为他们都是共享参数)。测试过程中不使用随机失活可以理解为是对数量巨大的子网络们做了模型集成,以此来计算出一个平均的预测。
前向传播中的噪声。测试时,通过分析法或数值法(通过抽象出很多的子网络随机选择不同子网络进行前向传播,最后对它们取平均)将噪声边缘化。
偏置正则化:不建议使用。
每层正则化。很少见,不建议使用。
实践中,通过交叉验证获得一个全局使用的L2正则化强度是比较常见的。在使用L2正则化的同时在所有层后面使用随机失活也很常见。
损失函数:正则化损失 + 数据损失。
数据损失是一个有监督学习问题,用于衡量分类算法的预测结果(即分类评分)和真实标签结果之间的一致性。数据损失是对所有的样本的数据损失求平均。
实际中,需要解决以下几类问题:
1)分类问题。注意,当类别数目巨大时,可以考虑使用分层Softmax损失函数。分层Softmax将标签分解成一个树。每个标签都表示成这个树上的一个路径,这个树的每个节点处都训练一个Softmax分类器来在左和右分支之间做决策。树的结构对于算法的最终结果影响很大,而且一般需要具体问题具体分析。
2)属性分类:方法有两种,其一,为每个属性创建一个独立的二分类的分类器;其二,对每种属性训练一个独立的逻辑回归分类器。
3)回归问题:它是预测实数的值的问题,如预测房价,预测图片中某个东西的长度等。对这种问题,通常计算预测值和真实值之间的损失。然后用L2平方范式或L1范式度量差异。
当面对一个回归任务,首先考虑是不是必须这样。一般而言,尽量把你的输出变成二分类,然后对它们进行分类,从而变成一个分类问题。
4)结构化预测:结构化损失是指标签可以是任意的结构,如图表、树或者其它复杂物体的情况。此情况下,还会假设结构空间非常巨大,不容易进行遍历。结构化SVM背后的基本思想是在正确的结构yi和得分最高的非正确结构之间画出一个边界。解决此类方法,需要特殊的解决方案,这样可以有效利用对于结构空间的特殊简化假设。
总结:
1)推荐的预处理操作是对数据的每个特征都进行零中心化,然后将其数值范围都归一化到[-1,1]范围之内。
2)使用标准差为根号2/n的高斯分布来初始化权重,其中n是输入的神经元数。
3)使用L2正则化和随机失活的倒置版本。
3)使用批量归一化。
4)在实践中,可能要面对不同的任务,以及每个任务对应的常用损失函数问题。