GRU(Gated Recurrent Unit) 更新过程推导及简单代码实现
GRU(Gated Recurrent Unit) 更新过程推导及简单代码实现
RNN网络考虑到了具有时间数列的样本数据,但是RNN仍存在着一些问题,比如随着时间的推移,RNN单元就失去了对很久之前信息的保存和处理的能力,而且存在着gradient vanishing问题。
所以有些特殊类型的RNN网络相继被提出,比如LSTM(long short term memory)和GRU(gated recurrent unit)(Chao,et al. 2014).这里我主要推导一下GRU参数的迭代过程
GRU单元结构如下图所示
数据流过程如下
其中表示Hadamard积,即对应元素乘积;下标表示节点的index,上标表示时刻;表示隐层到输出层的参数矩阵,分别是隐层和输出层的节点个数;分别表示输入和上一时刻隐层到更新门z的连接矩阵,表示输入数据的维度;分别表示输入和上一时刻隐层到重置门r的连接矩阵;分别表示输入和上一时刻的隐层到待选状态的连接矩阵。
针对于时刻t,使用链式求导法则,计算参数矩阵的梯度,其中E是代价函数,首先计算对隐层输出的梯度,因为隐层输出牵涉到多个时刻
所以
其中分别是对应激活函数的线性和部分
现在对参数计算梯度
令
则
将上面的式子矢量化(行向量)表示:
那接下来使用matlab来实现一个小例子,看看GRU的效果,同样是二进制相加的问题
- function error= GRUtest( )
- % 初始化训练数据
- uNum=16;%单元个数
- maxInt=2^uNum;
- % 初始化网络结构
- xdim=2;
- ydim=1;
- hdim=16;
- eta=0.1;
- %初始化网络参数
- Wy=rand(hdim,ydim)*2-1;
- Wr=rand(xdim,hdim)*2-1;
- Ur=rand(hdim,hdim)*2-1;
- W =rand(xdim,hdim)*2-1;
- U =rand(hdim,hdim)*2-1;
- Wz=rand(xdim,hdim)*2-1;
- Uz=rand(hdim,hdim)*2-1;
- rvalues=zeros(uNum+1,hdim);
- zvalues=zeros(uNum+1,hdim);
- hbarvalues=zeros(uNum,hdim);
- hvalues = zeros(uNum,hdim);
- yvalues=zeros(uNum,ydim);
- for p=1:10000
- aInt=randi(maxInt/2);
- bInt=randi(maxInt/2);
- cInt=aInt+bInt;
- at=dec2bin(aInt)-'0';
- bt=dec2bin(bInt)-'0';
- ct=dec2bin(cInt)-'0';
- a=zeros(1,uNum);
- b=zeros(1,uNum);
- c=zeros(1,uNum);
- a(1:size(at,2))=at(end:-1:1);
- b(1:size(bt,2))=bt(end:-1:1);
- c(1:size(ct,2))=ct(end:-1:1);
- xvalues=[a;b]';
- d=c';
- % 前向计算
- rvalues(1,:)=sigmoid(xvalues(1,:)*Wr);
- hbarvalues(1,:)=outTanh(xvalues(1,:)*W);
- zvalues(1,:)=sigmoid(xvalues(1,:)*Wz);
- hvalues(1,:)=zvalues(1,:).*hbarvalues(1,:);
- yvalues(1,:)=sigmoid(hvalues(1,:)*Wy);
- for t=2:uNum
- rvalues(t,:)=sigmoid(xvalues(t,:)*Wr+hvalues(t-1,:)*Ur);
- hbarvalues(t,:)=outTanh(xvalues(t,:)*W+(rvalues(t,:).*hvalues(t-1,:))*U);
- zvalues(t,:)=sigmoid(xvalues(t,:)*Wz+hvalues(t-1,:)*Uz);
- hvalues(t,:)=(1-zvalues(t,:)).*hvalues(t-1,:)+zvalues(t,:).*hbarvalues(t,:);
- yvalues(t,:)=sigmoid(hvalues(t,:)*Wy);
- end
- % 误差反向传播
- delta_r_next=zeros(1,hdim);
- delta_z_next=zeros(1,hdim);
- delta_h_next=zeros(1,hdim);
- delta_next=zeros(1,hdim);
- dWy=zeros(hdim,ydim);
- dWr=zeros(xdim,hdim);
- dUr=zeros(hdim,hdim);
- dW=zeros(xdim,hdim);
- dU=zeros(hdim,hdim);
- dWz=zeros(xdim,hdim);
- dUz=zeros(hdim,hdim);
- for t=uNum:-1:2
- delta_y=(yvalues(t,:)-d(t,:)).*diffsigmoid(yvalues(t,:));
- delta_h=delta_y*Wy'+delta_z_next*Uz'+delta_next*U'.*rvalues(t+1,:)+delta_r_next*Ur'+delta_h_next.*(1-zvalues(t+1,:));
- delta_z=delta_h.*(hbarvalues(t,:)-hvalues(t-1,:)).*diffsigmoid(zvalues(t,:));
- delta =delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:));
- delta_r=hvalues(t-1,:).*((delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:)))*U').*diffsigmoid(rvalues(t,:));
- dWy=dWy+hvalues(t,:)'*delta_y;
- dWz=dWz+xvalues(t,:)'*delta_z;
- dUz=dUz+hvalues(t-1,:)'*delta_z;
- dW =dW+xvalues(t,:)'*delta;
- dU =dU+(rvalues(t,:).*hvalues(t-1,:))'*delta ;
- dWr=dWr+xvalues(t,:)'*delta_r;
- dUr=dUr+hvalues(t-1,:)'*delta_r;
- delta_r_next=delta_r;
- delta_z_next=delta_z;
- delta_h_next=delta_h;
- delta_next =delta;
- end
- t=1;
- delta_y=(yvalues(t,:)-d(t,:)).*diffsigmoid(yvalues(t,:));
- delta_h=delta_y*Wy'+delta_z_next*Uz'+delta_next*U'.*rvalues(t+1,:)+delta_r_next*Ur'+delta_h_next.*(1-zvalues(t+1,:));
- delta_z=delta_h.*(hbarvalues(t,:)-0).*diffsigmoid(zvalues(t,:));
- delta =delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:));
- delta_r=0.*((delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:)))*U').*diffsigmoid(rvalues(t,:));
- dWy=dWy+hvalues(t,:)'*delta_y;
- dWz=dWz+xvalues(t,:)'*delta_z;
- dW =dW+xvalues(t,:)'*delta;
- dWr=dWr+xvalues(t,:)'*delta_r;
- Wy = Wy-eta*dWy;
- Wr = Wr-eta*dWr;
- Ur = Ur-eta*dUr;
- W = W -eta*dW;
- U = U-eta*dU;
- Wz = Wz-eta*dWz;
- Uz = Uz-eta*dUz;
- error = (norm(yvalues-d,2))/2.0;
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- if mod(p,500)==0
- fprintf('******************第%s次迭代****************\n',int2str(p));
- yvalues=round(yvalues(end:-1:1));
- y=bin2dec(int2str(yvalues'));
- fprintf('y=%d\n',y);
- fprintf('c=%d\n',cInt);
- fprintf('样本误差:e=%f\n',error);
- end
- end
- end
- function f=sigmoid(x)
- f=1./(1+exp(-x));
- end
- function fd = diffsigmoid(f)
- fd=f.*(1-f);
- end
- function g=outTanh(x)
- g=1-2./(1+exp(2*x));
- end
- function gd=diffoutTanh(g)
- gd=1-g.^2;
- end
部分实验结果
GRU(Gated Recurrent Unit) 更新过程推导及简单代码实现的更多相关文章
- Gated Recurrent Unit (GRU)
Gated Recurrent Unit (GRU) Outline Backgr ...
- Gated Recurrent Unit (GRU)公式简介
update gate $z_t$: defines how much of the previous memory to keep around. \[z_t = \sigma ( W^z x_t+ ...
- pytorch_SRU(Simple Recurrent Unit)
导读 本文讨论了最新爆款论文(Training RNNs as Fast as CNNs)提出的LSTM变种SRU(Simple Recurrent Unit),以及基于pytorch实现了SRU,并 ...
- Simple Recurrent Unit,单循环单元
SRU(Simple Recurrent Unit),单循环单元 src/nnet/nnet-recurrent.h 使用Tanh作为非线性单元 SRU不保留内部状态 训练时,每个训练序列以零向量开始 ...
- php网页,想弹出对话框, 消息框 简单代码
php网页,想弹出对话框, 消息框 简单代码 <?php echo "<script language=\"JavaScript\">alert(\&q ...
- C# 客服端上传文件与服务器器端接收 (简单代码)
简单代码: /*服务器端接收写入 可以实现断点续传*/ public string ConnectUpload(string newfilename,string filepath,byte[] fi ...
- Redis:安装、配置、操作和简单代码实例(C语言Client端)
Redis:安装.配置.操作和简单代码实例(C语言Client端) - hj19870806的专栏 - 博客频道 - CSDN.NET Redis:安装.配置.操作和简单代码实例(C语言Client端 ...
- 1 go 开发环境搭建与简单代码实现
什么是go语言 go是一门并发支持,垃圾回收的编译型 系统编程语言,旨在创造一门具有静态编译语言的高性能和动态语言的高效开发之间拥有一个良好平衡点 的一门编程语言. go有什么优点? 自动垃圾回收机制 ...
- 使用WinSCP进行简单代码文件同步
前言传输协议FTPFTPSSFTPSCP为什么使用WinSCP?CMD的FTP命令FileZillaPuTTYrsyncSublime的SFTP插件WinSCPWinSCP进行简单代码文件同步总结备注 ...
随机推荐
- MySQL报错:Got error 28 from storage engine
今天碰到数据库出错: Got error 28 from storage engine 查了一下,数据库文件所在的盘应该没事,应该是数据库用的临时目录空间不够 问题原因: 磁盘临时空间不够导致. 解决 ...
- 第3月第23天 EAIntroView
1. EAIntroView,界面和模型分离.EAIntroPage数据模型,EAIntroView界面. https://github.com/ealeksandrov/EAIntroView
- 【Android】Android如何一进入一个activity就弹出输入法键盘
在AndroidManife.xml中的Activity配置中加入 android:windowSoftInputMode="stateVisible|adjustResize"
- Yii2 assets注册的css样式文件没有加载
准备引入layui.css文件的,在LayuiAssets类中已经配置了资源属性 <?php namespace frontend\assets; use yii\web\AssetBundle ...
- MFC双缓存技术代码
屏蔽背景刷新,在View中添加对WM_ERASEBKGND的响应,直接返回TRUE: BOOL CTEMV1View::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息 ...
- 委托、Lambda表达式和事件
1.1 引用方法 委托是寻址方法的 .NET 版本.委托是类型安全的类.它定义了返回类型和参数的类型.委托类不仅包含对方法的引用,也可以包含对多个方法的引用. Lambda 表达式 ...
- JSPatch热更新的利器.
如果用一句话来描述JSPatch,就是利用系统自带的JavaScriptCore.framework配合RunTime机制,进行实时的代码下载与运行.. 而且使用也很简单,启动,加载JS,运行... ...
- c#和js互通的AES加密解密
一.使用场景 在使用前后端分离的框架中常常会进行传输数据相互加密解密以确保数据的安全性,如web Api返回加密数据客户端或web端进行解密,或者客户端或web端进行加密提交数据服务端解密数据等等. ...
- 更改WAS Profiles的概要文件的server1的SDK版本
WebSphere只能使用IBM JDK 哦,不能使用sun的JDK哦.不过如果只是改jdk的版本的话可以参考如下步骤:(以集群为例,假设具有管理节点Dmgr01,应用概要AppSrv01) 1. 确 ...
- C# IEnumberable & IQueryable 区别
转自 http://blog.csdn.net/daimeisi123/article/details/46976093 在应用到IEnumberable 和IQueryable两个接口时,代码往往很 ...