深度学习框架入门:PyTorch 基础 —— 张量、自动微分与模型构建

发布时间:2026/8/11 1:43:35
深度学习框架入门:PyTorch 基础 —— 张量、自动微分与模型构建 深度学习框架入门PyTorch 基础 —— 张量、自动微分与模型构建21.1 本章导学手动推导反向传播、用 NumPy 手写小型网络能够帮我们彻底理解深度学习的底层逻辑但真实工程场景中几乎不会有人从零手写所有层和求导逻辑。随着网络层数加深、结构复杂化手动求导不仅效率极低还极易出错更无法利用 GPU 的并行算力加速训练。深度学习框架的诞生就是为了将开发者从重复的底层实现中解放出来专注于模型结构设计与业务逻辑本身。在众多框架中PyTorch 凭借动态图机制、简洁易用的 API、强大的生态支持已经成为学术界与工业界的事实标准。从经典的 CNN、RNN到 Transformer 大模型几乎所有前沿算法与开源模型都优先提供 PyTorch 实现。对于大模型开发者而言PyTorch 是必备的基础工具模型加载、微调、推理、二次开发全部基于它完成。本章是 PyTorch 的入门篇章按照 “数据结构 - 核心机制 - 模型范式 - 实战落地” 的逻辑逐层展开首先讲解张量的定义、属性、常用操作对应 NumPy 的知识体系做迁移学习然后深入自动微分的原理与使用理解框架如何自动实现反向传播接着介绍 nn.Module 模型构建的标准范式掌握自定义网络的通用方法最后通过完整的小案例串联全流程搭建第一个可运行的神经网络。所有知识点均配套代码示例与工程注意事项为后续 CNN、RNN、Transformer 的学习打下工具基础。21.2 PyTorch 概述与环境配置21.2.1 框架定位与生态优势PyTorch 由 Meta AI 团队开发2017 年正式发布短短几年内就超越了此前占据主导地位的 TensorFlow成为深度学习领域的主流框架。它的核心优势集中在三点 第一动态计算图机制。计算图在每次前向传播时实时构建支持 Python 原生的控制流循环、条件判断都可以正常微分调试极其方便可以像调试普通 Python 代码一样打断点、查看中间张量的值。这一特性极大降低了学习门槛也让复杂模型的开发变得灵活。 第二API 设计简洁统一。张量操作、模型构建、训练流程都遵循直觉化的设计学习曲线平缓NumPy 的使用者可以快速迁移。 第三生态极其完善。计算机视觉有 TorchVision自然语言处理有 Hugging Face Transformers图学习有 PyG强化学习有稳定的第三方库。大模型时代几乎所有开源大模型都基于 PyTorch 实现配套的微调、推理、部署工具链全部围绕 PyTorch 构建。21.2.2 环境安装与验证工业界标准的安装方式是通过 conda 安装同时匹配对应版本的 CUDA 工具包实现 GPU 加速。安装前需要确认显卡支持 CUDA并且选择与显卡驱动匹配的 PyTorch 版本版本不匹配会导致 GPU 无法使用。 验证安装成功的标准代码非常简单import torch print(torch.__version__) print(torch.cuda.is_available()) # 返回True则GPU可用大模型开发对环境版本敏感推荐固定 Python、PyTorch、CUDA 的版本组合避免不同库之间的兼容性问题。生产环境通常使用 Docker 封装完整环境保证多机运行的一致性。21.3 张量 Tensor深度学习的基础数据结构21.3.1 张量的本质与核心属性张量Tensor是 PyTorch 中最基础的数据结构本质是多维数值数组和 NumPy 的 ndarray 高度相似。二者最大的区别在于张量可以部署在 GPU 上实现硬件加速并且内置自动微分机制能够追踪运算过程自动计算梯度。 所有深度学习运算从输入数据、模型权重、激活值到梯度全部以张量的形式存储和计算。大模型中一批文本的 token 序列、注意力权重、KV 缓存、百亿级的模型参数本质都是不同形状的张量。每个张量都有三个核心属性是操作张量的基础shape张量的形状元组类型描述每个维度的长度。比如形状为(32, 512, 768)的张量代表 32 个样本、序列长度 512、隐藏维度 768完全对应 Transformer 的批次输入格式。dtype张量的数据类型常用的有 32 位浮点float32、16 位浮点float16、64 位浮点float64、32 位整数int32、64 位整数int64。大模型训练与推理中为了节省显存、提升速度广泛使用半精度float16甚至更低的 8 位整数类型。device张量所在的设备cpu代表运行在 CPU 内存cuda代表运行在 GPU 显存。只有位于同一个设备上的张量才能进行运算设备不匹配是初学者最常遇到的报错之一。21.3.2 张量的创建方式PyTorch 提供了丰富的张量创建方法绝大多数和 NumPy 一一对应学习成本极低。 从已有数据创建torch.tensor()可以直接从 Python 列表、NumPy 数组生成张量。 特殊张量创建torch.zeros()生成全 0 张量torch.ones()生成全 1 张量torch.eye()生成单位矩阵用法和 NumPy 完全一致。 序列与随机张量torch.arange()生成等差序列torch.randn()生成标准正态分布随机张量torch.rand()生成 0-1 均匀分布张量。随机张量是权重初始化、数据增强的基础。 特别注意torch.randn是大模型权重初始化最常用的随机函数正态分布配合缩放因子能够保证初始数值的稳定性。21.3.3 索引、切片与维度变换张量的索引切片规则和 NumPy 几乎完全一致支持正向索引、反向索引、区间切片、布尔索引、花式索引。多维度之间用逗号分隔可以同时对多个维度做筛选。 例如对于形状为(8, 512, 768)的批次张量tensor[0]取第 0 个样本形状变为(512, 768)tensor[:, :128, :]取所有样本的前 128 个 token形状(8, 128, 768)tensor[tensor 0]筛选出所有大于 0 的元素返回一维张量维度变换是张量操作的高频技能对应不同层之间的形状适配。常用操作包括reshape()重新调整张量的形状元素总数保持不变可以用-1自动计算某个维度的大小。transpose()交换两个维度的位置常用于调整维度顺序。permute()一次性重排所有维度比多次 transpose 更直观。unsqueeze()在指定位置增加一个大小为 1 的维度常用于适配广播、增加批次维度。squeeze()移除指定的大小为 1 的维度压缩冗余维度。维度操作是大模型开发的日常工作调整序列维度、扩展掩码维度、交换注意力维度都依赖这些基础操作。熟练掌握维度变换是读懂模型代码的前提。21.3.4 张量运算与广播机制张量的运算分为三类逐元素运算、归约运算、矩阵运算。 逐元素运算加减乘除、幂运算、指数对数、激活函数等都是对应位置元素分别计算要求形状一致或者符合广播规则。 归约运算求和、均值、最大值、标准差等沿着指定轴做运算运算后对应轴被压缩。比如对批次维度求平均得到整个批次的平均损失。 矩阵运算使用运算符或者torch.matmul()实现矩阵乘法是神经网络最核心的运算。全连接层、注意力打分底层都是批量矩阵乘法。广播机制和 NumPy 规则完全一致从最右侧维度开始匹配维度大小相等或者其中一方为 1就可以广播。广播让不同形状的张量无需显式复制就能运算既节省内存又简化代码。偏置相加、掩码加权、归一化减均值底层都依赖广播机制。21.3.5 张量与 NumPy 的互转张量和 NumPy 数组可以快速互转.numpy()方法将张量转为 NumPy 数组torch.from_numpy()将 NumPy 数组转为张量。CPU 上的张量和 NumPy 数组共享底层内存修改一个另一个也会同步变化转换效率极高。 这种高度的兼容性意味着此前学习的所有 NumPy 知识都可以无缝迁移到 PyTorch。二者的 API 设计高度统一绝大多数函数名、参数、运算规则都保持一致大幅降低了框架的学习成本。21.4 自动微分 Autograd反向传播的自动实现21.4.1 自动微分的核心思想反向传播是训练神经网络的核心但手动推导每一层的梯度繁琐易错。PyTorch 的自动微分引擎 Autograd能够自动追踪所有张量运算动态构建计算图调用backward()后自动计算所有参数的梯度完全替代手动求导。 自动微分不是黑魔法它的底层就是链式法则和反向传播和我们手动推导的逻辑完全一致。框架只是帮我们完成了机械的求导运算让开发者专注于模型结构设计。21.4.2 梯度追踪与计算图张量有一个重要属性requires_grad设置为True时PyTorch 会追踪该张量参与的所有运算记录计算路径也就是计算图。 模型中的可训练参数比如nn.Linear的权重和偏置默认requires_gradTrue会自动纳入梯度计算。普通的输入数据、常量张量默认关闭梯度追踪。 计算图是动态构建的每执行一次前向传播就生成一张新的计算图反向传播完成后计算图默认释放下一次前向重新构建。这就是动态图的含义灵活度极高支持每次前向走不同的运算路径。21.4.3 反向传播与梯度获取计算得到损失标量后调用loss.backward()Autograd 就会从损失开始沿着计算图反向遍历用链式法则计算每个可训练参数的梯度。梯度会存储在对应张量的.grad属性中。 有两个非常重要的注意点是初学者的高频报错来源 第一只有标量才能调用backward()。如果损失是向量或矩阵需要先求和或取均值转为标量再反向。 第二梯度默认是累加的。多次调用backward()而不清零梯度会不断叠加导致参数更新错误。因此每一轮训练更新参数后必须手动将梯度清零也就是优化器的zero_grad()操作。21.4.4 关闭梯度追踪的场景并非所有场景都需要计算梯度。模型验证、推理的时候只需要前向传播得到结果不需要反向传播也就不需要构建计算图。此时可以用torch.no_grad()上下文管理器关闭梯度追踪with torch.no_grad(): output model(x)关闭梯度后运算不再记录计算图能够大幅节省显存提升运算速度。推理和验证阶段必须加上这是基础的性能优化习惯。21.5 nn.Module模型构建的标准范式21.5.1 为什么要用 nn.Moduletorch.nn.Module是 PyTorch 所有神经网络的基类无论是内置的全连接层、卷积层还是自定义的复杂模型都要继承这个类。 它提供了一整套模型管理能力让开发者不用重复造轮子自动管理所有可训练参数调用parameters()就能返回全部参数统一的设备迁移接口model.to(device)就能把所有参数移动到 CPU 或 GPU内置训练 / 推理模式切换自动处理 Dropout、BatchNorm 等训练推理行为不同的层支持权重的保存与加载。 自定义模型的标准结构非常固定在__init__方法中定义所有用到的层和可学习参数在forward方法中编写前向传播的逻辑。import torch import torch.nn as nn class SimpleNet(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super().__init__() self.linear1 nn.Linear(input_dim, hidden_dim) self.relu nn.ReLU() self.linear2 nn.Linear(hidden_dim, output_dim) def forward(self, x): x self.linear1(x) x self.relu(x) x self.linear2(x) return x这就是一个标准的两层全连接网络结构清晰逻辑和我们此前手写的两层网络完全对应。21.5.2 模型的模式切换模型有两种运行模式训练模式和评估模式。model.train()切换到训练模式Dropout 会随机失活神经元BatchNorm 会使用当前批次的均值方差更新统计量。model.eval()切换到评估模式Dropout 失效BatchNorm 使用训练阶段统计好的全局均值方差输出稳定。 推理和验证时必须调用model.eval()否则结果会出现随机波动准确率偏低。这是非常容易忽略的细节也是训练和推理效果不一致的常见原因。21.5.3 参数管理调用model.parameters()可以获取所有可训练参数优化器就是接收这个列表来更新权重的。调用model.state_dict()返回包含所有参数的有序字典键是参数名值是参数张量用于模型保存。 模型的子模块也会被自动递归管理嵌套定义的 Module 同样会被纳入参数管理非常适合搭建复杂的分层结构。Transformer 的编码器层、注意力模块都是通过嵌套 Module 实现的。21.6 常用层、损失函数与优化器21.6.1 基础神经网络层nn.Linear全连接层也叫线性层输入特征做线性变换内部包含权重矩阵和偏置向量。它是所有神经网络的基础单元Transformer 中的投影层、MLP 层本质都是全连接。 激活函数层nn.ReLU、nn.GELU、nn.Sigmoid、nn.Softmax对应我们学习过的各类激活函数。注意 Softmax 通常指定维度参数对指定维度做归一化。nn.Dropout随机失活层训练时按概率随机置零部分神经元是正则化的常用手段。21.6.2 损失函数PyTorch 内置了所有主流损失函数都在torch.nn模块下。nn.MSELoss均方误差损失用于回归任务。nn.CrossEntropyLoss交叉熵损失用于多分类任务。非常重要的一点它内部已经集成了 Softmax 运算输入直接传模型输出的原始 logits 即可不需要手动加 Softmax。重复加 Softmax 会导致梯度变小训练变慢是初学者最常踩的坑。nn.BCEWithLogitsLoss带 Sigmoid 的二元交叉熵用于二分类和多标签分类。21.6.3 优化器优化器在torch.optim模块中负责根据梯度更新模型参数。optim.SGD随机梯度下降带动量版本泛化性好但收敛慢。optim.Adam自适应学习率优化器收敛快调参简单通用场景首选。optim.AdamW修正权重衰减的 Adam是当前大模型预训练与微调的标准优化器。 优化器初始化时传入模型参数和学习率等超参数step()方法执行一步参数更新zero_grad()清空所有参数的梯度。 标准的单步训练流程永远是固定的五步梯度清零 → 前向传播 → 计算损失 → 反向传播 → 更新参数。21.7 实战从零搭建全连接分类网络结合本章所有知识点我们实现一个完整的二分类全连接网络覆盖从数据生成到模型训练的全流程。import torch import torch.nn as nn import torch.optim as optim # 1. 生成模拟数据1000个样本输入维度20二分类 torch.manual_seed(42) X torch.randn(1000, 20) y (X.sum(dim1) 0).long() # 2. 定义模型 class MLP(nn.Module): def __init__(self): super().__init__() self.layers nn.Sequential( nn.Linear(20, 64), nn.ReLU(), nn.Linear(64, 32), nn