Pytorch循环神经网络入门实现

循环神经网络的基本架构及其LSTM、GRU等变种。这些循环神经网 络PyTorch提供了相应的API,如单元版的有:nn.RNNCell、nn.LSTMCell、nn.GRUCell 等;封装版的有:nn.RNN、nn.LSTM、nn.GRU。单元版与封装版的最大区别就是输入, 前者是时间步或序列的一个元素,后者是一个时间步序列。利用这些API可以极大地提高 开发效率。

RNN实现

PyTorch提供了两个版本的循环神经网络接口,单元版的输入是每个时间步,或循 神经网络的一个循环,而封装版的是一个序列。下面我们从简单的封装版torch.nn.RNN开 始,其一般格式为:

torch.nn.RNN( args, * kwargs)

RNN状态输出 a t a_{t} at的计算公式为
a t = t a n h ( w i h ∗ x t + b i h + w h h ∗ a t − 1 + b h h ) a_{t}=tanh(w_{ih}*x_{t}+b_{ih}+w_{hh}*a_{t}-1+b_{hh}) at=tanh(wihxt+bih+whhat1+bhh)
nn.RNN函数中的参数说明如下
·input_size:输入x的特征数量。
·hidden_size:隐含层的特征数量。
·num_layers:RNN的层数。
·nonlinearity:指定非线性函数使用tanh还是relu。默认是tanh。
·bias:如果是False,那么RNN层就不会使用偏置权重bi和bh,默认是True。
·batch_first:如果True的话,那么输入Tensor的shape应该是(batch,seq,feature),输 出也是这样。默认网络输入是(seq,batch,feature),即序列长度、批次大小、特征维度。
·dropout:如果值非零(该参数取值范围为0~1之间),那么除了最后一层外,其他 层的输出都会加上一个dropout层,缺省为零。
·bidirectional:如果True,将会变成一个双向RNN,默认为False。

函数nn.RNN()的输入包括特征及隐含状态,记为(xt、h0),输出包括输出特征及输 出隐含状态,记为(outputt、hn)。

其中特征值xt的形状为(seq_len,batch,input_size),h0的形状为
(num_layers*num_directions,batch,hidden_size),其中num_layers为层数,num_directions
方向数,如果取2则表示双向(bidirectional,),取1则表示单向。

outputt的形状为 (seq_len,batch,num_directionshidden_size),hn的形状
(num_layers
num_directions,batch,hidden_size)。

首先建立一个简单循环神经网络,输入维度为10,隐含状态维度为20,单向两层网络。

rnn = nn.RNN(input_size=10, hidden_size=20,num_layers= 2)

因输入节点与隐含层节点是全连接的,根据输入维度、隐含层维度,可以推算出相关 权重参数的维度,wih应该是20×10,whh是20×20,bih和bhh都是hidden_size。以下我们通 过查询weight_ih_l0、weight_hh_l0等进行验证。

# 第一层相关权重参数形状
print("wih 形状{},whh 形状{},bih 形状{}".format(rnn.weight_ih_l0.shape,rnn.weight_hh_l0.shape,rnn.bias_hh_l0.shape))
# wih 形状torch.Size([20, 10]),whh 形状torch.Size([20, 20]),bih 形状torch.Size([20])
# 第二层相关权重参数形状
print("wih 形状{},whh 形状{},bih 形状{}".format(rnn.weight_ih_l1.shape,rnn.weight_hh_l1.shape,rnn.bias_hh_l1.shape))
# wih 形状torch.Size([20, 20]),whh 形状torch.Size([20, 20]),bih 形状torch.Size([20]) 

RNN网络已搭建好,接下来将输入(xt、h0)传入网络,根据网络配置及网络要求,来 生成输入数据。输入特征长度为100,批量大小为32,特征维度为10的张量。隐含状态按 网络要求,其形状为(2,32,20)。

# 生成输入数据
input = torch.randn(100, 32, 10)
h_0 = torch.randn(2, 32, 20)

将输入数据传入RNN网络,将得到输出及更新后隐含状态值。根据以上规则,输出 output的形状应该是(100,32,20),隐含状态的输出形状应该与输入的形状一致。

output, h_n = rnn(input, h_0)
print(output.shape, h_n.shape)
# torch.Size([100, 32, 20]) torch.Size([2, 32, 20])

import torch
import torch.nn as nn
import numpy as np

def test():
    # at=tanh(wih*xt+bih+whh*at-1+bhh)
    rnn = nn.RNN(input_size=10, hidden_size=20, num_layers=2)
    # 因输入节点与隐含层节点是全连接的,根据输入维度、隐含层维度,可以推算出相关权重参数的维度,wih应该是20×10,whh是20×20,bih和bhh都是hidden_​​size
    # 第一层相关权重参数形状
    print("wih 形状{},whh 形状{},bih 形状{}".format(rnn.weight_ih_l0.shape,rnn.weight_hh_l0.shape,rnn.bias_hh_l0.shape))
    # wih 形状torch.Size([20, 10]),whh 形状torch.Size([20, 20]),bih 形状torch.Size([20])
    # 第二层相关权重参数形状
    print("wih 形状{},whh 形状{},bih 形状{}".format(rnn.weight_ih_l1.shape,rnn.weight_hh_l1.shape,rnn.bias_hh_l1.shape))
    # wih 形状torch.Size([20, 20]),whh 形状torch.Size([20, 20]),bih 形状torch.Size([20])  
    
    # 生成输入数据
    input = torch.randn(100, 32, 10)
    h_0 = torch.randn(2, 32, 20)
    
    output, h_n = rnn(input, h_0)
    print(output.shape, h_n.shape)
    # torch.Size([100, 32, 20]) torch.Size([2, 32, 20])
if __name__ == '__main__':
    test()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值