这是深度学习笔记第六篇,完整的笔记目录可以点击这里查看。
设输入数据的维度为N×D,其中,N是数据量,D是它们的维数。对数据矩阵X进行数据预处理有三种常见形式:
1 Mean subtraction
Mean subtraction是最常见的预处理形式。它通过减去数据中每个维度的平均值,将数据的每个维度都以原点为中心进行居中。其python numpy的代码为X -= np.mean(X, axis = 0)
。
2 Normalization
Normalization(也就是标准化)通过规范化数据维度,使它们具有大致相同的比例。有两种常用的方法:
- zero-centered,将每个维度除以其标准差。其python numpy的代码为
X /= np.std(X, axis = 0)
。 - normalized,对每个维度进行规格化,以便沿每个维度的最小值和最大值分别为-1和1。这个操作不是必须的,比如在图像的情况下,像素值的相对比例已经大致相等(在0到255的范围内),因此不必严格地执行这个额外的预处理步骤。
3 PCA and Whitening
3.1 PCA(Principal Component Analysis,主成分分析)
在此过程中,首先按上述变换将数据居中。然后,计算协方差矩阵,它表示数据的相关性:
# Assume input data matrix X of size [N x D]
X -= np.mean(X, axis = 0) # zero-center the data (important)
cov = np.dot(X.T, X) / X.shape[0] # get the data covariance matrix
协方差矩阵的(i,j)元素表示数据的第 i 维和第 j 维之间的协方差。特别地,这个矩阵的对角线表示方差。此外,协方差矩阵是对称的半正定矩阵。我们可以计算数据协方差矩阵的SVD分解:
U,S,V = np.linalg.svd(cov)
其中U的每一列都是协方差矩阵的一个特征向量,S
是一个由奇异值的平方组成的矩阵(如果对SVD不熟的话,可以先补充一下SVD的相关知识)。为了消除数据的相关性,我们将居中后(以原点为中心)的数据投影到特征基(eigenbasis)中:
Xrot = np.dot(X, U) # decorrelate the data
需要注意的是,U
的每一列都是一组正交向量(模长为1,且彼此正交),所以可以将它们视为基向量。因此,该投影变换相当于围绕数据X的旋转(因为旋转矩阵的每一列也是模长为1的正交向量),使得新的轴是特征向量所指的方向。如果我们要计算Xrot
的协方差矩阵,我们会看到它的结果是对角的。由于在SVD分解函数np.linalg.svd
的返回值U
中,特征向量列是按其特征值从大到小进行排列的。因此,我们可以利用这一点来降低数据的维度,只使用前几个特征向量(也就是主成分):
Xrot_reduced = np.dot(X, U[:,:100]) # Xrot_reduced becomes [N x 100]
在这个操作之后,我们会将大小为N×D的原始数据集缩减为大小为N×100的数据集,保留最主要法100个成分。通常情况下,先对训练数据进行PCA来缩减数据量后,再用它们来训练线性分类器或神经网络,可以获得非常好的性能,达到节省空间和时间的目的。
3.2 Whitening
Whitening是通过取特征基中的数据,将每一维的数据都除以特征值,使尺度标准化。这种变换的几何解释是,如果输入数据是一个多变量的高斯分布,那么Whitening后的数据将是一个均值和单位协方差矩阵为零的高斯分布。此步骤的代码如下:
# whiten the data:
# divide by the eigenvalues (which are square roots of the singular values)
Xwhite = Xrot / np.sqrt(S + 1e-5)
在这里,将S加上1e-5(或一个小常数)是为了防止除零。需要注意的是,该操作的一个缺点就是它会放大数据中的噪声,因为它将输入中的所有维度(包括主要是噪声的微小方差对应的不相关维度)都拉伸到相同的大小。在实践中,这个问题可以通过施加更强的平滑来缓解(即,将1e-5更换为更大的数字)。
我们还可以尝试用CIFAR-10数据集里的图像来可视化这两种变换。CIFAR-10的训练集大小为50000×3072,其中每个图像都被拉伸成3072维的行向量(每张图像是32×32像素大小,然后有RGB 3个通道,将其拉伸为一个一维行向量,则该行向量的维度即为32×32×3=3072维)。然后我们可以计算[3072 x 3072]协方差矩阵并计算其SVD分解(这可能需要较大的计算量)。计算出的特征向量可视化如下:
其中,左一:数据集中的49张图像。左二:3072个特征向量中的前144个。排在前面的特征向量占数据中的大部分方差,我们可以看到它们对应于图像中的低频。右二:使用左二所示的144个特征向量,用PCA减少49幅图像的数据量。也就是说,现在用144维向量来表示原始图像中的3072维向量。为了可视化每个向量中的144个数字中保留了哪些图像信息,我们必须将其旋转回3072个数字的“像素”中去。由于U
代表旋转,可以将这些向量与U.transpose()[:144,:]
相乘,然后将结果的3072数字可视化为图像。你可以看到图像稍微模糊,反映了一个事实,即排在前面的特征向量表示的是图像中的低频数据。不过,原图的大部分信息还是保留下来了。右一:Whitening的可视化。和右二一样,Whitening操作后的数据为144维的,通过乘以U.transpose()[:144,:]
然后进行可视化。在这里,低频数据(占最大方差)现在可以忽略不计,而较高频率(最初占相对较小方差)被夸大了。
4 总结
这篇博客介绍了Mean subtraction、Normalization、PCA和Whitening这几种数据预处理操作。但是需要注意的是,在实际应用中,PCA和Whitening不常用于卷积网络。然而,将数据归零(zero-center,也即Mean subtraction)是非常重要的,而且每个像素的归一化(Normalization)也是常用的操作。
这里有一个常见的陷阱。关于预处理需要注意的一点是,任何对原始数据的预处理(例如,上述的几种操作)必须仅在训练数据(training data)上计算,然后才将计算结果应用于验证/测试数据(validation / test data)上。比如,对整个数据集计算平均值并从整个数据集的每个图像中减去平均值,然后再将数据拆分为train/val/test数据,这种做法是错误的。正确做法是,平均值必须仅在训练数据上计算,然后对所有数据(train/val/test)减去这个平均值。
*本博客翻译总结自CS231n课程作业网站,该网站需要翻墙才能访问。