pytorch之数据:pack_padded_sequence()与pad_packed_sequence()

本文详述PyTorch中处理变长序列数据的方法,包括pack_padded_sequence与pad_packed_sequence函数的使用,通过实例展示如何排序、填充及压缩序列数据,适用于循环神经网络的训练。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

可以结合最下面的例子来理解

pack_padded_sequence()pad_packed_sequence()这两个函数属于torch.nn.utils.rnn,很明显,意义就是为了rnn包来处理数据的。前者pack用于压紧数据,处理经过填充(padded)后的数据;后面pad用于解压数据,把原来咋填充的给你咋释放回去。

一. 官方+理解

1. pack_padded_sequence
'官方函数'
torch.nn.utils.rnn.pack_padded_sequence(input, lengths, batch_first=False) → PackedSequence
↓'返回'
return   一个PackedSequence对象

功能:这里的pack,理解成压紧比较好,压紧被填充过的数据。 将一个 填充过的变长序列 压紧。返回PackedSequence对象。

重点

  • 输入的数据input可以是[Seq_max, batch_size, *]格式,且Seq_max是序列的最大长度。且input必须按序列长度的长短排序,长的在前面,短的在后面,第一个时间步的数据必须是最长的数据。
  • input:我们要压缩的数据。当batch_firstFalse时候,shape的输入格式是[B,S *],其中Bbatch_size,S是seq_len(该batch中最长序列的长度),*可以是任何维度。如果batch_firstTrue时候,相应的的数据格式必须是[S,B,*]。关于数据格式转置参考
  • lengths:输入数据的每个序列的长度。
  • batch_first:当为True,数据格式必须[B, S, *],反之,默认是False
2. pad_packed_sequence
torch.nn.utils.rnn.pad_packed_sequence(sequence, batch_first=False)tuple'返回'
return (sequence_pad , list) # 这个元祖包含被填充后的序列 , 和batch中序列的长度列表。

功能:上面提到的函数的功能是将一个填充后的变长序列压紧。 这个操作和pack_padded_sequence()是相反的。把压紧的序列再填充回来,默认按返回中list最大的数字填充。

重点

  • sequence:将要被填充的batch,是一个PackedSequence对象。
  • batch_first:作用同上pack_padded_sequence的batch_size,但是影响的是输出的数据格式。

二. 结合例子。

注意上述官方+理解,我们明白了输入的数据一定是要经过排序的

  1. 准备例子数据
import torch

batch_size = 3   # 这个batch有3个序列
max_len = 6       # 最长序列的长度是6
embedding_size = 8 # 嵌入向量大小8
hidden_size = 16   # 隐藏向量大小16
vocab_size = 20    # 词汇表大小20

input_seq = [[3, 5, 12, 7, 2, ], [4, 11, 14, ], [18, 7, 3, 8, 5, 4]]
lengths = [5, 3, 6]   # batch中每个seq的有效长度。
# embedding
embedding = torch.nn.Embedding(vocab_size, embedding_size, padding_idx=0)
# GRU的RNN循环神经网络
gru = torch.nn.GRU(embedding_size, hidden_size)
  1. 排序数据
'由大到小排序'
input_seq = sorted(input_seq, key = lambda tp: len(tp), reverse=True)
lengths = sorted(lengths, key = lambda tp: tp, reverse=True)
'''
outputs:
input_seq: [[18, 7, 3, 8, 5, 4], [3, 5, 12, 7, 2], [4, 11, 14]]
lengths : [6, 5, 3]
'''
  1. 填充数据
PAD_token = 0 # 填充下标是0
def pad_seq(seq, seq_len, max_length):
	seq = seq
	seq += [PAD_token for _ in range(max_length - seq_len)]
	return seq

pad_seqs = []  # 填充后的数据
for i,j in zip(input_seq, lengths):
	pad_seqs.append(pad_seq(i, len_i, max_len))
'''
填充后数据
pad_seqs : [[18, 7, 3, 8, 5, 4], [3, 5, 12, 7, 2, 0, 0], [4, 11, 14, 0, 0, 0, 0, 0, 0]]
'''
  1. 使用pack和pad函数
pad_seqs = torch.tensor(pad_seqs)
embeded = embedding(pad_seqs)

# 压缩,设置batch_first为true
pack = torch.nn.utils.rnn.pack_padded_sequence(embeded, lengths, batch_first=True)
'这里如果不写batch_first,你的数据必须是[s,b,e],不然会报错lenghth错误'

# 利用gru循环神经网络测试结果
state = None
pade_outputs, _ = gru(pack, state)
# 设置batch_first为true;你可以不设置为true,为false时候只影响结构不影响结果
pade_outputs, others = torch.nn.utils.rnn.pad_packed_sequence(pade_outputs, batch_first=True)

# 查看输出的元祖
print(pade_outputs.shape) 'torch.Size([3, 6, 16])'
print(others) 'tensor([6, 5, 3])' 

到这里,大家基本知道如何使用这个函数了。

总结

这个函数就是用到填充tensor数据和解压数据的,进行循环神经网络的运算。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值