想象你接手了一家刚刚竣工的百货商场。一层散货区只摆一件镇店之宝,店员记一个数字就能描述它;二层的货架上,价格标签从左到右排成一串,说“第几个”就能找到;三层把货架摆成 6 排 8 列,找一件商品得说“第几排第几列”;四层往上,每一层都有自己的排和列,一个商品要“楼层+排号+列号”三个数字才能定位;如果你又开了连锁分店,还得加上“分店号”这一维度。多一个编号,就多一个维度——这就是张量从标量、向量、矩阵一路走向高阶的旅程。在深度学习中,图片、文本、模型参数,无一不是被装进这种“多维数字容器”里。这篇文章将用一个贯穿始终的商场比喻,把张量的阶、形状、索引、运算和坐标变换一次讲透。

岗位关联

张量是深度学习中一切数据的“栖身之所”。理解张量,你就拿到了读懂模型代码、排查维度报错的第一把钥匙。

目录
  1. 可视化演示
  2. 张量定义与由来
  3. 张量的阶与形状
  4. 索引与切片
  5. 张量运算
  6. 坐标变换规律
  7. 深度学习应用
  8. 张量实践要点
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

张量定义与由来

商场的一层散货区只摆一件镇店之宝,它的全部信息就是价格牌上的一个数字,这个“孤零零的数字”在数学里叫标量。二层的货架把 12 件商品的价格标签从左到右排成一串,报出“第几个”就能找到,这叫向量。三层把货架布置成 6 排 8 列,找一件商品得说“第几排第几列”,两个编号定位一个格子,这叫矩阵。四层的仓库每层都有相同的排和列,定位要报三个编号——楼层、排号、列号,这就是三维张量的雏形。

数学家的眼光很简单:把“定位一个元素需要 N 个下标”的数据结构,统一叫做 N 阶张量。标量是 0 阶,向量是 1 阶,矩阵是 2 阶,像楼层一样往上叠加,直到任意高阶。深度学习框架里的“张量”(Tensor),就是这套思想在计算机里的实现:一个带形状信息的多维数组容器,底层连续存储,上层按维度索引。

一个 N 阶张量的每个元素需要 N 个下标才能定位。我们把第 $i_1$ 个“楼层”、第 $i_2$ 个“排号”……对应的元素记为:

所以张量并不神秘,它只是把商场“越盖越高的楼层定位系统”翻译成了数学语言。你只需要记住一条铁律:有几个下标,就是几阶张量。

Ti1i2⋯iN∈Rd1×d2×⋯×dN\mathbf{T}_{i_1 i_2 \cdots i_N} \in \mathbb{R}^{d_1 \times d_2 \times \cdots \times d_N}
  1. 张量记号$\mathbf{T}$ 表示整个张量,它是一整栋“货架系统”的代号,而不是某一个具体数字。
    T\mathbf{T}
  2. 下标序列$i_1 i_2 \cdots i_N$ 是定位元素所需的 N 个下标,分别对应第 1 到第 N 个维度上的位置编号。
    i1i2⋯iNi_1 i_2 \cdots i_N
  3. 形状信息$d_1 \times d_2 \times \cdots \times d_N$ 依次给出每个维度的大小,例如 $2 \times 3 \times 4$ 表示三个维度各有 2、3、4 个位置。
    d1×d2×⋯×dNd_1 \times d_2 \times \cdots \times d_N
  4. 成员关系$\in \mathbb{R}$ 表示每个元素都是实数,整体记号说明“容器的形状由各维大小共同决定”。
    Ti1i2⋯iN∈Rd1×d2×⋯×dN\mathbf{T}_{i_1 i_2 \cdots i_N} \in \mathbb{R}^{d_1 \times d_2 \times \cdots \times d_N}

张量的阶与形状

商场工程部扩建时只关心两件事:楼一共几层——这决定定位需要几个编号;每层有几排几列——这决定每个编号的取值范围。在张量的世界里,前者叫“阶”(rank/order),后者叫“形状”(shape)。

形状用一列数字表示,例如 (3, 4) 表示第一维有 3 个位置、第二维有 4 个位置,好比“3 排货架,每排 4 个货格”。三阶张量的形状 (2, 3, 4) 则像“2 层楼、每层 3 排、每排 4 个货格”。在 PyTorch 或 NumPy 里,一行 tensor.shape 就能把这张“施工图”打印出来。

