当前位置:   article > 正文

RNN模型详细实现(pytorch+jupyter)_pytorch rnn模型训练代码

pytorch rnn模型训练代码

RNN网络构建

从零构建一个RNN网络模型

1、初始化模型参数

RNN模型计算表达式为 o t = H t W h q + b q o_t=H_{t}W_{hq}+b_q ot=HtWhq+bq ,其中 o t o_t ot t t t时间步的输出,维度为 n × d n \times d n×d(批量大小 乘以 时间步数), H t H_{t} Ht为隐变量,维度为 d × h d\times h d×h(批量大小 乘以 隐变量大小)。隐变量的更新公式为 H t = ϕ ( X t W x h + H t − 1 W h h + b h ) H_t=\phi(X_tW_{xh}+H_{t-1}W_{hh}+b_h) Ht=ϕ(XtWxh+Ht1Whh+bh) ,其中 X t X_t Xt的维度为 n × d n\times d n×d W x h W_{xh} Wxh的维度为 d × h d\times h d×h

需要哪些参数:

  • 隐藏层参数: W x h ∈ R d × h W_{xh}\in R^{d\times h} WxhRd×h W h h ∈ R h × h W_{hh}\in R^{h\times h} WhhRh×h b h ∈ R h × 1 b_h\in R^{h\times 1} bhRh×1
  • 输出层参数: W h q ∈ R h × d W_{hq}\in R^{h\times d} WhqRh×d b q ∈ R d × 1 b_q\in R^{d\times 1} bqRd×1

定义初始化函数:

  • Input: num_inputs(即上式中的d),num_hiddens(隐藏层数量)
  • Output: 初始化后的参数列表
# 初始化模型参数
def get_params(num_inputs, num_hiddens, device):
    num_outputs = num_inputs
    def normal(shape):
        return torch.randn(size=shape, device=device) * 0.01
    
    # 初始化隐藏层参数
    w_xh = normal(num_inputs, num_hiddens)
    w_hh = normal(num_hiddens, num_hiddens)
    b_h = torch.zeros(num_hiddens, device=device)

    # 初始化输出层参数
    w_hq = normal(num_hiddens, num_outputs)
    b_q = normal(num_outputs, device=device)

    # 初始化输出
    outpus = [w_xh, w_hh, b_h, w_hq, b_q]

    for output in outpus:
        output.requires_grad_(True)
        
    return outpus
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2、循环神经网络模型

建立一个循环神经网络模型,首先需要初始化隐变量(即 H 0 H_0 H0),然后将数据输入网络中进行计算。

  1. 首先初始化隐变量状态,以及如何进行前向传播计算
# 初始化隐变量H_0,维度为d*h批量大小*隐变量大小)
def init_rnn(batch_size, num_hiddens, device):
    return (torch.zeros(batch_size, num_hiddens, device=device),) # 这里为什么把返回值设置为一个tuple呢?

def rnn(inputs, state, params):
    w_xh, w_hh, b_h, w_hq, b_q = params
    H, = state # 因为要传入的state也是一个元组
    outputs = []
    for X in inputs:
        H = torch.tanh(torch.mm(X, w_xh) + torch.mm(H, w_hh) + b_h)
        Y = torch.mm(H, w_hq) + b_q
        outputs.append(Y)
    return torch.cat(outputs, dim=0), (H,)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. 有了计算函数,就可以建立模型类,用于实例化模型网络了

要实例化一个网络模型,需要哪些参数?

  • 数据集维度、隐藏层个数、设备、参数、初始化隐状态、计算函数

代码如下所示:

# 建立模型

# 初始化隐变量H_0,维度为d*h批量大小*隐变量大小)
def init_rnn_state(batch_size, num_hiddens, device):
    return (torch.zeros(batch_size, num_hiddens, device=device),) # 这里为什么把返回值设置为一个tuple呢?

def rnn(inputs, state, params):
    w_xh, w_hh, b_h, w_hq, b_q = params
    H, = state # 因为要传入的state也是一个元组
    outputs = []
    for X in inputs:
        H = torch.tanh(torch.mm(X, w_xh) + torch.mm(H, w_hh) + b_h)
        Y = torch.mm(H, w_hq) + b_q
        outputs.append(Y)
    return torch.cat(outputs, dim=0), (H,)

# 封装成类
class RNNModelScratch:
    def __init__(self, vocab_size, num_hiddens, device, 
                 get_params, init_state, forward_in):
        self.vocab_size = vocab_size
        self.num_hiddens = num_hiddens
        self.params = get_params(vocab_size, num_hiddens, device)
        self.init_state = init_state
        self.forward_in = forward_in

    def __call__(self, X, state):
        X = F.one_hot(X.T, self.vocab_size).type(torch.float32)
        return self.forward_in(X, state, self.params)
    
    def begin_state(self, batch_size, device):
        return self.init_state(batch_size, self.num_hiddens, device)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

3、使用网络模型进行预测

网络模型预测即使用训练出的模型进行预测,使用者给出初始化语句以及预测的步长,便可根据给出的语句实现续写,具体实现如下:

# 如何使用网络进行预测
def predict_char(prefix, num_preds, net, vocab, device):
    # prefix: 预热语句
    # num_preds:预测步长,单位:字母
    # net:网络模型
    # vocab:词表
    # device:设备
    # 预热部分,更新隐变量参数
    state = net.begin_state(batch_size=1, device=device)
    outputs = [vocab[prefix[0]]]
    for y in prefix[1:]:
        x = torch.tensor([outputs[-1]], device=device).reshape((1, 1))     
        _, state = net(x, state)
        outputs.append(vocab[y])
  
    for i in range(num_preds):
        final_char = torch.tensor(outputs[-1],device=device).reshape(1,1)
        final_char, state = net(final_char, state)
        outputs.append(int(final_char.argmax(dim=1).reshape(1)))
    return ''.join([vocab.idx_to_token[i] for i in outputs])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

编写测试代码:

num_hiddens = 512
device = 'cuda:0'
net = RNNModelScratch(len(vocab), num_hiddens, device, 
                      get_params, init_rnn_state, rnn)
predict_char('hello', 10, net, vocab, device)
  • 1
  • 2
  • 3
  • 4
  • 5

输出结果如下:

'hellonznqfkkkkk'

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/711255
推荐阅读
相关标签
  

闽ICP备14008679号