目录
2.1 ALL zero initialization 将权重全部初始化为0
2.3 Calibrating the variances with 1/sqrt(n)校准方差
3.5 Theme of noise in forward pass
4.2 Problem: Large number of classes
上节介绍了神经元模型和神经网络。其中神经元就是点积计算后输入到一个非线性函数;将多个神经元按层叠加就构成了神经网络。本节将介绍数据预处理,权重,初始化和损失函数。
1. Data Preprocessing
设输入数据为大小为的矩阵,代表元素的个数,代表特征维度。
- Mean Substraction减去均值/zero-centered中心化
最常用的预处理方法就是对每个特征减去该特征的均值,从几何角度来看这可以使数据在各个特征维度的都近乎关于零点对称。使用python时,mean substraction可以通过一行代码实现:
X -= np.mean(X,axis=0)
- Normalization 正则化
正则化是将数据各个维度都归一化,即将所有特征都近似到相同的范围。通常有两种方法:
1. 对每个特征,减去其特征的均值,再除以该特征的标准差
X -= np.mean(X,axis=0)
X /= np.std(X,axis=0)
2. 对于每个特征,将其最大值和最小值变换成和
注意:只有当输入特征的重要性相同,但是不同特征的特征值的数值范围相差很大的情况下,才可以使用这个方法将其归一化到相同的取值范围。
X = (np.max(X,axis=0) - X)/(np.max(X,axis=0) - np.min(X,axis=0))
下图给出了原始数据,中心化和正则化处理的效果:
- PCA and Whitening
PCA是一种降维的方法。在对数据进行中心化和归一化后,我们可以使用PCA进行降维。
PCA降维的过程如下:
1. 对中心化的数据计算协方差。
#中心化zero-centered data
X -= np.mean(X,axis=0)
#计算协方差
cov = np.dot(X.T,X) / X.shape[0]
其中,表示第维度和第维度特征的协方差。
2. 协方差矩阵是半正定矩阵,对它进行SVD分解(奇异值分解)
U,S,D = np.linalg.svd(cov)
其中,的每一列代表一个特征向量;是由奇异值组成的一维数组。
3. 为了去除相关性,我们将原始数据映射到特征向量上
Xrot = np.dot(X,U) #decorrelate the data
注意: 是每一列都是标准正交向量(norm of 1, and orthogonal to each other),并且已经按照特征值由大到小排列好了。原始数据与特征向量矩阵的点乘就相当于对做了一个旋转映射,将其映射到特征向量所对应的坐标空间上。
可以只保留前面较大特征值对应的特征向量,从而可以实现降维。这种方法就是PCA。
Xrot_reduced = np.dot(X,U[:,:100]) #[N*100]
降维后,我们保留了前100维度重要程度较高的数据(以方差大小为标准) 。
白化Whitening:PCA降维后,我们可以进行白化操作。白化操作是指,对PCA处理后的数据,每个维度除以对应的特征值,从而进行尺度正则化的操作。几何解释就是输入数据服从多维度高斯分布,经过白化处理后,服从均值为零,协方差相等的分布。
Xwhite = Xrot / np.sqrt(S+1e-5)
注意:为了避免分母为0,我们为分母加一个小常数1e-5。
警告:白化处理的缺点是会放大噪声。 由于白化处理将所有维度的特征(包括不相关性的、包含大量噪声的维度也不例外)都拉伸到相同的范围。实际中,可以通过增大分母(增大小常数1e-5)来进行平滑。
下图给出了原始数据,PCA去相关性处理后的数据和白化处理后的结果:
使用CIFAR-10来展示PCA和白化:
上图中,最左边为原始图片,每张图片可以看成一个3072长的列向量。左边第二幅图可以看成在3072个特征向量中的前144个特征向量,按照特征值排序。第三张图片经过降维处理后,只保留了144维特征的图片,可以看出图片变模糊了,说明只保留了低频的部分。最后一张为白化后的结果。
实际上,CNN中不需要进行PCA和白化操作,之所以介绍它们是因为他们是一种数据预处理的方法。
注意:预处理的只能针对训练集上使用,即:应该先将数据分成训练集、验证集、和测试集,之后再在训练集上使用数据与数理。
2. Weight Initialization
在训练神经网络前,我们需要初始化参数。
2.1 ALL zero initialization 将权重全部初始化为0
我们并不是知道最终训练得到的权重值是什么,但是通过前面的预处理过程,我们大概可以猜到权重的值应该差不多一半为正,一半为负。
但是如果将所有的权重初始化为0,会导致每个神经元输出相同的值,进而在反向传播中计算得到相同的梯度,然后权重更新也完全相同,这样训练结束后最终的到的神经元的权重也完全相同,即:网络中所有的神经元都相同。
2.2 Small random numbers
既然不能将所有的权重初始化为0 ,那么是不是可以让他们都接近于0,而不是等于0?
答案是可以的。常用的方法是,将神经元的参数初始化为较小的值,但是又不能对称。如果在初始化神经元的权重是随机、且不同的,那么在迭代过程中权重的更新也会不同,最终将得到不同的神经元。
例如,我们可以在Python中使用下面的代码进行权重初始化。
W = 0.01 * np.random.randn(D, H)
在上述代码中,randn()函数是基于均值为0、标准差为1的高斯分布生成随机数的。基于这段代码,每个神经权重向量是从多维高斯分布随机采样而来。当然,我们也可以使用基于均匀分布进行随机采样生成的随机数对权重进行初始化,但是在实际中,这样初始化的效果不好。
注意:不是越小的权重一定会得到更好的结果。神经网络中,如果权重比较小,那么反向传播时,梯度就比较小。这样会减小梯度传播的信号,这在深度神经网络中是个问题。
2.3 Calibrating the variances with 1/sqrt(n)校准方差
如果神经元的数据有着相似的分布,可以有效地提高收敛速度。前面使用的随机初始化存在一个问题:随着输入数据的增加,随机初始化的神经元的输出的方差也会增大。通过除以sqrt(n)
,其中n
是输入个数,可以将输出方差归一化到1,代码实现如下:
W = np.random.randn(n)/sqrt(n)
具体推导如下:不考虑非线性激活函数,假设输出为 ,那么输出的方差为:
其中,前2步基于方差的性质;第3步,我们假设输入和权重的均值为0,即:(注意,有些并不等于零,例如ReLU);最后一步假设了服从相同的分布。如果想要输出和有相同的方差,那么必须为1,即权重的方差应该为所以得到上面代码的初始化方程。
论文Understanding the difficulty of training deep feedforward neural networks给出了相似的分析,该论文建议使用,其中分别代表上一层和下一层神经元的个数。
最近的一篇论文 Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification 推荐针对ReLU的初始化,网络中神经元的方差为。在实践中使用ReLU时,推荐这样初始化。其代码实现为:
W = np.random.randn(n)*sqrt(2.0*n)
2.4 Sparse initialization
另外一种解决未校准方差问题的方法是:将所有权重设置为0,但是为了避免对称,随机在层之间连接个别神经元,这部分神经元的连接权重使用上述介绍的小高斯分布进行生成,连接个数常常设置为10。
2.5 Initializing the biases
实际应用中,通常将bias初始化为0即可, 因为随机初始化权重已经打破了对称性问题。
2.6 Batch normalization
Batch normalization是最近出现的技术,参考论文。BN操作的核心思想是:在激活函数前,添加一个normalization层,使得输入到激活函数的数据服从标准高斯分布,如下图所示。
Batch normalization能够在一定程度上解决神经网络权重初始化的问题。BN可以通过简单的求导操作进行计算,相当于在每个网络之前进行了预处理。
3. Regularization
正则化可以减少网络的过拟合,主要有以下几种:
3.1 L2 regularization
L2正则化是最常用的方法。它直接在目标函数上添加所有权重幅值的平方和。对于每个权重,都在目标函数上添加正则项,其中代表正则化强度,之所以乘以是为了方便求导。L2正则化可以直观的理解为限制较大的权重向量出现,倾向选择权重大小比较均匀的权重。
3.2 L1 regularization
L1正则化也是一种常用的方法。它为每个权重在目标函数上添加正则项。也可以将L1正则项和L2正则项结合起来,(叫做Elastic net regularization)。
L1正则化在优化过程中会使得权重矩阵变得稀疏。换句话说,经过L1正则化后,会选择出输入数据的稀疏子集(某些权重系数接近0,对应输入会变为0),对噪声不那么敏感。而L2正则化则倾向于选择大小分布比较均匀、且值都比较小的权重。
3.3 Max norm constrains
Max norm约束通过限制权重的幅值的上界,并使用投影梯度下降来确保约束的成立。实际应用中,参数更新方式不变,只不过限制每个神经元上的权重向量满足即可。通常将设置为为3或4。这种方法的显著优点是:即便选择设置的学习率,网络也不会“爆炸”。
3.4 Dropout
Dropout是非常有效、简单的正则化方法。(原始论文:Dropout: A Simple Way to Prevent Neural Networks from Overfitting )
论文介绍,Dropout可以作为对L1、L2或Max norm正则化的补充。
其思想是:在训练过程中,让神经元以概率的可能性被激活,否则将其设置为0,不激活。
在上图中,左边是没有使用dropout的网络,右边是使用了dropout的网络。需要注意的是,dropout只在训练使用,在训练时不使用dropout,而是将训练过程中生成的子网络进行ensemble,求得平均结果。
带dropout的3层神经网络代码实现:
""" Vanilla Dropout: Not recommended implementation (see notes below) """
p = 0.5 # probability of keeping a unit active. higher = less dropout
def train_step(X):
""" X contains the data """
# forward pass for example 3-layer neural network
H1 = np.maximum(0, np.dot(W1, X) + b1)
U1 = np.random.rand(*H1.shape) < p # first dropout mask
H1 *= U1 # drop!
H2 = np.maximum(0, np.dot(W2, H1) + b2)
U2 = np.random.rand(*H2.shape) < p # second dropout mask
H2 *= U2 # drop!
out = np.dot(W3, H2) + b3
# backward pass: compute gradients... (not shown)
# perform parameter update... (not shown)
def predict(X):
# ensembled forward pass
H1 = np.maximum(0, np.dot(W1, X) + b1) * p # NOTE: scale the activations
H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # NOTE: scale the activations
out = np.dot(W3, H2) + b3
从上述代码中可以看到,在训练的而过程中,使用dropout,令神经元以p的概率被激活,相当于每一层的输出变成原来的p倍;在测试过程中不使用dropout,为了使得每一层的输出值和训练时一直,应该在每一层的计算结果上乘以p。
我们更加关心测试时的性能,在预测时增加计算会减低生产环境性能。一个解决的方法为inverted dropout,即:在训练时,把使用DropOut的层除以概率p,其代码实现为:
"""
Inverted Dropout: Recommended implementation example.
We drop and scale at train time and don't do anything at test time.
"""
p = 0.5 # probability of keeping a unit active. higher = less dropout
def train_step(X):
# forward pass for example 3-layer neural network
H1 = np.maximum(0, np.dot(W1, X) + b1)
U1 = (np.random.rand(*H1.shape) < p) / p # first dropout mask. Notice /p!
H1 *= U1 # drop!
H2 = np.maximum(0, np.dot(W2, H1) + b2)
U2 = (np.random.rand(*H2.shape) < p) / p # second dropout mask. Notice /p!
H2 *= U2 # drop!
out = np.dot(W3, H2) + b3
# backward pass: compute gradients... (not shown)
# perform parameter update... (not shown)
def predict(X):
# ensembled forward pass
H1 = np.maximum(0, np.dot(W1, X) + b1) # no scaling necessary
H2 = np.maximum(0, np.dot(W2, H1) + b2)
out = np.dot(W3, H2) + b3
更多内容参考:
Dropout paper by Srivastava et al. 2014.
Dropout Training as Adaptive Regularization “we show that the dropout regularizer is first-order equivalent to an L2 regularizer applied after scaling the features by an estimate of the inverse diagonal Fisher information matrix”
3.5 Theme of noise in forward pass
Dropout在前向传播过程中引入了一些随机行为,在预测时可以通过一些数值方法补偿这个随机性(如:乘以p)。类似的补偿行为还包括:DropConnect。
3.6 Bias regularization
通常不考虑对bias添加正则化约束,原因是因为通常它们不直接与数据相乘,不会直接影响数据。实际上,即便对bias进行正则化也很少会导致算法性能变差,这可能是由于bias的数量远远小于weights的数量的缘故。
3.7 Pre-layer regularization
很少对不同的层使用不同的正则化方法。
实践tips:
1. 通常使用全局L2正则化,大小通过交叉验证获得。
2. 使用L2正则化后,常常再结合Dropout,一般可以设置p=0.5,也可以通过交叉验证获得。
4. Loss functions
上小节我们讨论了损失函数其中的一部分:正则化损失。正则化损失用来度量模型的复杂度。本节我们讨论损失函数的另外一部分:数据损失。数据损失用来度量模型给出的预测值和真实值得差异。数据损失是输入数据的平均损失,可以写成:,其中N是训练集的大小。
在实际中碰到的问题可以分为以下几类:
4.1 Classification
假设每个样本只有一个标签,常用的两个损失函数有:
SVM损失 | |
Cross-entropy loss |
SVM损失是SVM分类过程中用到的;交叉熵损失是Softmax使用的损失函数。
4.2 Problem: Large number of classes
当标签集合非常大时(例如:分词、ImageNet图像的类别有22000种等),要使用Hierarchical Softmax。其思想是:将标签集合构造城一棵树,每一个标签为树的一条路径。在树的每个节点训练一个softmax分类器,用来区分左、右分支。标签树的结构直接影响分类的性能,并且要根据具体问题具体分析。
4.3 Attribute classification
如果一个样本的标签不止有一个时,例如:标签是一个二值向量,一个样本可能包含标签集合中的某几个标签,且标签之间不互斥。这时,可以采用两种解决方法。
方法1:可以为每一个标签建立一个二值分类器:
其中,对于所有的类别,表示第个样本是否包含第个标签,如果包含则,否则;代表打分函数,表示预测值,如果样本被预测为类别,那么,否则。由该损失函数的定义可知,当正确预测且分值小于1,或预测错误,且分值大于时,loss就会大于0。
方法2:为每一个标签简历一个逻辑回归分类器,那么损失函数为:
打分函数f的定义: |
其中,表示第个样本是否包含第个标签,若包含则,否则;f代表打分函数,若其值大于0.5,则代表属于j类,否则代表不属于j类。
4.4 Regression
对于回归问题,经常使用的Loss函数有L2范式和L1范式:
相对于L1范式,L2范式在梯度的计算时更加方便。
注意:
1. 相对于Softmax用的交叉熵损失函数而言,L2损失更加难以优化。L2损失要求每个输出都必须恰好正确;而softmax使用的交叉熵损失并不那么care得分,只有当评分在适当量级时才有意义。
2. L2 Norm的鲁棒性不好,异常点可能引起较大的梯度。
3. 面对回归问题时,优先看看能不能将其转化成分类问题
4. 如果使用回归,L2是一个不错的选择;但是在dorpout网络结构中,不宜再用L2。
4.4 Structured Prediction
结构化预测是指标签是任意的形状(树,图等),通常假设结构空间非常大且难以遍历。其思想和结构化SVM类似,在正确分类和分值最高的错误分类间建立一个分类面。
5. Summary
- 数据预处理:将数据进行zero-centered,正则化将特征规范化到
- 初始化权重方法:使用高斯分布,标准差为。
- 正则化:L2,L1,dropout ,Max norm constrains
- Batch Normalization
- Loss函数:Multiclass SVM Loss,Cross-entropy loss,log loss,L1,L2等等。