一般RNN的输入为 X X X和历史状态 h t − 1 h_{t-1} ht−1,输出为当前状态 h t h_t ht和输出 Y Y Y。
在GRU中,首先计算得到两个门控信号,分别用于控制重置和更新,用sigmoid函数将输入映射到0-1之间,作为该信息的重要性分数,之后通过哈达玛乘积的方式对数据进行重要性控制。越重要的数据权重越大,留下的就越多。
r e s e t _ g a t e : r = σ ( W r ( X t ∣ ∣ H t − 1 ) ) u p d a t e _ g a t e : z = σ ( W z ( X t ∣ ∣ H t − 1 ) ) reset\_gate: \quad r=\sigma(W_r(X_t||H_{t-1})) \\ update\_gate: \quad z=\sigma(W_z(X_t||H_{t-1})) reset_gate:r=σ(Wr(Xt∣∣Ht−1))update_gate:z=σ(Wz(Xt∣∣Ht−1))
用重置门“重置”历史状态, h t − 1 ′ = h t − 1 ⊙ X t h_{t-1}'=h_{t-1}\odot X_t ht−1′=ht−1⊙Xt
然后拼接输入信号和历史状态,用tanh放松到-1~1之间, h ′ = t a n h ( W ( X t ∣ ∣ h t − 1 ′ ) ) h'=tanh(W(X_t||h_{t-1}')) h′=tanh(W(Xt∣∣ht−1′)),其中保存了X的信息,作为记忆体。
更新记忆阶段: h t = ( 1 − z ) ⊙ h t − 1 + z ⊙ h ′ h_t=(1-z)\odot h_{t-1}+z \odot h' ht=(1−z)⊙ht−1+z⊙h′,门控信号(这里的 [公式] )的范围为0~1。门控信号越接近1,代表”记忆“下来的数据越多;而越接近0则代表”遗忘“的越多。
最后的式子表示对历史隐藏状态的选择性遗忘,对当前节点信息的选择性记忆,即最终的结果包含忘记上一步传递来的某些信息和当前输入的某些信息的融合。
"""
gru模型定义:第一维表示input特征数,第二维表示隐层特征数,也是输出特征数,第三维表示gru单元个数
要求input维度是3维,第一维表示样本数,第二维表示batch数,第三维表示input特征数;
h维度,第一维同gru单元个数,第二维表示batch数,第三维表示隐层特征数
"""
import torch.nn as nn
import torch
rnn = nn.GRUCell(10, 1)
input = torch.randn(6, 3, 10)
hx = torch.randn(3, 1)
output = []
for i in range(6):
hx = rnn(input[i], hx) # (3,10) (3,1)
output.append(hx)
print(output[0].shape,len(output))
torch.Size([3, 1]) 6
# layer
rnn = nn.GRU(input_size=2, hidden_size=3, num_layers=4) # 2个输入特征,3个输出特征,4个GRU单元
ffn = nn.Linear(in_features=3, out_features=1)
# data
input = torch.randn(12,10,2) # 12个样本,10个batch,2个输入特征
# train
output, hn = rnn(input)
print(rnn,output.shape,hn.shape)
hn = ffn(hn)
hn.shape
GRU(2, 3, num_layers=4) torch.Size([12, 10, 3]) torch.Size([4, 10, 3])
torch.Size([4, 10, 1])
>>> rnn = nn.GRU(10, 20, 2) # 表示输入的特征为10个;隐藏状态的特征为20个,最后的2表示每次执行模型GRU的堆叠个数,默认是1
>>> input = torch.randn(5, 3, 10) # 表示模型的输入,有5条序列,每个序列有3个batch,每个XX有10个特征(也就是模型定义处的特征数)
>>> h0 = torch.randn(2, 3, 20) # 隐层的size,第一维特征表示GRU单元个数,20个特征即模型定义处的第二个特征数
>>> output, hn = rnn(input, h0) # 训练模型,将最后特征符合模型定义的数据输入,需要一个输入序列和隐层初始化向量
rnn,output.shape,hn.shape # 输出维度同输入维度
(GRU(10, 20, num_layers=2), torch.Size([5, 3, 20]), torch.Size([2, 3, 20]))
>>> rnn = nn.GRU(10, 20, 3) # 表示输入的特征为10个;隐藏状态的特征为20个,最后的2表示每次执行模型GRU的堆叠个数,默认是1
>>> input = torch.randn(64, 5, 10) # 表示模型的输入,有5条序列,每个序列有3个XX,每个XX有10个特征(也就是模型定义处的特征数)
>>> output, hn = rnn(input) # 训练模型,将最后特征符合模型定义的数据输入,需要一个输入序列和隐层初始化向量
rnn,output.shape,hn.shape # 输出维度同输入维度
(GRU(10, 20, num_layers=3), torch.Size([64, 5, 20]), torch.Size([3, 5, 20]))
rnn = nn.GRU(3, 2, 2) # input_size, hidden_size, num_layers
input = torch.randn(64, 3, 3) # input_shape = [时间步数, 批量大小, 特征维度]
h0 = torch.randn(2, 3, 2) # (层数, 批量大小,隐藏单元个数)
output, hn = rnn(input, h0)
print(output.shape) # torch.Size([5, 3, 20]) (64,3,2)
print(hn.shape) # torch.Size([2, 3, 20]) (2,3,2)
for param in rnn.parameters():
print(param)
print('param:',sum([param.nelement() for param in rnn.parameters()]))
class GRUModel(nn.Module):
def __init__(self, input_num, hidden_num, output_num):
super(GRUModel, self).__init__()
self.hidden_size = hidden_num
# 这里设置了 batch_first=True, 所以应该 inputs = inputs.view(inputs.shape[0], -1, inputs.shape[1])
# 针对时间序列预测问题,相当于将时间步(seq_len)设置为 1。
self.GRU_layer = nn.GRU(input_size=input_num, hidden_size=hidden_num, batch_first=True)
self.output_linear = nn.Linear(hidden_num, output_num)
self.hidden = None
def forward(self, x):
# h_n of shape (num_layers * num_directions, batch, hidden_size)
# 这里不用显式地传入隐层状态 self.hidden
x, self.hidden = self.GRU_layer(x)
x = self.output_linear(x)
return x, self.hidden
t1 = torch.zeros(1, 1)
t2 = torch.ones(1, 2)
print(torch.cat((t1, t2), -1).shape)
torch.Size([64, 3, 2])
torch.Size([2, 3, 2])
Parameter containing:
tensor([[-0.4385, -0.2698, 0.3349],
[-0.3022, 0.1954, 0.4030],
[-0.6135, -0.1722, 0.5763],
[ 0.6764, -0.1170, -0.0541],
[-0.2956, 0.0528, -0.3111],
[-0.0285, -0.1929, -0.6618]], requires_grad=True)
Parameter containing:
tensor([[ 0.2394, 0.1823],
[-0.5309, -0.0750],
[-0.7071, -0.5324],
[-0.5180, 0.6251],
[-0.5600, 0.6648],
[-0.2130, -0.5524]], requires_grad=True)
Parameter containing:
tensor([-0.0990, 0.0845, 0.1791, 0.6717, -0.1239, -0.3096],
requires_grad=True)
Parameter containing:
tensor([-0.4856, -0.2056, 0.5476, 0.0852, 0.2697, -0.5429],
requires_grad=True)
Parameter containing:
tensor([[-0.5405, 0.6149],
[-0.2233, -0.2913],
[ 0.0295, 0.3668],
[ 0.4580, 0.4449],
[-0.6158, -0.0386],
[ 0.3589, -0.7000]], requires_grad=True)
Parameter containing:
tensor([[-0.1134, 0.7012],
[-0.1659, 0.5221],
[-0.6751, -0.2485],
[-0.6934, -0.4501],
[ 0.5098, -0.5580],
[ 0.6155, 0.7004]], requires_grad=True)
Parameter containing:
tensor([-0.0764, -0.2113, -0.2269, 0.2555, -0.2457, -0.5794],
requires_grad=True)
Parameter containing:
tensor([-0.4711, -0.6222, 0.3527, 0.0559, 0.2789, -0.4424],
requires_grad=True)
78
torch.Size([1, 3])
人人都能看懂的GRU