CS231n第五课:神经网络2学习记录

来源:互联网 发布:redis存储数据大小 编辑:程序博客网 时间:2024/05/01 18:35

结合视频5和笔记:https://zhuanlan.zhihu.com/p/21560667?refer=intelligentunit

数据预处理

数据预处理的手段一般有:
· 去均值(mean subtraction)
· 规范化/归一化(normalization)
· 主成分分析(PCA)和白化(whitening)

这里写图片描述
这里写图片描述
这里写图片描述
PCA和白化(Whitening)是另一种预处理形式。在这种处理中,先对数据进行零中心化处理,然后计算协方差矩阵,它展示了数据中的相关性结构。

# 假设输入数据矩阵X的尺寸为[N x D]X -= np.mean(X, axis = 0) # 对数据进行零中心化(重要)cov = np.dot(X.T, X) / X.shape[0] # 得到数据的协方差矩阵

协方差计算公式:这里写图片描述
假设 X 是以 n 个标量随机变量组成的列向量,并且μk 是其第k个元素的期望值,即,μk= E[X(k)];协方差矩阵然后被定义为:
Σ=E 这里写图片描述
这里写图片描述
矩阵中的第(i,j)个元素是xi与xj的协方差

该矩阵的对角线上的元素是方差。还有,协方差矩阵是对称和半正定的。我们可以对数据协方差矩阵进行SVD(奇异值分解)运算。

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

SVD(奇异值分解):
http://blog.csdn.net/zhongkejingwang/article/details/43053513
http://blog.sina.com.cn/s/blog_3f738ee00102val0.html

这里写图片描述

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

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

实际上在卷积神经网络中并不会采用PCA和白化。然而对数据进行零中心化操作还是非常重要的,对每个像素进行归一化也很常见。

常见错误。进行预处理很重要的一点是:任何预处理策略(比如数据均值)都只能在训练集数据上进行计算,算法训练完毕后再应用到验证集或者测试集上。例如,如果先计算整个数据集图像的平均值然后每张图片都减去平均值,最后将整个数据集分成训练/验证/测试集,那么这个做法是错误的。应该怎么做呢?应该先分成训练/验证/测试集,只是从训练集中求图片平均值,然后各个集(训练/验证/测试集)中的图像再减去这个平均值。

权重初始化

错误:全零初始化:因为如果网络中的每个神经元都计算出同样的输出,然后它们就会在反向传播中计算出同样的梯度,从而进行同样的参数更新。换句话说,如果权重被初始化为同样的值,神经元之间就失去了不对称性的源头。
这里写图片描述
这里写图片描述
可见,全零会导致输出都为0,全1则神经元太快饱和,梯度也将趋向于0. 所以应该选择0-1之间的某个值。

小随机数初始化:通常我们会将权重随机初始化为:均值为0,标准差为一个很小的正数(如0.001)的高斯分布,在numpy中可以写成:w = np.random.randn(n)。这样的初始化方式对于小型的神经网络是可以的

但是对于深度神经网络,这样的初始化方式并不好。我们以激活函数为tanh为例,如果标准差设置得较小,后面层的激活值将全部趋于0,反向传播时梯度也会变的很小;如果我们将标准差设置得大些,神经元就会趋于饱和,梯度将会趋于零。

为了解决这个问题,我们可以使用方差校准技术:
· 实践经验告诉我们,如果每个神经元的输出都有着相似的分布会使收敛速度加快。而上面使用的随机初始化方式,会使得各个神经元的输出值的分布产生较大的变化。
· 抛开激活函数,我们假设神经元的带权输入这里写图片描述,则s和x的方差关系如下:
这里写图片描述
得到的结果显示,如果希望s与输入变量x同分布就需要使w的方差为1/n。即权重初始化方式改为:w = np.random.randn(n) / sqrt(n)。

使用1/sqrt(n)校准方差。上面做法存在一个问题,随着输入数据量的增长,随机初始化的神经元的输出数据的分布中的方差也在增大。我们可以除以输入数据量的平方根来调整其数值范围,这样神经元输出的方差就归一化到1了。也就是说,建议将神经元的权重向量初始化为:w = np.random.randn(n) / sqrt(n)。其中n是输入数据的数量。这样就保证了网络中所有神经元起始时有近似同样的输出分布。实践经验证明,这样做可以提高收敛的速度。

