PyTorch张量切片是否共享内存及支持梯度,取决于索引方式:基础方括号切片(如x[1:3, :, 0])通常返回视图、可微;高级索引(如x[[0,2], :, 0])触发拷贝、不可微;布尔索引需bool类型且同设备,结果为1D;index_select/gather用于可控采样;赋值仅视图支持,条件赋值用torch.where。
PyTorch张量切片本质是视图(view)或副本(copy)的生成,是否共享内存、是否可梯度回传,全由索引方式决定——直接用方括号多数情况返回视图,而或布尔索引可能触发拷贝,且不支持梯度流向原始张量。
用基础方括号索引做高效视图切片
PyTorch的
语法默认返回原张量的视图(view),内存共享、支持反向传播。但前提是索引操作满足“连续内存块映射”条件,比如步长为1、无重复索引、维度未打散。
是安全视图;
则强制拷贝(高级索引)
切片中混用
和列表索引(如
)会触发高级索引,结果不可微、不共享内存
避免写
——这会链式调用三次
,每次返回新视图,效率低且易出错;改用
负索引合法:
取最后一行,
取最后两列
用布尔Mask过滤时必须注意梯度与设备一致性
布尔掩码(boolean mask)是最常用的条件筛选方式,但极易因类型或设备不匹配导致静默失败或梯度中断。
Mask必须是
类型,
返回的就是
;若用
再转,就变成浮点掩码,
会报错
Mask和目标张量必须在同一个设备上:GPU张量不能用CPU上的mask索引,否则报
布尔索引结果总是1维展平输出:
不管
是3D还是4D,返回的都是1D张量;需用
保留原始坐标结构
若需保持维度,优先考虑
:例如
可实现掩码置零,且全程可导
用
和
控制采样粒度
当需要按指定下标沿某维度稳定采样(尤其batch维度),
比高级索引更可控;而
适合按每个样本独立选一个位置(如top-k预测)。
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
立即学习
“
Python免费学习笔记(深入)
”;
沿第0维取第2、第0、第2行,结果形状与
一致,且是视图(若
连续)
要求
与输入同维,常用于分类任务:例如
提取每个样本的真实类得分
的结果不可导到
(索引本身不参与梯度),但可导到
;若需索引可导,得换用
加权求和
所有
张量必须是
,传
numpy数组或
会报
切片后修改值:
的隐含规则
赋值操作看似简单,但PyTorch对左值切片有严格校验——它不仅检查形状兼容性,还判断是否能将梯度正确回传。
仅视图切片(非高级索引)支持原地赋值:
合法;
会报
赋值右值若为标量(如
或
),自动广播;若为张量,必须满足广播规则,且不能跨设备
在
上下文外对切片赋值,梯度仍正常流动——但只流回被修改的视图对应位置,其余位置梯度为0
想实现“条件赋值”,别用
直接索引左值(不支持),改用
:例如
最常被忽略的一点:切片操作是否产生视图,不取决于你写了什么符号,而取决于PyTorch内部的内存连续性判定逻辑。调试时可用
验证是否共享内存,比查文档更快。
[...]torch.where[...]x[1:3, :, 0]x[[0,2], :, 0]:x[[0,1], 2:] x[0][1][2]__getitem__x[0, 1, 2]x[-1]x[:, -2:] torch.boolx > 0.5bool(x > 0.5).float()x[mask]RuntimeError: Expected all tensors to be on the same devicex[mask]xtorch.nonzero(mask, as_tuple=True)torch.wheretorch.where(mask, x, torch.zeros_like(x))torch.index_selecttorch.gathertorch.index_selecttorch.gathertorch.index_select(x, dim=0, index=torch.tensor([2,0,2]))indexdimtorch.gatherindexlogits.gather(1, labels.unsqueeze(1))torch.gatherindexinputtorch.softmaxindextorch.longint32torch.int32Expected dtype torch.int64tensor[...] = valuex[1:3] = 0x[[0,2]] = 0IndexError: shape mismatch01.0torch.no_grad()masktorch.wherex = torch.where(mask, new_value, x)x.data_ptr() == x[1:].data_ptr()