Deeplearning.ai第二门课第一周11-14笔记

1.11 神经网络的权重初始化

神经网络的参数初始化是很重要的一项能力,为了更好地理解它,我们首先举一个例子来说明它。
我们来看看只有一个神经元的状况。
Deeplearning.ai第二门课第一周11-14笔记
首先来看它的结构,输入有四个单元,输出y^\hat{y},而这里, z=w1x1+w2x2++wnxn\ z=w_1x_1+w_2x_2+…………+w_nx_n我们可以暂时忽略b对z的影响。所以z就变成了一个由w和x决定的数值,为了预防z过大或者过小,n越大,你希望相应的w越小。此时理所当然的想法是设置 w=1/n\ w = 1/n.
但其实实际上,你要做的就是设置某层权重矩阵 W\ W,用python来表示就是:
W = np.random.randn(shape func)*np.sqrt(1/(n^(l-1)))
这就是l层上拟合的单元数量。
但实验结果表明,如果你用的是Relu函数,也就是方差设置为2/n,效果会更好。不过这并没有完全解决初始化问题。如果**函数的输入特征被零均值化,方差就变成了1,这会是z也调整到相应的范围。 Relu\ Relu函数的使用,或者设置方差的操作,只是单纯降低了坡度消失和爆炸的问题出现概率。因为它给权重矩阵 W\ W设置了合理的初值。使得它的速度不会过快或者过慢。
当然还有其他的**函数,比如 Tanh\ Tanh函数,有篇论文证明上面的数字为1时效果会更好,也就是 Tanh=1n[l1]\ Tanh = \sqrt{\frac 1{n^{[l-1]}}}.这个过程叫做 Xavier\ Xavier初始化。
另一种方法是:2n[l1]+n[l]\sqrt{\frac 2{n^{[l-1]}+n^{[l]}}}.
如果你想使用 Relu\ Relu**函数,也是最常用的**函数,或者什么其他的函数,我认为这些所有的公式只是给了你一个起点,它们给出初始化权重矩阵的方差默认值,如果你想使用方差的话,方差参数将是另一个你需要调整的超级参数。你可以选择给根号下面的部分乘上一个数来作为超级参数的调优,但有时调优效果一般。考虑到它的不怎么重要性,我们一般把它的优先级放得比较低。

1.12 梯度的数值逼近

这一小节主要讲了双边误差相对于单边误差对于求梯度的效果更好。它的证明类似于导数定义,所以原谅刚考完复变的我在此就先略过了……
此处上图:
Deeplearning.ai第二门课第一周11-14笔记

1.13 梯度检验

吴老师说梯度检验在帮他检查backprop的bug方面有很大作用,我们来康一下吧(

为了实现梯度检验,首先要做的就是把所有参数转换成一个巨大的向量数据。
我们把 w[1],b[1],w[l],b[l]\ w^{[1]},b^{[1]},…… w^{[l]},b^{[l]}转成矩阵,再做连接运算,就会得到一个巨型向量θ\theta,代价函数J是所有W和b的函数,所以现在代价函数可以写成 J(θ)\ J(\theta)了。
根据上面的操作,你也同样可以把 dw[1],db[1],dw[l],db[l]\ dw^{[1]},db^{[1]},…… dw^{[l]},db^{[l]}转成矩阵做连接运算等等,用它来初始化向量dθd\theta,它与θ\theta有相同的维度。
根据我们所学到的知识,dθd\theta,也就是θ\theta的导数,跟θ\theta的梯度的值应该是一样的,或者说,是极度相似的。这就是实施梯度下降的方法了,我们通常称为“grad check".
为了实施梯度检验,你要做的就是循环执行,对于每一个 i,计算 Dθapprox[i]\ D\theta approx[i]的值,当然要使用双边误差的方法了(毕竟上节刚新鲜地证明完)。但每一次只对一个θ\theta做双边误差,也就是:
Deeplearning.ai第二门课第一周11-14笔记
而这个值,理论上是与当前点的导数值dθ[i]d\theta [i]相似。
我们所要做的就是,验证这些向量是否彼此接近。具体说来就是,计算这两个向量的距离,就是俩个向量之差的欧几里得范数(就是绝对值……我不太懂为什么字幕翻译要坚持用这个生僻而又装逼的描述),然后用向量长度做归一化,最后式子为:
DθapproxdθDθapprox+dθ\frac{|D\theta approx-d\theta|}{|D\theta approx|+|d\theta| }
之所以要做归一化处理,就是避免分子过大或者过小。正常的数据大约是 107\ 10^{-7}左右,如果是 105\ 10^{-5},那可能其中某一项存在问题,如果是 103\ 10^{-3},那么就大概是哪里存在bug了。
现在你已经知道了梯度检验的基本原理了,在第一遍跑完梯度检验之后,根据所得的值,会怀疑有相应的bug,然后开始调试调试调试,调试一段时间后,最后得到了一个很小的梯度检验值。等到最后的数据在大概 107\ 10^{-7}左右时,我就可以自信地说,我的神经网络实施是正确的。

1.14 关于梯度检验实现的注记

 Tip1\ Tip 1 梯度检验不要用于实际训练,只用于调试
用双边误差去计算每一个点的梯度是一个耗时非常长的运算,为了实施梯度下降,你必须用backprop来计算dθd\theta,只有在你验证时需要用到梯度检验,来一点点计算梯度是否贴近它。完成之后,你会关闭梯度检验,之后的每一个迭代过程都不执行它(因为实在是太慢了

 Tip2\ Tip 2 如果算法的梯度检验失败,要检查所有项,试着去定为bug的位置
如果dθd\theta Dθapprox\ D\theta approx的值相差过大,我们要做的就是查找不同的i值,看看是哪个导致 Dθapprox[i]\ D\theta approx[i] dθ[i]\ d\theta[i]的值相差这么多。

 Tip3\ Tip 3 如果在实施梯度检验中使用正则化,那么要注意一下正则项
记得在求取梯度和导数时,不要忘了加上正则项,否则会造成比较大的误差。

 Tip4\ Tip 4 梯度检验不能与dropout一同使用
因为在每次迭代过程中,dropout会随机消除隐层单元的不同子集,这会造成我们很难计算在梯度下降上的代价函数J。dropout就像是对函数单元做抽样,你无法保证在抽样过程中,你的代价函数J会保持相对稳定而精确的数值。所以很难用梯度检验来检验你dropout的计算是否精确。如果你非要这样做的话,那不妨把keep.prob设置为1,然后寄希望于你的dropout正确运行(

 Tip5\ Tip 5在随机初始化过程中,运行梯度检验
这当然不是在大多数情况下。在极少数情况下,backprop只在w和b接近于0的过程中效果比较好,在w和b越来越大的过程中,back prop会变得越来越不准确,这时候就要采取这种方法了。在随机初始化过程中,运行梯度检验,这样w和b会有一段时间远离0了。