阶与形状共同决定总容量:各维大小连乘,得到元素总数。例如形状 (2, 3, 4) 的仓库,总有 24 个货格:

面试算法岗时,面试官最常拿来“热身”的问题就是:形状 (2, 3, 4) 的张量有多少个元素?答案不是背出来的,而是“楼层 × 排 × 列”乘出来的。

元素总数=d1×d2×⋯×dN\text{元素总数} = d_1 \times d_2 \times \cdots \times d_N
  1. 维度大小$d_k$ 表示第 k 个维度上的位置个数,例如形状 (2, 3, 4) 中 $d_1 = 2$、$d_2 = 3$、$d_3 = 4$。
    d1=2,d2=3,d3=4d_1 = 2, \quad d_2 = 3, \quad d_3 = 4
  2. 连乘运算$\times$ 把每个维度的位置数依次相乘,相当于“楼层数 × 排数 × 列数”。
    d1×d2×d3d_1 \times d_2 \times d_3
  3. 计算总数代入数字得到 $2 \times 3 \times 4 = 24$,说明这栋仓库共有 24 个货格。
    2×3×4=242 \times 3 \times 4 = 24

索引与切片

顾客对店员说“四层、第 2 排、第 5 个货格”,三个编号一报,商品就到手了——这就是索引。如果顾客说“四层第 2 排整排我都要”,店员把一排货格连锅端——这就是切片。索引是“精确到点”,切片是“批量取段”。

在代码里,索引从 0 开始数。数学书上写 $T_1$ 的位置,程序里是 T[0];数学书的 $T_{2,3}$,对应程序里的 T[1][2]。切片用冒号表示范围,T[1:3] 取下标 1 和 2 两个元素(不含 3,左闭右开);某个维度写一个冒号 :,表示“这一维全要”。切片通常返回视图而非拷贝,修改切片会改动原张量,就像店员告诉你“那排货架的位置没变,只是挪了个角度”——底层数据还是同一批。

数学与程序两种写法本质是同一套“定位口令”:

商场里找商品靠“报编号”,程序里取数据靠“写下标”。把索引练熟了,你 debug 张量代码时就能像老店员一样,指哪打哪。

Ti1,i2,…,iN⟷T[i1][i2]⋯[iN]T_{i_1, i_2, \ldots, i_N} \quad \longleftrightarrow \quad T[i_1][i_2]\cdots[i_N]
  1. 数学下标$T_{i_1, i_2, \ldots, i_N}$ 用逗号分隔的 N 个下标表示元素位置,数学惯例从 1 开始编号。
    Ti1,i2,…,iNT_{i_1, i_2, \ldots, i_N}
  2. 程序下标$T[i_1][i_2]\cdots[i_N]$ 用方括号依次给出各维下标,编程惯例从 0 开始编号。
    T[i1][i2]⋯[iN]T[i_1][i_2]\cdots[i_N]
  3. 对照关系$\longleftrightarrow$ 表示两种写法一一对应,只是起始编号差 1,例如 $T_{2,3}$ 对应 T[1][2]。
    T2,3⟷T[1][2]T_{2,3} \longleftrightarrow \texttt{T[1][2]}

张量运算

商场促销有三件事最常用:全场打八折——每件商品的价签统一乘 0.8,这叫逐元素运算,形状不变;收银台结算购物车——每件商品“单价 × 数量”之后全部加起来,这叫点积与矩阵乘法;不同分店之间调货——货架规格不同也能灵活配对,这叫广播。

矩阵乘法是深度学习最核心的“搬运工”:把输入特征矩阵与权重矩阵做乘加,得到输出特征。一条规则决定结果形状:左矩阵的列数必须等于右矩阵的行数,结果的行数等于左矩阵的行数、列数等于右矩阵的列数。设 $A$ 形状为 $(m,p)$、$B$ 形状为 $(p,n)$,则乘积 $C$ 形状为 $(m,n)$:

促销、收银、调货三个场景,对应着逐元素、矩阵乘法、广播三种运算。写代码时务必分清:* 是逐元素,@ 才是矩阵乘法。

