pytorch中RNN函数

'''
参考https://www.cnblogs.com/lindaxin/p/8052043.html
以及pytorch中文文档https://pytorch-cn.readthedocs.io/zh/latest/package_references/torch-nn/#class-torchnnrnn-args-kwargssource
'''
import torch
import torch.nn as nn
from torch.autograd import Variable
from torch.nn import utils as nn_utils

batch_size = 2
max_length = 3
hidden_size = 2
n_layers =1

tensor_in = torch.FloatTensor([[1,2,3],[4,5,6]]).resize_(2,3,1)  # 使用resize将输入变为[batch_size, time_step, feature]
torch_in = Variable(tensor_in)  # 输入Tensor的shape是[batch_size, time_step, feature],这是肯定的
print('tensor_in')
print(tensor_in)
'''
tensor([[[1.],
         [2.],
         [3.]],

        [[4.],
         [5.],
         [6.]]])
'''

# list of integers holding information about the batch size at each sequence step?
# 可以理解为3个时间步,每个时间步一个特征吧
seq_lengths = [3,1]

# pack it 参考:https://www.cnblogs.com/sbj123456789/p/9834018.html
pack = nn_utils.rnn.pack_padded_sequence(tensor_in, seq_lengths, batch_first=True)
'''
输入的形状可以是(T×B×* )。T是最长序列长度,B是batch size,*代表任意维度(可以是0)。
参数说明:
input (Variable) – 变长序列 被填充后的 batch
lengths (list[int]) – Variable 中 每个序列的长度。应该按序列长度的长短排序 ?
batch_first (bool, optional) – 如果是True,input的形状应该是B*T*size。

返回值:
一个PackedSequence 对象。
'''

# initialize
rnn = nn.RNN(1,hidden_size,n_layers,batch_first=True)
'''
RNN参数说明:
input_size – 输入x的特征数量。
hidden_size – 隐层的特征数量。
num_layers – RNN的层数。
nonlinearity – 指定非线性函数使用tanh还是relu。默认是tanh。
bias – 如果是False,那么RNN层就不会使用偏置权重 $b_ih$和$b_hh$,默认是True
batch_first – 如果True的话,那么输入Tensor的shape应该是[batch_size, time_step, feature],输出也是这样。
dropout – 如果值非零,那么除了最后一层外,其它层的输出都会套上一个dropout层。
bidirectional – 如果True,将会变成一个双向RNN,默认为False。
'''
h0 = Variable(torch.randn(n_layers, batch_size, hidden_size))

out,_ = rnn(pack,h0)
'''
RNN的输入: 
(input, h_0) - input (seq_len, batch, input_size): 保存输入序列特征的tensor。input可以是被填充的变长的序列。
h_0 (num_layers * num_directions, batch, hidden_size): 保存着初始隐状态的tensor

RNN的输出: (output, h_n)
output (seq_len, batch, hidden_size * num_directions): 保存着RNN最后一层的输出特征。如果输入是被填充过的序列,那么输出也是被填充的序列。
h_n (num_layers * num_directions, batch, hidden_size): 保存着最后一个时刻隐状态。
'''

unpacked = nn_utils.rnn.pad_packed_sequence(out,batch_first=True)
'''
 这个操作和pack_padded_sequence()是相反的。把压紧的序列再填充回来。
 参数说明:
sequence (PackedSequence) – 将要被填充的 batch
batch_first (bool, optional) – 如果为True,返回的数据的格式为 B×T×*。
返回值: 一个tuple,包含被填充后的序列,和batch中序列的长度列表。
'''
print('unpacked')
print(unpacked)
'''
(tensor([[[-0.0543,  0.1340],
         [ 0.2547,  0.6385],
         [ 0.3781,  0.9012]],

        [[ 0.5487,  0.9719],
         [ 0.0000,  0.0000],
         [ 0.0000,  0.0000]]], grad_fn=<TransposeBackward0>), tensor([3, 1]))
         
变成两列应该是因为hidden_size=2,即上面提到的*
'''

