pytorch api文档:张量的.view() 和 torch.transpose() 函数的区别

区别

.view():重塑形状(不改变元素排列)

.transpose() 维度转置(交换维度顺序,改变元素排列)

差异总览

特征 .view(*shape) .transpose(dim0, dim1)
核心作用 重塑张量形状(维度数/维度大小可改),仅改变“维度解读方式” 交换两个指定维度的位置,维度数不变,改变元素排列
元素顺序 保持原内存中元素的顺序不变 改变元素在内存中的逻辑顺序(物理顺序可能不变)
内存连续性 要求张量内存连续(否则报错) 转置后张量内存通常变为非连续
共享内存 与原张量共享内存(修改其一则同步变化) 与原张量共享内存(修改其一则同步变化)
总元素数 必须保持不变(形状乘积相等) 总元素数始终不变(仅维度顺序交换)
典型场景 展平特征、调整批量维度(如 [2,3]→[6]) 维度交换(如 [2,3]→[3,2]、[B,C,H,W]→[B,H,W,C])

例子

通过具体例子,看两者对同一张量的操作效果差异:

import torch

# 基础张量:shape [2, 3],元素按行排列
x = torch.tensor([[1, 2, 3], 
                  [4, 5, 6]])
print("原张量:")
print(x)
print("原张量内存顺序(展平):", x.view(-1))  # [1,2,3,4,5,6]

# ========== .view() 操作 ==========
# 重塑为 [3, 2]:仅改变维度解读,元素内存顺序不变
x_view = x.view(3, 2)
print("\n--- .view(3, 2) 结果 ---")
print(x_view)
print("view后展平:", x_view.view(-1))  # 仍为 [1,2,3,4,5,6]

# ========== .transpose() 操作 ==========
# 交换维度0和维度1(行和列):改变元素排列,内存顺序变化
x_trans = x.transpose(0, 1)
print("\n--- .transpose(0, 1) 结果 ---")
print(x_trans)
print("transpose后展平:", x_trans.contiguous().view(-1))  # [1,4,2,5,3,6]

# ========== 共享内存验证 ==========
# 修改view后的张量,原张量同步变化
x_view[0, 0] = 100
print("\n修改view张量后,原张量:")
print(x)  # [100,2,3; 4,5,6]

# 重置原张量,验证transpose的共享内存
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
x_trans = x.transpose(0, 1)
x_trans[0, 1] = 200
print("\n修改transpose张量后,原张量:")
print(x)  # [1,2,3; 200,5,6]

# ========== 内存连续性验证 ==========
print("\n原张量是否连续:", x.is_contiguous())  # True
print("transpose后是否连续:", x_trans.is_contiguous())  # False
# x_trans.view(6)  # 直接调用会报错!需先contiguous
print("transpose后contiguous再view:", x_trans.contiguous().view(6))  # 正常

输出特征:

  • .view(3,2) 只是把原张量的6个元素“按顺序拆成3行2列”,元素顺序未变;
  • .transpose(0,1) 是真正的“行列交换”,元素排列改变,展平后顺序变为 [1,4,2,5,3,6];
  • 转置后的张量内存非连续,直接用 .view() 会报错,需先调用 .contiguous() 整理内存。

使用场景对比

.view() 的核心场景

  • 特征展平:CNN输出 [B,C,H,W] → 全连接层输入 [B, C*H*W](x.view(x.size(0), -1));
  • 批量维度调整:将 [B*seq_len, dim] 恢复为 [B, seq_len, dim];
  • 维度压缩/扩展:如 [32,64] → [32,1,64](适配Conv1d输入)。

.transpose() 的核心场景

  • 维度顺序调整:
    • 图像处理:将PyTorch默认的 [B,C,H,W] 转为OpenCV的 [B,H,W,C](x.transpose(1,3).transpose(2,3));
    • NLP:将 [seq_len, B, dim] 转为 [B, seq_len, dim](x.transpose(0,1));
  • 矩阵转置:二维矩阵的行列交换(等价于 .t(),.t() 是 .transpose(0,1) 的简化版)。

注意事项

  1. .transpose() 仅交换两个维度:若需交换多个维度(如 [B,C,H,W]→[B,H,W,C]),需多次调用 .transpose(),或用更灵活的 .permute()(.permute(0,2,3,1) 一步到位);
  2. 非连续张量的.view() 限制:转置/切片后的非连续张量,必须先用 .contiguous() 整理内存,才能调用 .view();
  3. 共享内存的风险:两者都与原张量共享内存,修改新张量会同步改变原张量,需独立张量时加 .clone()。

总结

  1. .view() 是形状重塑,不改变元素排列,要求内存连续、总元素数不变,适合展平/调整维度结构;
  2. .transpose() 是维度交换,改变元素排列,维度数不变,转置后内存非连续,适合调整维度顺序;
  3. 核心区分:看是否需要改变元素的排列顺序——仅改形状用 .view(),改维度顺序用 .transpose()。

原文出处:/show_1GW2dKLmsG0U.html