pytorch api文档:张量的 .view()形状变换方法 作者:马育民 • 2026-01-21 17:05 • 阅读:10001 # 介绍 `.view()` 方法,这个方法是张量形状变换的核心工具,用于在不改变张量数据的前提下,调整张量的维度结构(如将一维张量转为二维、将四维特征图展平为二维等)。 ### 作用 返回一个与原张量**共享内存**的新视图(新形状),张量的 **总元素数必须保持不变(即形状的乘积相等)**,数据本身不复制、不修改,仅改变维度的解读方式。 ### 关键特征 新张量与原张量共享内存,**修改其中一个,另一个也会同步变化**。 # 语法 ``` Tensor.view(*shape) → Tensor ``` **参数:** - `*shape`:指定新的形状,可以是单个整数、多个整数,或包含 `-1`(自动计算该维度的大小,且只能有一个 `-1`); # 对比 .reshape() `.reshape()` 是 `.view()` 的升级版,功能类似,但 `.view()` 仅支持连续内存的张量,`.reshape()` 可自动处理非连续张量(必要时复制数据)。 # 例子 通过不同场景的示例,演示 `.view()` 的核心用法: ```python import torch # 原张量:shape [2, 3](总元素数=6) x = torch.tensor([[1, 2, 3], [4, 5, 6]]) print("原张量形状:", x.shape) # torch.Size([2, 3]) ``` ### 示例1:基础形状变换(总元素数不变) # 转为 [3, 2] ``` x_view1 = x.view(3, 2) print("\nview(3, 2) 结果:") print(x_view1) # 输出: # tensor([[1, 2], # [3, 4], # [5, 6]]) ``` ### 示例2:使用-1自动计算维度(常用!) ``` # -1 表示“自动计算该维度的大小”,仅能出现一次 x_view2 = x.view(-1) # 展平为一维(6个元素) print("\nview(-1) 结果(展平):", x_view2) # tensor([1, 2, 3, 4, 5, 6]) x_view3 = x.view(2, -1) # 固定第一维为2,第二维自动算(3) print("view(2, -1) 形状:", x_view3.shape) # torch.Size([2, 3]) x_view4 = x.view(-1, 3) # 固定第二维为3,第一维自动算(2) print("view(-1, 3) 形状:", x_view4.shape) # torch.Size([2, 3]) ``` ### 示例3:高维张量变换(如CNN特征图展平) ``` # 模拟CNN输出:[batch_size=2, channel=3, height=4, width=4](总元素=2*3*4*4=96) feat = torch.randn(2, 3, 4, 4) # 展平为 [2, 3*4*4](batch保留,特征展平) feat_flat = feat.view(2, -1) print("\n高维张量view后形状:", feat_flat.shape) # torch.Size([2, 48]) ``` ### 示例4:共享内存特性(修改新视图,原张量也变) ``` x_view1[0, 0] = 100 # 修改view后的张量 print("\n修改view张量后,原张量:") print(x) # 原张量[0,0]也变为100! # 输出: # tensor([[100, 2, 3], # [ 4, 5, 6]]) ``` # 使用场景 `.view()` 是深度学习中高频使用的操作,典型场景包括: ### 全连接层前的特征展平 CNN模型中,卷积层输出的四维张量(`[batch, channel, h, w]`)需展平为二维(`[batch, channel*h*w]`)才能输入全连接层: ```python class CNN(nn.Module): def __init__(self): super().__init__() self.conv = nn.Conv2d(3, 16, 3) # 输出[batch,16,30,30](假设输入224x224) self.fc = nn.Linear(16*30*30, 10) # 全连接层需要一维特征 def forward(self, x): x = self.conv(x) # 展平:保留batch维度,其余展平 x = x.view(x.size(0), -1) # x.size(0) = batch_size,-1自动计算16*30*30 x = self.fc(x) return x ``` ### 调整批量数据形状 将一维的批量数据(如 `[batch*seq_len, dim]`)恢复为二维(`[batch, seq_len, dim]`): ```python # 输入:[8, 768](batch=2, seq_len=4,总长度=8) x = torch.randn(8, 768) # 恢复为 [2, 4, 768] x_reshaped = x.view(2, 4, 768) ``` ### 维度压缩/扩展 临时调整维度以适配层的输入要求(如将 `[batch, dim]` 转为 `[batch, 1, dim]` 适配卷积层): ```python x = torch.randn(32, 64) # [batch=32, dim=64] # 转为 [32, 1, 64](适配Conv1d的输入格式) x_expand = x.view(32, 1, 64) ``` # 注意事项 ### 总元素数必须相等 新形状的乘积必须等于原张量的总元素数,否则报错。例如: ```python x = torch.randn(2, 3) x.view(4, 2) # 报错!2*3=6 ≠ 4*2=8 ``` ### 仅支持连续内存张量 如果张量经过转置(`.t()`)、切片等操作后内存不连续,`.view()` 会报错,此时需用 `.contiguous()` 先整理内存,或直接用 `.reshape()`: ```python x = torch.randn(2, 3).t() # 转置后内存不连续 # x.view(6) # 报错! x_contig = x.contiguous() x_contig.view(6) # 正常 # 更简单:用reshape x.reshape(6) # 自动处理非连续内存 ``` ### 共享内存的风险 修改 `.view()` 返回的张量会同步修改原张量,若需独立张量,需用 `.clone()` 复制: ```python x = torch.tensor([1,2,3]) x_view = x.view(3,1).clone() # 复制后不再共享内存 x_view[0,0] = 100 print(x) # 仍为[1,2,3],不受影响 ``` ### -1的使用限制 `.view()` 中 `-1` 只能出现一次,用于自动计算维度,多次出现会报错: ```python x.view(-1, -1) # 报错!只能有一个-1 ``` # 总结 1. `.view()` 核心是**共享内存的形状变换**,总元素数必须不变,常用 `-1` 自动计算维度; 2. 典型场景:CNN特征展平、批量数据形状调整、维度适配; 3. 注意内存连续性问题(报错时用 `.contiguous()` 或 `.reshape()`),以及共享内存的修改风险。 原文出处:http://malaoshi.top/show_1GW2dKE8Ksnx.html