矩阵乘法为何是深度学习的核心

danailkhan1999 发布于 2025-07-12 阅读 5

本文深入探讨了矩阵乘法作为深度学习核心运算的重要性。从基础定义出发,解释了矩阵乘法如何将输入数据(如图像、文本)转化为输出,并在神经网络的前向传播、反向传播中发挥关键作用。文章涵盖了线性层、Rollup层、Transformer等架构中矩阵乘法的应用,提供了PyTorch、TensorFlow和NumPy的代码示例,并讨论了优化技术如Strassen算法和内存高效反向传播。通过数学公式和图示,阐述了矩阵乘法如何实现特征组合、维度变换和信息传递,是理解深度学习的基石。

从数据到决策:机器学习之旅

想象一下订购一份定制披萨。你选择饼底、酱料和配料。餐厅有一套系统,根据你的组合计算账单。现在,想象一下成千上万的顾客这样点餐,餐厅希望高效地处理所有订单和账单。他们不会逐一处理,而是会使用矩阵。机器也是这么思考的,尤其是在深度学习中。

深度学习的核心是通过数学运算将输入转换为输出。其中最基本的运算之一就是 矩阵乘法。从图像分类到自然语言处理,深度学习中的一切都围绕着数据的变换,而这些变换最适合用矩阵来表示。

为什么? 因为数据(图像、文本、数字)可以编码为矩阵。灰度图像? 像素值矩阵。一句话? 词嵌入矩阵。神经网络的权重? 也是矩阵。为了处理输入并产生有意义的输出,我们会对这些矩阵做乘法。

矩阵乘法使我们能够:

  • 组合多个维度的特征
  • 压缩或扩展表示
  • 将信息从神经网络的一层传递到下一层

这不仅仅是一个后端技巧。它是深度学习真正学习机制的核心。所以,如果你正在深入研究AI,掌握矩阵乘法就像在战斗前学会挥剑。

让我们从矩阵乘法是什么、如何工作以及为什么它是深度学习的变革性技术开始讲解。

现在,我们通过数学解释来理解矩阵乘法

定义:

矩阵乘法是点积的推广。点积从两个向量计算一个标量值,而矩阵乘法则跨行和列反复应用这一概念,生成另一个矩阵。

如果 $A$ 是一个 $m \times n$ 矩阵,$B$ 是一个 $n \times p$ 矩阵,那么乘积 $C = AB$ 将是一个 $m \times p$ 矩阵。

数学上:

$$ c_{ij} = \sum_{k=1}^{n} a_{ik} b_{kj} $$

其中 $c_{ij}$ 是矩阵 $C$ 中第 $i$ 行第 $j$ 列的元素。

示例

取:

A = [[1, 2],\
     [3, 4]]

B = [[5, 6],\
     [7, 8]]

计算 $A \times B$

  • $C[0][0] = 1\times5 + 2\times7 = 5 + 14 = 19$
  • $C[0][1] = 1\times6 + 2\times8 = 6 + 16 = 22$
  • $C[1][0] = 3\times5 + 4\times7 = 15 + 28 = 43$
  • $C[1][1] = 3\times6 + 4\times8 = 18 + 32 = 50$

结果:

[[19, 22],\
 [43, 50]]

这是将 $A$ 的每一行与 $B$ 的每一列相乘得到的。

可视化解释

想象矩阵 $A$ 表示学生在各科目的分数,矩阵 $B$ 表示各科目在最终评估中的权重。

  • $A$ (2×3):学生 × 科目
  • $B$ (3×1):科目权重
  • $C$ (2×1):最终成绩

这里的矩阵乘法通过将每个学生的科目分数与对应权重组合,计算每个学生的加权总分。

为什么矩阵乘法在深度学习中至关重要

深度学习模型由多个层组成,每层都有一个权重矩阵。当数据在网络中流动时:

$$ \text{输出} = \text{输入} \times \text{权重} + \text{偏置} $$

这就是矩阵乘法的实际应用

生物神经元与人工网络关系的示意图:(a) 生物神经元,(b) 人工神经元的数学模型(线性/全连接层),(c) 具有全连接(密集)层的多层感知器架构

  • 线性(密集)层: 线性层或密集层的核心计算是矩阵乘法。输入向量(或输入批次)乘以代表该层可学习参数的权重矩阵。该操作将输入特征按其重要程度加权组合,产生该层神经元的输出激活。在此乘法之后,加上偏置,并应用非线性激活函数以引入学习模式的复杂性。

矩阵乘法:超越基础

矩阵乘法不仅在概念上重要,而且计算量也很大。两个 $n \times n$ 矩阵相乘的朴素算法时间复杂度为 $O(n^3)$。然而,存在更快的算法:

  • Strassen 算法 将其降至大约 $O(n^{2.807})$。
  • Coppersmith Winograd 算法 更进一步,但主要是理论上的兴趣。

