20170304#cs231n#6.Neural Networks Part 2: Setting up the Data and the Loss

来源:互联网 发布:首页源码 编辑:程序博客网 时间:2024/05/01 19:20

Data Preprocessing 数据预处理

Mean subtraction 零均值化:

对每一个特征减去均值
X -= np.mean(X, axis = 0)

Normalization 归一化:

把数据的所有维度归一化,使其数值范围近似相等,归一化操作只有在确定不同输入特征有不同数值范围(或单位)才有意义,但是图像处理中由于范围为[0,255]所以这个数据预处理的步骤意义不是特别大。归一化大概有两种方法

  • 第一种是先进行零均值化然后再除以标准差 X /= np.std(X, axis=0)
  • 第二种是对每个维度都除以该维度的数据范围归一化使其范围为[1,1]

PCA and Whitening(白化)

PCA主成分分析

PCA代码如下

U,S,V = np.linalg.svd(cov)Xrot = np.dot(X,U)Xrot_reduced = np.dot(X, U[:,:100])

白化

白化操作的输入是eigenbasis特征基向量上的数据,然后对每个维度除以其eigenvalue特征值来对数值范围进行归一化。该变换的几何解释是:如果数据服从multivariable gaussian多变量的高斯分布,那么经过白化后,数据的分布将会是一个均值为零,且协方差相等的矩阵。

该操作的代码如下:

# 对数据进行白化操作:# 除以特征值(即奇异值的平方根)Xwhite = Xrot / np.sqrt(S + 1e-5)

但这里面会有Exaggerating noise(夸大的噪声)

注意分母中添加了1e-5(或一个更小的常量)来防止分母为0。该变换的一个缺陷是在变换的过程中可能会夸大数据中的噪声,这是因为它将所有维度都除以特征值,拉伸到相同的数值范围,这些维度中也包含了那些只有极少差异性(方差小)而大多是噪声的维度。在实际操作中,这个问题可以用更强的平滑来解决(例如:采用比1e-5更大的值)


PCA和白化结果是对数据在各个方向上拉伸压缩,使之变成服从高斯分布的一个数据点分布
关于PCA的实际效果可以看CS231nNeuralNetwork2中的一个example

在实际中,PCA和白化这些变化并不会被用到卷积神经网络中,但是零均值化和归一化就经常会见到

常见错误:预处理的时候(如数据的均值mean)只能在TrainingSet上计算,算法训练完毕后再用刀validation验证集、testSet测试集上

例如,如果先计算整个DataSet的图像mean平均值然后每张照片都减去mean值,最后将整个DataSet分为Train/validation/test Set,这是错误的

正确的做法应该是先把dataset分为Training/validation/test,只是从Training中求图片的平均值,然后各个集(Training/validation/test)中的图像再减去这个平均值

Weight Initialization 权值初始化

不可以因为均值为0就把W初值矩阵全部置0,因为这样会使得神经网络参数失去不对称性(也就是最后结果是对称的)

Small random numbers 小随机数初始化

用小随机数使得权值初值很接近0但又不是0,以打破对称性
一种实现方法是W = 0.01* np.random.randn(D,H) 其中randn为基于零均值和标准差的一个高斯分布

但不是一定小数据就有好的结果,

例如,一个神经网络的层中的权重值很小,那么在反向传播的时候就会计算出非常小的梯度(因为梯度与权重值是成比例的)。这就会很大程度上减小反向传播中的“梯度信号”,在深度网络中,就会出现问题。

Calibrating the variances with 1/sqrt(n) 使用1/sqrt(n)校正方差

随着输入数据量的增长,随机初始化的神经元的输出数据的分布中的方差也在增大
我们可以对权重矩阵W除以输入数据量的平方根n来调整其数值范围,这样神经元输出的方差就归一化到1了(原因应该是原先标准高斯分布的方差为1)。
神经元的权重向量初始化实现方法为:w = np.random.randn(n) / sqrt(n)。其中n是输入数据的数量。

推导详见CS231n中的相关公式

对于ReLU神经元的特殊初始化,网络中神经元方差和要除以(n/2.0),所以代码应该为w = np.random.randn(n) / sqrt(N/2.0)。其中n是输入数据的数量。
这是因为ReLU为一半为0,一半为线性的函数,方差为其他函数的一半(ReLU f(x)=0的那一半区间没有方差)

Sparse initialization 稀疏初始化

另一个处理非标定方差的方法是先将所有权重矩阵W设为0,但是为了打破对称性,每个神经元都同下一层固定数目的神经元randomly connected随机连接(其权重数值W再由一个小的高斯分布生成)。一个比较典型的连接数目是10个。

