cs224n作业 神经网络前向传播后向传播
原来只是自己没有往后看,后面视频解释了前向和后向传播。
前向传播网络
一个简单的网络:
我看不懂这个红点图,同层神经元组与组之间的空格意味着什么?希望有大神赐教一下
后向传播网络
对于后向传播网络,从视频里的多种方式,我觉得最好理解的还是FLOW CHART,就是后向传播的时候,像流水一样一层一层的往后走。
核心:后向的时候记录下每一层的梯度,然后不断往后流动
看完(前两讲)视频做这个作业的时候,可卡住我好一会,这里特此记录一下。其实神经网络前向后向推导不难,难就在于网上很多教程没有把特征和维数讲清楚,以致于在具体写代码实现的过程中卡壳,同样也反映了自己目前思考问题还是平面,没有达到空间思考的程度。
其实首先不是去思考前向传播时什么,后向传播是什么,首先应该思考这每一层的维数,即shape是什么 。
基本定义:
激活函数:第一层为sigmod,第二层为softmax
n:样本数量
:第一层的特征数
H:第二层的特征数
:第三层的特征数
很明显,下图就存在这样的维度转化:
知道了具体的维度,然后我们来推前向和后向传播的公式
前向传播很容易理解,就是按照公式得到下一层结果,不需要求导什么的复杂公式。这里我们定义第一层是sigmod函数,第二层是softmax函数。
前向传播:
反向传播
反向传播实际上就是一系列的链式求导法则,这里有一些常识需要补充一下
:通常是代指整个公式中涉及到的所有参数的代名词,并不是指公式中真的需要有一个参数叫,比如说这里的W,b(代码里他们是放到一个数组里面,需要的时候再按需取不同位置的参数)
交叉熵函数:为什么使用交叉熵函数是有一番讲究的,我了解到的,一个是求导后的形式好用,另一个是求导后的导数比单纯L2变化更快。具体可以参考
这里反向传播没有用上正则项,后面用上了再补。
定义损失函数:
注意i是样本数,j是具体的特征维数,理解清楚这里的下标非常重要
我们先关注内层的求和公式,即交叉熵函数(因为外层的求和跟我们求导的参数其实无关,只是对各个样本求导后的平均值)
自己踩的一坑就是没有把形式写清楚就取摸索求导过程了,一开始应该先把形式过程写清楚
推导第二层:
推导第一层(形式是类似的),为什么叫反向传播,就是每一层推导都保存了$ \frac{\partial J}{\partial h$,方便下一层的推导
具体函数求导的过程这里不详细展开,主要说明一下,关于交叉熵函数的求导
这里的i和j都是指特征维数,这就导致对第k维进行求导的时候,会存在两种形式,一个可以忽略softmax的分子,一个不可以忽略
这里的i是指针对某一维的参数进行求导。
具体其他函数的求导过程可以百度,以下给出代码形式:
# 变量还是要写清楚维度,不然写代码的时候很容然忘记转置
#前向传播
layer1=np.dot(data,W1)+b1
layer1_a=sigmoid(layer1)
layer2=np.dot(layer1_a,W2)+b2
probs=softmax(layer2)
#后向传播
cost = -np.sum(np.sum(labels*np.log(probs),axis=1)) /N
#这里要注意矩阵乘法的时候就把n个样本的值加再一起了,所以不需要sum直接除N
gradW2=np.dot(layer1_a.T,probs-labels)/N
#这里要注意sum,因为损失函数还有外层对每个样本求导后的平均值
gradb2=np.sum((probs-labels),axis=0)/N
# 记录下当前层的导数,便于下一层计算
dlayer2=np.dot(probs-labels,W2.T)/N
dlayer1 = (1-layer1_a)*layer1_a*dlayer2
gradW1 = np.dot(data.T, dlayer1)
gradb1 = np.sum(dlayer1,axis =0)