深度学习的预处理:从协方差矩阵到图像白化

深度学习的预处理:从协方差矩阵到图像白化

这篇文章的目标是从数据预处理的基础知识到深度学习中使用的现代技术。我的观点是我们可以使用代码(例如Python / NumPy)来更好地理解抽象的数学概念。


我们将从数据科学和机器学习/深度学习中的基本但非常有用的概念开始,如方差和协方差矩阵。我们将进一步介绍一些用于将图像输入神经网络的预处理技术。我们将尝试使用代码获得更具体的见解,以实际了解每个等式的作用。


预处理是指在将原始数据馈送到机器学习或深度学习算法之前对原始数据进行的所有转换。例如,在原始图像上训练卷积神经网络可能会导致糟糕的分类性能(Pal&Sudeep,2016)。预处理对于加速训练也很重要(例如,居中和缩放技术,参见Lecun等,2012;见4.3)。


以下是本教程的教学大纲:

1.背景:在第一部分中,我们将得到关于方差和协方差的一些提醒。我们将看到如何生成和绘制数据以更好地理解这些概念。

2.预处理:在第二部分中,我们将看到一些可应用于任何类型数据的预处理技术的基础知识 -  均值归一化标准化白化

3.白化图像:在第三部分中,我们将使用在1.2.中获得的工具和概念来进行称为零分量分析(ZCA)的特殊白化。它可用于预处理图像以进行深度学习。这部分将非常实用和有趣☃️!

本文辅助代码:hadrienj/Preprocessing-for-deep-learning

1.背景

A.方差和协方差

变量的方差描述了值的离散程度。协方差是一种衡量两个变量之间依赖程度的指标。正协方差意味着当第一变量的值大时,第二变量的值也大。负协方差则相反:来自一个变量的大值与另一个变量的小值相关联。协方差值取决于变量的大小,因此很难对其进行分析。但可以使用更容易解释的相关系数。相关系数只是归一化的协方差。

正协方差意味着一个变量的大值与另一个变量的大值相关联(左)。负协方差意味着一个变量的大值与另一个变量的小值(右)相关联。


协方差矩阵是一个矩阵,它总结了一组向量的方差和协方差,它可以告诉你关于变量的很多事情。它的对角线对应于每个向量的方差:

矩阵A及其协方差矩阵。对角线对应于每个列向量的方差。


我们来看看方差的公式:


n是矢量的长度, \bar{x} 是向量的平均值。例如,A的第一列向量的方差是:


这是我们协方差矩阵的第一个单元格。对角线上的第二个元素对应于第二列向量与A的方差,依此类推。


注意:从矩阵中提取的矢量A对应的列A。


其他单元对应于来自A的两个列向量之间的协方差。例如,第一列和第三列之间的协方差位于协方差矩阵中作为列1和行3(或列3和行1)。

协方差矩阵中的位置。列对应于第一个变量,行对应于第二个(或相反)。第一和第三列向量之间的协方差位于协方差矩阵的第1列第3行(或第3列第1行)。


让我们检查A的第一和第三列向量之间的协方差是否等于-2.67。两个变量XY之间的协方差公式为:

变量X和变量Y是分别上一个例子中的第一和第三列向量。让我们分开这个公式以便更好地讲述:

  1. 和符号(Σ)意味着我们将迭代向量的元素。我们将从第一个元素(i = 1)开始,计算X的第一个元素减去向量X的平均值。

2.将结果乘以Y的第一个元素减去向量Y的平均值。

3.重复向量的每个元素的过程并计算所有结果的总和。

4.除以向量中的元素数量。


例1。

让我们从矩阵A开始:

我们将计算第一个和第三个列向量之间的协方差:



= 3ȳ= 4n = 3,所以我们有:



现在简单的方法。使用NumPy,可以使用函数计算协方差矩阵np.cov

值得注意的是,如果您希望NumPy将列用作向量,则必须使用该参数rowvar=False。此外,bias=True意味着 除以n 而不是n-1


让我们先创建数组:

A = np.array([[1, 3, 5], [5, 4, 1], [3, 8, 6]])
A
array([[1, 3, 5],
[5, 4, 1],
[3, 8, 6]])


现在我们将使用NumPy函数计算协方差:

np.cov(A, rowvar=False, bias=True)
array([[ 2.66666667, 0.66666667, -2.66666667],
[ 0.66666667, 4.66666667, 2.33333333],
[-2.66666667, 2.33333333, 4.66666667]])


