pytorch對可變長度序列的處理
主要是用函數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對象有一個很不錯的特性,就是我們無需對序列解包(這一步操作非常慢)即可直接在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中序列的長度列表。
例子:
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], [1, 0, 0]]).resize_(2,3,1) tensor_in = Variable( tensor_in ) #[batch, seq, feature], [2, 3, 1] seq_lengths = [3,1] # list of integers holding information about the batch size at each sequence step # pack it pack = nn_utils.rnn.pack_padded_sequence(tensor_in, seq_lengths, batch_first=True) # initialize rnn = nn.RNN(1, hidden_size, n_layers, batch_first=True) h0 = Variable(torch.randn(n_layers, batch_size, hidden_size)) #forward out, _ = rnn(pack, h0) # unpack unpacked = nn_utils.rnn.pad_packed_sequence(out) print(‘111‘,unpacked)
輸出:
111 (Variable containing: (0 ,.,.) = 0.5406 0.3584 -0.1403 0.0308 (1 ,.,.) = -0.6855 -0.9307 0.0000 0.0000 [torch.FloatTensor of size 2x2x2] , [2, 1])
pytorch對可變長度序列的處理