PyTorch Tensor 形状变化操作详解
PyTorch Tensor 形状变化操作详解
在深度学习中,Tensor 的形状变换是非常常见的操作。PyTorch 提供了丰富的 API 来帮助我们调整 Tensor 的形状,以满足模型输入、计算或数据处理的需求。本文将详细介绍 PyTorch 中常见的 Tensor 形状变换操作,并通过示例代码进行说明。
1. 基础形状操作
1.1 view
和 reshape
- 功能:改变 Tensor 的形状而不改变其数据。
- 区别:
view
要求新形状的总元素数与原形状一致,否则会报错。reshape
更灵活,如果无法直接改变形状,会尝试创建一个新的 Tensor。
- 示例:
tensor = torch.randn(2, 3, 4) # 原形状为 (2, 3, 4)
reshaped_tensor = tensor.view(2, 12) # 改变形状为 (2, 12)
print(reshaped_tensor.shape) # 输出: torch.Size([2, 12])
1.2 squeeze
和 unsqueeze
- 功能:
squeeze
:移除大小为 1 的维度。unsqueeze
:在指定位置插入大小为 1 的维度。
- 示例:
tensor = torch.randn(1, 3, 1, 4) # 原形状为 (1, 3, 1, 4)
squeezed_tensor = tensor.squeeze() # 移除所有大小为 1 的维度
print(squeezed_tensor.shape) # 输出: torch.Size([3, 4])
unsqueezed_tensor = squeezed_tensor.unsqueeze(0) # 在第 0 维插入大小为 1 的维度
print(unsqueezed_tensor.shape) # 输出: torch.Size([1, 3, 4])
2. 高级形状操作
2.1 permute
- 功能:重新排列 Tensor 的维度顺序。
- 示例:
tensor = torch.randn(2, 3, 4) # 原形状为 (2, 3, 4)
permuted_tensor = tensor.permute(2, 0, 1) # 调整为 (4, 2, 3)
print(permuted_tensor.shape) # 输出: torch.Size([4, 2, 3])
2.2 transpose
- 功能:交换指定的两个维度。
- 示例:
tensor = torch.randn(3, 4) # 原形状为 (3, 4)
transposed_tensor = tensor.transpose(0, 1) # 交换第 0 和第 1 维度
print(transposed_tensor.shape) # 输出: torch.Size([4, 3])
2.3 flatten
- 功能:将指定范围内的维度展平为一维。
- 示例:
tensor = torch.randn(2, 3, 4) # 原形状为 (2, 3, 4)
flattened_tensor = tensor.flatten(start_dim=1) # 展平从第 1 维开始
print(flattened_tensor.shape) # 输出: torch.Size([2, 12])
2.4 repeat
- 功能:沿指定维度重复 Tensor。
- 示例:
tensor = torch.tensor([[1, 2], [3, 4]]) # 原形状为 (2, 2)
repeated_tensor = tensor.repeat(2, 3) # 在第 0 维重复 2 次,在第 1 维重复 3 次
print(repeated_tensor.shape) # 输出: torch.Size([4, 6])
2.5 expand
- 功能:在不复制数据的情况下扩展 Tensor 的形状(仅适用于大小为 1 的维度)。
- 示例:
tensor = torch.tensor([[1], [2], [3]]) # 原形状为 (3, 1)
expanded_tensor = tensor.expand(3, 4) # 扩展为 (3, 4)
print(expanded_tensor)
# 输出:
# tensor([[1, 1, 1, 1],
# [2, 2, 2, 2],
# [3, 3, 3, 3]])
3. 数据提取与分散
3.1 narrow
- 功能:按指定维度和范围提取部分 Tensor。
- 示例:
tensor = torch.arange(10) # 原形状为 (10,)
narrowed_tensor = tensor.narrow(0, 2, 4) # 从第 0 维索引 2 开始提取长度为 4 的部分
print(narrowed_tensor) # 输出: tensor([2, 3, 4, 5])
3.2 gather
- 功能:根据索引从指定维度收集元素。
- 示例:
tensor = torch.tensor([[1, 2], [3, 4]]) # 原形状为 (2, 2)
indices = torch.tensor([[0, 1], [1, 0]]) # 索引矩阵
gathered_tensor = torch.gather(tensor, 1, indices) # 按列索引收集
print(gathered_tensor)
# 输出:
# tensor([[1, 2],
# [4, 3]])
3.3 scatter
- 功能:根据索引将值分散到目标 Tensor 中。
- 示例:
tensor = torch.zeros(2, 3) # 目标 Tensor,初始为零
indices = torch.tensor([[0, 1, 2], [2, 0, 1]]) # 索引矩阵
values = torch.tensor([[5, 6, 7], [8, 9, 10]]) # 值矩阵
scattered_tensor = tensor.scatter(1, indices, values) # 按列分散赋值
print(scattered_tensor)
# 输出:
# tensor([[5., 6., 7.],
# [0., 9., 8.]])
4. 对角操作
4.1 diag
- 功能:提取对角线元素或将一维 Tensor 转换为对角矩阵。
- 示例:
tensor = torch.tensor([1, 2, 3]) # 一维 Tensor
diag_tensor = torch.diag(tensor) # 创建对角矩阵
print(diag_tensor)
# 输出:
# tensor([[1, 0, 0],
# [0, 2, 0],
# [0, 0, 3]])