Cij=∑k=1pAikBkjC_{ij} = \sum_{k=1}^{p} A_{ik} B_{kj}
  1. 取元素$A_{ik}$ 是 $A$ 第 $i$ 行第 $k$ 列的值,$B_{kj}$ 是 $B$ 第 $k$ 行第 $j$ 列的值。
    Aik,  BkjA_{ik}, \; B_{kj}
  2. 匹配内维求和指标 $k$ 从 1 到 $p$,要求 $A$ 的列数等于 $B$ 的行数,就像左右两段履带必须齿数相同才能咬合。
    k=1,2,…,pk = 1, 2, \ldots, p
  3. 累加求和$\sum$ 把 $p$ 个乘积加起来,得到 $C_{ij}$ 这一个数字,相当于“一车商品的逐件结算总额”。
    ∑k=1pAikBkj\sum_{k=1}^{p} A_{ik} B_{kj}
  4. 结果形状$C_{ij}$ 中的 $i$ 来自 $A$ 的行、$j$ 来自 $B$ 的列,所以 $C$ 的形状是 $(m, n)$。
    C∈Rm×nC \in \mathbb{R}^{m \times n}

坐标变换规律

商场重新装修,把四层整层货架从“南北朝向”统一旋转成“东西朝向”。商品一件不少,但每个货格的位置描述全变了——原来的“第 3 排第 5 列”可能变成“第 5 排第 3 列”。坐标一变,编号就变,但货还是那些货。

数学上“张量”有一个比“多维数组”更严格的定义:当坐标系的基向量发生变化时,张量的分量必须按照一套确定的变换法则同步变化。满足这个法则的数组才叫“数学张量”;不满足的,只能叫普通多维数组。深度学习框架里绝大多数场景把两者混用,但物理、力学等领域的张量分析,靠的就是这条法则。N 阶张量在基变换下,每个下标都要乘上一个变换系数:

这个法则你可能一辈子不会手写一次,但它划清了“张量”和“数组”的边界:数组是外壳,张量是有“坐标灵魂”的数组。

Ti1i2⋯iN′=ai1j1ai2j2⋯aiNjNTj1j2⋯jNT'_{i_1 i_2 \cdots i_N} = a_{i_1 j_1} a_{i_2 j_2} \cdots a_{i_N j_N} T_{j_1 j_2 \cdots j_N}
  1. 变换系数$a_{i j}$ 是新旧基之间的转换系数,相当于“旋转角度对应的三角函数值”,描述坐标轴转了多少。
    aija_{i j}
  2. 一个下标一个因子$a_{i_1 j_1} a_{i_2 j_2} \cdots a_{i_N j_N}$ 表示 N 阶张量要乘 N 个系数,每多一阶就多一层“转换”。
    ai1j1 ai2j2 ⋯ aiNjNa_{i_1 j_1}\, a_{i_2 j_2}\, \cdots\, a_{i_N j_N}
  3. 重复下标求和按爱因斯坦求和约定,重复出现的下标 $j_1, j_2, \ldots, j_N$ 要分别求和,把旧坐标下所有位置的贡献累加过来。
    Tj1j2⋯jNT_{j_1 j_2 \cdots j_N}
  4. 阶数不变变换后 $T'$ 依然带 N 个下标,仍是 N 阶张量——装修可以换方向,楼层数不会变。
    Ti1i2⋯iN′T'_{i_1 i_2 \cdots i_N}

深度学习应用

连锁商场的总仓每天收到所有分店的库存快照:每件商品要标“分店号、楼层、排号、列号”——四个编号,就是一个四阶张量。深度学习里最常见的四阶张量,就是批量图片。

一张 RGB 彩色图片是 (3, H, W) 的三阶张量:3 个通道(红、绿、蓝),每个通道是一张 H×W 的灰度网格。一次训练要喂入 B 张图,就把 B 张图叠成一个整体 (B, 3, H, W)——B 就相当于“分店号”维度。模型的参数和梯度同样是张量:全连接层的权重是 (输入维度,输出维度) 的矩阵,卷积核是 (输出通道,输入通道,高,宽) 的四阶张量。PyTorch 中图像批量的标准形状写作:

如果你的数据死活进不了模型的输入形状,八成不是数据错了,而是“楼层、排号、列号”的顺序没对齐——把张量想象成总仓的库存快照,顺序问题一眼就能看出来。