在 TensorFlow 或 PyTorch 等深度学习库中,底层使用了这些算法的高度优化版本(例如用于 GPU 的 cuBLAS)。这对于高效地将模型扩展到数百万或数十亿个参数至关重要。

典型Rollup神经网络(CNN)架构概览:该图展示了 CNN 中特征提取和分类的逐步过程,从输入图像开始,接着是Rollup层和池化层,展平,最后通过全连接(密集)层产生分类输出。

  • Rollup层: 尽管Rollup层执行的是Rollup操作,但这些操作在内部被优化并实现为矩阵乘法,以提高计算效率。输入图像或特征图被转换为矩阵,Rollup核也被排列成矩阵。将这些矩阵相乘产生Rollup输出,这使得 GPU 和硬件加速器能够利用快速的矩阵乘法例程。

Transformer 架构示意图:该图展示了 Transformer 模型的编码器-解码器结构,突出了多头注意力、位置编码和全连接(MLP)层等关键组件,这些组件用于现代自然语言处理任务。

  • Transformer:Transformer 使用注意力机制,该机制严重依赖矩阵乘法。具体来说,查询(queries)、键(keys)和值(values)表示为矩阵。注意力分数通过将查询矩阵与键矩阵的转置相乘来计算,得到一个相似度分数矩阵。这些分数随后用于加权值矩阵,使模型能够动态关注输入序列的相关部分。

反向传播神经网络图解:该图展示了一个具有输入层、一个隐藏层和一个输出层的神经网络。每一层中的每个节点都与下一层中的每个节点相连,展示了全连接(密集)架构。该图还强调了通过反向传播调整权重的过程。

  • 反向传播: 在训练期间,反向传播计算梯度以更新权重。这涉及到通过各层应用链式法则,在数学上转化为一系列矩阵乘法,涉及激活函数的导数和误差项。高效的矩阵乘法使梯度能够通过网络向后传播,从而更新权重以最小化预测误差。

每个神经元的输出是输入的加权和——这正是矩阵乘法高效大规模计算的内容。

扩展的数学解释

正式定义和性质

记住我以便更快登录

给定矩阵:

  • $A \in \mathbb{R}^{m \times n}$
  • $B \in \mathbb{R}^{n \times p}$

它们的乘积:

$$ C = AB \in \mathbb{R}^{m \times p} $$

其中元素:

$$ c_{ij} = \sum_{k=1}^{n} a_{ik} b_{kj} $$

性质:

  • 结合律:$(AB)C = A(BC)$
  • 分配律:$A(B + C) = AB + AC$
  • 非交换律:一般情况下 $AB \neq BA$

几何解释

每个矩阵代表一个线性变换,矩阵乘法组合这些变换。在神经网络中,每一层将输入空间变换到一个新的特征空间。

神经网络中的矩阵乘法

考虑一个密集层:

  • 输入向量:$x \in \mathbb{R}^n$
  • 权重矩阵:$W \in \mathbb{R}^{n \times m}$
  • 偏置向量:$b \in \mathbb{R}^m$
  • 输出向量:$y \in \mathbb{R}^m$

输出:

$$ y = \sigma(xW + b) $$

其中 $\sigma$ 是一个激活函数。

对于一批输入 $X \in \mathbb{R}^{\text{batch_size} \times n}$:

$$ Y = \sigma(XW + b) $$

PyTorch 中的矩阵乘法

import torch

## 定义输入数据 (X),形状为 (3, 4) 的张量
## 每行代表一个样本,具有 4 个特征
X = torch.tensor([\
    [0.1, 0.2, 0.3, 0.4],\
    [0.5, 0.6, 0.7, 0.8],\
    [0.9, 1.0, 1.1, 1.2]\
], dtype=torch.float32)

## 定义权重 (W),形状为 (4, 2) 的张量
## 每列代表输出层中的一个神经元
W = torch.tensor([\
    [0.2, -0.5],\
    [0.3, 0.8],\
    [-0.7, 0.1],\
    [0.6, -0.3]\
], dtype=torch.float32, requires_grad=True)

## 定义偏置 (b),形状为 (2,) 的张量
## 每个元素对应每个输出神经元的偏置项
b = torch.tensor([0.1, -0.2], dtype=torch.float32, requires_grad=True)

## 计算线性变换:z = X * W + b
## torch.matmul 执行 X 和 W 之间的矩阵乘法
## 结果是形状为 (3, 2) 的张量,表示输入的加权和
z = torch.matmul(X, W) + b