初始化biases的值

更常见的是把biases直接设置为0,因为对称性已经被小随机初始化的W打破了。
对于ReLU等非线性函数,有些人会用小的常数例如0.01作为biases以保证ReLU单元在一开始就被激活因此能够保存并传递一些梯度(不过不确定有啥卵用好像有时候还会使结果更糟)。所以一般biases还是用0去初始化

Batch Normalization 批量归一化

Batch Normalization论文

其做法是让激活数据在训练开始前通过一个网络,用网络处理每一个dimension的数据使其服从unit gaussian标准高斯分布。因为归一化是一个简单可求导的操作,所以上述思路是可行的。在实际中,应用BN通常意味着FullyConnected全连接层(或者是Convolutional卷积层)与激活函数之间添加一个BatchNorm层。

对每一个维度运用unit gaussian,即在这一层中:
1. 先计算每一dimension的empirical mean经验均值和variance方差
2. 归一化:

xˆ(k)=x(k)E[x(k)]Var[x(k)]

BN的使用位置

如果神经网络需要改变归一化的压缩范围,用:

y(k)=γ(k)xˆ(k)+β(k)

最终如果神经网络对γ(k)β(k)这两个参数训练出来的结果是
γ(k)=Var[x(k)]β(k)=E[x(k)]

那么就是神经网络训练这些参数后选择使得这一层的BN变成了一个恒等映射…




* 改善了神经网络中的梯度流
* 允许更高的learningrates
* 减少对initialization的严重依赖
* 一种特殊形式的的regularization,或许可以减少dropout的使用

在test中,有点不同,不会再对test set计算每一dimension的均值/方差,而是利用之前training训练的时候得到的均值/方差进行BN操作

Batch Normalization可以理解为在网络的每一层之前都做preprocess,只是这种操作以另一种方式与网络集成在了一起。添加BN层已经很常用了。

Regularization 正则化

L2 regularization L2正则化

12λw2

1/2是为了上式关于w的梯度为λw而不是2λw
L2 regularization可以认为是对大数值的weight vectors进行大的惩罚,倾向于更加分散的weight vectors。
由于输入x和权重W之间的乘法操作,使得网络更倾向于使用所有输入特征,而不是严重依赖于小部分输入特征。
然后在梯度下降和参数更新的时候,使用L2正则化意味着所有的权重都以W += -lambda * W向着0线性下降

L1 regularization L1正则化

λ|w|

Elastic net regularization:
λ1|w|+λ2w2

L1正则化会让weight vectors在最优化过程中变得稀疏(即非常接近0)。也就是说使用L1正则化的神经元最后使用的是他们最重要的输入数据的稀疏子集,同时对于噪声输入则几乎不变了。

L2正则化最后的weight vectors大多是分散的小数字 。在实际中如果不是特别关注某些明确的特征选择,一般来说L2正则化效果都会比L1正则化好

Max norm constraints 最大范式约束

另一种形式的正则化是给每个神经元中权重向量的量级设定上限,并使用投影梯度下降来确保这一约束。
在实践中,与之对应的是参数更新方式不变,然后要求神经元中的权重向量w⃗ 必须满足w⃗ 2<c。c通常值为3或4。
有人说使用这种正则化方法时效果更好。
这种正则化有一个好性质就是即使在learning rates设置过高的时候,网络中也不会出现数值“爆炸”。因为它的参数更新始终是被一个上限所限制的。

Dropout 随机失活

Dropout: A Simple Way to Prevent Neural Networks from Overfitting
dropout与L1正则化,L2正则化和最大范式约束等方法互为补充。

在训练的时候,随机失活的实现方法是让神经元以超参数p的概率被激活或者被设置为0。