使用点积查找协方差矩阵

还有另一种计算A的协方差矩阵的方法。你可以将A居中于0左右。从向量的每个元素中减去向量的平均值,得到一个平均值等于0的向量。它乘以自己的转置,并除以矩阵的数量。


让我们从一个实现开始,然后我们将尝试理解与前一个等式的关联:

def calculateCovariance(X): 
  meanX = np.mean(X, axis = 0) 
  lenX = X.shape[0] 
  X = X - meanX 
  covariance = X.T.dot(X)/lenX 
  return covariance

让我们在矩阵A上测试它:

calculateCovariance(A)
array([[ 2.66666667, 0.66666667, -2.66666667],
[ 0.66666667, 4.66666667, 2.33333333],
[-2.66666667, 2.33333333, 4.66666667]])

我们最终得到与以前相同的结果。


这样做的原意很简单。两个向量之间的点积可以表示为:

这是正确的,它是向量的每个元素的乘积之和:

点积对应于矢量的每个元素的乘积之和。若n是我们向量中的元素总数,我们除以n

你可以注意到,这与我们之前看到的协方差公式相差不远:


唯一的区别是,在协方差公式中,我们从每个元素中减去一个向量的均值。这就是为什么我们需要在做点积之前将数据集中在一起?


现在,如果我们有一个矩阵AA和它的转置之间的点积将给你一个新的矩阵:

这是协方差矩阵!


B.可视化数据和协方差矩阵

为了获得关于协方差矩阵以及它如何有用的更多见解,我们将创建一个函数来将其与2D数据一起可视化。您将能够看到协方差矩阵和数据之间的关联。


该函数将如上所述计算协方差矩阵。它将创建两个子图 - 一个用于协方差矩阵,另一个用于数据。Seabornheatmap()功能用于创建颜色渐变 - 小值将以浅绿色着色,大值以深蓝色着色。我们选择了一种调色板颜色,但您可能更喜欢其他颜色。数据表示为散点图。

def plotDataAndCov(data):
    ACov = np.cov(data, rowvar=False, bias=True)
    print 'Covariance matrix:\n', ACov

    fig, ax = plt.subplots(nrows=1, ncols=2)
    fig.set_size_inches(10, 10)

    ax0 = plt.subplot(2, 2, 1)
    
    # Choosing the colors
    cmap = sns.color_palette("GnBu", 10)
    sns.heatmap(ACov, cmap=cmap, vmin=0)

    ax1 = plt.subplot(2, 2, 2)
    
    # data can include the colors
    if data.shape[1]==3:
        c=data[:,2]
    else:
        c="#0A98BE"
    ax1.scatter(data[:,0], data[:,1], c=c, s=40)
    
    # Remove the top and right axes from the data plot
    ax1.spines['right'].set_visible(False)
    ax1.spines['top'].set_visible(False)
 

C.模拟数据

不相关的数据

现在我们已经有了绘图功能,我们将生成一些随机数据来显示协方差矩阵可以告诉我们的内容。我们将从使用NumPy函数的正态分布np.random.normal()中提取的一些数据开始。


该函数需要平均值,标准差和分布的观察数作为输入。我们将创建300个观测值的两个随机变量,标准差为1.第一个平均值为1,第二个平均值为2.如果我们从正态分布中随机抽取两组300个观测值,则两个矢量将是不相关的。

np.random.seed(1234)
a1 = np.random.normal(2, 1, 300)
a2 = np.random.normal(1, 1, 300)
A = np.array([a1, a2]).T
A.shape
(300,2)

注1:我们转置数据是 .T因为原始形状是(2, 300),我们希望观察数量为行(因此有形状(300, 2))。

注2:我们使用np.random.seed函数进行再现性。下次运行单元格时将使用相同的随机数。

我们来看看数据的样子:

A[:10,:]
array([[ 2.47143516, 1.52704645],
[ 0.80902431, 1.7111124 ],
[ 3.43270697, 0.78245452],
[ 1.6873481 , 3.63779121],
[ 1.27941127, -0.74213763],
[ 2.88716294, 0.90556519],
[ 2.85958841, 2.43118375],
[ 1.3634765 , 1.59275845],
[ 2.01569637, 1.1702969 ],
[-0.24268495, -0.75170595]])

很好,我们有两个列向量。现在,我们可以检查分布是否正常:

