一、引入
主成分分析(PCA)是一种降维算法,能大大加速你的无监督特征学习算法。更重要的是,理解PCA能让我们后面实现白化,这是一个对所有算法适用的重要的预处理步骤。
假设你在图像上训练你的算法。不过输入稍微有点冗余,因为图像中相邻的像素值是高度相关的。具体来说,假设我们在16*16的灰度图像块上训练。那么x∈R256是256维的向量,一个特征xj对应着图像中每个像素强度。由于相邻像素之间的相关性,PCA使我们能够以一个维数小得多的输入来近似原输入,而造成误差极小。
二、例子与数学背景
对我们运行例子来说,我们使用数据集{x(1),x(2),…,x(m)},输入是n=2维的,因此x(i)∈R2。假设我们想要将二维数据将为1维。(实际上,我们比如可能想要将256维数据降为50维;但在我们的例子中使用低一点的维度数据能让我们更好地可视化算法。)这是我们的数据集:
这些数据有经过预处理,因此每个特征x1和x2都有相同的均值(0)和方差。
为了阐述,我们还将每一个点着色,有三种颜色,取决于x1的值;这些颜色不是给算法用的,只是为了阐述。
PCA会寻找一个投影我们数据的较低维的子空间。
通过可视化验证数据,能看出u1是数据变化的主要方向,u2是变化的第二个方向:
即,相比u2方向,数据更多地在u1方向上变化。为了更正式地得到方向u1和u2,我们首先计算如下矩阵:
如果x有零均值,那么Σ恰好是x的协方差矩阵。(Σ符号,发音为sigma,是表示协方差矩阵的标准表示。不幸的是,它看起来就像求和的符号,和∑ni=1i中的一样;但实际上这是两种不同的东西。)
然后就可以看出,u1——数据变化的主要方向——是Σ的第一个(主要的)特征向量,u2是第二个特征向量。
注意:如果你感兴趣于阅读关于这个结果的更正式的数学推导/证明,可以阅读CS229(机器学习)关于PCA的课程笔记。然而在这个课程中你不需要这样做。
你可以使用标准的数值线性代数软件来得到这些特征向量(看实现提示)。具体而言,让我们计算Σ的特征向量,并将特征向量按列排列,得到矩阵U:
在这里,u1是主要特征向量(对应于最大的特征值),u2是第二个特征向量,等等。另外,令λ1,λ2,…,λn为相应特征值。
在我们的例子中,向量u1和u2构成新的基,我们的数据将用其表示。具体而言,令x∈R2为一些训练样本。然后uT1x为x投影到向量u1的长度(量)。
同理,uT2x是x投影到向量u2的量。
三、旋转数据
现在,我们可以用(u1,u2)基来表示x,通过计算
(下标“rot”来自对原始数据的旋转(或者反射)的表示。)我们采用整个训练集,为每个i计算x(i)rot=UTx(i)。将变换后的xrot在图中表示,我们得到:
这是旋转到基u1、u2下的训练集。在通常情况下,UTx将是旋转到基u1、u2……un下的训练集。
U的其中一个特性是它是一个“正交”矩阵,意味着它满足UTU=UUT=I。因此,如果你想要从旋转的向量xrot变回到原始数据x,你可以计算
x=Uxrot,
因为Uxrot=UUTx=x。
四、减少数据维度
我们看到数据的变化的主要方向是其旋转数据的第一个维度xrot,1。因此,如果我们想要将数据维度减小到1维,我们可以令
更一般地说,如果x是n维的且我们想要把它减少到k维表示(k<n),我们可以取xrot的前k部分,对应着变化的前k个方向。
另外一个解释PCA的方法是xrot是一个n维向量,其中前几个部分可能比较大(例如,在我们的例子中,我们看到x(i)rot,1=uT1x(i),随机取了大多数样本的较大值),后面的部分可能是小值(例如,在我们的例子中,x(i)rot,2=uT2x(i)更可能是小值)。PCA所做的是丢弃xrot后面的(较小的)部分,将他们近似为0。具体而言,我们对x~的定义也可以通过使用对xrot的逼近,其除了前面k个部分,其它的都为0得到。换句话说,我们有:
在我们的例子中,我们得到以下x~的图(使用n=2,k=1):
然而,既然上面定义的x~最后的n-k部分总是为0,没有必要把这些0带在旁边,因此我们定义x~为k维向量,只有前k项不为0的部分。
这也解释了为什么我们想要在基u1,u2,…,un下表示我们的数据:决定保留哪些部分变成了只需保留前k个部分。当我们这么做时,我们也称我们“持有前k个PCA(或主要的)成分”。
五、恢复数据的近似
现在,k维的x~是原始n维的x一个低维的,“压缩的”表示。给定x~,我们怎么恢复x原始值的近似x^?从之前的小节,我们知道x=Uxrot。更进一步,我们将x~视为xrot的近似,其中我们把最后n-k部分设为0。这样,给定k维的x~,我们可以补上n-k个0得到n维xrot的近似。最后,前面乘上U得到对x的近似。具体而言,我们有,
上面最后的等式来自前面对U的定义。(在实际实现中,我们不会用0补充x~并前面乘U,因为这意味着用0乘以一大堆东西;而是,在上面最后的表达式中只需要用U的前k列乘以x~∈Rk。)应用到我们的数据集中,我们得到下面x^的图:
于是我们使用原始数据的一维近似。
如果你在训练一个自动编码器或是其它无监督特征学习算法,你的算法的运行时间取决于输入的维度。如果你用k维的x~代替x输入到你的学习算法中,那么你会在较低维度的输入上训练,这样一来你的算法会运行快很多。对于许多数据集,较低维度的表示x~是对原始数据一个非常好的近似,因此这样使用PCA能显著加快你的算法运行速度,而且引入的近似误差非常小。
六、保留成分的数目
我们如何设置k;即,我们应该保留多少PCA成分?在我们简单的二维例子中,保留俩个成分中的一个看起来很自然,但对于更高维的数据而言,这个决定就不那么显然了。如果k太大,我们不会对数据压缩很多;在限制边界k=n上,我们只是在使用原数据(但旋转到不同的基上)。相反,如果k太小,我们可能使用对原数据非常差的近似值。
为决定如何设置k,我们通常会看不同的k值“保留的变化的百分比”。具体而言,如果k=n,那么我们得到对数据的精确近似,我们就说100%的变化保留了下来。即,原始数据的所有变化被保留。相反,如果k=0,那么我们用零向量逼近所有数据,于是0%的变化被保留了下来。
更一般的情况,令λ1,λ2,…,λn为Σ的特征值(递减排列),因此λj是对应特征向量uj的特征值。如果我们保留了k个主要成分,保留的百分比由下式给出:
在我们上面的二维例子中,λ1=7.29,λ2=0.69。这样,我们只保留k=1的成分,就保留了7.29/(7.29+0.69)=0.913,或91.3%的变化。
对于保留的变化的百分比更正式的定义超过了这些内容的范畴。然而,仍可能得出。这样,如果λj≈0,表明xrot,j通常也接近0,因此用常数0逼近它几乎不损失什么。这也解释了为什么我们保留最顶层的主要成分(对应于λj的较大值)而不是最底下的。最顶层的主要成分xrot,j变化更大,而且占据更大值,如果我们把它们设置为0会引起较大的逼近误差。
对于图像的情况,一个常见的启发是选择k使得保留99%的变化。换句话说,我们选择最小的k使得满足
取决于应用场合,如果你愿意承受一些偶然误差,90%~98%范围的值有时候也使用。当你给别人介绍你怎么使用PCA时,说你选择k保留了95%的变化比你说保留了120(或者其它任意值)个成分更容易说明问题。
七、PCA用于图像
为了让PCA起作用,通常我们想让每一个特征x1,x2,…,xn和其它的一样有近似范围的值(并且有近似0的均值)。如果你之前在其它应用场合使用过PCA,你可能因此分别对每个特征做了预处理,通过预测每个特征sj的均值和方差,使得拥有零均值和单位方差。然而,这并不是我们应用到大多数图像类型的预处理。具体而言,假设我们在“自然图像”上训练我们的算法,xj是像素j的值。通过“自然图像”,非正式地说,我们意味着是这样一种类型的图像,在有生之年可能看到的典型动物或人。
注意:通常我们使用室外场景的图像,有草,树等等,并随机从中裁下小(比如16*16)图像块用来训练算法。但实际中,大多数学习算法对训练的特定图像类型都有很强的鲁棒性,因此大多数图像用标准相机采集,只要它们不会过度模糊或者有奇怪的人工迹象,都能工作。
当在自然图像上训练时,估计每个像素点的均值和方差毫无意义,因为在图像某一部分的统计特性应该(理论上)和其它任意部分相同。这个图像的特性称为“不变性”。
细节上说,为了让PCA效果好些,非正式地说我们需要:
(1) 特征近似有零均值;
(2) 不同的特征和其它特征有相似的方差。
对自然图像而言,即使没有方差标准化,(2)也已经满足,因此我们不需要任何方差标准化。(如果你在音频数据上训练——例如在声谱上——或在文字数据上——例如词袋向量——我们也通常不需要方差标准化。)
事实上,PCA对图像的缩放是不变的,不管输入的缩放都会返回相同的特征向量。更正式地说,如果你对每个特征量x乘以一些正数(因此对每个样本的每个特征都缩放相同的数字),PCA的输出特征向量不会改变。
因此,我们不会使用方差标准化。我们唯一需要做的标准化是均值标准化,确保特征有0附近的均值。取决于应用场合,大多数情况我们对整幅图像有多亮不感兴趣。例如,在目标识别任务中,图像的整体亮度并不影响图像中的目标的有无。更正式地讲,我们对图像块的平均强度值不感兴趣;这样,我们可以减去这个值,作为均值标准化的一种方式。
具体而言,假如x(i)∈Rn是16*16的图像块(n=256)的(灰度)强度值,我们可以标准化每幅图像x(i)的强度值如下:对所有j,
注意到上面两步分别对每幅图像x(i)执行,这里μ(i)是图像x(i)强度值的平均。特别注意,这和分别对每个像素xj估计平均值不是一回事。
如果你不在自然图像上处理你的算法(例如,手写字符的图像,或者在白色背景中间的单一的孤立的物体),其它类型的标准化是值得考虑的,最好的选择也取决于应用场合。但当在自然图像上训练时,每幅图像按上面等式使用均值标准化的方法默认是合理的。
八、白化
我们使用了PCA降低了数据的维度。有一个接近的相关的预处理步骤称为白化(或者,在一些其它文章中,球化?),对一些算法来说是需要的。如果我们在图像上训练,原始输入是冗余的,因为相邻的像素值高度相关。白化的目标是使输入不那么冗余;更正式来说,我们急需的是,我们的算法对这样的训练输入起作用:
(1) 特征之间没有那么高的相关性;
(2) 所有特征有相等的方差。
八、2D例子
我们将首先使用我们之前2D的例子介绍白化。然后我们将介绍怎么和平滑相结合,最后如何和PCA相结合。
我们如何使得输入特征之间互不相关?当我们计算x(i)rot=UTx(i)时其实已经做到了。重复我们之前的图,我们的xrot图:
数据的协方差矩阵为:
(注意:从技术上讲,这节中许多关于“协方差”的陈述只有在数据拥有零均值的条件下才正确。在这节剩余部分,我们在陈述中将不加说明的采用这个假设。然而,即使数据的均值不是精确为0,我们抛出的直觉依然认为这是正确的,因此你不需要担心这个问题。)
对角线上的值为λ1和λ2并不是偶然。更进一步,非对角线上为0;这样,xrot,1和xrot,2是不相关的,满足白化数据所需的第一个条件(即特征没有强的相关性)。
为了使我们每一个输入特征都拥有单位方差,我们可以简单地用√1/λi 重新改变xrot,1的大小。具体而言,我们如下,定义我们的白化数据xPCAwhite∈Rn:
画出xPCAwhite,我们得到:
现在数据的协方差等于单位矩阵。我们说xPCAwhite是数据的PCA白化版本:xPCAwhite不同成分是不相关的且有单位方差。
白化与降维相结合。如果你想要经过白化且比原始输入维度更低的数据,你也可以只取xPCAwhite的前k个成分。当我们将PCA白化与正则化(稍后介绍)相结合,xPCAwhite最后几个成分几乎为0,因此可以安全地舍弃。
九、ZCA白化
最后,得到协方差为单位矩阵的数据的方法并不唯一。具体而言,如果R是任意正交矩阵,因此满足RRT=RTR=I(不那么正式,如果R是一个旋转/反射矩阵(同样满足)),那么RxPCAwhite也拥有单位矩阵协方差。
在ZCA白化中,我们选择R=U。我们定义
xZCAwhite=UxPCAwhite
画出xZCAwhite,我们得到:
可以看出,在R的所有可能的选择中,这个旋转的选择使xZCAwhite与原始输入数据x尽可能的接近。
当使用ZCA白化时(不像PCA白化),我们通常保留数据所有n维,而不试图降维。
十、正则化
在实际中实现PCA白化或ZCA白化时,有时候一些特征值λi在数值上接近0,这样在用√1/λi缩放的一步会涉及除以一个接近0的数;这会导致数据突然增大(占据大值)或者数值不稳定。实际中,我们因此使用少量的正则化实现缩放这一步,给特征值增加一个小常数ϵ,然后在计算平方根和倒数:
当x取值在[−1,1]附近,则典型值取ϵ≈10−5。
对于图像的情况,增加ϵ也会有影响,对图像有稍微平滑(或者低通滤波)的影响。这也能取得所需要的去除由图像像素排布引起的混淆假影的效果,能改善学习到的特征(其细节超出了这篇文章的范围)。
ZCA白化是数据预处理的一种方式,从x映射到xZCAwhite。这也是生物学上眼睛如何处理图像是一个粗略的模型。具体而言,当你的眼睛接收到图像时,眼睛内大多数相邻的“像素点”会感知到非常相似的值,因为图像中相邻部分往往在像素强度上高度相关。这样,单独传输每一个像素(经过视觉神经)到你的大脑会造成浪费。取而代之的是,你的视网膜执行了去相关性的操作(通过视网膜神经元计算一个“在中心,不在周围/不在中心,在周围”的函数),类似于ZCA的操作。这形成了输入图像较低冗余度的表示,然后才传输到你的大脑。