一、写在前面
这里首先对上一篇内容的做一下更正与解释,上一篇的主要内容是使用2隐层的全连接网络来训练MNIST手写字体分类模型,但是由于一开始设计网络的时候,权重参数给定的值为0,于是在训练的过程中发现第一层隐层被设置为0的权重参数没有进行迭代更新,其它层级更新迭代的速度非常之慢,就误以为是单纯的由网络层级的加深导致的梯度消失问题,这里我们简单分析一下第一层隐层为0情况下的FP和BP过程。其中2隐层的节点数量都为64,且这里仅考虑SGD的情况。
二、FP过程
首先,输入层MNIST数据集的每张图片的像素值,我们输入一张图片,图片的大小为(1,784)然后到达第一层隐层,因为隐层的权重参数为0,则所有的输入值变为0,再加上偏置项0,然后经过sigmoid函数激活,然后每个输入值都会变为0.5,第一层隐层输出之后的形状为(1,64),且输出二维数据中的每个参数值都为0.5。
然后第一层的数据输出至第二层隐层,来自上一层0.5的输入乘以0依然是0,加上偏置项0后不变,然后再一次经过sigmoid函数激活,输出再一次的变为0.5,第二层隐层输出之后的形状为(1,64),同样的该层输出的二维数据中的每一个参数值为0.5。
之后便是由第二层隐层输出至输出层,来自上一层的0.5的输入乘以0依然为0,加上偏执项后不变,这里不需要激活,然后直接输出,输出结果为(1,10)的0张量。
最后,对输出的张量进行softmax转换,也就是将得分值转化为概率值,转换后的结果为(1,10)的数值为0.1的张量结果。然后通过交叉熵计算loss值(损失值),这里的损失值通过计算的结果为loss=3.321928094887362.
# _*_ coding:utf-8 _*_
import numpy as np
c=[0,0,0,0,0,0,0,0,0,0,0]
def softmax(list):
return np.exp([list[i] for i in range(10)])/np.sum([np.exp(list[i]) for i in range(10)])
print(softmax(c))
a=[0,1,0,0,0,0,0,0,0,0]
b=softmax(c)
print(np.mean(-np.sum(a*np.log2(b))))
三、BP过程
这里需要计算损失值loss对输出层和隐层的偏导数,值得注意的一点是,因为最后一层经过了softmax,所以w11(举例w11为相应层级的对应位置的参数)和其它所有输出层的节点有关系,所以loss在对w’11求偏导的时候,应对所有的out的输出整体求偏导之后求和。这里推荐大家看一下具体的计算方法。
总之,经过链式求导法则求出来的偏导数的值非常的小,再加上学习率的影响。梯度消失的情况会非常的明显,进而导致几乎全部的神经元死亡(弥散),下图分别展示迭代一个batch_size和迭代29次training_epochs的weights和b的变化情况。
由上图可以看出,w权重参数确实变化的程度非常之少,神经元确定已经死亡。
四、总结 不管在线性网络中间还是其它网络如CNN等的网络模型中间,初始化的值设置为0一定是个错误的选择,一般我们初始化权重参数选择使用均值为0,方差为输入数据的维度数的1/2来给定,一般这么给定是一个很优良的选择。
Tips:在深度学习的过程中对于代码的理解应该在原理的理解的基础上进行的,这要求我们拥有一些刨根问底的精神,并且还需要保持对代码的熟练度和加强对网络的计算推导能力,这样才能在之后的学习过程中保持出色的效果。