想象你接手了一家刚刚竣工的百货商场。一层散货区只摆一件镇店之宝,店员记一个数字就能描述它;二层的货架上,价格标签从左到右排成一串,说“第几个”就能找到;三层把货架摆成 6 排 8 列,找一件商品得说“第几排第几列”;四层往上,每一层都有自己的排和列,一个商品要“楼层+排号+列号”三个数字才能定位;如果你又开了连锁分店,还得加上“分店号”这一维度。多一个编号,就多一个维度——这就是张量从标量、向量、矩阵一路走向高阶的旅程。在深度学习中,图片、文本、模型参数,无一不是被装进这种“多维数字容器”里。这篇文章将用一个贯穿始终的商场比喻,把张量的阶、形状、索引、运算和坐标变换一次讲透。
张量是深度学习中一切数据的“栖身之所”。理解张量,你就拿到了读懂模型代码、排查维度报错的第一把钥匙。
可视化演示
展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。
本节配有交互动效(进入视口后自动加载,约 3KB)。
系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T
张量定义与由来
商场的一层散货区只摆一件镇店之宝,它的全部信息就是价格牌上的一个数字,这个“孤零零的数字”在数学里叫标量。二层的货架把 12 件商品的价格标签从左到右排成一串,报出“第几个”就能找到,这叫向量。三层把货架布置成 6 排 8 列,找一件商品得说“第几排第几列”,两个编号定位一个格子,这叫矩阵。四层的仓库每层都有相同的排和列,定位要报三个编号——楼层、排号、列号,这就是三维张量的雏形。
数学家的眼光很简单:把“定位一个元素需要 N 个下标”的数据结构,统一叫做 N 阶张量。标量是 0 阶,向量是 1 阶,矩阵是 2 阶,像楼层一样往上叠加,直到任意高阶。深度学习框架里的“张量”(Tensor),就是这套思想在计算机里的实现:一个带形状信息的多维数组容器,底层连续存储,上层按维度索引。
一个 N 阶张量的每个元素需要 N 个下标才能定位。我们把第 $i_1$ 个“楼层”、第 $i_2$ 个“排号”……对应的元素记为:
所以张量并不神秘,它只是把商场“越盖越高的楼层定位系统”翻译成了数学语言。你只需要记住一条铁律:有几个下标,就是几阶张量。
- 张量记号$\mathbf{T}$ 表示整个张量,它是一整栋“货架系统”的代号,而不是某一个具体数字。
- 下标序列$i_1 i_2 \cdots i_N$ 是定位元素所需的 N 个下标,分别对应第 1 到第 N 个维度上的位置编号。
- 形状信息$d_1 \times d_2 \times \cdots \times d_N$ 依次给出每个维度的大小,例如 $2 \times 3 \times 4$ 表示三个维度各有 2、3、4 个位置。
- 成员关系$\in \mathbb{R}$ 表示每个元素都是实数,整体记号说明“容器的形状由各维大小共同决定”。
张量的阶与形状
商场工程部扩建时只关心两件事:楼一共几层——这决定定位需要几个编号;每层有几排几列——这决定每个编号的取值范围。在张量的世界里,前者叫“阶”(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) 的张量有多少个元素?答案不是背出来的,而是“楼层 × 排 × 列”乘出来的。
- 维度大小$d_k$ 表示第 k 个维度上的位置个数,例如形状 (2, 3, 4) 中 $d_1 = 2$、$d_2 = 3$、$d_3 = 4$。
- 连乘运算$\times$ 把每个维度的位置数依次相乘,相当于“楼层数 × 排数 × 列数”。
- 计算总数代入数字得到 $2 \times 3 \times 4 = 24$,说明这栋仓库共有 24 个货格。
索引与切片
顾客对店员说“四层、第 2 排、第 5 个货格”,三个编号一报,商品就到手了——这就是索引。如果顾客说“四层第 2 排整排我都要”,店员把一排货格连锅端——这就是切片。索引是“精确到点”,切片是“批量取段”。
在代码里,索引从 0 开始数。数学书上写 $T_1$ 的位置,程序里是 T[0];数学书的 $T_{2,3}$,对应程序里的 T[1][2]。切片用冒号表示范围,T[1:3] 取下标 1 和 2 两个元素(不含 3,左闭右开);某个维度写一个冒号 :,表示“这一维全要”。切片通常返回视图而非拷贝,修改切片会改动原张量,就像店员告诉你“那排货架的位置没变,只是挪了个角度”——底层数据还是同一批。
数学与程序两种写法本质是同一套“定位口令”:
商场里找商品靠“报编号”,程序里取数据靠“写下标”。把索引练熟了,你 debug 张量代码时就能像老店员一样,指哪打哪。
- 数学下标$T_{i_1, i_2, \ldots, i_N}$ 用逗号分隔的 N 个下标表示元素位置,数学惯例从 1 开始编号。
- 程序下标$T[i_1][i_2]\cdots[i_N]$ 用方括号依次给出各维下标,编程惯例从 0 开始编号。
- 对照关系$\longleftrightarrow$ 表示两种写法一一对应,只是起始编号差 1,例如 $T_{2,3}$ 对应
T[1][2]。
张量运算
商场促销有三件事最常用:全场打八折——每件商品的价签统一乘 0.8,这叫逐元素运算,形状不变;收银台结算购物车——每件商品“单价 × 数量”之后全部加起来,这叫点积与矩阵乘法;不同分店之间调货——货架规格不同也能灵活配对,这叫广播。
矩阵乘法是深度学习最核心的“搬运工”:把输入特征矩阵与权重矩阵做乘加,得到输出特征。一条规则决定结果形状:左矩阵的列数必须等于右矩阵的行数,结果的行数等于左矩阵的行数、列数等于右矩阵的列数。设 $A$ 形状为 $(m,p)$、$B$ 形状为 $(p,n)$,则乘积 $C$ 形状为 $(m,n)$:
促销、收银、调货三个场景,对应着逐元素、矩阵乘法、广播三种运算。写代码时务必分清:* 是逐元素,@ 才是矩阵乘法。
- 取元素$A_{ik}$ 是 $A$ 第 $i$ 行第 $k$ 列的值,$B_{kj}$ 是 $B$ 第 $k$ 行第 $j$ 列的值。
- 匹配内维求和指标 $k$ 从 1 到 $p$,要求 $A$ 的列数等于 $B$ 的行数,就像左右两段履带必须齿数相同才能咬合。
- 累加求和$\sum$ 把 $p$ 个乘积加起来,得到 $C_{ij}$ 这一个数字,相当于“一车商品的逐件结算总额”。
- 结果形状$C_{ij}$ 中的 $i$ 来自 $A$ 的行、$j$ 来自 $B$ 的列,所以 $C$ 的形状是 $(m, n)$。
坐标变换规律
商场重新装修,把四层整层货架从“南北朝向”统一旋转成“东西朝向”。商品一件不少,但每个货格的位置描述全变了——原来的“第 3 排第 5 列”可能变成“第 5 排第 3 列”。坐标一变,编号就变,但货还是那些货。
数学上“张量”有一个比“多维数组”更严格的定义:当坐标系的基向量发生变化时,张量的分量必须按照一套确定的变换法则同步变化。满足这个法则的数组才叫“数学张量”;不满足的,只能叫普通多维数组。深度学习框架里绝大多数场景把两者混用,但物理、力学等领域的张量分析,靠的就是这条法则。N 阶张量在基变换下,每个下标都要乘上一个变换系数:
这个法则你可能一辈子不会手写一次,但它划清了“张量”和“数组”的边界:数组是外壳,张量是有“坐标灵魂”的数组。
- 变换系数$a_{i j}$ 是新旧基之间的转换系数,相当于“旋转角度对应的三角函数值”,描述坐标轴转了多少。
- 一个下标一个因子$a_{i_1 j_1} a_{i_2 j_2} \cdots a_{i_N j_N}$ 表示 N 阶张量要乘 N 个系数,每多一阶就多一层“转换”。
- 重复下标求和按爱因斯坦求和约定,重复出现的下标 $j_1, j_2, \ldots, j_N$ 要分别求和,把旧坐标下所有位置的贡献累加过来。
- 阶数不变变换后 $T'$ 依然带 N 个下标,仍是 N 阶张量——装修可以换方向,楼层数不会变。
深度学习应用
连锁商场的总仓每天收到所有分店的库存快照:每件商品要标“分店号、楼层、排号、列号”——四个编号,就是一个四阶张量。深度学习里最常见的四阶张量,就是批量图片。
一张 RGB 彩色图片是 (3, H, W) 的三阶张量:3 个通道(红、绿、蓝),每个通道是一张 H×W 的灰度网格。一次训练要喂入 B 张图,就把 B 张图叠成一个整体 (B, 3, H, W)——B 就相当于“分店号”维度。模型的参数和梯度同样是张量:全连接层的权重是 (输入维度,输出维度) 的矩阵,卷积核是 (输出通道,输入通道,高,宽) 的四阶张量。PyTorch 中图像批量的标准形状写作:
如果你的数据死活进不了模型的输入形状,八成不是数据错了,而是“楼层、排号、列号”的顺序没对齐——把张量想象成总仓的库存快照,顺序问题一眼就能看出来。
- 批次大小$B$ 是一次送入模型的样本数量,好比“同时处理多少家分店的订单”。
- 通道数$C$ 是每个像素的颜色通道数,RGB 图为 3,灰度图为 1。
- 空间尺寸$H$ 是图片高度、$W$ 是宽度,$H \times W$ 相当于一层楼的“排数 × 列数”。
- 维度顺序框架规定顺序为“批次、通道、高、宽”,顺序写错,模型第一行就会报 shape mismatch 错误。
张量实践要点
再资深的仓库主管,盘点前也要先翻账本再进仓库——先看“形状”再操作数据,是和张量打交道的铁律。90% 的张量报错都是形状不匹配,而形状不匹配的根源,往往是“没先看 shape”。
reshape 是最高频的变形操作,它的规则只有一条:元素总数守恒。(2, 3, 4) 可以变成 (24,)、变成 (6, 4)、变成 (2, 12),只要连乘结果还是 24。任何改变总数的 reshape 都会直接报错——这是框架在帮你踩刹车。遇到高维张量也别慌,把它想象成多层商场:先取 tensor[0] 看第一块样例,再把剩余维度压平观察;打印时只看前几个元素即可。形状合法性用连乘表达式表示:
记住“总量守恒”这四个字,再配合“先 shape 后操作”的习惯,你在 debug 形状报错时就已经赢在了起跑线上。
- 原形状连乘$\prod_{k=1}^{N} d_k$ 表示 reshape 前各维大小的乘积,即原元素总数。
- 新形状连乘$\prod_{m=1}^{M} e_m$ 表示 reshape 后各维大小的乘积,$M$ 是新形状的维数。
- 守恒等式两个乘积必须相等,这是 reshape 合法性的唯一约束,也是你检查维度时的“总账本”。
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 演示
# -*- 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()
tensor3 = np.arange(24).reshape(2, 3, 4)生成 0 到 23 共 24 个数,再重排成“2 层 × 3 排 × 4 列”的三阶张量。print("tensor3 shape:", tensor3.shape, "ndim:", tensor3.ndim)shape 是形状(各维大小),ndim 是阶(维度个数),像商场的“楼层数”和“每层排列表”。print("matrix[1, 2] =", matrix[1, 2])下标从 0 开始,取矩阵第 2 行第 3 列的元素 6。print("tensor3[:, 1, :] =\n", tensor3[:, 1, :])冒号表示该维全取,结果是从三阶张量中切出“第 2 排”的二维切片,形状 (2, 4)。a = np.array([[1, 2], [3, 4]])构造 2×2 矩阵,用于对比两种乘法。print("a @ b (matmul):\n", a @ b)@是真正的矩阵乘法,内维匹配后按“行 × 列求和”得到结果。x = np.ones((3, 1))构造 (3, 1) 的全 1 张量,配合 (1, 4) 演示广播。print("broadcast add shape:", (x + y).shape)(3, 1) 与 (1, 4) 广播后形状为 (3, 4),像用标准托盘对齐不同规格的货架。vec = np.array([1.0, 0.0])构造 x 轴方向的单位向量,用于观察坐标变换。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)指的是什么?
- A.张量元素数值的大小
- B.张量所具有的维度数量← 正确答案
- C.张量在内存中的占用大小
- D.张量中包含的元素总个数
答案:B。阶就是“定位一个元素需要几个下标”。标量是 0 阶,向量是 1 阶,矩阵是 2 阶。就像商场里“报几个编号能找到商品”:一个编号是向量,两个是矩阵,三个就是三阶张量。A 描述数值大小,C 描述内存,D 描述元素总数,都不是阶。
Q2. 形状为 (3, 4) 的张量一共有多少个元素?
- 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 中,张量索引的起始数字是几?
- 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 的结果形状是?
- A.(2, 4) 这样的结果形状← 正确答案
- B.(3, 4) 这样的结果形状
- C.(2, 3) 这样的结果形状
- D.(4, 2) 这样的结果形状
答案:A。矩阵乘法的结果形状是“左矩阵行数 × 右矩阵列数”,即 (2, 4)。内维 3 必须匹配,相当于两段履带齿数相同才能咬合。B 是右矩阵的形状,C 是左矩阵的形状,D 把行列写反了。
Q5. 张量 T 的形状为 (2, 3, 4),下列切片说法正确的有?
- 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. 关于张量的运算,下列说法正确的有?
- A.广播允许形状不同的张量按规则运算← 正确答案
- B.矩阵乘法要求左矩阵列数等于右矩阵行数← 正确答案
- C.逐元素乘法要求形状满足广播规则即可← 正确答案
- D.任何形状的两个张量都可以做矩阵乘法
答案:ABC。广播从右往左逐维比较,维度为 1 或相等即可对齐,A 对。矩阵乘法要求内维匹配,B 对。逐元素乘法在广播规则下也允许不同形状,C 对。D 错在“任何形状”——不满足内维匹配就无法做矩阵乘法,就像货架齿数不咬合就转不动。
Q7. 在 PyTorch 中,图像批量的默认张量形状是?
- A.(批次,通道,高,宽) 形状← 正确答案
- B.(通道,批次,高,宽) 形状
- C.(高,批次,通道,宽) 形状
- D.(批次,高,宽,通道) 形状
答案:A。PyTorch 默认 NCHW,即 (批次,通道,高,宽),32 张 RGB 图就是 (32, 3, 224, 224)。D 是 NHWC,TensorFlow 常用,但 PyTorch 默认不是。记住“分店—楼层—排—列”的比喻:批次是分店号,通道是楼层,高宽是排与列。
Q8. 关于数学张量与坐标变换,下列说法正确的有?
- 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) 的张量相加,结果形状是?
- 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),以下说法正确的是?
- A.元素总数会变成原来的两倍
- B.元素总数会变为原来的一半
- C.元素总数保持不变依旧为 24← 正确答案
- D.元素总数会变为原来的四倍
答案:C。reshape 的唯一约束是元素总数守恒:2×3×4 = 3×4×2 = 24。改变排列方式不改变总货格数。A、B、D 都在暗示总数变化,违背“重塑前后连乘相等”的基本规则。