并给出结论:网络中神经元的方差应该是2.0/n。代码为w = np.random.randn(n) * sqrt(2.0/n)。这个形式是神经网络算法使用ReLU神经元时的当前最佳推荐。

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

偏置(biases)的初始化。通常将偏置初始化为0

批量归一化(Batch Normalization)
在每一层的wx+b和f(wx+b)之间加一个归一化(将wx+b归一化成:均值为0,方差为1(标准高斯分布))
这里写图片描述

这个方法可以进一步加速收敛,因此学习率可以适当增大,加快训练速度;过拟合现象可以得倒一定程度的缓解,所以可以不用Dropout或用较低的Dropout,而且可以减小L2正则化系数,训练速度又再一次得到了提升。即Batch Normalization可以降低我们对正则化的依赖程度。
现在的深度神经网络基本都会用到Batch Normalization。

正则化 Regularization
这里写图片描述

这里写图片描述

这里写图片描述
这里写图片描述
一个3层神经网络的普通版随机失活可以用下面代码实现:

""" 普通版随机失活: 不推荐实现 (看下面笔记) """p = 0.5 # 激活神经元的概率. p值更高 = 随机失活更弱def train_step(X):  """ X中是输入数据 """  # 3层neural network的前向传播  H1 = np.maximum(0, np.dot(W1, X) + b1)  U1 = np.random.rand(*H1.shape) < p # 第一个随机失活遮罩  H1 *= U1 # drop!  H2 = np.maximum(0, np.dot(W2, H1) + b2)  U2 = np.random.rand(*H2.shape) < p # 第二个随机失活遮罩  H2 *= U2 # drop!  out = np.dot(W3, H2) + b3  # 反向传播:计算梯度... (略)  # 进行参数更新... (略)def predict(X):  # 前向传播时模型集成  H1 = np.maximum(0, np.dot(W1, X) + b1) * p # 注意:激活数据要乘以p  H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # 注意:激活数据要乘以p  out = np.dot(W3, H2) + b3

这里写图片描述

上述操作不好的性质是必须在测试时对激活数据要按照p进行数值范围调整。既然测试性能如此关键,实际更倾向使用反向随机失活(inverted dropout),它是在训练时就进行数值范围调整,从而让前向传播在测试时保持不变。这样做还有一个好处,无论你决定是否使用随机失活,预测方法的代码可以保持不变。反向随机失活的代码如下:

作者:杜客链接:https://zhuanlan.zhihu.com/p/21560667来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。""" 反向随机失活: 推荐实现方式.在训练的时候drop和调整数值范围,测试时不做任何事."""p = 0.5 # 激活神经元的概率. p值更高 = 随机失活更弱def train_step(X):  # 3层neural network的前向传播  H1 = np.maximum(0, np.dot(W1, X) + b1)  U1 = (np.random.rand(*H1.shape) < p) / p # 第一个随机失活遮罩. 注意/p!  H1 *= U1 # drop!  H2 = np.maximum(0, np.dot(W2, H1) + b2)  U2 = (np.random.rand(*H2.shape) < p) / p # 第二个随机失活遮罩. 注意/p!  H2 *= U2 # drop!  out = np.dot(W3, H2) + b3  # 反向传播:计算梯度... (略)  # 进行参数更新... (略)def predict(X):  # 前向传播时模型集成  H1 = np.maximum(0, np.dot(W1, X) + b1) # 不用数值范围调整了  H2 = np.maximum(0, np.dot(W2, H1) + b2)  out = np.dot(W3, H2) + b3

损失函数

分类问题:当标签集非常庞大(例如字典中的所有英语单词,或者ImageNet中的22000种分类),就需要使用分层Softmax(Hierarchical Softmax)了。分层softmax将标签分解成一个树。每个标签都表示成这个树上的一个路径,这个树的每个节点处都训练一个Softmax分类器来在左和右分枝之间做决策。树的结构对于算法的最终结果影响很大,而且一般需要具体问题具体分析。

回归问题是预测实数的值的问题,比如预测房价,预测图片中某个东西的长度等。对于这种问题,通常是计算预测值和真实值之间的损失。然后用L2平方范式或L1范式度量差异

0 0
原创粉丝点击