sns.distplot(A[:,0], color="#53BB04")
sns.distplot(A[:,1], color="#0A98BE")
plt.show()
plt.close()

看起来不错!我们可以看到分布具有相同的标准偏差但是具有不同的均值(1和2)。这正是我们所要求的。现在我们可以用我们的函数绘制数据集及其协方差矩阵:

plotDataAndCov(A) 
plt.show() 
plt.close()
Covariance matrix:
[[ 0.95171641 -0.0447816 ]
[-0.0447816 0.87959853]]


我们可以在散点图上看到两个维度是不相关的。注意,我们有一个平均值为1(y轴),另一个平均值为2(x轴)。


此外,协方差矩阵显示每个变量的方差非常大(大约1),并且第1列和第2列的协方差非常小(大约为0)。由于我们确保两个向量是独立的,因此这是连贯的。相反的情况不一定如此:0的协方差不能保证独立性(见这里)。


相关数据

现在,让我们通过从另一列中指定一列来构造依赖数据。

np.random.seed(1234) 
b1 = np.random.normal(3, 1, 300) 
b2 = b1 + np.random.normal(7, 1, 300)/2. 
B = np.array([b1, b2]).T plotDataAndCov(B) 
plt.show() 
plt.close()
Covariance matrix:
[[ 0.95171641 0.92932561]
[ 0.92932561 1.12683445]]


在散点图上可以看到两个维度之间的相关性。我们可以看到可以绘制一条线并用于从x预测y,反之亦然。协方差矩阵不是对角的(对角线外有非零单元)。这意味着维度之间的协方差不为零。那很棒!我们现在拥有了查看不同预处理技术的所有工具。

2.预处理

A.平均归一化

平均归一化只是减去平均值。

其中X'是标准化数据集,X是原始数据集,X的平均值。均值归一化具有将数据居中于0的效果。我们将创建执行此操作的函数center():

def center(X): 
newX = X - np.mean(X, axis = 0) 
return newX


让我们试试我们之前创建的矩阵B

BCentered = center(B)

print 'Before:\n\n'

plotDataAndCov(B)
plt.show()
plt.close()

print 'After:\n\n'

plotDataAndCov(BCentered)
plt.show()
plt.close()
Before:


Covariance matrix:
[[ 0.95171641 0.92932561]
[ 0.92932561 1.12683445]]



After:


Covariance matrix:
[[ 0.95171641  0.92932561]
 [ 0.92932561  1.12683445]]


第一个图再次显示原始数据B,第二个图显示居中数据(查看比例)。

B.标准化或归一化

标准化用于将所有特征放在相同的比例上。每个零中心尺寸除以其标准偏差。

其中X'是标准化的数据集,X是原始数据集, \bar{x} 是的平均值, 并且σ是标准偏差。

def standardize(X): 
newX = center(X)/np.std(X, axis = 0) 
return newX


让我们创建另一个具有不同比例的数据集来检查它是否正常工作。

np.random.seed(1234) 
c1 = np.random.normal(3, 1, 300) 
c2 = c1 + np.random.normal(7, 5, 300)/2. 
C = np.array([c1, c2]).T 
plotDataAndCov(C) plt.xlim(0, 15) 
plt.ylim(0, 15) 
plt.show() 
plt.close()
Covariance matrix:
[[ 0.95171641 0.83976242]
[ 0.83976242 6.22529922]]



我们可以看到xy的尺度不同。另请注意,由于比例差异,相关性似乎较小。现在让我们标准化它:

CStandardized = standardize(C) 
plotDataAndCov(CStandardized) 
plt.show() 
plt.close()
Covariance matrix:
[[ 1. 0.34500274]
[ 0.34500274 1. ]]


看起来不错。您可以看到比例相同,并且数据集根据两个轴以零为中心。现在,看一下协方差矩阵。您可以看到每个坐标的方差 - 左上角单元格和右下角单元格 - 等于1。这个新的协方差矩阵实际上是相关矩阵。两个变量(c1c2)之间的Pearson相关系数是0.54220151。

C.白化

白化意味着我们想要将其转换为具有协方差矩阵,该矩阵是对齐矩阵 - 对角线为1,其他单元为0。参照白噪声,它被称为白噪声。以下是有关单位矩阵的更多详细信息。


白化比其他预处理要复杂一些,但我们现在拥有了所需的所有工具。它涉及以下步骤:

  • 零中心数据
  • 数据解相关
  • 重新缩放数据

让我们再次使用矩阵C并尝试执行这些步骤。

