大致按照使用频率递减给出
这里可以给出一个结论性的规律, 便于判断张量形状, 索引操作时, 有几个 : , 就有几个维度
1. 基本下标与切片(Python 风格)
import torch
x = torch.arange(24).reshape(2,3,4) # shape (2,3,4)
# x[batch, row, col]
x[0,0,0] # 标量 tensor(0)
x[0, :, :] # 第一维=0,取出 shape (3,4)
x[:, 1, :] # 所有batch, 第二个row -> shape (2,4)
x[..., 2] # 省略号,等价于 x[:, :, 2] -> shape (2,3)
x[0] # 等价于 x[0, :, :] -> shape (3,4)
- 切片语法支持
start:stop:step(含 start,不含 stop),支持负数索引和步长。 - 例如
x[:, ::-1, :]会在中间维度上反转顺序(返回 view 还是 copy 取决于实现;在 PyTorch 中 negative step 会返回 copy)。
2. 使用 None / np.newaxis(增加维度)
CodeBlock Loading...
- 常用于把向量转为列/行以便广播。
3. 布尔掩码(Boolean Masking)
CodeBlock Loading...
masked_select(a, mask)等价于a[mask]。- 当 mask 是多维且与 a 同 shape 时,结果是扁平的 1D 张量(按行主序提取元素)。
- 可用于筛样本、实现 padding 掩码筛选等。
4. 花式索引(整数数组索引 / Advanced Indexing)
CodeBlock Loading...
- 若使用多个 1D 整数索引(同维度),会进行逐元素配对索引,输出长度等于索引数组长度。
- 若混合切片和整数数组索引,规则稍复杂:整数索引会先被应用,结果维度位置会消失或变为新维度。
例(多维):
CodeBlock Loading...
5. 广播与索引(注意形状)
CodeBlock Loading...
- 常用于按-batch 选择每个样本对应的索引(如分类预测的 top-k 判断)。
6. gather 与 scatter(按索引收集/写入,适用于高维批量操作)
CodeBlock Loading...
gather要求index与src在除了dim外的维度完全相同;返回与index同形状的张量。- 常用于实现按位置取值(例如 beam-search、按预测索引从概率张量中取值)。
scatter_/scatter用于把值写入指定位置,可做 one-hot 化或累积(有reduce参数)。
7. index_select / take(按维度选择)
CodeBlock Loading...
index_select返回的顺序与索引一致;与 fancy indexing(M[idx])相似,但有些后端实现行为细微不同(比如保留 contiguous 性)。
8. masked_fill, where(掩码赋值 / 条件选择)
CodeBlock Loading...
where(cond, A, B)返回与A/B广播后的形状相同的张量。
9. unsqueeze / squeeze 与 view/reshape(维度控制)
CodeBlock Loading...
squeeze(dim)只在指定维度为 1 时删除该维度。reshape/view会改变内存视图(view要求连续 contiguous;reshape在必要时会复制)。
10. Ellipsis ...(省略号)
CodeBlock Loading...
- 在不确定前面/后面维度数时非常有用,特别是在写通用层时。
11. 多维返回与维度插入(保持/丢失维度)
- 使用整数索引会减少维度(那一维被消除);
- 使用切片或
None,或保持长度为 1 的索引会保留维度。 示例:
CodeBlock Loading...
12. 视图(view)与 copy(内存/contiguous)相关注意
- 大多数简单切片和整型索引会返回原张量的 view(共享内存),但有些操作会返回 copy(例如带负步长的切片、某些高级索引)。
is_contiguous()可以检查是否连续。若对返回的张量执行view()可能会报错,需先.contiguous()。
CodeBlock Loading...
- 在 in-place 操作(如
t += 1)时,如果 t 与原张量共享内存,可能会影响原张量;对 copy 则无影响。
13. 反向传播(autograd)相关
- 索引、切片会保留计算图信息(如果原张量
requires_grad=True),因此从张量中取出的部分仍可对原张量反向传播。 - 但是,用高级索引赋值(
x[idx] = something)不记录梯度;需要使用scatter或构造新的张量再计算 loss。 detach()可以切断梯度传播(例如x = x.detach())。
示例(反向传播影响):
CodeBlock Loading...
14. 常见用途与模式(实战片段)
- 按 batch 取样(分类概率取预测值):
CodeBlock Loading...
- padding mask(seq 长短不一):
CodeBlock Loading...
- one-hot:
CodeBlock Loading...
- 按索引更新参数(embedding lookup 与更新):
CodeBlock Loading...