X∈RB×C×H×W\mathcal{X} \in \mathbb{R}^{B \times C \times H \times W}
  1. 批次大小$B$ 是一次送入模型的样本数量,好比“同时处理多少家分店的订单”。
    BB
  2. 通道数$C$ 是每个像素的颜色通道数,RGB 图为 3,灰度图为 1。
    CC
  3. 空间尺寸$H$ 是图片高度、$W$ 是宽度,$H \times W$ 相当于一层楼的“排数 × 列数”。
    H×WH \times W
  4. 维度顺序框架规定顺序为“批次、通道、高、宽”,顺序写错,模型第一行就会报 shape mismatch 错误。
    X∈RB×C×H×W\mathcal{X} \in \mathbb{R}^{B \times C \times H \times W}

张量实践要点

再资深的仓库主管,盘点前也要先翻账本再进仓库——先看“形状”再操作数据,是和张量打交道的铁律。90% 的张量报错都是形状不匹配,而形状不匹配的根源,往往是“没先看 shape”。

reshape 是最高频的变形操作,它的规则只有一条:元素总数守恒。(2, 3, 4) 可以变成 (24,)、变成 (6, 4)、变成 (2, 12),只要连乘结果还是 24。任何改变总数的 reshape 都会直接报错——这是框架在帮你踩刹车。遇到高维张量也别慌,把它想象成多层商场:先取 tensor[0] 看第一块样例,再把剩余维度压平观察;打印时只看前几个元素即可。形状合法性用连乘表达式表示:

记住“总量守恒”这四个字,再配合“先 shape 后操作”的习惯,你在 debug 形状报错时就已经赢在了起跑线上。

∏k=1Ndk=∏m=1Mem\prod_{k=1}^{N} d_k = \prod_{m=1}^{M} e_m
  1. 原形状连乘$\prod_{k=1}^{N} d_k$ 表示 reshape 前各维大小的乘积,即原元素总数。
    ∏k=1Ndk\prod_{k=1}^{N} d_k
  2. 新形状连乘$\prod_{m=1}^{M} e_m$ 表示 reshape 后各维大小的乘积,$M$ 是新形状的维数。
    ∏m=1Mem\prod_{m=1}^{M} e_m
  3. 守恒等式两个乘积必须相等,这是 reshape 合法性的唯一约束,也是你检查维度时的“总账本”。
    ∏k=1Ndk=∏m=1Mem\prod_{k=1}^{N} d_k = \prod_{m=1}^{M} e_m

AI 应用场景

图像数据批量加载

阶段:数据预处理与加载

解决的问题:传统方式用嵌套 list 一张张存图片,无法利用 GPU 并行,且维度顺序容易乱。AI 的做法是把整个批次组织成一个四阶张量,让“批次、通道、高、宽”各占一个维度,一次性送入显卡计算,吞吐量提升一个数量级。

具体案例:训练图像分类模型时,DataLoader 每次输出形状 (32, 3, 224, 224) 的批量张量。模型第一行常写 x = x.view(x.size(0), -1) 把后三维压平成特征向量,再喂给全连接层。

特征图可视化与调试

阶段:模型调试与分析

解决的问题:神经网络中间层输出是“看不见”的高维张量。用索引和切片把 (1, 256, 28, 28) 的特征图切成 256 张 28×28 的二维热力图,就能直观看到每个通道学到了什么。

具体案例:在 PyTorch 中注册 forward hook,取 T[0, i, :, :] 用 matplotlib 绘制第 i 个通道的热力图,观察浅层学边缘、深层学语义的经典现象,帮助定位模型是否“学偏”。

形状不匹配报错排错

阶段:训练与调试

解决的问题:shape mismatch 是训练中最高频的报错。理解“全连接权重是 (输入,输出)、输入特征是 (批次,输入)”的形状语义,就能在报错栈里一眼定位是哪个维度写反。

具体案例:报错信息显示 (512, 128) 与 (512, 10) 无法相乘,排查发现输入特征被错误地转置成了 (512, 128),调用 transpose(0, 1) 恢复 (128, 512) 后训练正常。

Python 演示