CCentered = center(C) 
plotDataAndCov(CCentered) 
plt.show() 
plt.close()
Covariance matrix:
[[ 0.95171641 0.83976242]
[ 0.83976242 6.22529922]]



2.去相关

此时,我们需要对数据进行去相关。直觉上,这意味着我们想要旋转数据直到不再存在相关性。看下面的图片,看看我的意思:

左图显示相关数据。例如,如果您使用具有较大x值的数据点,则相关联的y也可能非常大。现在取所有数据点并进行旋转(可能逆时针旋转45度左右。右侧绘制的新数据不再相关。您可以看到大小y值与相同类型的x值相关。


问题是:我们怎样才能找到正确的旋转以获得不相关的数据?实际上,它正是协方差矩阵的特征向量所做的。它们指示数据扩散的最大方向:

协方差矩阵的特征向量为您提供最大化方差的方向。绿线的方向是方差最大的地方。只要看看这条线上预测的最小和最大点 - 差距很大。将其与橙色线上的投影相比- 离散非常小。有关特征分解的更多详细信息,请参阅此文章


因此,我们可以通过使用特征向量投影来解相关数据。这将具有应用所需旋转并移除尺寸之间的相关性的效果。以下是步骤:

  • 计算协方差矩阵
  • 计算协方差矩阵的特征向量
  • 将特征向量矩阵应用于数据 - 这将应用旋转

    让我们将其打包到函数中:
def decorrelate(X):
    newX = center(X)
    cov = X.T.dot(X)/float(X.shape[0])
    # Calculate the eigenvalues and eigenvectors of the covariance matrix
    eigVals, eigVecs = np.linalg.eig(cov)
    # Apply the eigenvectors to X
    decorrelated = X.dot(eigVecs)
    return decorrelated

让我们试着去掉我们的以零为中心的矩阵C来看它的实际效果:

plotDataAndCov(C)
plt.show()
plt.close()

CDecorrelated = decorrelate(CCentered)
plotDataAndCov(CDecorrelated)
plt.xlim(-5,5)
plt.ylim(-5,5)
plt.show()
plt.close()
Covariance matrix:
[[ 0.95171641 0.83976242]
[ 0.83976242 6.22529922]]
[[242  6.22529922]]



Covariance matrix:
[[  5.96126981e-01  -1.48029737e-16]
 [ -1.48029737e-16   3.15205774e+00]]


我们可以看到相关性不再存在了。协方差矩阵,现在是对角矩阵,证实了两个维度之间的协方差等于0。


3.重新缩放数据

下一步是缩放不相关的矩阵,以便获得对应于单位矩阵的协方差矩阵。为此,我们通过将每个维度除以其对应的特征值的平方根来缩放我们的去相关数据。

def whiten(X):
    newX = center(X)
    cov = X.T.dot(X)/float(X.shape[0])
    # Calculate the eigenvalues and eigenvectors of the covariance matrix
    eigVals, eigVecs = np.linalg.eig(cov)
    # Apply the eigenvectors to X
    decorrelated = X.dot(eigVecs)
    # Rescale the decorrelated data
    whitened = decorrelated / np.sqrt(eigVals + 1e-5)
    return whitened


注意:我们添加一个小值(此处为10 ^ -5)以避免除以0。

CWhitened = whiten(CCentered)
plotDataAndCov(CWhitened)
plt.xlim(-5,5)
plt.ylim(-5,5)
plt.show()
plt.close()


Covariance matrix:
[[ 9.99983225e-01 -1.06581410e-16]
[ -1.06581410e-16 9.99996827e-01]]


注意:我们添加一个小值(此处为10 ^ -5)以避免除以0。

CWhitened = whiten(CCentered)

plotDataAndCov(CWhitened)
plt.xlim(-5,5)
plt.ylim(-5,5)
plt.show()
plt.close()
Covariance matrix:
[[ 9.99983225e-01 -1.06581410e-16]
[ -1.06581410e-16 9.99996827e-01]]

我们可以看到,使用协方差矩阵,这一切都很好。我们的东西看起来像一个单位矩阵 - 对角线上1,其他地方0。

3.图像白化

我们将看到如何应用白化来预处理图像数据集。为此,我们将使用Pal&Sudeep(2016)的论文,其中提供了有关该过程的一些细节。这种预处理技术称为零分量分析(ZCA)。查看论文,但这是他们得到的结果。显示原始图像(左)和ZCA(右)后的图像。


首先要做的事情。我们将从CIFAR数据集加载图像。此数据集可从Keras获得,您也可以在此处下载。

from keras.datasets import cifar10

(X_train, y_train), (X_test, y_test) = cifar10.load_data()

X_train.shape
(50000, 32, 32, 3)


CIFAR10数据集的训练集包含50000个图像。形状X_train(50000, 32, 32, 3)。每幅图像为32像素×32像素,每个像素包含3个维度(R,G,B)。每个值是0到255之间相应颜色的亮度。我们将从仅选择图像的一个子集开始,假设为1000:

X = X_train[:1000] 
print X.shape
(1000, 32, 32, 3)

现在我们将对阵列进行reshape,以获得每行一个图像的平面图像数据。每个图像都是(1, 3072)因为32 x 32 x 3 = 3072.因此,包含所有图像的数组将是(1000, 3072)

X = X.reshape(X.shape[0], X.shape[1]*X.shape[2]*X.shape[3]) 
print X.shape
(1000, 3072)

下一步是能够看到图像。imshow()Matplotlib(doc)中的函数可用于显示图像。它需要具有形状(M x N x 3)的图像,所以让我们创建一个reshape图像的函数,并能够从形状中可视化它们(1, 3072)

def plotImage(X):
    plt.figure(figsize=(1.5, 1.5))
    plt.imshow(X.reshape(32,32,3))
    plt.show()
    plt.close()

例如,让我们绘制我们加载的图像之一:

plotImage(X[12, :])

我们现在可以实现图像的白化。Pal&Sudeep(2016)描述了这个过程:

1.第一步是通过除以255(像素的最大值)来重新缩放图像以获得范围[0,1]。

回想一下,获得范围[0,1]的公式是:

但是,这里,最小值为0,因此这导致:

X_norm = X / 255.
print 'X.min()', X_norm.min()
print 'X.max()', X_norm.max()


X.min() 0.0
X.max() 1.0



1.从所有图像中减去均值。

平均减法:每像素还是每图像?这里要小心。


其中一种方法是使用每张图像并从每个像素中减去该图像的平均值(Jarrett等,2009)。这个过程背后的直觉是它将每个图像的像素集中在0左右。


另一种方法是使用图像的3072个像素(R,G和B为32乘32像素)的每一个,并在所有图像中减去该像素的平均值。这称为每像素平均减法。这次,根据所有图像,每个像素将以0为中心。当您使用图像为网络提供信息时,每个像素都被视为不同的特征。通过每像素平均减法,我们将每个特征(像素)集中在0左右。这种技术是常用的(例如Wan等,2013)。


我们现在将从1000张图像中进行每像素平均减法。我们的数据按维度(images, pixels)进行组织。也就是(1000, 3072),因为有1000张图像,32 x 32 x 3 = 3072像素。因此,可以从第一轴获得平均每像素:

X_norm.mean(axis=0).shape
(3072,)

这给了我们3072个值,即每个像素有一个平均值 。让我们看看我们拥有的值:

X_norm.mean(axis=0)
array([ 0.5234 , 0.54323137, 0.5274 , ..., 0.50369804,
0.50011765, 0.45227451])


这接近0.5,因为我们已经归一化到范围[0,1]。但是,我们仍然需要从每个像素中减去均值:

 X_norm = X_norm - X_norm.mean(axis=0)


为了说服自己它的有效性,我们将计算第一个像素的平均值。我们希望结果是0。

X_norm.mean(axis=0)
array([ -5.30575583e-16, -5.98021632e-16, -4.23439062e-16, ...,
-1.81965554e-16, -2.49800181e-16, 3.98570066e-17])


这不完全是0,但它足够小,我们可以认为它有效!


现在我们想要计算零中心数据的协方差矩阵。就像我们在上面看到的那样,我们可以使用NumPy中的函数np.cov()来计算它。


请注意,我们的变量是我们不同的图像。这意味着变量是矩阵X的行。为了清楚起见,我们将使用参数将此信息告诉NumPy,设置rowvar=TRUE(参见文档):

cov = np.cov(X_norm, rowvar=True)


我们将计算协方差矩阵的奇异值和向量,并使用它们来旋转我们的数据集。如果您需要更多细节,请查看关于奇异值分解(SVD)的帖子


注意:大量图像可能需要一些时间,这就是我们仅使用1000的原因。在论文中,他们使用了10000张图像。您可以根据您使用的图像数量来比较结果:

U,S,V = np.linalg.svd(cov)


在论文中,他们使用以下等式:


X是标准化的数据集,U是左奇异向量和S是图像归一化后的数据集的协方差的奇异值。ε是称为白化系数的超参数。diag(a)对应于一个矩阵,其中对角线为向量a,所有其他单元格为0。


我们将尝试实现这个等式。让我们首先检查SVD的尺寸:

print U.shape, S.shape
(1000, 1000) (1000,)


S是包含1000个元素的向量(奇异值)。因此,diag(S)的形状是(1000, 1000),它的对角线为S

print np.diag(S) 
print '\nshape:', np.diag(S).shape
[[ 8.15846654e+00 0.00000000e+00 0.00000000e+00 ..., 0.00000000e+00
0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 4.68234845e+00 0.00000000e+00 ..., 0.00000000e+00
0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 2.41075267e+00 ..., 0.00000000e+00
0.00000000e+00 0.00000000e+00]
...,
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ..., 3.92727365e-05
0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ..., 0.00000000e+00
3.52614473e-05 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ..., 0.00000000e+00
0.00000000e+00 1.35907202e-15]]