dropout可以认为是整个neuralnetwork的采样,然后输入数据只用于更新采样网络。
数量巨大的子网络们并不是相互独立的,因为它们都共享参数。(这里数量巨大指的是子网络的选取有很多种组合…
测试过程中不使用随机失活,通过利用数量巨大的子网络的集合去估计一个平均的数据结果(讲得很拗口其实就是利用最后训练好的网络去估计结果….)

""" 普通版dropout做法:不推荐 """p = 0.5 # probability of keeping a unit active. higher = less dropoutdef 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的mask矩阵,然后应用。反向传播的过程基本不变,但也要把这个mask矩阵算进去
在predict函数中不进行dropout,但是隐层的输出都要乘以p。(因为predict的时候没有dropout,为了保持和训练时的预期输出一致必须乘上p)
上述操作不好的地方在于必须在测试时对激活数据要按照p进行数值范围调整。
所以就有了

inverted dropout 反向随机失活

它在训练的时候就已经进行数值范围调整,从而让前向传播在test中保持不变。这样做还有一个好处,无论你决定是否使用随机失活,预测方法的代码可以保持不变。

""" Inverted Dropout: 推荐实现的例子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 dropoutdef 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

视频中提到: inverted dropout和dropout 可能 是不等价的,因为网络里面可能有非线性函数

在卷积神经网络中,前面几层的unit被dropout的数量比较少,后面几层的unit被dropout得可能会比较多

前向传播中的噪音。在更一般化的分类上,随机失活属于网络在前向传播中有随机行为的方法。测试时,通过分析法(在使用随机失活的本例中就是乘以p)或数值法(例如通过抽样出很多子网络,随机选择不同子网络进行前向传播,最后对它们取平均)将噪音边缘化。在这个方向上的另一个研究是DropConnect,它在前向传播的时候,一系列权重被随机设置为0。提前说一下,卷积神经网络同样会吸取这类方法的优点,比如随机汇合(stochastic pooling),分级汇合(fractional pooling),数据增长(data augmentation)。我们在后面会详细介绍。

Bias regularization 偏差正则化

很少用,就算用了,由于biases的总量和W相比太少了,所以就算用了对结果的影响不大…

Per-layer regularization 每层正则化

对于不同的层进行不同强度的正则化很少见(可能除了输出层以外),关于这个思路的相关文献也很少。

总之,通过cross-validated交叉验证获得一个全局使用的L2正则化strength是比较常见的。在使用L2正则化的同时在所有层后面使用dropout也很常见。p值一般默认设为0.5,在cross-validated上调整这个参数也是可以的。

Loss Function

在数据的类总数很大的时候可以考虑Hierarchical Softmax

Attribute classification 属性分类

这里意思是指一张图片可能会有多个label,也就是多个属性,一个方法是为每个属性创建一个独立的binary classifier。例如,针对每个类的binary classifier会采用下面的公式:

Li=jmax(0,1yijfj)

第i个样本的第j个属性为yijyij的值为1或-1
正样本的scores值fj<1或负样本的scores值fj>1时,loss值会累积

逻辑回归

由于binary logistic regression只有两个类(0,1)

P(y=1x;w,b)=11+e(wTx+b)=σ(wTx+b)P(y=0x;w,b)=1P(y=1x;w,b)

如果σ(wTx+b)>0.5wTx+b>0的时候,样本被预测为正样本(y=1)

损失函数:

Li=jyijlog(σ(fj))+(1yij)log(1σ(fj))

yij有1(正样本)和0(负样本)两个值
导数为Li/fj=yijσ(fj)

L2范式和L1范式

L2范式:

Li=fyi22

L2范式梯度算起来比较简单
L1范式:
Li=fyi1=jfj(yi)j

如果有多个属性被预测了,就要对预测的所有维度的预测求和,即j

  • L2范式损失的最优化过程相比于Softmax要困难。L2范式需要网络对于每个输入(和增量)都输出一个确切的值。而在Softmax中每个评分的确切值并不是那么重要(只有当它们量级相当的时候才有意义)。
  • L2损失鲁棒性不好,因为异常值可以导致很大的梯度。
  • Classification还有一个额外优点,就是能给出关于regression的输出的分布,而不是一个简单的毫无把握的输出值。

所以在解决regression问题的时候先考虑输出成binary是否可行,如果确信Classification不适用,那使用L2损失。不过L2非常脆弱,因此在网络中使用dropout(尤其是在L2损失层的上一层)并不好。

当面对一个regression任务,首先考虑是不是必须这样。一般而言,尽量把你的输出变成二分类,然后对它们进行分类,从而变成一个分类问题。

Structured prediction 结构化预测

(CS231n中不做要求)

结构化损失是指标签可以是任意的结构,例如图表、树或者其他复杂物体的情况。通常这种情况还会假设结构空间非常巨大,不容易进行遍历。。结构化SVM背后的基本思想就是在正确的结构yi和得分最高的非正确结构之间画出一个边界。解决这类问题,并不是像解决一个简单无限制的最优化问题那样使用梯度下降就可以了,而是需要设计一些特殊的解决方案,这样可以有效利用对于结构空间的特殊简化假设。

参考资料:
https://zhuanlan.zhihu.com/p/21560667?refer=intelligentunit
https://cs231n.github.io/
http://cs231n.stanford.edu/slides/winter1516_lecture5.pdf

这次CS231n神经网络第二节中出现了很多论文,有时间的话就可以去翻翻

0 0
原创粉丝点击