python49 行
# -*- coding: utf-8 -*-# Tensor basics demo: build tensors from scalar to 3Dimport numpy as np  def main():    # 1. From scalar to 3-order tensor    scalar = np.array(5)    vector = np.array([1, 2, 3, 4])    matrix = np.array([[1, 2, 3], [4, 5, 6]])    tensor3 = np.arange(24).reshape(2, 3, 4)     print("scalar shape:", scalar.shape, "ndim:", scalar.ndim)    print("vector shape:", vector.shape, "ndim:", vector.ndim)    print("matrix shape:", matrix.shape, "ndim:", matrix.ndim)    print("tensor3 shape:", tensor3.shape, "ndim:", tensor3.ndim)    print("element count:", tensor3.size)     # 2. Indexing and slicing: start from 0, use colon    print("matrix[1, 2] =", matrix[1, 2])    print("tensor3[:, 1, :] =\n", tensor3[:, 1, :])     # 3. Element-wise vs matrix multiplication    a = np.array([[1, 2], [3, 4]])    b = np.array([[5, 6], [7, 8]])    print("a * b (element-wise):\n", a * b)    print("a @ b (matmul):\n", a @ b)     # 4. Broadcasting: (3,1) + (1,4) -> (3,4)    x = np.ones((3, 1))    y = np.ones((1, 4))    print("broadcast add shape:", (x + y).shape)     # 5. Coordinate transform: rotate a vector by 45 degrees    theta = np.pi / 4    rot = np.array([[np.cos(theta), -np.sin(theta)],                    [np.sin(theta), np.cos(theta)]])    vec = np.array([1.0, 0.0])    print("rotated vector:", rot @ vec)     # 6. Always check shape before operations    try:        a.reshape(3, 3)    except ValueError as err:        print("reshape error (expected):", err)  if __name__ == "__main__":    main()
目的:用 NumPy 从标量、向量、矩阵到三阶张量逐级构建,演示形状、索引、切片、运算、广播与坐标变换,最后展示 reshape 的形状校验机制。
  1. tensor3 = np.arange(24).reshape(2, 3, 4)生成 0 到 23 共 24 个数,再重排成“2 层 × 3 排 × 4 列”的三阶张量。
  2. print("tensor3 shape:", tensor3.shape, "ndim:", tensor3.ndim)shape 是形状(各维大小),ndim 是阶(维度个数),像商场的“楼层数”和“每层排列表”。
  3. print("matrix[1, 2] =", matrix[1, 2])下标从 0 开始,取矩阵第 2 行第 3 列的元素 6。
  4. print("tensor3[:, 1, :] =\n", tensor3[:, 1, :])冒号表示该维全取,结果是从三阶张量中切出“第 2 排”的二维切片,形状 (2, 4)。
  5. a = np.array([[1, 2], [3, 4]])构造 2×2 矩阵,用于对比两种乘法。
  6. print("a @ b (matmul):\n", a @ b)@ 是真正的矩阵乘法,内维匹配后按“行 × 列求和”得到结果。
  7. x = np.ones((3, 1))构造 (3, 1) 的全 1 张量,配合 (1, 4) 演示广播。
  8. print("broadcast add shape:", (x + y).shape)(3, 1) 与 (1, 4) 广播后形状为 (3, 4),像用标准托盘对齐不同规格的货架。
  9. vec = np.array([1.0, 0.0])构造 x 轴方向的单位向量,用于观察坐标变换。
  10. a.reshape(3, 3)6 个元素无法重排成 9 个位置,触发 ValueError,验证“元素总数守恒”。

常见误区

误区学了 Python 就能用 list 套 list 表示多维数据,为什么要专门搞一个“张量”概念?我觉得张量就是普通多维数组。

正解深度学习里的张量确实以多维数组为实现形式,但比嵌套 list 多了两个关键能力:一是明确的形状语义,每个维度都有具体含义(如批次、通道、高、宽),list 只能靠“约定”记在心里;二是底层连续存储和多维步长索引,支持 GPU 并行计算。普通 list 既慢又丢语义,无法承担大规模训练。

为何常见:因为打印张量时,看到的就是一堆嵌套方括号和数字,和 list 的输出长得一模一样。

误区(2, 3) 和 (3, 2) 不都是 6 个数吗?我照着写应该没问题吧,反正元素一样多。

正解元素总数相同,维度语义完全不同。(2, 3) 可以表示“2 张图、每张图 3 个像素”,(3, 2) 则是“3 张图、每张图 2 个像素”。就像“2 层楼每层 3 排”和“3 层楼每层 2 排”,货架总数都是 6,但楼层和排数完全不同。模型运算要求维度语义对齐,顺序错了就报错。

