神经网络与深度学习习题解答 改进神经网络的学习方法 最近在看 Michael Nielsen的Neural Networks and Deep Learning,这本书是以网页的形式放在网上,非常合适入门,附上传送地址:http:///chap1.html#learning_with_gradient_descent 国内哈工大社会计算与信息检索研究中心将这本书翻译成中文版放在网络上,地址为:https://hit-scir./neural-networks-and-deep-learning-zh_cn/content/chap1/c1s5.html 该章详细介绍交叉熵正则化等一系列可以对神经网络做改进的技巧和方法。下面给出该章习题 交叉熵部分
1. 高中导数知识
2. 这里注意y=0或者1,而激活值a一般只可能接近0或1。对于−[alny+(1−a)ln(1−y)],式子本身就不成立,lny在y=0处并没有定义,及时按照无限接近这样的思想来处理,lny在y=0处也趋近于无穷大,而a是一个比较小的定值,使得和的第一项趋近于无穷大,而和的第二项的ln(1-y)在y=0的时候为0,因而代价函数无穷大,这显然不是理想的结果。用−[ylna+(1−y)ln(1−a)]公式就没有这样的结果,因为y不是0就是1,整个代价函数也在0~1范围内并接近0。 3. 这个证明俨然一个导数的高考题啊,证明也比较简单。
假设可以通过选择一个合适的代价函数来消除 xj 项,此时对于同一个输出, 、...的计算结果均一致,甚至的变化率也和权重变化率一致,此时整个网络的所有参数将保持一致的变化率和变化趋势,这显然不符合神经网络更新权重的理想结果,也难以达到理想的目标。所以不可通过一个合适好的代价函数来消除 xj 项。 softmax网上关于softmax有一个很好的图来表示。带有softmax层的神经网络,每个神经元的输出均与所有的带权输入有关。
练习有如下:
1. 这样的例子很多,下面给出一个简单的例子。我们也可以这么假设,假设某种情况下满足激活值的和为1,那么此时调整其中一个神经元的偏置,该神经元的激活值就会改变,输出层激活值的和显然不为1了。
2. 按部就班求导就行。这里注意指数函数本身大于0的性质。
3. 见上文的图(*),显然softmax层的每个神经元的输出公式里包含了所有的带权输入。 4. 证明如下,因为已知激活值ajL,所以等式右边 ln 的那个式子是比依赖于 j 的常数,即为题目中所述的C。
5. 在很多资料中,神经网络中的log和ln似乎没有区分,计算均作为ln计算,求导都是倒数。该题求解见下图。其中参考了 https://blog.csdn.net/u014313009/article/details/51045303。这里表达式C写成累加和的形式是因为yi代表真实值,如果只预测一个结果,那个yi只有一种情况为1,所有表达式简写为 C = -ykln(ak),其中k是正确输出的结果。一般yk=1,那么就写成 C= -lna,即书中的形式。是不是感觉这里与交叉熵非常相似,书中明明说的是对log似然,或者说对数似然,但是这里却和交叉熵公式一致,我也有这样的困惑。查阅资料后,得知对数似然代价函数在多分类时可以化简为交叉熵代价函数的形式。来源为https:///post/5b38971be51d4558b10aad26#heading-11
6. softmax在有的译本中被翻译为柔性最大值,这里的柔性和变化率有关。图(4)已经给出了激活函数对于带权输入的偏导数,这也被直接用于图(6)中代价函数关于权重和偏置的变化率的证明中。对于式(83),因为多了c,该式求导后将要多出系数c,当c趋近于无穷,权重和偏置的变化率将非常大,c=1的时候变化率最小,可以认为使得函数变化变得柔和很多。 7. 这个证明和图(6)中的证明方法和过程均一致,emm就是一样的。不过这里还是写下 本章到该部分为止讲了交叉熵和softmax的原理和一些公式原理的推导和证明。这里注意两个组合,sigmoid激活函数和交叉熵代价函数的组合,以及softmax和log-likelihood (对数似然)代价函数的组合,两个组合都能有效解决学习速度下降的问题。关于二分类中交叉熵函数和log似然函数的总结,其他博客给出了比较好的解释
权重初始化
1. 权重初始化目的是为了让每一层的输出z(神经元前的那一项)和该层输出 x 保持一致的数据分布。权重初始化的方法是对权重的数据除以输入权重神经元个数的根号,即通过w=np.random.randn(n)/sqrt(n)来初始化。这个题目的证明需要注意 w 和 x 和 b 三个变量相互独立。过程见下图 其他改进神经网络方法的技术该节主要介绍了momentum及人工神经元的其他模型。momentum的公式如下,该方法引入了一个称为速度(velocity)的概念,梯度的作用是改变速度,而不是直接改变位置,另外,momentum方法引入了一种摩擦力的项,用来逐渐减少速度。如书中所述,这里需要注意变量之间的对应关系,速度变量 v = v1,v2,v3...其中每一个对应wj变量,我理解这里的 v 和 w 是维度和大小(shape)是一样的,即每个Wij都对应一个vij。
1. 这个µ类似于物理中的摩擦力,这里用来约束v的变化,µ=1时,没有摩擦,速度由▽C决定,速度每次都在叠加,梯度下降的速度将比正常的梯度下降速度快很多;µ=0时,存在很大的摩擦,速度无法叠加,这个时候就等同于通常所说的梯度下降。在实践中,使用0和1之间的µ值可以为我们避免过量而又能够叠加速度的好处。 那么 µ > 1或者 µ < 0有什么问题呢,显然,作为摩擦力来理解的话,µ > 1就是凭空出现v的叠加,可以理解在完全光滑的平面上一个物体不受外力作用速度却在增加,这就使得梯度下降几乎不受控制一直增大,及时▽C反向也不能阻止w向一个方向更新,最后w越来越大,越来越大(或者越来越小)...效果在达到最优之后越过,从而越来越差。当µ < 0时,可以认为摩擦力太大,大到摩擦力竟然比物体本身的重量还要大,相当于给物体一个额外的向下的压力,此时,参数更新不是叠加地增加了,是叠加的减少,即梯度下降一开始朝一个方向,但momentum 会使得梯度下降比常规的梯度下降更慢,甚者,在▽C最小(约为0),即达到最优的时候,权重开始反向改变,始终无法停留在最优处。 2. 根据公式感觉这个代码还是比较好改的,真正改的时候对于变量的类型和维度还是要考虑一些地方。如下在 update_mini_batch函数的参数更新的地方做了修改。
注意这里多了 momentum以及self.vs,前者传递的是公式(107)的µ,后者存储的是公式(107)的v。这里的self.vs和self.weights存储类型一致,其为list类型,list的每个元素是一个矩阵,存储的是每个权重wij的变化速率。而该速率初始化为0,因而default_weight_initializer函数也加了self.vs的初始化。
之后记得在SGD函数和update_mini_batch函数的参数传递里加上momentum就行了。另外,我这样的修改方法没有考虑到正则化,如果需要还需要另行添加。 3. 公式证明比较简单 |
|