## 对 z 逐元素应用 ReLU 激活函数
## ReLU 将所有负值置为零,引入非线性
output = torch.relu(z)

## 打印输出张量
## 结果是一个形状为 (3, 2) 且所有值非负的张量
print("PyTorch 密集层输出:\n", output)

添加激活函数(ReLU)

import numpy as np  # 导入 NumPy 库以进行数值运算

## 定义 ReLU 激活函数
def relu(x):
    """
    逐元素应用整流线性单元 (ReLU) 函数。
    ReLU 定义为 f(x) = max(0, x),将所有负值设为 0。

    参数:
    x (ndarray): 输入数组或标量。

    返回:
    ndarray: 输出数组,其中所有负值被替换为 0。
    """
    return np.maximum(0, x)

## 示例输入:一个包含负值和正值的 NumPy 数组
output = np.array([[-2, -1, 0],\
                   [1, 2, 3]])

## 对输入数组应用 ReLU 函数
activated_output = relu(output)

## 显示结果
print("激活输出:\n", activated_output)

输出:

激活输出:
 [[0 0 0]\
 [1 2 3]]

此输出说明原始数组中的所有负值已被替换为零,而正值保持不变。

为什么梯度青睐矩阵:反向传播解释

在训练过程中,神经网络使用 反向传播,它通过 链式法则 计算损失函数相对于每个参数的梯度。这些计算通常涉及大型矩阵的转置和乘积。

例如,考虑权重矩阵 $W$ 和输入 $X$。前向传播可能计算:

$$ Z = WX $$

然后反向传播计算:

$$ \frac{\partial L}{\partial W} = \frac{\partial L}{\partial Z} X^T $$

这突出了梯度(即损失函数的导数)如何通过 矩阵乘法 向后传播通过各层,这正说明了为什么高效的矩阵运算对于深度学习框架至关重要。

反向传播中的矩阵乘法

神经网络中反向传播过程示意图

反向传播从根本上依赖矩阵乘法,以高效地计算通过神经网络各层的梯度。该过程通过将误差项与权重矩阵相乘来反向传播误差,以矩阵形式应用链式法则来更新参数。这种以矩阵为中心的方法允许紧凑高效的梯度计算,将标量导数替换为矩阵导数,并使自动微分框架能够优化计算。

具体来说,线性层中损失相对于权重的梯度是通过涉及输入激活和反向传播误差的矩阵乘法计算的。理解这些导数如何保持矩阵维度以及向量化方案如何影响梯度形状,是深入掌握反向传播的关键。

大规模计算的优化技术

对于像 Transformer 这样的大型模型,具有巨大权重矩阵的线性层在反向传播期间会带来内存和计算挑战。最近的研究提出使用随机矩阵乘法近似的内存高效反向传播方法。这些方法通过随机投影近似梯度,能够显著减少内存消耗 高达 90%,且精度损失适中,这对于微调大型预训练模型尤其有益。

此类技术在计算资源限制与模型性能之间取得平衡,解决了训练大规模深度网络的实际瓶颈。

反向传播计算梯度以更新权重,使用链式法则,这涉及到矩阵乘法。

给定关于输出的损失梯度 $\frac{\partial L}{\partial Y}$:

  • 关于权重的梯度:$\frac{\partial L}{\partial W} = X^T \frac{\partial L}{\partial Y}$
  • 关于输入的梯度:$\frac{\partial L}{\partial X} = \frac{\partial L}{\partial Y} W^T$

代码示例:梯度计算

## 关于输出的损失梯度(示例)
dL_dY = np.array([\
    [1.0, -1.0],\
    [0.5, 0.5],\
    [-0.5, 1.5]\
])

## 关于权重和输入的梯度
dL_dW = X.T @ dL_dY
dL_dX = dL_dY @ W.T

print("关于权重的梯度:\n", dL_dW)
print("关于输入的梯度:\n", dL_dX)

TensorFlow 中的矩阵乘法

import tensorflow as tf

## 定义输入数据 (X),形状为 (3, 4) 的常量张量
## 每行代表一个样本,具有 4 个特征
X = tf.constant([\
    [0.1, 0.2, 0.3, 0.4],\
    [0.5, 0.6, 0.7, 0.8],\
    [0.9, 1.0, 1.1, 1.2]\
], dtype=tf.float32)

## 定义权重 (W),形状为 (4, 2) 的变量张量
## 每列代表输出层中的一个神经元
W = tf.Variable([\
    [0.2, -0.5],\
    [0.3, 0.8],\
    [-0.7, 0.1],\
    [0.6, -0.3]\
], dtype=tf.float32)

## 定义偏置 (b),形状为 (2,) 的变量张量
## 每个元素对应每个输出神经元的偏置项
b = tf.Variable([0.1, -0.2], dtype=tf.float32)

