张量、形状与维度:今天真正弄懂
先记住:一句话定义:张量是一个用固定规则排成多维网格的数字容器;形状是每个方向上有多少个数;维度是这个容器有几个方向。记忆口诀:“几维看中括号,形状数元素量;从外往里剥,轴号从零数。”
【生活类比】 把张量想象成收纳盒: - 0维标量:盒子里单独的一粒药丸(单一数值,无方向)。 - 1维向量:一排药盒(周一到周日,只有“左右”1个方向)。 - 2维矩阵:一个药盘(多行多列,有“上下、左右”2个方向)。 - 3维张量:多层药架(有“层、行、列”3个方向)。 - 4维张量:多栋楼里的药架(“楼、层、行、列”4个方向)。
【必要公式与符号解释】 数学上,一个 $N$ 维张量表示为: $$X \in \mathbb{R}^{d_0 \times d_1 \times \dots \times d_{N-1}}$$ - $X$:张量本身的名字。 - $\mathbb{R}$:里面的数字是实数(如浮点数)。 - $N$:维度的总数(数学上常叫阶数/Rank,PyTorch 叫 `ndim` 或轴的个数)。 - $d_k$:第 $k$ 个轴(axis $k$)上的长度。 - $(d_0, d_1, \dots, d_{N-1})$:就是这个张量的形状(`shape`)。
【它解决什么问题?没有它会怎样】 - 解决的问题:计算机内存是一根“单行道”(一维连续字节)。没有张量,我们要把“一段 5 秒、有 4 个说话人的音频频谱”塞进一维长数组里,每次找“第 2 个说话人在第 3 秒的能量”都必须手动计算步长偏移量(比如 `i * 128 + j`)。 - 没有张量:多模态代码会充斥着嵌套的 for 循环和手动内存索引,GPU 根本无法做并行矩阵乘法,现代音视频深度学习完全无法运转。
【在音视频与说话人日志中的实际位置】 你在做音视频理解与说话人日志时,天天面对的就是不同形状的张量在变换: 1. 原始音频:形状通常是 `[Batch, Samples]`。若取梅尔频谱(Log-Mel),变成 `[Batch, 1, Mel_bins, Time]`(批次, 声道, 频点, 时间帧)。 2. 视频画面:形状通常是 `[Batch, Channel, Frames, Height, Width]`(即 `[B, C, T, H, W]`)。 3. 说话人日志(Diarization)输出:预测哪个时间点谁在说话,形状通常是 `[Batch, Time, Num_Speakers]`。 模型(如 Conformer、Transformer)的每一层,本质上都在对这些张量的不同轴做切片、聚合、投影与变形。
最直观判断一个张量是几维的方法是什么?
张量的 shape 是 [8, 128, 64],请问它的轴 1(axis 1)的长度是多少?
在 PyTorch 中,`tensor.ndim` 和 `tensor.numel()` 分别代表什么?
【发展流程】 - 之前怎么做:在深度学习流行前,处理音频用 C/C++ 或 MATLAB 的二维数组,特征(如 MFCC)按帧串行处理,批处理全靠外部写循环遍历。 - 为什么出现:2010 年后 GPU 并行计算兴起,单帧计算太慢,必须把多段音频、多个通道“打包”成固定规格的多维网格,交由硬件并行加速。NumPy 确立了 `ndarray` 规范,随后 Torch/TensorFlow 赋予张量“自动求导”与“显卡加速”能力。 - 现在怎么用:在 PyTorch 中,通过 `torch.Tensor` 一体化完成数据装载、在指定轴上的缩减运算(如沿时间轴做均值池化)以及模态拼接。想深入打牢基础,推荐在 Dive into Deep Learning 中先看直觉和公式,再运行章节中的代码;在 PyTorch Tutorials 中对照官方示例掌握张量与训练写法。
【与相近概念的区别】 1. 维度(Dimension / ndim / Axis)vs 特征维度(Feature Dimension): - 形状是 `[32, 100, 256]` 的张量,“维度/轴数”是 3(有 3 个方向)。 - 其中的 256 是第 2 轴的长度,口语里常被称为“特征维度/隐藏层维度”。切勿把“张量总共有几维”和“特征向量的长度”混为一谈。 2. 形状(Shape)vs 大小(Size): - 在 PyTorch 中 `tensor.shape` 和 `tensor.size()` 完全等价,返回一个元组,代表各轴长度;而 `tensor.numel()` 返回元素总个数(所有轴长度的乘积)。
【当前局限与未来作用】 - 当前事实:张量必须是“矩形/齐整网格”。如果一个批次里的 4 段音频长度不同(10秒、3秒、7秒、12秒),必须将短的填充补零(Padding)至 12 秒,造成显存和计算浪费。 - 未来推测与演进:虽然目前通过 Nested Tensor(嵌套张量)和变长注意力(如 FlashAttention varlen)在底层跳过填充计算,但真正的“非齐整动态稀疏张量”若想在全流程编译器上零开销普及,仍需硬件与底层运行时的深度协同支持。
- 形状为 [16, 80, 500] 的梅尔频谱张量,它的总维度是多少?它在内存中总共包含多少个浮点数?
- 如果要把说话人日志输出张量 [4, 200, 8] 在时间轴上做全局平均池化,池化后的形状是什么?
- 为什么把长短不一的音频打包成一个批次张量时必须补零(Padding)?