为何常见:只看元素数量,忽视了维度顺序承载的业务含义,这是初学者最高发的错误。

误区a * b 不是矩阵乘法吗?我看结果也是两个矩阵对应数字相乘,所以矩阵乘法就是逐元素乘。

正解* 是逐元素相乘(Hadamard 积),要求形状兼容,$C_{ij} = A_{ij} B_{ij}$;@ 才是矩阵乘法,要求内维匹配,$C_{ij} = \sum_k A_{ik} B_{kj}$。两者的区别就像“全场商品统一打八折”和“购物车逐件结算求和”,完全是两种操作。NumPy 里 * 与 @ 是两套运算符,混用会得到莫名其妙的形状。

为何常见:初学编程时对普通数字的“相乘”印象太深,见到 * 就以为是矩阵乘法。

误区数学书里 $a_1$ 是第一个元素,那代码里第一个元素也应该是 T[1] 吧?为什么取出来不对?

正解几乎所有主流编程语言(Python、C、Java)和深度学习框架的下标都从 0 开始:数学的 $T_1$ 在代码里是 T[0]。从 0 开始有一个数学上的好处:切片区间 [start, stop) 的长度恰好是 stop - start,不用再加减 1。把“数学下标减 1”当成习惯,就能避免绝大多数越界错误。

为何常见:从数学课的 1-based 下标转换到编程的 0-based,是每个新手都要经历的一道坎。

误区广播机制把 (1, 4) 扩展成 (3, 4),肯定是把小数组复制了三份,这样很浪费内存吧?

正解广播在概念上是“虚拟扩展”,主流框架用步长(stride)视图实现,不会真的把小数组复制成大数组,内存开销几乎为零。但要注意两个坑:np.broadcast_to 返回的是只读视图,写入会报错;对广播结果做原地修改(如 +=)也可能因为视图共享而影响原数据。理解“视图”和“拷贝”的区别,比背广播规则更重要。

为何常见:看到输出形状变大,就直觉认为底层内存也变大了,忽略了框架的惰性求值和视图机制。

面试题

Q1. 在深度学习中,张量的“阶”(rank)指的是什么?

单选题 · easy

  • A.张量元素数值的大小
  • B.张量所具有的维度数量← 正确答案
  • C.张量在内存中的占用大小
  • D.张量中包含的元素总个数

答案:B。阶就是“定位一个元素需要几个下标”。标量是 0 阶,向量是 1 阶,矩阵是 2 阶。就像商场里“报几个编号能找到商品”:一个编号是向量,两个是矩阵,三个就是三阶张量。A 描述数值大小,C 描述内存,D 描述元素总数,都不是阶。

Q2. 形状为 (3, 4) 的张量一共有多少个元素?

单选题 · easy

  • A.一共有 7 个元素
  • B.一共有 12 个元素← 正确答案
  • C.一共有 34 个元素
  • D.一共有 81 个元素

答案:B。元素总数等于各维大小连乘,3 × 4 = 12。这就像“3 排货架每排 4 个货格”,一共 12 个格。7 是把 3 和 4 相加,34 是把数字拼在一起,81 是 3 的 4 次方,都不符合连乘规则。

Q3. 在 NumPy 和 PyTorch 中,张量索引的起始数字是几?

单选题 · easy

  • A.从数字 1 开始计数
  • B.从数字 0 开始计数← 正确答案
  • C.从数字 -1 开始计数
  • D.由用户自行设定起始

答案:B。主流编程语言和深度学习框架的下标一律从 0 开始,数学书上的 T_1 对应代码里的 T[0]。从 0 开始让切片 [start, stop) 的长度正好是 stop - start,省去频繁的加减 1。-1 通常表示最后一个元素,而不是起始位置。

Q4. A 的形状为 (2, 3),B 的形状为 (3, 4),则 A @ B 的结果形状是?

单选题 · mid

  • A.(2, 4) 这样的结果形状← 正确答案
  • B.(3, 4) 这样的结果形状
  • C.(2, 3) 这样的结果形状
  • D.(4, 2) 这样的结果形状