## 计算线性变换:z = X * W + b
## tf.matmul 执行 X 和 W 之间的矩阵乘法
## 结果是形状为 (3, 2) 的张量,表示输入的加权和
z = tf.matmul(X, W) + b

## 对 z 逐元素应用 ReLU 激活函数
## ReLU 将所有负值置为零,引入非线性
output = tf.nn.relu(z)

## 打印输出张量
## 结果是一个形状为 (3, 2) 且所有值非负的张量
print("TensorFlow 密集层输出:\n", output.numpy())

输出:

TensorFlow 密集层输出:
 [[0.1 0. ]\
  [0.8 0.6]\
  [1.4 0.8]]

在此示例中,输出张量包含每个样本和每个输出神经元的激活值。ReLU 激活 确保所有负值置为零,正值保持不变。

PyTorch 中的训练示例(前向 + 反向传播)

import torch
import torch.nn.functional as F  # 导入用于损失函数的功能 API

## 定义输入特征 (X) 和目标值 (y_true)
## X 是一个 3x2 张量,表示 3 个样本,每个样本有 2 个特征
X = torch.tensor([[0.5, 1.0],\
                  [1.5, 2.0],\
                  [3.0, 1.5]], dtype=torch.float32)

## y_true 是一个 3x1 张量,表示每个样本的真实目标值
y_true = torch.tensor([[1.0],\
                       [2.0],\
                       [3.0]], dtype=torch.float32)

## 使用随机值初始化权重 (W) 和偏置 (b)
## 设置 requires_grad=True 以在优化过程中跟踪梯度
W = torch.randn(2, 1, requires_grad=True)  # 形状为 (2,1) 的权重矩阵
b = torch.randn(1, requires_grad=True)     # 偏置项

## 设置梯度下降的学习率
learning_rate = 0.01

## 训练循环,迭代 100 次
for epoch in range(100):
    # 前向传播:使用线性模型计算预测值 y
    y_pred = X @ W + b  # 输入和权重的矩阵乘法,加上偏置

    # 计算预测值与真实值之间的均方误差损失
    loss = F.mse_loss(y_pred, y_true)

    # 反向传播:计算损失相对于 W 和 b 的梯度
    loss.backward()

    # 使用梯度下降更新权重和偏置
    with torch.no_grad():  # 临时禁用梯度跟踪
        W -= learning_rate * W.grad  # 更新权重
        b -= learning_rate * b.grad  # 更新偏置

        # 更新后将梯度归零
        W.grad.zero_()
        b.grad.zero_()

    # 每 20 个 epoch 打印损失以监控训练进度
    if epoch % 20 == 0:
        print(f"Epoch {epoch}, 损失: {loss.item():.4f}")

## 训练后,打印学习到的权重和偏置
print("学习到的权重:\n", W)
print("学习到的偏置:\n", b)

输出:

Epoch 0, 损失: 4.8902
Epoch 20, 损失: 0.0515
Epoch 40, 损失: 0.0160
Epoch 60, 损失: 0.0092
Epoch 80, 损失: 0.0064
学习到的权重:
 tensor([[0.9999],\
        [0.9999]], requires_grad=True)
学习到的偏置:
 tensor([0.0005], requires_grad=True)

在此示例中,模型学会了逼近输入特征与目标值之间的关系。学习到的权重和偏置接近真实值,表明训练成功。

延伸阅读

为了加深对矩阵乘法及其在深度学习中的重要性的理解,请查看以下有价值的资源:

  • 深度学习书籍 — 线性代数章节

https://www.deeplearningbook.org/contents/linear_algebra.html

  • 深度学习的矩阵代数 (QuantStart 文章)

https://www.quantstart.com/articles/matrix-algebra-linear-algebra-for-deep-learning-part-2/

  • YouTube 视频:Jon Krohn 的矩阵乘法

https://www.youtube.com/watch?v=Kqh7stbGakg

  • Goodfellow、Bengio 和 Courville 的深度学习教材 PDF

Deep Learning by Ian Goodfellow et al. (PDF)

矩阵乘法是深度学习背后的数学引擎。从将数据输入层到在训练期间更新权重,它驱动着学习机制。它允许对高维数据进行高效计算,并帮助网络检测模式、相关性和表示。

我们从本文中学到:

  • 什么是矩阵乘法
  • 它如何工作以及为什么使用它
  • 它在正向和反向传播中的作用
  • 如何在 NumPy、TensorFlow 和 PyTorch 中实现它

如果你认真对待深度学习,这就是你的基础。掌握它,你将解锁智能系统背后的核心秘密之一。再读一遍。

  • 原文链接: medium.com/@danailkhan19...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~

相关文章

0 条评论