shape: (1000, 1000)

它的形状也(1000, 1000)U U^{t} 的形状也是(1000, 1000)。我们也看到X的形状(1000, 3072)。因此X_ZCA的形状是:

它对应于初始数据集的形状,我们有:

epsilon = 0.1
X_ZCA = U.dot(np.diag(1.0/np.sqrt(S + epsilon))).dot(U.T).dot(X_norm)
plotImage(X[12, :])
plotImage(X_ZCA[12, :])

结果令人失望!如果你看过原论文,这不是他们所展示的那种结果。实际上,这是因为我们没有重新调整像素,并且存在负值。为此,我们可以使用与上述相同的技术将其放回[0,1]范围内:

X_ZCA_rescaled = (X_ZCA - X_ZCA.min()) / (X_ZCA.max() - X_ZCA.min()) 
print 'min:', X_ZCA_rescaled.min() 
print 'max:', X_ZCA_rescaled.max()
min: 0.0
max: 1.0
plotImage(X[12, :]) 
plotImage(X_ZCA_rescaled[12, :])


现在它看起来像论文上的图像。如前所述,他们使用了10000张图像而不是像我们这样的1000张。要根据您使用的图像数量和超参数ε的效果来查看结果的差异,以下是不同值的结果:

根据我们使用的图像的数量和超参数ε的值,白化的结果是不同的。左侧的图像是原始图像。在论文中,Pal&Sudeep(2016)使用了10000个图像,epsilon = 0.1。这对应于左下图像。


