目录
nn.utils.rnn.pack_padded_sequence
nn.utils.rnn.pad_packed_sequence
torch.nn子模块详解
nn.utils.rnn.PackedSequence
torch.nn
子模块是 PyTorch 框架的一部分,专门用于构建神经网络。这个模块提供了许多预定义的层(例如全连接层、卷积层、循环神经网络层),以及用于构建自定义网络结构的功能。torch.nn
的一个关键特点是它的模块和层是面向对象的,使得神经网络的构建和实验变得更加简洁和直观。
PackedSequence
类是 torch.nn.utils.rnn
模块中的一个重要类,专门用于处理循环神经网络中的变长序列。在处理像自然语言这样的序列数据时,不同的样本可能会有不同的长度。PackedSequence
允许有效地处理这种不等长的序列数据。
参数说明
data (Tensor)
: 包含打包序列的张量。batch_sizes (Tensor)
: 包含每个序列步骤中批量大小的整数张量。sorted_indices (Tensor, 可选)
: 包含如何从序列构建此PackedSequence
的整数张量。unsorted_indices (Tensor, 可选)
: 包含如何恢复具有正确顺序的原始序列的整数张量。
注意事项
- 不应手动创建
PackedSequence
实例。它们应该由诸如pack_padded_sequence()
之类的函数实例化。 batch_sizes
应始终是 CPU 上的torch.int64
张量。data
可以在任意设备上,有任意的数据类型。但sorted_indices
和unsorted_indices
必须是与data
相同设备上的torch.int64
张量。
示例代码
import torch
import torch.nn.utils.rnn as rnn_utils
# 假设我们有一些变长的序列数据
sequences = [torch.tensor([1,2,3]), torch.tensor([4,5]), torch.tensor([6])]
# 对序列进行填充并打包
padded_sequences = rnn_utils.pad_sequence(sequences, batch_first=True)
packed_sequences = rnn_utils.pack_padded_sequence(padded_sequences, batch_first=True, lengths=[3, 2, 1])
# 使用RNN处理打包的序列
rnn = torch.nn.RNN(input_size=1, hidden_size=5, batch_first=True)
output, hidden = rnn(packed_sequences.data.unsqueeze(-1))
# 解包序列
output, output_lengths = rnn_utils.pad_packed_sequence(output, batch_first=True)
在这个例子中,首先通过 pad_sequence
将不同长度的序列填充到相同的长度,然后使用 pack_padded_sequence
将填充后的序列打包。之后,使用 RNN 对这个打包后的序列进行处理。最后,通过 pad_packed_sequence
将输出解包。这种方法可以有效处理变长序列,同时提高 RNN 的效率和性能。
nn.utils.rnn.pack_padded_sequence
torch.nn.utils.rnn.pack_padded_sequence
是 PyTorch 中处理循环神经网络(RNN)时非常重要的一个函数。它用于将填充过的、长度不一的序列数据打包成一个 PackedSequence
对象,以便更高效地在 RNN 中使用。这个函数特别适用于处理像自然语言这样的序列数据,其中每个样本(例如一个句子)的长度可能不同。
参数说明
input (Tensor)
: 填充过的变长序列的批次。它可以是 T x B x * 的形状,其中 T 是最长序列的长度(等于lengths[0]
),B 是批量大小,* 是任意数量的维度(包括 0)。如果batch_first
为 True,则期望输入为 B x T x * 的格式。lengths (Tensor 或 list(int))
: 每个批次元素的序列长度列表(如果提供为张量,则必须在 CPU 上)。batch_first (bool, 可选)
: 如果为 True,则输入预期为 B x T x * 格式。enforce_sorted (bool, 可选)
: 如果为 True,则输入应包含按长度递减排序的序列。如果为 False,则无条件对输入进行排序。默认值为 True。
返回值
- 返回一个
PackedSequence
对象。
注意事项
- 这个函数接受至少有两个维度的任何输入。你可以将它应用于打包标签,并将 RNN 的输出与它们一起用来直接计算损失。可以通过访问其
.data
属性从PackedSequence
对象中检索张量。 - 如果
enforce_sorted
为 True,则序列应按长度降序排序。这在准备进行 ONNX 导出时是必要的。
示例代码
import torch
import torch.nn.utils.rnn as rnn_utils
# 假设我们有填充过的变长序列和它们的长度
padded_sequences = torch.tensor([[1, 2, 3, 0], [4, 5, 0, 0], [6, 0, 0, 0]])
lengths = [3, 2, 1]
# 将填充过的序列打包
packed_sequences = rnn_utils.pack_padded_sequence(padded_sequences, lengths, batch_first=True)
# 现在可以将 packed_sequences 用于 RNN
在这个例子中,padded_sequences
包含三个序列,长度分别为 3、2 和 1。通过 pack_padded_sequence
函数,这些序列被有效地打包成一个 PackedSequence
对象,然后可以直接传递给 RNN 模块进行处理。这种方法有助于提高 RNN 在处理变长序列时的效率和性能。
nn.utils.rnn.pad_packed_sequence
torch.nn.utils.rnn.pad_packed_sequence
是 PyTorch 中用于处理循环神经网络(RNN)的一个重要函数。这个函数执行的是 pack_padded_sequence()
的逆操作,即它将 PackedSequence
对象解压缩并填充回原始维度的张量中。这在 RNN 处理完变长序列后,需要恢复到原始序列形状以进行进一步操作时非常有用。
参数说明
sequence (PackedSequence)
: 需要填充的打包序列批次。batch_first (bool, 可选)
: 如果为 True,则输出将以 B x T x * 的格式排列。padding_value (float, 可选)
: 用于填充元素的值。total_length (int, 可选)
: 如果非 None,则输出将填充至长度为total_length
。如果total_length
小于序列中的最大序列长度,则此方法将抛出 ValueError。
返回值
- 返回一个元组,包含填充后的序列的张量,以及一个包含批次中每个序列长度的张量。批次元素将按照它们最初在
pack_padded_sequence
或pack_sequence
中被排列的顺序重新排序。
注意事项
total_length
参数在将序列打包 -> 通过循环网络处理 -> 解压序列的模式在DataParallel
包装的模块中非常有用。有关详细信息,请参见相关的 FAQ 部分。
示例代码
from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence
import torch
# 假设有一些填充过的序列和它们的长度
seq = torch.tensor([[1, 2, 0], [3, 0, 0], [4, 5, 6]])
lens = [2, 1, 3]
# 将填充过的序列打包
packed = pack_padded_sequence(seq, lens, batch_first=True, enforce_sorted=False)
# 解压打包的序列
seq_unpacked, lens_unpacked = pad_packed_sequence(packed, batch_first=True)
print(seq_unpacked) # 输出解压后的序列
print(lens_unpacked) # 输出解压后的序列长度
在这个例子中,首先使用 pack_padded_sequence
将填充过的序列进行打包,然后通过 pad_packed_sequence
将打包的序列解压回原始的填充形式。这个过程在 RNN 模型处理变长序列后,需要将输出转换回可理解的形式时非常有用。
nn.utils.rnn.pad_sequence
torch.nn.utils.rnn.pad_sequence
是 PyTorch 中的一个用于处理循环神经网络(RNN)的有用函数。这个函数主要用于将长度不同的一系列张量(tensors)填充至相同的长度,从而可以将它们有效地组合成一个批次(batch)并用于 RNN 操作。
参数说明
sequences (list[Tensor])
: 需要填充的不同长度序列的列表。batch_first (bool, 可选)
: 如果为 True,则输出将以 B x T x * 的格式排列;如果为 False,则输出将以 T x B x * 的格式排列。默认为 False。padding_value (float, 可选)
: 用于填充元素的值。默认值为 0。
返回值
- 返回一个张量(Tensor),其大小为 T x B x *(如果
batch_first
为 False)或 B x T x *(如果batch_first
为 True),其中 T 是最长序列的长度。
注意事项
- 这个函数假设所有序列中的尾随维度和类型是相同的。
- 这个函数通过在一个新的维度上堆叠一系列张量,并填充它们以使它们具有相同的长度,来工作。例如,如果输入是一系列大小为 L x * 的序列,并且
batch_first
为 False,则输出的大小为 T x B x *。
示例代码
from torch.nn.utils.rnn import pad_sequence
import torch
# 假设有几个不同长度的张量
a = torch.ones(25, 300) # 第一个张量
b = torch.ones(22, 300) # 第二个张量
c = torch.ones(15, 300) # 第三个张量
# 使用 pad_sequence 来填充这些张量
padded_sequence = pad_sequence([a, b, c])
print(padded_sequence.size()) # 输出填充后的张量大小
在这个例子中,三个不同长度的张量 a
、b
和 c
被填充至相同的长度(最长序列的长度,即 25)。pad_sequence
函数在一个新的维度上堆叠这些张量,并填充较短的张量以匹配最长的张量。这使得它们可以作为一个批次输入到 RNN 中。
nn.utils.rnn.pack_sequence
torch.nn.utils.rnn.pack_sequence
是 PyTorch 中用于处理循环神经网络(RNN)的一个有用函数。它用于将一系列不同长度的张量(tensors)打包成一个 PackedSequence
对象。这个函数实际上是 pad_sequence
和 pack_padded_sequence
这两个函数的连续调用的简化版本。
参数说明
sequences (list[Tensor])
: 一系列张量的列表,这些张量应按长度递减的顺序排列。enforce_sorted (bool, 可选)
: 如果为 True,则检查输入是否包含按长度递减排序的序列。如果为 False,则不检查此条件。默认为 True。
返回值
- 返回一个
PackedSequence
对象。
注意事项
- 如果
enforce_sorted
为 True,序列应按长度降序排序。这在准备进行 ONNX 导出时是必要的。 - 每个张量应该是大小为 L x * 的形状,其中 L 是序列的长度,* 是任意数量的尾随维度(包括零)。
示例代码
from torch.nn.utils.rnn import pack_sequence
import torch
# 创建几个不同长度的张量
a = torch.tensor([1, 2, 3]) # 第一个张量
b = torch.tensor([4, 5]) # 第二个张量
c = torch.tensor([6]) # 第三个张量
# 使用 pack_sequence 将这些张量打包
packed_sequence = pack_sequence([a, b, c])
print(packed_sequence)
在这个例子中,三个不同长度的张量 a
、b
和 c
被打包成一个 PackedSequence
对象。这个过程有助于后续将这些序列有效地输入到 RNN 中进行处理。这种方法特别适用于处理像自然语言这样的序列数据,其中每个样本(例如一个句子)的长度可能不同。
nn.utils.rnn.unpack_sequence
torch.nn.utils.rnn.unpack_sequence
是 PyTorch 中用于处理循环神经网络(RNN)的一个函数。这个函数的作用是将 PackedSequence
对象解包成一系列不同长度的张量(tensors)。这通常在 RNN 处理完 PackedSequence
后,需要将其转换回原始序列形式时使用。
参数说明
packed_sequences (PackedSequence)
: 需要解包的PackedSequence
对象。
返回值
- 返回一个由张量(Tensor)对象组成的列表。
注意事项
unpack_sequence
函数是pack_sequence
的逆过程,用于将经过 RNN 处理的数据转换回其原始序列的形式。- 请注意,PyTorch 中截至最后更新(2023年4月)并没有名为
unpack_sequence
的官方函数。通常情况下,使用pad_packed_sequence
来完成类似的解包操作。如果unpack_sequence
存在于某个特定版本的 PyTorch 中或是新添加的功能,可能需要查阅最新的官方文档以获取最准确的信息。
示例代码
from torch.nn.utils.rnn import pack_sequence, unpack_sequence
import torch
# 创建几个不同长度的张量
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5])
c = torch.tensor([6])
# 将这些张量打包成一个 PackedSequence
sequences = [a, b, c]
packed_sequences = pack_sequence(sequences)
# 解包 PackedSequence
unpacked_sequences = unpack_sequence(packed_sequences)
print(unpacked_sequences)
在这个例子中,pack_sequence
用于将几个不同长度的张量打包成一个 PackedSequence
对象,然后 unpack_sequence
(假设该函数存在)用于将这个打包的对象解包成原始的序列列表。这个过程有助于在 RNN 中处理完数据后,将其恢复到可理解的形式。
nn.utils.rnn.unpad_sequence
torch.nn.utils.rnn.unpad_sequence
是 PyTorch 中用于处理循环神经网络(RNN)的一个函数。它的作用是将填充过的张量(Tensor)解压缩成一系列原始长度的张量。这个函数在处理经过填充以适应批次处理要求的序列数据后,需要恢复到其原始长度的场景中非常有用。
参数说明
padded_sequences (Tensor)
: 已填充的序列。lengths (Tensor)
: 原始(未填充)序列的长度。batch_first (bool, 可选)
: 批次维度是否在前。默认为 False。
返回值
- 返回一个由张量(Tensor)对象组成的列表。
注意事项
unpad_sequence
是pad_sequence
的逆过程,用于将填充后的序列恢复到其原始长度。- 这个函数对于处理那些因为批次处理要求而被填充过的序列数据特别有用,尤其是在序列数据处理完毕后需要还原到它们的原始形式时。
示例代码
from torch.nn.utils.rnn import pad_sequence, unpad_sequence
import torch
# 创建几个不同长度的张量
a = torch.ones(25, 300)
b = torch.ones(22, 300)
c = torch.ones(15, 300)
sequences = [a, b, c]
# 将这些张量填充成相同长度
padded_sequences = pad_sequence(sequences)
lengths = torch.as_tensor([v.size(0) for v in sequences])
# 将填充过的序列解压缩回原始长度
unpadded_sequences = unpad_sequence(padded_sequences, lengths)
# 验证解压缩是否正确
assert torch.allclose(sequences[0], unpadded_sequences[0])
assert torch.allclose(sequences[1], unpadded_sequences[1])
assert torch.allclose(sequences[2], unpadded_sequences[2])
在这个例子中,pad_sequence
用于将几个不同长度的张量填充至相同的长度,然后 unpad_sequence
用于将这些填充过的序列恢复到它们的原始长度。通过这样的处理,可以确保在批次处理中的序列数据能够在处理完毕后被正确地还原。
nn.Flatten
torch.nn.Flatten
是 PyTorch 中的一个神经网络模块,用于将张量中指定范围的连续维度展平。它常用于卷积神经网络(CNN)到全连接层(Dense layer)的过渡,其中需要将多维特征映射转换为一维特征向量。
形状变换
- 输入: 形状为
的张量,其中
是第 i 维度的大小,∗ 表示包括零在内的任意数量的维度。
- 输出: 形状为
的张量,即从
start_dim
到end_dim
维度的大小相乘得到的展平维度。
参数
start_dim (int)
: 开始展平的维度(默认为 1)。end_dim (int)
: 结束展平的维度(默认为 -1)。
示例
-
默认参数:
import torch
import torch.nn as nn
input = torch.randn(32, 1, 5, 5)
m = nn.Flatten()
output = m(input)
print(output.size()) # 输出: torch.Size([32, 25])
在这个例子中,Flatten
默认从第 1 维(第一个 1)开始,展平到最后一维,将 5×55×5 的二维特征映射转换为一维的 25 个特征。
2. 非默认参数:
m = nn.Flatten(0, 2)
output = m(input)
print(output.size()) # 输出: torch.Size([160, 5])
在这个例子中,Flatten
从第 0 维开始,展平到第 2 维,即将原始的 32×1×532×1×5 形状的张量转换为 160×5160×5 的形状。
Flatten
模块在神经网络中非常有用,尤其是在需要处理多维数据并将其转换为一维数据以输入到全连接层的场景中。
nn.Unflatten
torch.nn.Unflatten
是 PyTorch 中的一个神经网络模块,用于将一个张量的指定维度展开为所需的形状。它通常用于神经网络中,尤其是在序列化的数据需要被还原为多维数据时,例如在将一维特征向量转换回原始的多维图像或序列格式。
形状变换
- 输入: 形状为(∗,Sdim,∗) 的张量,其中
是在
dim
维度的大小,∗∗ 表示包括零在内的任意数量的维度。 - 输出: 形状为(∗,U1,...,Un,∗) 的张量,其中 U 是
unflattened_size
,且。
参数
dim (Union[int, str])
: 要展开的维度。unflattened_size (Union[torch.Size, Tuple, List, NamedShape])
: 展开维度的新形状。
示例
使用整数元组:
import torch
import torch.nn as nn
input = torch.randn(2, 50)
m = nn.Sequential(
nn.Linear(50, 50),
nn.Unflatten(1, (2, 5, 5))
)
output = m(input)
print(output.size()) # 输出: torch.Size([2, 2, 5, 5])
在这个例子中,Unflatten
将第 1 维展开为形状 (2, 5, 5)。
使用 torch.Size
:
m = nn.Sequential(
nn.Linear(50, 50),
nn.Unflatten(1, torch.Size([2, 5, 5]))
)
output = m(input)
print(output.size()) # 输出: torch.Size([2, 2, 5, 5])
使用命名形状(NamedShape):
input = torch.randn(2, 50, names=('N', 'features'))
unflatten = nn.Unflatten('features', (('C', 2), ('H', 5), ('W', 5)))
output = unflatten(input)
print(output.size()) # 输出: torch.Size([2, 2, 5, 5])
Unflatten
在需要对数据维度进行灵活操作的神经网络设计中非常有用,特别是在需要从平展的特征向量恢复到多维空间表示的情况下。
总结
本文介绍了 PyTorch 框架中 torch.nn
子模块的关键组成部分及其功能。这个模块提供了多种用于构建神经网络的预定义层,如全连接层、卷积层和循环神经网络层。特别强调了 torch.nn.utils.rnn
中的几个重要类和函数,如 PackedSequence
、pack_padded_sequence
、pad_packed_sequence
、pad_sequence
、pack_sequence
、unpad_sequence
,它们在处理变长序列时特别有用。此外,还介绍了 Flatten
和 Unflatten
模块,这两个模块在处理多维数据时非常有用,前者将数据展平为一维,而后者则将一维数据还原为多维格式。整体上,本文提供了对 PyTorch 中重要网络构建模块的全面理解,强调了它们在实际应用中的重要性和灵活性。