GRU模型
GRU(Gated Recurrent Unit)也称门控循环单元结构, 它也是传统RNN的变体, 同LSTM一样能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆炸现象. 同时它的结构和计算要比LSTM更简单。
它的核心结构可以分为两个部分去解析:
- 更新门
- 重置门
GRU的内部结构图和计算公式
结构解释图:
GRU的更新门和重置门结构图:
内部结构分析
- 和之前分析过的LSTM中的门控一样, 首先计算更新门和重置门的门值, 分别是z(t)和r(t), 计算方法就是使用X(t)与h(t-1)拼接进行线性变换, 再经过sigmoid激活. 之后重置门门值作用在了h(t-1)上, 代表控制上一时间步传来的信息有多少可以被利用. 接着就是使用这个重置后的h(t-1)进行基本的RNN计算, 即与x(t)拼接进行线性变化, 经过tanh激活, 得到新的h(t). 最后更新门的门值会作用在新的h(t),而1-门值会作用在h(t-1)上, 随后将两者的结果相加, 得到最终的隐含状态输出h(t), 这个过程意味着更新门有能力保留之前的结果, 当门值趋于1时, 输出就是新的h(t), 而当门值趋于0时, 输出就是上一时间步的h(t-1).
- Bi-GRU与Bi-LSTM的逻辑相同, 都是不改变其内部结构, 而是将模型应用两次且方向不同, 再将两次得到的LSTM结果进行拼接作为最终输出. 具体参见上小节中的Bi-LSTM.
举例
'''
Description: GRU举例
Autor: 365JHWZGo
Date: 2021-12-10 11:02:58
LastEditors: 365JHWZGo
LastEditTime: 2021-12-10 11:21:06
'''
import torch
import torch.nn as nn
torch.manual_seed(1)
#hyper parameters
BATCH_SIZE = 3
SEQ_LEN = 2
HIDDEN_SIZE = 6
INPUT_SIZE = 5
NUM_LAYER = 1
NUM_DIRECTION = 1
input_data = torch.randn(BATCH_SIZE,SEQ_LEN,INPUT_SIZE)
h0 = torch.randn(NUM_LAYER*NUM_DIRECTION,BATCH_SIZE,HIDDEN_SIZE)
gru = nn.GRU(INPUT_SIZE,HIDDEN_SIZE,NUM_LAYER*NUM_DIRECTION,batch_first = True)
output,hn = gru(input_data,h0)
print(f'output:\t{output}')
print(f'hn:\t{hn}')
Run:
GRU的优势
- GRU和LSTM作用相同, 在捕捉长序列语义关联时, 能有效抑制梯度消失或爆炸, 效果都优于传统RNN且计算复杂度相比LSTM要小.
GRU的缺点
- GRU仍然不能完全解决梯度消失问题, 同时其作用RNN的变体, 有着RNN结构本身的一大弊端, 即不可并行计算, 这在数据量和模型体量逐步增大的未来, 是RNN发展的关键瓶颈.