另外一个例子:

参考:https://www.cnblogs.com/sbj123456789/p/9834018.html

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
# 直接从文本处理开始
'''
To the world.
the one who is.
when you are sad
We met at the wrong time
'''
import numpy as np
import wordfreq
import torch
import torch.nn as nn
from torch.autograd import Variable

vocab = {}
token_id = 1
lengths = []
with open('test.txt', 'r', encoding='utf-8') as f:
    for l in f:
        tokens = wordfreq.tokenize(l.strip(), 'en')
        lengths.append(len(tokens))  # length: <class 'list'>: [3, 4, 4, 6]
        for t in tokens:
            if t not in vocab:
                vocab[t] = token_id  # vocab: {'to': 1, 'the': 2, 'world': 3, 'one': 4, 'who': 5, 'is': 6, 'when': 7, 'you': 8, 'are': 9, 'sad': 10, 'we': 11, 'met': 12, 'at': 13, 'wrong': 14, 'time': 15}
                token_id += 1

x = np.zeros((len(lengths), max(lengths)))
l_no = 0
with open('test.txt', 'r', encoding='utf-8') as f:
    for l in f:
        tokens = wordfreq.tokenize(l.strip(), 'en')
        for i in range(len(tokens)):
            x[l_no, i] = vocab[tokens[i]]
        l_no += 1
# 此时的x:
# [[ 1.  2.  3.  0.  0.  0.]
#  [ 2.  4.  5.  6.  0.  0.]
#  [ 7.  8.  9. 10.  0.  0.]
#  [11. 12. 13.  2. 14. 15.]]


# 使用pack_padded_sequence
x = Variable(torch.tensor(x))
lengths = torch.Tensor(lengths)  # tensor([3., 4., 4., 6.])
_, idx_sort = torch.sort(torch.Tensor(lengths), dim=0, descending=True)  # idx_sort: tensor([3, 1, 2, 0])
_, idx_unsort = torch.sort(idx_sort, dim=0)  # idx_unsort:tensor([3, 1, 2, 0])

x = x.index_select(0, idx_sort)
# 此时的x:
# tensor([[11., 12., 13.,  2., 14., 15.],
        # [ 2.,  4.,  5.,  6.,  0.,  0.],
        # [ 7.,  8.,  9., 10.,  0.,  0.],
        # [ 1.,  2.,  3.,  0.,  0.,  0.]], dtype=torch.float64)
lengths = list(lengths[idx_sort])  # <class 'list'>: [tensor(6.), tensor(4.), tensor(4.), tensor(3.)]
x_packed = nn.utils.rnn.pack_padded_sequence(input=x, lengths=lengths, batch_first=True)
# x_packed如下:
# PackedSequence(data=tensor([11.,  2.,  7.,  1., 12.,  4.,  8.,  2., 13.,  5.,  9.,  3.,  2.,  6.,
#         10., 14., 15.], dtype=torch.float64), batch_sizes=tensor([4, 4, 4, 3, 1, 1]), sorted_indices=None, unsorted_indices=None)

# 使用pad_packed_sequence
x_padded = nn.utils.rnn.pad_packed_sequence(x_packed, batch_first=True)
# x_padded如下:
#<class 'tuple'>: (tensor([[11., 12., 13.,  2., 14., 15.],
                        # [ 2.,  4.,  5.,  6.,  0.,  0.],
                        # [ 7.,  8.,  9., 10.,  0.,  0.],
                        # [ 1.,  2.,  3.,  0.,  0.,  0.]], dtype=torch.float64), tensor([6, 4, 4, 3]))
output = x_padded[0].index_select(0, idx_unsort)
# output如下:
# tensor([[ 1.,  2.,  3.,  0.,  0.,  0.],
#         [ 2.,  4.,  5.,  6.,  0.,  0.],
#         [ 7.,  8.,  9., 10.,  0.,  0.],
#         [11., 12., 13.,  2., 14., 15.]], dtype=torch.float64)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值