RNN循环神经网络中的权重更新算法-BPTT

参考:

http://ir.hit.edu.cn/~jguo/docs/notes/bptt.pdf

http://www.cnblogs.com/wacc/p/5341670.html

https://zybuluo.com/hanbingtao/note/541458

http://www.wildml.com/2015/10/recurrent-neural-networks-tutorial-part-3-backpropagation-through-time-and-vanishing-gradients/

一段时间学习了ML的基础算法,但是对与DL没怎么接触,这次算首次触电吧。写的不足之处,请大家指正。

一、下图是对RNN的整体解析,大家应该比较熟悉了:

                                  

若我们以E表示交叉熵误差,V、W、U为各传递权重,则权重的更新算法为:

                                            V=V-lr \cdot \frac{\partial E}{\partial V}, W=W-lr \cdot \frac{\partial E}{\partial W},U=U-lr \cdot \frac{\partial E}{\partial U}

二、我们所用于分析权重梯度变化的无非用到里面的一个具体环节,现在把它形式化展现:

                                                  

此处的S_{t-1}表示t-1时刻的隐含层输出作为t时刻隐含层的输入,X_{t}表示t时刻的输入。net_t=S_{t-1} \cdot W+X_t \cdot U,代表前一时刻和本时刻输入的融合。设激活函数act=f(x),则有S_t=f(net_t);设输出层函数为g(x),则输出\hat{y_t} = g(VS_t)是输出标签。

若我们以E_t表示第t时刻的损失函数,并将其定义为交叉熵误差E_t=-y_{t}^Tlog(\hat{y_t})。那么整个序列的误差,就是所有时刻误差的总和。

三、下面,我们来展现权值更新的计算细节:

        self.calc_delta(sensitivity_array, activator)
        self.calc_gradient()
    def calc_delta(self, sensitivity_array, activator):
        self.delta_list = []  # 用来保存各个时刻的误差项
        for i in range(self.times):
            self.delta_list.append(np.zeros(
                (self.state_width, 1)))
				#对每一时刻的误差项进行初始化
        self.delta_list.append(sensitivity_array)
		#将sensitivity_array作为最后的误差项;就是t时刻的误差项delta
        for k in range(self.times - 1, 0, -1):
            self.calc_delta_k(k, activator)
			 # 迭代计算每个k时刻的误差项
			 
    def calc_delta_k(self, k, activator):
        '''
        根据k+1时刻的delta计算k时刻的delta
        '''
        state = self.state_list[k+1].copy()
        element_wise_op(self.state_list[k+1],
                    activator.backward)
					#对于k+1时刻的s状态,每个隐层中的s执行反向backward()操作,实际上得到上一时刻k对应的s状态state_list[k];
        self.delta_list[k] = np.dot(
            np.dot(self.delta_list[k+1].T, self.W),
            np.diag(state[:,0])).T
			# .T代表矩阵的转置

        计算每个时刻t权重的梯度
        '''
        gradient = np.dot(self.delta_list[t],
            self.state_list[t-1].T)
        self.gradient_list[t] = gradient
    def calc_gradient(self):
        self.gradient_list = [] # 保存各个时刻的权重梯度
        for t in range(self.times + 1):
            self.gradient_list.append(np.zeros(
                (self.state_width, self.state_width)))
        for t in range(self.times, 0, -1):
            self.calc_gradient_t(t)
        # 实际的梯度是各个时刻梯度之和
        self.gradient = reduce(
            lambda a, b: a + b, self.gradient_list,
            self.gradient_list[0]) # [0]被初始化为0且没有被修改过

 

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值