【硬核数学】2.1 升级你的线性代数:张量,深度学习的多维数据语言《从零构建机器学习、深度学习到LLM的数学认知》
欢迎来到本系列的第六篇文章,也是我们正式踏入“深度学习”领域的第一站。在前五篇中,我们已经系统地学习了构建经典机器学习模型所需的核心数学知识。我们知道,线性代数用向量和矩阵为数据提供了优雅的表示。一个数据集,通常可以被看作一个巨大的矩阵,每一行是一个样本,每一列是一个特征。
这种表示方法在处理表格数据时非常有效。但请思考一下,我们如何用一个矩阵来表示一张彩色图片?或者一段视频?或是一个批次 (batch) 的文本句子?
一张彩色图片,不仅有长和宽,还有红(R)、绿(G)、蓝(B)三个颜色通道。它天然就是一个三维的结构。一段视频,更是在图片的基础上增加了一个时间维度。一个批次的文本,则可能是 (句子数量, 句子长度, 每个词的向量表示) 这样的三维结构。试图将这些多维结构“压扁”成一个二维矩阵,会不可避免地丢失宝贵的结构信息。
深度学习的巨大成功,很大程度上就源于它能够直接处理这些高维的、结构化的数据。而这一切的背后,都离不开对经典线性代数的自然推广——张量 (Tensor)。今天,我们将一起完成这次认知升级,从向量和矩阵的世界,迈入张量的多维宇宙。这不仅是概念的扩展,更是理解所有现代神经网络(从CNN到Transformer)运作方式的钥匙。
第一部分:从矩阵到张量 —— 深度学习的通用数据容器
在物理学中,张量有着严格而复杂的定义,通常与坐标系变换下的不变量有关。但在深度学习的语境下,我们可以极大地简化这个概念,将它理解为一种极其灵活的多维数据容器。
到底什么是张量?
忘掉那些复杂的物理定义。在AI领域,一个张量就是一个多维数组。它是对我们熟悉的标量、向量和矩阵的自然推广。我们可以通过它的阶 (Rank) 或轴 (Axis) 的数量来定义它:
- 0阶张量 (Rank-0 Tensor):就是一个标量 (Scalar)。它是一个单独的数字,没有任何轴。例如: s = 42 s = 42 s=42。
- 1阶张量 (Rank-1 Tensor):就是一个向量 (Vector)。它是一组有序的数字,有一个轴。例如: v = [ 1 , 2 , 3 ] \mathbf{v} = [1, 2, 3] v=[1,2,3]。
- 2阶张量 (Rank-2 Tensor):就是一个矩阵 (Matrix)。它是一个数字组成的矩形阵列,有两个轴(行和列)。例如: M = ( 1 2 3 4 ) \mathbf{M} = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} M=(1324)。
现在,让我们继续向上推广:
- 3阶张量 (Rank-3 Tensor):可以想象成一个“数字立方体”,它有三个轴。
- N阶张量 (Rank-N Tensor):就是一个拥有N个轴的数字容器。
张量的形状 (Shape) 是一个元组(tuple),它表示了张量在每个轴上的维度大小。例如:
- 一个向量
[1, 2, 3]
的形状是(3,)
。 - 一个3行2列的矩阵的形状是
(3, 2)
。 - 一个3阶张量的形状可能是
(height, width, depth)
。
这张图清晰地展示了张量是我们已有知识的自然延伸。它不是一个全新的、需要从零开始学习的概念,而是一个统一了标量、向量和矩阵的更通用的框架。
为什么是张量?深度学习数据的天然形态
为什么这个推广如此重要?因为深度学习处理的现实世界数据,其本质就是高阶张量。
-
图像数据 (Image Data)
一张黑白图片可以表示为一个2阶张量(矩阵),形状为(height, width)
。但一张彩色图片,每个像素都有RGB三个通道的值。因此,它是一个3阶张量,形状为(height, width, channels)
。例如,一张224x224像素的RGB图片,就是一个形状为(224, 224, 3)
的3阶张量。 -
批量处理 (Batch Processing)
在训练神经网络时,我们几乎从不一次只处理一张图片。为了提高计算效率和训练稳定性,我们会将多张图片组成一个批次 (batch)。如果一个批次包含64张224x224的彩色图片,那么这个批次的数据就是一个4阶张量,形状为(batch_size, height, width, channels)
,即(64, 224, 224, 3)
。这是计算机视觉任务中最常见的数据形态。 -
视频数据 (Video Data)
视频数据在图片的基础上增加了一个时间维度,即一系列连续的帧。因此,一个视频可以表示为一个4阶张量,形状为(frames, height, width, channels)
。一个包含64个视频的批次,就是一个5阶张量,形状为(batch_size, frames, height, width, channels)
。 -
文本数据 (Text Data)
文本数据经过处理后,也常常以张量的形式存在。一个常见的表示方法是,将每个单词映射为一个高维向量(词嵌入,Word Embedding)。那么,一个由10个单词组成的句子,如果每个单词用一个128维的向量表示,这个句子就是一个2阶张量(矩阵),形状为(sequence_length, embedding_dim)
,即(10, 128)
。一个包含32个这样句子的批次,就是一个3阶张量,形状为(batch_size, sequence_length, embedding_dim)
,即(32, 10, 128)
。这正是处理语言模型(如LLM)时输入数据的标准形态。
张量提供了一个统一的语言,让我们能够无缝地处理和操作这些来自不同模态、结构各异的数据。在PyTorch、TensorFlow等深度学习框架中,张量是唯一的核心数据结构。
第二部分:张量运算 —— 神经网络的计算引擎
定义了张量这个数据容器后,我们必须定义它的运算规则。正是这些运算,构成了神经网络中信息前向传播和梯度反向传播的全部计算过程。张量运算可以看作是矩阵运算的直接推广。
逐元素运算 (Element-wise Operations) 和广播 (Broadcasting)
这是最简单的一类运算,包括加、减、乘、除、取幂等。它们独立地作用于张量中的每一个元素。对于两个形状完全相同的张量,它们的逐元素运算非常直观,就是对应位置的元素进行运算。
但如果两个张量的形状不同呢?这就引出了一个在实践中极其重要的概念——广播 (Broadcasting)。广播是深度学习框架为了方便计算而提供的一种机制,它允许在一定规则下对不同形状的张量进行运算。其核心思想是,将较小的张量“复制”或“扩展”其维度,使其形状与较大的张量匹配。
广播的规则(以NumPy/PyTorch为例):
- 如果两个张量的阶数不同,先在阶数较小的张量前面补1,使它们的阶数相同。
- 从后往前,逐个比较两个张量在每个轴上的维度大小:
- 如果维度大小相同,则该维度匹配。
- 如果其中一个张量的维度大小为1,则该维度匹配(可以进行广播)。
- 如果维度大小不同且均不为1,则无法广播,会报错。
一个典型的例子是在神经网络中给一个批次的输出添加偏置(bias)。
假设我们有一个全连接层的输出,是一个形状为 (batch_size, num_features)
的2阶张量,例如 (64, 10)
。我们还有一个偏置,是一个形状为 (10,)
的1阶张量(向量)。
当执行 output + bias
时:
- 偏置的形状
(10,)
首先被看作(1, 10)
。 - 输出的形状是
(64, 10)
。 - 比较维度:
- 最后一个维度:10 vs 10,匹配。
- 第一个维度:64 vs 1,匹配(可以广播)。
- 广播机制会将偏置向量
(1, 10)
“复制”64次,变成一个(64, 10)
的张量,然后与输出进行逐元素相加。
广播机制避免了我们手动创建和复制张量,让代码更简洁,也更节省内存。它是深度学习编程中无处不在的基本操作。
张量缩并 (Tensor Contraction)
这是张量运算中最核心、最强大的部分,是广义上的“乘法”。它通过将两个张量在一个或多个共同的轴上进行相乘并求和,从而产生一个阶数更低的新张量。
我们熟悉的运算都是张量缩并的特例:
- 向量点积 (Dot Product):将两个1阶张量(向量)缩并为一个0阶张量(标量)。
a ⋅ b = ∑ i a i b i \mathbf{a} \cdot \mathbf{b} = \sum_i a_i b_i a⋅b=∑iaibi - 矩阵-向量乘法:将一个2阶张量(矩阵)和一个1阶张量(向量)缩并为一个1阶张量(向量)。
( M v ) i = ∑ j M i j v j (\mathbf{Mv})_i = \sum_j M_{ij} v_j (Mv)i=∑jMijvj - 矩阵-矩阵乘法:将两个2阶张量(矩阵)缩并为一个2阶张量(矩阵)。
( A B ) i k = ∑ j A i j B j k (\mathbf{AB})_{ik} = \sum_j A_{ij} B_{jk} (AB)ik=∑jAijBjk
在更高阶的张量世界里,缩并可以发生在任意指定的轴上。例如,我们可以将一个形状为 (a, b, c)
的3阶张量和一个形状为 (c, d)
的2阶张量,在它们的共同轴(维度为c)上进行缩并,得到一个形状为 (a, b, d)
的3阶张量。
为了精确地描述这些复杂的缩并操作,爱因斯坦求和约定 (einsum
) 是一种非常强大和简洁的表示法,被广泛用于深度学习库中。例如,矩阵乘法可以写成 ij,jk->ik
,清晰地表明了输入张量的轴和输出张量的轴,以及在哪个轴上(j
)进行求和。
改变视图:重塑 (Reshape) 与轴换位 (Permutation)
除了计算,我们还经常需要改变张量的“视图”而不改变其内容。
-
重塑 (Reshape):改变张量的形状,但保持元素总数不变。一个经典应用是在将卷积层的输出送入全连接层之前,需要将其“压平”(Flatten)。例如,一个批次的特征图输出,形状为
(batch_size, height, width, channels)
,可以被重塑为一个2阶张量,形状为(batch_size, height * width * channels)
。 -
轴换位 (Permutation / Transpose):交换张量的轴的顺序。这在处理不同框架或库的输入要求时非常重要。例如,PyTorch中的卷积层通常期望输入形状为
(batch, channels, height, width)
,而TensorFlow/Keras则默认为(batch, height, width, channels)
。从一种格式转换到另一种,就需要进行轴换位操作。
这个流程图展示了重塑和轴换位在神经网络数据流中的实际作用。它们是连接不同类型层、适配不同数据格式的“胶水”操作。
第三部分:张量在行动 —— 构建神经网络层
现在,让我们将前面学到的张量及其运算知识应用起来,看看它们是如何构建起现代神经网络的两个最核心的层:全连接层和卷积层。
全连接层 (Fully Connected Layer)
全连接层,也叫稠密层 (Dense Layer),是神经网络中最基本的一种层。它的作用是对输入数据进行一次线性的仿射变换。
其数学表达式我们已经很熟悉了:
y = f ( x W + b ) \mathbf{y} = f(\mathbf{xW} + \mathbf{b}) y=f(xW+b)
这里 f f f 是激活函数(如ReLU),我们暂时忽略它,只关注线性变换部分 x W + b \mathbf{xW} + \mathbf{b} xW+b。现在,我们用张量的语言来重新解读它,特别是当输入是一个批次的数据时。
- 输入张量 X:一个2阶张量,形状为
(batch_size, in_features)
。 - 权重张量 W:一个2阶张量(矩阵),形状为
(in_features, out_features)
。这是该层的可学习参数。 - 偏置张量 b:一个1阶张量(向量),形状为
(out_features,)
。这也是可学习参数。
计算过程:
- 张量缩并:计算
Z = X @ W
(这里@
代表矩阵乘法)。这是一个(batch_size, in_features)
和(in_features, out_features)
两个2阶张量的缩并,结果Z
是一个形状为(batch_size, out_features)
的2阶张量。 - 广播相加:计算
Y = Z + b
。这里,偏置向量b
(形状(out_features,)
)被广播,与Z
的每一行(每个样本的输出)相加。
这个图清晰地展示了,一个看似简单的全连接层,其内部的批量计算过程完美地融合了张量缩并和广播这两种核心运算。
卷积层 (Convolutional Layer)
卷积层是计算机视觉领域的王者,它通过“局部连接”和“参数共享”的思想,极大地提高了处理图像等网格状数据的效率。用张量的语言来描述卷积,能让我们最深刻地理解其工作原理。
卷积操作的核心,是一个小的“卷积核”(Kernel) 或“滤波器”(Filter) 在输入张量上滑动,进行计算。
让我们来定义参与这场“舞蹈”的张量们:
- 输入张量 (Input):一个4阶张量,形状为
(N, C_in, H, W)
,其中N
是批量大小,C_in
是输入通道数(比如RGB图就是3),H, W
是高和宽。 - 卷积核张量 (Kernel):这也是一个4阶张量!形状为
(C_out, C_in, K_h, K_w)
。C_out
是我们希望得到的输出通道数(即滤波器的数量),C_in
必须与输入通道数匹配,K_h, K_w
是卷积核的高和宽(例如3x3)。这个张量是卷积层的可学习参数。 - 输出张量 (Output):一个4阶张量,形状为
(N, C_out, H_out, W_out)
。输出的高和宽取决于卷积的步长(stride)和填充(padding)。
卷积运算的本质:
卷积运算是一次极其复杂的、高度结构化的张量缩并。我们可以这样理解它:
为了计算输出张量中 (n, c_out, h, w)
位置的一个标量值,我们需要:
- 从输入张量中,以
(h, w)
为中心,取出一个形状为(C_in, K_h, K_w)
的子张量(一个3D小方块)。 - 从卷积核张量中,取出第
c_out
个滤波器,它也是一个形状为(C_in, K_h, K_w)
的3D张量。 - 对这两个3D张量,进行逐元素相乘,然后将所有乘积结果全部相加,得到一个标量值。这个值就是输出张量在
(n, c_out, h, w)
位置的值。
整个卷积过程,就是通过滑动窗口,重复上述计算,填满整个输出张量。
(这个动态图直观地展示了一个3x3的卷积核在输入图像上滑动,每次覆盖一个区域,计算后在输出特征图上生成一个值的过程。这是理解卷积最直观的方式。)
从张量的视角看,卷积层之所以强大,是因为它的权重张量(卷积核)的形状 (C_out, C_in, K_h, K_w)
远小于全连接层所需要的权重。如果将一张224x224x3的图用全连接层处理,权重参数会是天文数字。而卷积层通过共享一个小的卷积核张量,在整个空间上进行滑动计算,极大地减少了参数量,同时又有效地提取了局部空间特征。
融会贯通:张量——深度学习的统一语言
今天,我们完成了从经典线性代数到深度学习线性代数的关键一跃。我们看到,张量并非一个可怕的怪兽,而是我们熟悉的向量和矩阵的自然延伸。它为我们提供了一个统一而强大的框架,来表示和操作深度学习中各种复杂的数据结构。
- 张量是通用容器:无论是图像、视频还是文本,所有数据在进入神经网络后,都被转化为张量这一标准格式。
- 张量运算是计算核心:神经网络的前向传播,本质上就是一系列预定义好的张量运算(缩并、广播、逐元素计算等)构成的计算图。全连接层是经典的矩阵乘法,卷积层是更复杂的结构化张量缩并。
- 张量是参数载体:神经网络需要学习的权重和偏置,其本身也是以张量的形式存在和更新的。
W
和b
都是张量。
掌握了张量的语言,你就掌握了阅读和理解所有现代深度学习模型架构图的“密码”。当你看到一个模型图时,你看到的不再是简单的方块和箭头,而是数据在不同形状的张量之间流转、变换的动态过程。
这是我们深度学习之旅的第一步。在接下来的文章中,我们将看到,微积分如何在这个张量的世界里进行“自动微分”,从而实现梯度在复杂计算图中的反向传播;优化理论又是如何演化出SGD、Adam等算法,来高效地更新这些巨大的权重张量。张量,是我们通往深度学习所有后续主题的基石。
习题
第1题:张量的阶 (Rank)
请确定以下数据结构通常被表示为几阶张量:
A. 一张256x256像素的灰度图片。
B. 一个包含32张512x512像素的RGB彩色图片的批次。
C. 一个神经网络中,连接100个输入特征和50个输出特征的全连接层的偏置(bias)。
D. 一个用于处理RGB图像的3x3卷积核(单个滤波器)。
第2题:广播 (Broadcasting)
假设你有一个形状为 (4, 1, 3)
的张量A,和一个形状为 (5, 3)
的张量B。请问A和B是否可以进行广播相加?如果可以,结果张量的形状是什么?如果不行,请说明理由。
第3题:张量形状与神经网络设计
你正在设计一个简单的卷积神经网络来处理MNIST手写数字数据集。输入图片是 28x28
的灰度图,你使用一个包含16张图片的批次。
A. 输入到网络第一个卷积层的张量,其形状应该是什么?(假设格式为 N, C, H, W
)
B. 第一个卷积层使用了32个 5x5
的滤波器,步长为1,无填充。经过这个卷积层后,输出的特征图张量的形状是什么?
C. 在将这个特征图送入全连接层之前,你需要将其“压平”。压平后的2阶张量形状是什么?
答案
第1. 答案:
A. 2阶张量。形状为 (256, 256)
。
B. 4阶张量。形状为 (32, 512, 512, 3)
(如果格式是 N, H, W, C) 或 (32, 3, 512, 512)
(如果格式是 N, C, H, W)。
C. 1阶张量 (向量)。形状为 (50,)
,因为偏置是针对每个输出特征的。
D. 3阶张量。一个滤波器需要覆盖输入的所有通道,所以它的形状是 (in_channels, kernel_height, kernel_width)
。对于RGB图像,in_channels
是3,所以形状是 (3, 3, 3)
。整个卷积层的权重是4阶张量,但单个滤波器是3阶。
第2. 答案:
可以进行广播相加,结果张量的形状是 (4, 5, 3)
。
理由如下:
- 张量A的形状是
(4, 1, 3)
,张量B的形状是(5, 3)
。 - 根据广播规则1,先将B的阶数提升到与A相同,在前面补1。B的形状变为
(1, 5, 3)
。 - 现在比较A
(4, 1, 3)
和 B(1, 5, 3)
的形状,从后往前:- 最后一个轴:3 vs 3,匹配。
- 中间的轴:1 vs 5,匹配(1可以广播到5)。
- 第一个轴:4 vs 1,匹配(1可以广播到4)。
- 所有轴都匹配,可以广播。结果张量的形状取每个轴上较大的那个维度,即
(4, 5, 3)
。
第3. 答案:
A. 输入张量的形状是 (16, 1, 28, 28)
。
N=16
(批量大小),C=1
(灰度图只有一个通道),H=28
, W=28
。
B. 输出特征图的形状是 (16, 32, 24, 24)
。
N=16
保持不变。C_out=32
因为使用了32个滤波器。- 输出尺寸计算公式: W o u t = W i n − K + 2 P S + 1 W_{out} = \frac{W_{in} - K + 2P}{S} + 1 Wout=SWin−K+2P+1。这里 W i n = 28 , K = 5 , P = 0 , S = 1 W_{in}=28, K=5, P=0, S=1 Win=28,K=5,P=0,S=1。
- H o u t = W o u t = 28 − 5 + 0 1 + 1 = 24 H_{out} = W_{out} = \frac{28 - 5 + 0}{1} + 1 = 24 Hout=Wout=128−5+0+1=24。
C. 压平后的形状是 (16, 18432)
。
batch_size=16
保持不变。- 新的特征维度是
C_out * H_out * W_out
=32 * 24 * 24
=18432
。