pack_padded_sequence,pad_packed_sequence

pack_padded_sequence:

我们正常传进RNN模型的是一个被填充之后的序列矩阵。但是这样pad会影响模型的效果,所以要把pad删除再传进模型。

pack_padded_sequence就是起这个功能的。

        pack之后,原来填充的 PAD占位符被删掉了。
        输入的形状可以是(T×B×* )。T是最长序列长度,B是batch size,*代表任意维度(可以是0)。如果batch_first=True的话,那么相应的 input size 就是 (B×T×*) 。

          

  enforce_sorted默认是True,被处理的序列要求按序列长度降序排序。如果是False则没有要求。

  lengths里的长度要对应于batch_size。

import torch
import torch.nn.utils.rnn as rnn
a = [[1,2,2,4,5],[2,2,1,3,0],[1,6,5,0,0],[1,0,0,0,0]]
a = torch.tensor(a)
# 长度降序
lenths = [5,4,3,1]
pack = rnn.pack_padded_sequence(a,lenths,batch_first=True)
print(pack)
print(pack.data)


PackedSequence(data=tensor([1, 2, 1, 1, 2, 2, 6, 2, 1, 5, 4, 3, 5]), batch_sizes=tensor([4, 3, 3, 2, 1]), sorted_indices=None, unsorted_indices=None)
tensor([1, 2, 1, 1, 2, 2, 6, 2, 1, 5, 4, 3, 5])
import torch
import torch.nn.utils.rnn as rnn
a = [[1,0,0,0,0],[1,2,2,4,5],[2,2,1,3,0],[1,6,5,0,0]]
a = torch.tensor(a)
# 长度没有顺序,再没设置enfore_sort参数时会报错。
lenths = [1,4,3,5]
pack = rnn.pack_padded_sequence(a,lenths,batch_first=True)
print(pack)
print(pack.data)


RuntimeError: `lengths` array must be sorted in decreasing order when `enforce_sorted` is True. You can pass `enforce_sorted=False` to pack_padded_sequence and/or pack_sequence to sidestep this requirement if you do not need ONNX exportability.


import torch
import torch.nn.utils.rnn as rnn
# a = [[1,2,2,4,5],[2,2,1,3,0],[1,6,5,0,0],[1,0,0,0,0]]
a = [[1,0,0,0,0],[1,2,2,4,5],[2,2,1,3,0],[1,6,5,0,0]]
a = torch.tensor(a)
lenths = [1,5,4,3]
# 设置enforce_sorted=False
pack = rnn.pack_padded_sequence(a,lenths,batch_first=True,enforce_sorted=False)
print(pack)
print(pack.data)

# 得出的结果和排序好的是一样的
PackedSequence(data=tensor([1, 2, 1, 1, 2, 2, 6, 2, 1, 5, 4, 3, 5]), batch_sizes=tensor([4, 3, 3, 2, 1]), sorted_indices=tensor([1, 2, 3, 0]), unsorted_indices=tensor([3, 0, 1, 2]))
tensor([1, 2, 1, 1, 2, 2, 6, 2, 1, 5, 4, 3, 5])

pad_packed_sequence:

上面提到的函数的功能是将一个填充后的变长序列压紧。 这个操作和pack_padded_sequence()是相反的。把压紧的序列再填充回来。填充时会初始化为0。
返回的Varaible的值的size是 T×B×*, T 是最长序列的长度,B 是 batch_size,如果 batch_first=True,那么返回值是B×T×*。
Batch中的元素将会以它们长度的逆序排列。
参数说明:
    sequence (PackedSequence) – 将要被填充的 batch
    batch_first (bool, optional) – 如果为True,返回的数据的格式为 B×T×*。
    返回值: 一个tuple,包含被填充后的序列,和batch中序列的长度列表

tensor经过pack_padded_sequence之后,看似数据都连接在一起,但是传入模型的是PackedSequence。模型仍然会并行计算得到结果的。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn
a = [[1,0,0,0,0],[1,1,2,4,5],[2,2,1,3,0],[1,6,5,0,0]]
# a经过pack_padded_sequence后,降低一个维度。如果不在最后面加上一维,pack_padded_sequence后就变成一维张量,传不进模型。
# tensor要是浮点型
a = torch.tensor(a).view(4,5,1).float()
# print(a.size())
lenths = [1,5,4,3]
pack = rnn.pack_padded_sequence(a,lenths,batch_first=True,enforce_sorted=False)
print(pack.data)
RNN = nn.RNN(1,1,batch_first=True)
out,hi = RNN(pack)
# 输出也是PackedSequence
print(out)

out = rnn.pad_packed_sequence(out,batch_first=True)
print(out)


tensor([[1.],
        [2.],
        [1.],
        [1.],
        [1.],
        [2.],
        [6.],
        [2.],
        [1.],
        [5.],
        [4.],
        [3.],
        [5.]])

PackedSequence(data=tensor([[-0.1629],
        [ 0.0738],
        [-0.1629],
        [-0.1629],
        [-0.2759],
        [ 0.1272],
        [ 0.7204],
        [-0.1267],
        [-0.0714],
        [ 0.8655],
        [ 0.4286],
        [ 0.2545],
        [ 0.8012]], grad_fn=<CatBackward>), batch_sizes=tensor([4, 3, 3, 2, 1]), sorted_indices=tensor([1, 2, 3, 0]), unsorted_indices=tensor([3, 0, 1, 2]))

(tensor([[[-0.1629],
         [ 0.0000],
         [ 0.0000],
         [ 0.0000],
         [ 0.0000]],

        [[-0.1629],
         [-0.2759],
         [-0.1267],
         [ 0.4286],
         [ 0.8012]],

        [[ 0.0738],
         [ 0.1272],
         [-0.0714],
         [ 0.2545],
         [ 0.0000]],

        [[-0.1629],
         [ 0.7204],
         [ 0.8655],
         [ 0.0000],
         [ 0.0000]]], grad_fn=<IndexSelectBackward>), tensor([1, 5, 4, 3]))

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值