Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

训练框架总结

在前十六章,我们从零开始,每一章都是在上一章的基础上逐步扩展,一步步搭建出了张量、计算图、网络层、损失函数、优化器、调度器、训练器……实现了深度学习向大语言模型跨越的基础构件。

现在,是时候把所有这些模块全部收集起来,组装成一个完整的、可复用的网络模型训练框架了。

这一章是前两部分的代码总结;也是下一部分,大语言模型,的起点。我们把现有的基本组件汇集成一个代码库,之后的部分将不再每次重复这些组件的代码。

张量

张量是整个框架的基石,也是自动微分的载体。我们对张量进行了一些重要的功能扩展:

  • 运算符重载:我们之前已经实现了张量加法,现在完整实现了减法、乘法、除法,以及矩阵乘法和矩阵转置。使得张量之间可以像数字一样,直接用 +、-、*、/、@ 运算,同时会自动记录计算图,和整个多层模型融为一体;

  • 广播支持:处理不同形状的张量之间的计算,比如一个 (2, 6) 的张量和一个 (1, 6) 的张量的加法。这在处理复杂模型,或者多维度数据时非常常见;

  • 关闭梯度(no_grad):允许在推理阶段不需要计算图时,临时关闭梯度计算,节约内存和算力;

  • 统一数据类型(DTYPE = np.float32):统一明确定义张量数值为 32 位浮点数。

⚠️ 注意:运算符的两边必须都是张量。张量和 Python 数字直接运算(例如 x * 2)会报错,需要先把数字包装成张量,例如 x * Tensor(2.0)。

模型

神经网络模型由多个网络层组成。所有层都支持由抽象层定义的基本功能。

抽象层

抽象层定义了最重要的函数接口:

  • forward(推理函数):实现前向传播;

  • parameters(参数列表):提供所有需要训练的参数;

  • train(训练函数):进入训练模式;

  • eval(测试函数):进入评估、推理模式。

线性层

加权求和,是最基本的网络层。

组合抽象层

定义了可以用作子层容器的抽象层,是复杂网络层的基础。

顺序层

最基本的网络层容器,所有子层顺序执行。

嵌入层

把字符或者词的索引编码通过查表转换成稠密嵌入向量,避免了使用独热编码的稀疏向量。

平均池化层

把一段序列的向量组采用平均值合并成一个向量。

激活函数

激活函数为网络模型引入了非线性,让模型可以学习到复杂关系。

线性整流函数(ReLU)

隐藏层默认首选。计算快,不会造成梯度消失。

双曲正切函数(Tanh)

输出 0 中心化,限制在 (-1, 1) 的范围内,存在梯度饱和问题。

S 形曲线函数(Sigmoid)

用于二元分类问题的输出层。

归一化指数函数(Softmax)

用于多元分类问题的输出层。

损失函数

损失函数衡量预测值和标签的误差,是训练的“指挥棒”,反向传播的起始点。

抽象类

损失函数抽象类定义了唯一的函数接口:

  • loss(损失函数):计算损失值。

均方误差损失函数

用于回归问题。

交叉熵损失函数

用于多元分类问题。内部已经包含 Softmax 计算。

二元交叉熵损失函数

用于二元分类问题。

优化器

优化器负责根据梯度和学习率更新参数。

抽象类

优化器抽象类定义了两个基本函数接口:

  • step(步进函数):更新参数;

  • zero_grad(清零函数):每次迭代前清空参数梯度。

随机梯度下降优化器

最简单、快速,学习率固定。

自适应矩估计优化器

给每个参数单独调整有效步幅,附带梯度裁剪。

权重衰减自适应矩估计优化器

附带权重衰减的 Adam。

学习率调度器

学习率调度器可以在训练过程中动态调整学习率(自动调参)。

抽象类

学习率调度器抽象类定义唯一的函数接口:

  • step(步进函数):根据当前步数调整学习率。

预热余弦退火调度器

让学习率从 0 爬升(预热),再沿余弦曲线平滑下降(余弦退火)。是训练大模型的标准做法。

数据集

数据集负责加载数据,划分训练集、测试集,以及按照批次遍历所有样本。

抽象类

数据集抽象类定义了基本的函数接口:

  • load(加载函数):加载数据;

  • train(训练函数):提供训练集数据;

  • eval(测试函数):提供测试集数据;

  • all(全部样本):读取全部样本;

  • __len__(样本数量):返回样本数量;

  • __getitem__(单个样本):根据索引读取样本。

训练器

训练器把模型、损失函数、优化器打包在一起,实现模型训练和测试逻辑。

抽象类

训练器抽象类定义两个基本的函数接口:

  • train(训练函数):用数据集训练集进行多轮次训练,可以接入学习率调度器;

  • test(测试函数):在数据集测试集上评估模型。

至此,我们的核心框架基本成型。

这套框架虽然只用 NumPy 写成,但是具备了现代深度学习框架的核心功能。下一部分,我们将在此基础上,搭建真正的 GPT 模型。

课后练习

  1. 张量目前不支持和 Python 数字直接运算。请修改 __add__、__sub__、__mul__、__truediv__,让 x * 2 和 x + 1.0 也能正常运行,并且反向传播的梯度仍然正确。提示:在运算开始时,先把数字包装成张量。