pytorch学习笔记(20)

# GRU

具体原理可以看沐神的b站课程,也可以看书,我仅对代码部分进行讲解。

# 从零开始实现

def get_params(vocab_size, num_hiddens, device):  # vocab_size 表示词汇表的大小,num_hiddens 表示隐藏单元的数量
    num_inputs = num_outputs = vocab_size  # num_inputs 和 num_outputs,它们都被设置为 vocab_size,表示输入和输出数据的维度,因为这里我们是在字符级别的文本数据上进行建模,所以输入和输出的维度都等于词汇表的大小。

    def normal(shape): # 生成随机初始化的张量,并将其元素初始化为标准差为 0.01 的随机值。这个函数将用于初始化模型参数。
        return torch.randn(size=shape, device=device)*0.01

    def three():  # W_xz、W_hz、b_z、W_xr、W_hr、b_r 和 W_xh、W_hh、b_h。这些参数用于门控循环单元(GRU)模型中的更新门、重置门和候选隐状态。
        return (normal((num_inputs, num_hiddens)),
                normal((num_hiddens, num_hiddens)),
                torch.zeros(num_hiddens, device=device))

    W_xz, W_hz, b_z = three()  # 更新门参数
    W_xr, W_hr, b_r = three()  # 重置门参数
    W_xh, W_hh, b_h = three()  # 候选隐状态参数
    # 输出层参数
    W_hq = normal((num_hiddens, num_outputs))
    b_q = torch.zeros(num_outputs, device=device)
    # 附加梯度
    params = [W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q]
    for param in params:  # 将所有的模型参数存储在 params 列表中,然后使用循环将每个参数的 requires_grad 属性设置为 True,以便在训练过程中计算梯度。
        param.requires_grad_(True)
    return params

定义隐状态的初始化函数init_gru_state。此函数返回一个形状为(批量大小,隐藏单元个数)的张量,张量的值全部为零。

def gru(inputs, state, params):  # inputs 表示输入数据,state 表示模型的初始状态,params 表示模型的参数。
    W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q = params # 将模型的参数 params 解包成多个变量,其中包括更新门(W_xz, W_hz, b_z)、重置门(W_xr, W_hr, b_r)、候选隐状态(W_xh, W_hh, b_h)、以及输出层参数(W_hq, b_q)。
    H, = state  # 从初始状态 state 中解包隐藏状态 H。H 是一个张量,表示模型的隐藏状态。
    outputs = [] # 用于存储模型在每个时间步上的输出。
    for X in inputs:  # torch.sigmoid 函数用于将门的值映射到 [0, 1] 的范围内。
        Z = torch.sigmoid((X @ W_xz) + (H @ W_hz) + b_z)
        R = torch.sigmoid((X @ W_xr) + (H @ W_hr) + b_r)
        H_tilda = torch.tanh((X @ W_xh) + ((R * H) @ W_hh) + b_h)  # 代码计算了候选隐状态 H_tilda, torch.tanh 函数用于将候选隐状态的值映射到 [-1, 1] 的范围内。
        H = Z * H + (1 - Z) * H_tilda  # 根据更新门 Z 和候选隐状态 H_tilda 更新了隐藏状态 H。这是GRU模型的关键部分,它控制了信息的传递和保存。
        Y = H @ W_hq + b_q  # 计算了输出 Y,它是隐藏状态 H 通过全连接层(使用参数 W_hq 和 b_q)映射到输出空间的结果。
        outputs.append(Y)
    return torch.cat(outputs, dim=0), (H,)  # 将所有的输出 Y 沿着第一个维度拼接在一起,形成一个长序列。同时,将更新后的隐藏状态 H 包装在元组中,并返回作为函数的输出。

训练

#简洁实现

直接用现成的API,代码简洁了许多,速度也更快了

num_inputs = vocab_size
gru_layer = nn.GRU(num_inputs, num_hiddens)  # gru_layer 是一个 GRU 层,它接受 num_inputs 维的输入数据,有 num_hiddens 个隐藏单元。
model = d2l.RNNModel(gru_layer, len(vocab))
model = model.to(device)
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值