ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

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

2026/8/11 1:46:44 拓冰建站 浏览量
深度学习框架入门: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_grad=True,会自动纳入梯度计算。普通的输入数据、常量张量默认关闭梯度追踪。 计算图是动态构建的:每执行一次前向传播,就生成一张新的计算图;反向传播完成后,计算图默认释放,下一次前向重新构建。这就是动态图的含义,灵活度极高,支持每次前向走不同的运算路径。

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.Module

torch.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.ReLUnn.GELUnn.Sigmoidnn.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(dim=1) > 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