GRU(Gated Recurrent Unit) 更新过程推导及简单代码实现

RNN
GRU
matlab codes

RNN网络考虑到了具有时间数列的样本数据,但是RNN仍存在着一些问题,比如随着时间的推移,RNN单元就失去了对很久之前信息的保存和处理的能力,而且存在着gradient vanishing问题。

所以有些特殊类型的RNN网络相继被提出,比如LSTM(long short term memory)和GRU(gated recurrent unit)(Chao,et al. 2014).这里我主要推导一下GRU参数的迭代过程

GRU单元结构如下图所示

1479126283494.jpg

数据流过程如下

其中表示Hadamard积,即对应元素乘积;下标表示节点的index,上标表示时刻;表示隐层到输出层的参数矩阵,分别是隐层和输出层的节点个数;分别表示输入和上一时刻隐层到更新门z的连接矩阵,表示输入数据的维度;分别表示输入和上一时刻隐层到重置门r的连接矩阵;分别表示输入和上一时刻的隐层到待选状态的连接矩阵。

针对于时刻t,使用链式求导法则,计算参数矩阵的梯度,其中E是代价函数,首先计算对隐层输出的梯度,因为隐层输出牵涉到多个时刻

所以

其中分别是对应激活函数的线性和部分

现在对参数计算梯度

将上面的式子矢量化(行向量)表示:

