pytorch api文档:张量的.view() 和 torch.transpose() 函数的区别 作者:马育民 • 2026-01-21 17:18 • 阅读:10000 # 区别 `.view()`:**重塑形状**(不改变元素排列) `.transpose()` **维度转置**(交换维度顺序,改变元素排列) ### 差异总览 | 特征 | `.view(*shape)` | `.transpose(dim0, dim1)` | |---------------------|------------------------------------------|-----------------------------------------| | **核心作用** | 重塑张量形状(维度数/维度大小可改),仅改变“维度解读方式” | 交换两个指定维度的位置,维度数不变,改变元素排列 | | **元素顺序** | 保持原内存中元素的顺序不变 | 改变元素在内存中的逻辑顺序(物理顺序可能不变) | | **内存连续性** | 要求张量内存连续(否则报错)| 转置后张量内存通常变为**非连续** | | **共享内存** | 与原张量共享内存(修改其一则同步变化)| 与原张量共享内存(修改其一则同步变化)| | **总元素数** | 必须保持不变(形状乘积相等)| 总元素数始终不变(仅维度顺序交换)| | **典型场景** | 展平特征、调整批量维度(如 [2,3]→[6])| 维度交换(如 [2,3]→[3,2]、[B,C,H,W]→[B,H,W,C]) | # 例子 通过具体例子,看两者对同一张量的操作效果差异: ```python 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()`。 原文出处:http://malaoshi.top/show_1GW2dKLmsG0U.html