一、GRU  

1.1、解释

        GRU也是RNN的一种变体,也是为了解决RNN长期依赖问题,但它的结构 比LSTM更简单高效。

        GRU使用了门的结构而对比LSTM,GRU门结构的 数量会少一些,这就使它的结构更简单。GRU只有两个门结构,一个是更 新门一个是重置门,其次是GRU没有了记忆单元C 。

GRU 

 STML

1.2、更新门(update gate)

        沿着红色的线往回看,这个门就是由上一时间步h_t-1和当前时间x_t决定的。 接着看一下它与谁相乘,可以看到一方面它和h分支进行相乘,另一方面是 与tanh的结果相乘,但两种乘的方式不一样,与隐藏状态是经过1-之后相 乘而与tanh结果是直接相乘,这里很好理解,对于隐藏状态我们希望模型 遗忘掉一些没用的而希望在当前状态下保留一些有用的,可以看到‘遗 忘’和‘保留’实际上就是一个对立事件,而我们之前说过sigmoid的结果介于 0和1之间表示一种概率或程度,那可以理解为你有多大的概率保留就应该 有1-多大概率遗忘。

1.3、重置门(reset gate)

        还是先看sigmoid找到门,然后沿着线往后看这个门是由谁决定,可以看到 重置门依然是由上一时间步h_t-1和当前时间x_t决定的。 接着看sigmoid的结果与谁相乘,可以看到是与上一时间步 h_t-1相乘,那它 表示的含义自然就是在过去的信息中获取一定程度的信息了。

1.4、 更新过程(update)

        在每个时间步t ,模型接收输入x_t和上一时间步的隐藏状态h_t-1 。首先, 通过重置门(reset gate)决定如何将过去的信息与当前输入相结合。重置 门的输出r_t决定了保留或遗忘上一时间步信息的程度。利用重置门的输 出,更新上一时间步的信息h_t-1 。同时,通过更新门(update gate)决 定如何结合当前输入和更新后的上一时间步信息来计算新的隐藏状态 h_t。 更新门的输出z_t决定了保留或遗忘当前输入的程度。

        这个隐藏状态可以被用于后续的时间步骤,同时也可以作为当前时间步的 输出。整个过程通过重置门和更新门的调控,使得模型能够在处理时间序 列数据时更灵活地管理和利用过去的信息。

import torch
import numpy as np
from torch import nn
 
# 1.字符输入
text = "In Beijing Sarah bought a basket of apples In Guangzhou Sarah bought a basket of bananas"
 
torch.manual_seed(1)
 
# 3.数据集划分
input_seq = [text[:-1]]
output_seq = [text[1:]]
print("input_seq:", input_seq)
# print("output_seq:", output_seq)
 
# 4.数据编码:one-hot
chars = set(text)
chars = sorted(chars)
# print("chars:", chars)
# {" ":0, "a":1 }
char2int = {char: ind for ind, char in enumerate(chars)}
# print("char2int:", char2int)
# {0:" ", 1: "a"}
int2char = dict(enumerate(chars))
 
# 将字符转成数字编码
input_seq = [[char2int[char] for char in seq] for seq in input_seq]
# print("input_seq:", input_seq)
output_seq = [[char2int[char] for char in seq] for seq in output_seq]
 
# one-hot 编码,pytorch的RNN的输入张量的填充
def one_hot_encode(seq, bs, seq_len, size):
    features = np.zeros((bs, seq_len, size), dtype=np.float32)
    for i in range(bs):
        for u in range(seq_len):
            features[i, u, seq[i][u]] = 1.0
    return torch.tensor(features, dtype=torch.float32)
 
input_seq = one_hot_encode(input_seq, 1, len(text)-1, len(chars))
output_seq = torch.tensor(output_seq, dtype=torch.long).view(-1)
print("output_seq:", output_seq)
 
# 5.定义前向模型
class Model(nn.Module):
    def __init__(self, input_size, hidden_size, out_size):
        super(Model, self).__init__()
        self.hidden_size = hidden_size
        self.gru1 = nn.GRU(input_size, hidden_size, num_layers=1, batch_first=True)
        self.fc1 = nn.Linear(hidden_size, out_size)
 
    def forward(self, x):
        out, hidden = self.gru1(x)
        x = out.contiguous().view(-1, self.hidden_size)
        x = self.fc1(x)
        return x, hidden
 
model = Model(len(chars), 32, len(chars))
 
# 6.定义损失函数和优化器
cri = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
 
# 7.开始迭代
epochs = 1000
for epoch in range(1, epochs+1):
    output, hidden = model(input_seq)
    loss = cri(output, output_seq)
 
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    # 8.显示频率设置
    if epoch == 0 or epoch % 50 == 0:
        print(f"Epoch [{epoch}/{epochs}], Loss {loss:.4f}")
 
# print("input_seq.shape:", input_seq.shape)
# print("hidden.shape:", hidden.shape)
# print("output.shape:", output.shape)
# print("input_w:", model.rnn1.weight_ih_l0.shape)
 
# 预测下面几个字符
input_text = "In Beijing Sarah bought a basket of"  # re
to_be_pre_len = 20
 
for i in range(to_be_pre_len):
    chars = [char for char in input_text]
    # print(chars)
    character = np.array([[char2int[c] for c in chars]])
    character = one_hot_encode(character, 1, character.shape[1], 23)
    character = torch.tensor(character, dtype=torch.float32)
 
    out, hidden = model(character)
    char_index = torch.argmax(out[-1]).item()
    input_text += int2char[char_index]
print("预测到的:", input_text)
参数描述
input_size输入 x 中预期特征的数量
hidden_size处于隐藏状态 h 的特征数量
num_layers循环层数。例如,设置意味着将两个 GRU 堆叠在一起以形成一个堆叠的 GRU, 第二个 GRU 接收第一个 GRU 的产出,并且 计算最终结果。默认值:1num_layers=2
bias如果 ,则层不使用 b_ih 和 b_hh 的偏差权重。 违约:FalseTrue
batch_first如果 ,则提供输入和输出张量 作为 (batch, seq, feature) 而不是 (seq, batch, feature)。 请注意,这不适用于隐藏状态或单元格状态。请参阅 Inputs/Outputs 部分了解详细信息。违约:TrueFalse
dropout 如果为非零,则在每个 除最后一层外,丢弃概率等于 的 GRU 层。默认值:0dropout
bidirectional 如果 ,则变为双向 GRU。违约:TrueFalse
输出:
output形状的张量(L,D∗Hout)( L,D∗H​)对于未批处理的输入,(L,N,D∗Hout)(北、H​)when 或batch_first=False(N,L,D∗Hout)(NLDH​)当包含来自 GRU 最后一层的输出特征 (h_t) 时,对于每个 t。如果已将 a 作为输入,则输出 也将是一个打包序列。batch_first=True
h_n形状的张量(D∗num_layers,Hout)(D∗num_layers,H​)(D∗num_layers,N,Hout)(D∗num_layers,N,H​)包含最终的 Hidden 状态 对于输入序列。
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