那接下来使用matlab来实现一个小例子,看看GRU的效果,同样是二进制相加的问题

  1. function error= GRUtest( ) 

  2. % 初始化训练数据 

  3. uNum=16;%单元个数 

  4. maxInt=2^uNum; 

  5. % 初始化网络结构 

  6. xdim=2; 

  7. ydim=1; 

  8. hdim=16; 

  9. eta=0.1; 

  10. %初始化网络参数 

  11. Wy=rand(hdim,ydim)*2-1; 

  12. Wr=rand(xdim,hdim)*2-1; 

  13. Ur=rand(hdim,hdim)*2-1; 

  14. W =rand(xdim,hdim)*2-1; 

  15. U =rand(hdim,hdim)*2-1; 

  16. Wz=rand(xdim,hdim)*2-1; 

  17. Uz=rand(hdim,hdim)*2-1; 


  18. rvalues=zeros(uNum+1,hdim); 

  19. zvalues=zeros(uNum+1,hdim); 

  20. hbarvalues=zeros(uNum,hdim); 

  21. hvalues = zeros(uNum,hdim); 

  22. yvalues=zeros(uNum,ydim); 


  23. for p=1:10000 

  24. aInt=randi(maxInt/2); 

  25. bInt=randi(maxInt/2); 

  26. cInt=aInt+bInt; 

  27. at=dec2bin(aInt)-'0'; 

  28. bt=dec2bin(bInt)-'0'; 

  29. ct=dec2bin(cInt)-'0'; 

  30. a=zeros(1,uNum); 

  31. b=zeros(1,uNum); 

  32. c=zeros(1,uNum); 

  33. a(1:size(at,2))=at(end:-1:1); 

  34. b(1:size(bt,2))=bt(end:-1:1); 

  35. c(1:size(ct,2))=ct(end:-1:1); 

  36. xvalues=[a;b]'; 

  37. d=c'; 


  38. % 前向计算 

  39. rvalues(1,:)=sigmoid(xvalues(1,:)*Wr); 

  40. hbarvalues(1,:)=outTanh(xvalues(1,:)*W); 

  41. zvalues(1,:)=sigmoid(xvalues(1,:)*Wz); 

  42. hvalues(1,:)=zvalues(1,:).*hbarvalues(1,:); 

  43. yvalues(1,:)=sigmoid(hvalues(1,:)*Wy); 

  44. for t=2:uNum 

  45. rvalues(t,:)=sigmoid(xvalues(t,:)*Wr+hvalues(t-1,:)*Ur); 

  46. hbarvalues(t,:)=outTanh(xvalues(t,:)*W+(rvalues(t,:).*hvalues(t-1,:))*U); 

  47. zvalues(t,:)=sigmoid(xvalues(t,:)*Wz+hvalues(t-1,:)*Uz); 

  48. hvalues(t,:)=(1-zvalues(t,:)).*hvalues(t-1,:)+zvalues(t,:).*hbarvalues(t,:); 

  49. yvalues(t,:)=sigmoid(hvalues(t,:)*Wy);  

  50. end 


  51. % 误差反向传播 

  52. delta_r_next=zeros(1,hdim); 

  53. delta_z_next=zeros(1,hdim); 

  54. delta_h_next=zeros(1,hdim); 

  55. delta_next=zeros(1,hdim); 


  56. dWy=zeros(hdim,ydim); 

  57. dWr=zeros(xdim,hdim); 

  58. dUr=zeros(hdim,hdim); 

  59. dW=zeros(xdim,hdim); 

  60. dU=zeros(hdim,hdim); 

  61. dWz=zeros(xdim,hdim); 

  62. dUz=zeros(hdim,hdim); 


  63. for t=uNum:-1:2 

  64. delta_y=(yvalues(t,:)-d(t,:)).*diffsigmoid(yvalues(t,:)); 

  65. 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,:)); 

  66. delta_z=delta_h.*(hbarvalues(t,:)-hvalues(t-1,:)).*diffsigmoid(zvalues(t,:)); 

  67. delta =delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:)); 

  68. delta_r=hvalues(t-1,:).*((delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:)))*U').*diffsigmoid(rvalues(t,:)); 


  69. dWy=dWy+hvalues(t,:)'*delta_y; 

  70. dWz=dWz+xvalues(t,:)'*delta_z; 

  71. dUz=dUz+hvalues(t-1,:)'*delta_z; 

  72. dW =dW+xvalues(t,:)'*delta; 

  73. dU =dU+(rvalues(t,:).*hvalues(t-1,:))'*delta ; 

  74. dWr=dWr+xvalues(t,:)'*delta_r; 

  75. dUr=dUr+hvalues(t-1,:)'*delta_r; 


  76. delta_r_next=delta_r; 

  77. delta_z_next=delta_z; 

  78. delta_h_next=delta_h; 

  79. delta_next =delta; 


  80. end 


  81. t=1; 

  82. delta_y=(yvalues(t,:)-d(t,:)).*diffsigmoid(yvalues(t,:)); 

  83. 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,:)); 

  84. delta_z=delta_h.*(hbarvalues(t,:)-0).*diffsigmoid(zvalues(t,:)); 

  85. delta =delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:)); 

  86. delta_r=0.*((delta_h.*zvalues(t,:).*diffoutTanh(hbarvalues(t,:)))*U').*diffsigmoid(rvalues(t,:)); 


  87. dWy=dWy+hvalues(t,:)'*delta_y; 

  88. dWz=dWz+xvalues(t,:)'*delta_z; 

  89. dW =dW+xvalues(t,:)'*delta; 

  90. dWr=dWr+xvalues(t,:)'*delta_r; 


  91. Wy = Wy-eta*dWy; 

  92. Wr = Wr-eta*dWr; 

  93. Ur = Ur-eta*dUr; 

  94. W = W -eta*dW; 

  95. U = U-eta*dU; 

  96. Wz = Wz-eta*dWz; 

  97. Uz = Uz-eta*dUz; 

  98. error = (norm(yvalues-d,2))/2.0; 

  99. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

  100. if mod(p,500)==0 

  101. fprintf('******************第%s次迭代****************\n',int2str(p)); 

  102. yvalues=round(yvalues(end:-1:1)); 

  103. y=bin2dec(int2str(yvalues')); 

  104. fprintf('y=%d\n',y); 

  105. fprintf('c=%d\n',cInt); 

  106. fprintf('样本误差:e=%f\n',error); 

  107. end 

  108. end 

  109. end 


  110. function f=sigmoid(x) 

  111. f=1./(1+exp(-x)); 

  112. end 


  113. function fd = diffsigmoid(f) 

  114. fd=f.*(1-f); 

  115. end 


  116. function g=outTanh(x) 

  117. g=1-2./(1+exp(2*x)); 

  118. end 


  119. function gd=diffoutTanh(g) 

  120. gd=1-g.^2; 

  121. end 

部分实验结果

1479392393541.jpg

GRU(Gated Recurrent Unit) 更新过程推导及简单代码实现的更多相关文章

  1. Gated Recurrent Unit (GRU)

                                   Gated Recurrent Unit (GRU) Outline                             Backgr ...

  2. 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+ ...

  3. pytorch_SRU(Simple Recurrent Unit)

    导读 本文讨论了最新爆款论文(Training RNNs as Fast as CNNs)提出的LSTM变种SRU(Simple Recurrent Unit),以及基于pytorch实现了SRU,并 ...

  4. Simple Recurrent Unit,单循环单元

    SRU(Simple Recurrent Unit),单循环单元 src/nnet/nnet-recurrent.h 使用Tanh作为非线性单元 SRU不保留内部状态 训练时,每个训练序列以零向量开始 ...

  5. php网页,想弹出对话框, 消息框 简单代码

    php网页,想弹出对话框, 消息框 简单代码 <?php echo "<script language=\"JavaScript\">alert(\&q ...

  6. C# 客服端上传文件与服务器器端接收 (简单代码)

    简单代码: /*服务器端接收写入 可以实现断点续传*/ public string ConnectUpload(string newfilename,string filepath,byte[] fi ...

  7. Redis:安装、配置、操作和简单代码实例(C语言Client端)

    Redis:安装.配置.操作和简单代码实例(C语言Client端) - hj19870806的专栏 - 博客频道 - CSDN.NET Redis:安装.配置.操作和简单代码实例(C语言Client端 ...

  8. 1 go 开发环境搭建与简单代码实现

    什么是go语言 go是一门并发支持,垃圾回收的编译型 系统编程语言,旨在创造一门具有静态编译语言的高性能和动态语言的高效开发之间拥有一个良好平衡点 的一门编程语言. go有什么优点? 自动垃圾回收机制 ...

  9. 使用WinSCP进行简单代码文件同步

    前言传输协议FTPFTPSSFTPSCP为什么使用WinSCP?CMD的FTP命令FileZillaPuTTYrsyncSublime的SFTP插件WinSCPWinSCP进行简单代码文件同步总结备注 ...

随机推荐

  1. android中xml tools属性详解

    第一部分 安卓开发中,在写布局代码的时候,ide可以看到布局的预览效果. 但是有些效果则必须在运行之后才能看见,比如这种情况:TextView在xml中没有设置任何字符,而是在activity中设置了 ...

  2. Windows无线网“无法连接到这个网络”的解决办法

    最近我的笔记本(Win10系统)连接无线网时总是出现"无法连接到这个网络"的错误.为此折腾了一天,通过各种百度,终于找到了适合我的解决办法,在此记录一下. 问题描述 最近因为宿舍的 ...

  3. Java中的24种设计模式与7大原则

    一.创建型模式 1.抽象工厂模式(Abstract factory pattern): 提供一个接口, 用于创建相关或依赖对象的家族, 而不需要指定具体类.2.生成器模式(Builder patter ...

  4. python3 -pip

    https://docs.python.org/3/installing/ ===== pip is the preferred installer program. Starting with Py ...

  5. android 4.4/5.1上使用aar的问题

    在Android6.0上可以使用LOCAL_STATIC_JAVA_AAR_LIBRARIES.build脚本会把指定的aar解压缩到临时目录,并将class.jar和res添加到对应的变量. LOC ...

  6. 解决自定义Shiro.Realm扩展类不能用注解(@Resource或@Autowire)自动装配的问题

    问题产生原因:加载Realm时其他Spring配置文件(xml)尚未加载,导致注入失败. 解决方法:编写一个设置类把注入工作提前完成. package com.xkt.shiro import org ...

  7. js方法入参或局部变量和全局变量重名,用来赋值全局变量会失败

    今天遇到个bug,最后终于知道原因了,js方法入参和全局变量重名,用入参赋值全局变量失败,就是说方法入参不能和全局变量重名. 现在下面的例子也说明,局部变量和全局变量不可以同名不光是入参,只要同名赋值 ...

  8. ionic使用方法

    windows下安装配置 npm install -g ionic npm install -g cordova ionic start myproject cd myproject ionic pl ...

  9. mysql 分页查询

    mysql,; : mysql,; -last. //如果只给定一个参数,它表示返回最大的记录行数目: mysql; 个记录行 ,n. 动态传参的分页查询 SELECT * FROM table LI ...

  10. Div 定时移动

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...