答案:A。矩阵乘法的结果形状是“左矩阵行数 × 右矩阵列数”,即 (2, 4)。内维 3 必须匹配,相当于两段履带齿数相同才能咬合。B 是右矩阵的形状,C 是左矩阵的形状,D 把行列写反了。

Q5. 张量 T 的形状为 (2, 3, 4),下列切片说法正确的有?

多选题 · mid

  • A.T[0,1,:] 的切片形状是 (4,)← 正确答案
  • B.T[:,1,2] 的切片形状是 (2,)← 正确答案
  • C.T[0] 能取出第一块完整数据← 正确答案
  • D.T[3,:,:] 的切片不越界

答案:ABC。T[0,1,:] 固定前两维、第三维全取,形状 (4,);T[:,1,2] 第一维全取、后两维固定,形状 (2,);T[0] 省略后两维,取出形状 (3,4) 的第一块。D 中第一维大小为 2,合法下标只有 0 和 1,T[3,:,:] 越界。

Q6. 关于张量的运算,下列说法正确的有?

多选题 · mid

  • A.广播允许形状不同的张量按规则运算← 正确答案
  • B.矩阵乘法要求左矩阵列数等于右矩阵行数← 正确答案
  • C.逐元素乘法要求形状满足广播规则即可← 正确答案
  • D.任何形状的两个张量都可以做矩阵乘法

答案:ABC。广播从右往左逐维比较,维度为 1 或相等即可对齐,A 对。矩阵乘法要求内维匹配,B 对。逐元素乘法在广播规则下也允许不同形状,C 对。D 错在“任何形状”——不满足内维匹配就无法做矩阵乘法,就像货架齿数不咬合就转不动。

Q7. 在 PyTorch 中,图像批量的默认张量形状是?

单选题 · easy

  • A.(批次,通道,高,宽) 形状← 正确答案
  • B.(通道,批次,高,宽) 形状
  • C.(高,批次,通道,宽) 形状
  • D.(批次,高,宽,通道) 形状

答案:A。PyTorch 默认 NCHW,即 (批次,通道,高,宽),32 张 RGB 图就是 (32, 3, 224, 224)。D 是 NHWC,TensorFlow 常用,但 PyTorch 默认不是。记住“分店—楼层—排—列”的比喻:批次是分店号,通道是楼层,高宽是排与列。

Q8. 关于数学张量与坐标变换,下列说法正确的有?

多选题 · hard

  • A.数学张量需要满足坐标变换法则← 正确答案
  • B.普通多维数组不必满足变换法则← 正确答案
  • C.坐标变换不会改变张量的阶数← 正确答案
  • D.坐标变换中张量的元素值保持不变

答案:ABC。数学张量的严格定义要求分量在基变换下按法则 $T'_{i_1\cdots i_N} = a_{i_1j_1}\cdots a_{i_Nj_N}T_{j_1\cdots j_N}$ 变换,A 对。普通数组只是数据的堆放方式,没有变换约束,B 对。变换只改变分量数值,阶数不变,C 对。D 正是常见误解——张量本身不变,但它的分量(元素值)一般会随坐标改变,就像同一件商品在新旧两套货架编号下坐标不同。

Q9. 广播机制中,形状 (3, 1) 与 (1, 4) 的张量相加,结果形状是?

单选题 · mid

  • A.结果形状是 (3, 1)
  • B.结果形状是 (1, 4)
  • C.结果形状是 (3, 4)← 正确答案
  • D.结果形状是 (4, 3)

答案:C。广播从右往左对齐维度:第一维 3 与 1 取较大值 3,第二维 1 与 4 取较大值 4,所以结果是 (3, 4)。这就像 3 排货架和 4 列货位用标准托盘对齐成大网格。A、B 只是原始形状,D 把行列顺序写反了。

Q10. 张量 T 的形状为 (2, 3, 4),将其重塑为 (3, 4, 2),以下说法正确的是?

单选题 · hard

  • A.元素总数会变成原来的两倍
  • B.元素总数会变为原来的一半
  • C.元素总数保持不变依旧为 24← 正确答案
  • D.元素总数会变为原来的四倍

答案:C。reshape 的唯一约束是元素总数守恒:2×3×4 = 3×4×2 = 24。改变排列方式不改变总货格数。A、B、D 都在暗示总数变化,违背“重塑前后连乘相等”的基本规则。