微信号:deep_intelligence(欢迎关注!)

weixin.qq.com/r/ry7r8xz (二维码自动识别)

参考资料

K. Jarrett, K. Kavukcuoglu, M. Ranzato, and Y. LeCun, “What is the best multi-stage architecture for object recognition?,” in 2009 IEEE 12th International Conference on Computer Vision, 2009, pp. 2146–2153.

A. Krizhevsky, “Learning Multiple Layers of Features from Tiny Images,” Master’s thesis, University of Tront, 2009.

Y. A. LeCun, L. Bottou, G. B. Orr, and K.-R. Müller, “Efficient BackProp,” in Neural Networks: Tricks of the Trade, Springer, Berlin, Heidelberg, 2012, pp. 9–48.

K. K. Pal and K. S. Sudeep, “Preprocessing for image classification by convolutional neural networks,” in 2016 IEEE International Conference on Recent Trends in Electronics, Information Communication Technology (RTEICT), 2016, pp. 1778–1781.

L. Wan, M. Zeiler, S. Zhang, Y. L. Cun, and R. Fergus, “Regularization of Neural Networks using DropConnect,” in International Conference on Machine Learning, 2013, pp. 1058–1066.

And also these great resources and QA:

Wikipedia - Whitening transformation

CS231 - Convolutional Neural Networks for Visual Recognition

Dustin Stansbury - The Clever Machine

Some details about the covariance matrix

Is this the correct way of whitening an image in python?

Mean normalization per image or from the entire dataset

Mean subtraction - all images or per image?

Why centering is important - See section 4.3

Kaggle kernel on ZCA

How ZCA is implemented in Keras


本文翻译自:medium.freecodecamp.org

作者:hadrienj

编辑于 2018-09-27

文章被以下专栏收录