转自:https://www.cnblogs.com/lindaxin/p/8052043.html
主要是用函数torch.nn.utils.rnn.
PackedSequence()和
torch.nn.utils.rnn.
pack_padded_sequence()以及
torch.nn.utils.rnn.
pad_packed_sequence
()来进行的,分别来看看这三个函数的用法。
1、torch.nn.utils.rnn.
PackedSequence()
NOTE:
这个类的实例不能手动创建。它们只能被 pack_padded_sequence()
实例化。
PackedSequence对象包括:
- 一个
data
对象:一个torch.Variable(令牌的总数,每个令牌的维度),在这个简单的例子中有五个令牌序列(用整数表示):(18,1) - 一个
batch_sizes
对象:每个时间步长的令牌数列表,在这个例子中为:[6,5,2,4,1]
用pack_padded_sequence函数来构造这个对象非常的简单:
如何构造一个PackedSequence对象(batch_first = True)
PackedSequence对象有一个很不错的特性,就是我们无需对序列解包(这一步操作非常慢)即可直接在PackedSequence数据变量上执行许多操作。特别是我们可以对令牌执行任何操作(即对令牌的顺序/上下文不敏感)。当然,我们也可以使用接受PackedSequence作为输入的任何一个pyTorch模块(pyTorch 0.2)。
2、torch.nn.utils.rnn.
pack_padded_sequence()
这里的pack
,理解成压紧比较好。 将一个 填充过的变长序列 压紧。(填充时候,会有冗余,所以压紧一下)
输入的形状可以是(T×B×* )。T
是最长序列长度,B
是batch size
,*
代表任意维度(可以是0)。如果batch_first=True
的话,那么相应的 input size
就是 (B×T×*)
。
Variable
中保存的序列,应该按序列长度的长短排序,长的在前,短的在后。即input[:,0]
代表的是最长的序列,input[:, B-1]
保存的是最短的序列。
NOTE:
只要是维度大于等于2的input
都可以作为这个函数的参数。你可以用它来打包labels
,然后用RNN
的输出和打包后的labels
来计算loss
。通过PackedSequence
对象的.data
属性可以获取 Variable
。
参数说明:
-
input (Variable) – 变长序列 被填充后的 batch
-
lengths (list[int]) –
Variable
中 每个序列的长度。 -
batch_first (bool, optional) – 如果是
True
,input的形状应该是B*T*size
。
返回值:
一个PackedSequence
对象。
3、torch.nn.utils.rnn.
pad_packed_sequence
()
填充packed_sequence
。
上面提到的函数的功能是将一个填充后的变长序列压紧。 这个操作和pack_padded_sequence()是相反的。把压紧的序列再填充回来。
返回的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中序列的长度列表。
例子:
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 |
|
输出:
1 2 3 4 5 6 7 8 9 10 |
|