PyTorch 张量变形指南:彻底搞懂 view, reshape, permute, transpose
·
简介
在 PyTorch 中, view 、 reshape 、 permute 和 transpose 都是用于改变张量(Tensor)形状或维度的操作,但它们的实现机制、使用限制和底层原理存在关键区别。
下面我将为你详细解析它们的功能、区别与联系。
| 接口 | 主要功能 | 核心特点 |
|---|---|---|
view | 改变张量形状 | 返回新张量,与原张量共享内存,要求张量在内存中是连续的。 |
reshape | 改变张量形状 | 功能与 view 类似,但更灵活,能处理非连续张量。 |
permute | 重排所有维度顺序 | 返回新张量,交换维度,不改变元素总数。 |
transpose | 交换两个指定维度 | permute 的特例,专门用于交换两个维度。 |
实例
1、view 与 reshape
创建一个 2×3 的张量
import torch
x = torch.arange(6).reshape(2, 3)
print(x)
print(x.shape)
输出:
tensor([[0, 1, 2],
[3, 4, 5]])
torch.Size([2, 3])
view :改变形状
y_view = x.view(6)
print(y_view)
输出:
tensor([0, 1, 2, 3, 4, 5])
transpose :交换两个指定维度,会使张量在内存中变得不在连续
y_transpose = x.transpose(0, 1)
print(y_transpose)
print(y_transpose.is_contiguous())
输出:
由原始的(2,3)变为(3,2)
tensor([[0, 3],
[1, 4],
[2, 5]])
False
直接对 x_transpose 使用 view 会报错,因为 view 只能处理在内存中连续的张量
y_transpose_view = y_transpose.view(6)
print(y_transpose_view)
输出:
RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.
必须先使用 contiguous() 把张量变为连续
y_transpose_view = y_transpose.contiguous().view(6)
print(y_transpose_view)
输出:
tensor([0, 3, 1, 4, 2, 5])
reshape :会自动处理不连续的情况
y_reshape = y_transpose.reshape(6)
print(y_reshape)
输出:
tensor([0, 3, 1, 4, 2, 5])
2、permute 和 transpose
创建出一个三维张量
import torch
z = torch.randn(2,3,4)
print(z.shape)
输出:
torch.Size([2, 3, 4])
transpose::交换最后两个维度
z_transpose = z.transpose(1,2)
print(f"交换维度后的形状:{z_transpose.shape}")
输出:
原来的形状是[2, 3, 4]
0,1,2 交换1和2 也就是 [2, 4, 3]
交换维度后的形状:torch.Size([2, 4, 3])
permute :将维度顺序完全颠倒
z_permute = z.permute(2,1,0)
print(f"重排维度后的形状:{z_permute.shape}")
输出:
原来的形状是[2, 3, 4]
0,1,2 维度变为 2,1,0 也就变为[4, 3, 2],如果permute(2,0,1) 则是 [4, 2, 3]
重排维度后的形状:torch.Size([4, 3, 2])
对比
view vs reshape: 改变形状
这两个方法都用于改变张量的“外观”(形状),而不改变其内部元素的总数。
view- 工作原理:它只是创建了一个指向原始数据的新“视图”,不会复制数据。因此,修改
view返回的张量也会影响原始张量。 - 关键限制:它要求原始张量在内存中是**连续存储(contiguous)**的。如果你对张量进行了
transpose或permute等操作,它在内存中的存储顺序会变得不连续,此时直接调用view会报错。 - 解决方法:在不连续的张量上调用
view前,必须先调用.contiguous()方法,使其在内存中变为连续。
- 工作原理:它只是创建了一个指向原始数据的新“视图”,不会复制数据。因此,修改
reshape- 工作原理:它是
view的一个更“智能”和“宽容”的版本。如果原始张量是连续的,reshape的行为和view完全一样(共享内存)。如果张量不连续,reshape会自动复制数据,创建一个新的连续张量并返回。 - 优点:使用更方便,不用担心连续性问题。
- 缺点:由于可能触发数据复制,在某些情况下性能开销会比
view稍大。
- 工作原理:它是
一句话总结:在确定张量是连续的情况下,优先使用 view;如果不确定或想图省事,就用 reshape。
permute vs transpose: 交换维度
这两个方法都用于改变张量的维度顺序,而不是改变形状本身。
permute- 功能:可以对张量的所有维度进行任意顺序的重排。你需要传入一个包含所有维度索引的元组。
- 示例:一个形状为
(C, H, W)的图像张量,如果想变为(H, W, C),就需要使用tensor.permute(1, 2, 0)。
transpose- 功能:是
permute的一个特例,专门用于交换两个指定的维度。 - 示例:一个形状为
(N, C)的二维矩阵,进行转置操作tensor.transpose(0, 1)后,形状变为(C, N)。对于二维张量,transpose(0, 1)和permute(1, 0)的效果是完全一样的。
- 功能:是
一句话总结:当只需要交换两个维度时,使用 transpose 更直观;当需要重排多个维度时,必须使用 permute。
核心区别与联系
- 功能目的不同
view/reshape用于改变形状(例如,将[2, 3]变为[6])。permute/transpose用于改变维度顺序(例如,将[2, 3]变为[3, 2])。
- 内存连续性要求不同
view对内存连续性有严格要求。reshape、permute和transpose通常不要求张量是连续的(reshape会自动处理,permute/transpose会返回一个非连续的新视图)。
- 联系
reshape可以看作是view的“超集”,功能上包含了view。transpose是permute在二维情况下的特例。- 一个常见的组合操作是:先使用
permute或transpose交换维度,然后调用.contiguous(),最后使用view来改变形状。
完整代码
import torch
# view 与 reshape
x = torch.arange(6).reshape(2, 3)
print(x)
print(x.shape)
y_view = x.view(6)
print(y_view)
y_transpose = x.transpose(0, 1)
print(y_transpose)
print(y_transpose.is_contiguous())
y_transpose_view = y_transpose.contiguous().view(6)
print(y_transpose_view)
y_reshape = y_transpose.reshape(6)
print(y_reshape)
# permute 与 transpose
z = torch.randn(2,3,4)
print(z.shape)
z_transpose = z.transpose(1,2)
print(f"交换维度后的形状:{z_transpose.shape}")
z_permute = z.permute(2,1,0)
print(f"重排维度后的形状:{z_permute.shape}")
更多推荐



所有评论(0)