【PyTorch 深度学习从入门到实战】超完整保姆级笔记(可直接运行代码)
前言
本文档系统梳理深度学习全链路核心知识点,基于 PyTorch 框架实现,包含完整概念详解 + 可直接运行的代码实战 + 工业级标准化训练流程,覆盖从张量基础到 ANN/CNN/RNN 三大核心网络,适合深度学习入门、进阶学习与面试复习。
目录
- 深度学习简介
- PyTorch 环境搭建
- PyTorch 核心:张量 Tensor 操作
- PyTorch 自动微分机制 Autograd
- ANN 人工神经网络
- CNN 卷积神经网络
- RNN 循环神经网络
- 深度学习模型通用训练开发流程
- 核心知识点重点总结
1. 深度学习简介
1.1 深度学习的核心定义
深度学习是机器学习的一个分支,是一种以深层神经网络为载体,自动从海量数据中学习特征表示的算法体系。它无需人工手动设计特征,能够端到端地完成复杂任务的学习与推理。
1.2 深度学习的核心特点
- 端到端的特征自动学习:无需人工提取特征,模型自动从原始数据中学习从底层到高层的特征表示(比如图像从边缘→纹理→物体→场景的层级特征)
- 黑盒特性:当前深度学习模型的内部决策逻辑无法完全可解释,仅能通过输入输出的对应关系验证效果,属于数据驱动的黑盒模型
- 核心适用场景:以分类任务为核心,同时覆盖回归、生成、分割、检测等几乎所有 AI 任务
- 数据依赖:模型效果高度依赖数据量与数据质量,深层网络需要海量标注数据支撑训练
1.3 深度学习与机器学习的核心区别
| 对比维度 | 传统机器学习 | 深度学习 |
|---|---|---|
| 特征提取 | 人工手动设计特征 | 模型自动学习特征 |
| 数据依赖 | 小样本即可训练 | 依赖海量标注数据 |
| 计算需求 | 普通 CPU 即可完成 | 高度依赖 GPU/TPU 算力 |
| 可解释性 | 可解释性强 | 黑盒模型,可解释性弱 |
2. PyTorch 环境搭建
PyTorch 是当前学术界与工业界最主流的深度学习框架,采用动态计算图设计,语法简洁、调试友好,是深度学习入门的首选框架。
2.1 官方稳定版安装(pip 方式)
# CPU版本安装(无NVIDIA显卡首选)
pip install torch torchvision torchaudio
# GPU版本安装(需匹配CUDA版本,以CUDA 12.1为例)
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
2.2 安装验证
安装完成后,执行以下代码验证安装是否成功,同时查看 CUDA 是否可用:
import torch
# 查看PyTorch版本
print(f"PyTorch版本:{torch.__version__}")
# 查看CUDA是否可用
print(f"CUDA是否可用:{torch.cuda.is_available()}")
# 查看CUDA版本
print(f"CUDA版本:{torch.version.cuda}")
3. PyTorch 核心:张量 Tensor 操作
张量(Tensor)是 PyTorch 的底层核心数据结构,深度学习的所有计算都基于张量完成。张量只能存储数字类型数据,可以理解为高维数组:
- 0 维张量:标量(单个数字)
- 1 维张量:向量(一维数组)
- 2 维张量:矩阵(二维数组)
- 3 维及以上张量:高维数组(如图像、视频、序列数据)
3.1 张量的创建方式
3.1.1 普通创建方式
| API | 功能说明 | 注意事项 |
|---|---|---|
torch.tensor(data, dtype) | 最常用的张量创建方式 | 传入列表 / 数组,dtype 指定数据类型(如torch.float32) |
torch.Tensor() | 类构造方式创建张量 | 传入标量时,表示张量的元素个数;传入数值需用[]包裹 |
torch.ShortTensor()/IntTensor()/FloatTensor() | 指定数据类型的构造方式 | 后缀对应张量的默认数据类型 |
代码示例:
import torch
# 1. 最常用的tensor创建方式
t1 = torch.tensor([[1,2,3], [4,5,6]], dtype=torch.float32)
print("t1:\n", t1)
print("t1形状:", t1.shape)
# 2. torch.Tensor()构造方式
t2 = torch.Tensor(3) # 传入标量3,创建长度为3的张量,元素为随机值
print("t2:\n", t2)
t3 = torch.Tensor([3]) # 传入[3],创建值为3的张量
print("t3:\n", t3)
3.1.2 线性序列创建
| API | 功能说明 | 核心注意事项 |
|---|---|---|
torch.arange(start, end, step) | 创建等差序列张量 | 区间左闭右开,step 为步长 |
torch.linspace(start, end, steps) | 创建等间隔序列张量 | 区间左右均为闭区间,steps 为元素个数 |
代码示例:
# 1. arange创建
t4 = torch.arange(0, 10, 2) # 0,2,4,6,8(不包含10)
print("t4:", t4)
# 2. linspace创建
t5 = torch.linspace(0, 10, 5) # 0,2.5,5,7.5,10(包含10,共5个元素)
print("t5:", t5)
3.1.3 随机张量创建
| API | 功能说明 | 核心特性 |
|---|---|---|
torch.rand(size) | 生成 [0,1) 区间的均匀分布随机张量 | 所有值均大于等于 0,小于 1 |
torch.randn(size) | 生成标准正态分布随机张量 | 均值为 0,方差为 1 |
torch.randint(low, high, size) | 生成 [low, high) 区间的整数随机张量 | 区间左闭右开,size 指定张量形状 |
随机数种子控制:固定随机数种子,保证每次运行生成的随机数完全一致,可复现实验结果
# 获取当前随机数种子
print("当前随机数种子:", torch.initial_seed())
# 设置固定随机数种子
torch.manual_seed(42)
# 随机张量创建示例
t6 = torch.rand(2,3) # 2行3列,[0,1)均匀分布
print("t6:\n", t6)
t7 = torch.randn(2,3) # 2行3列,标准正态分布
print("t7:\n", t7)
t8 = torch.randint(0, 10, (2,3)) # 2行3列,0-9的整数
print("t8:\n", t8)
3.1.4 指定值张量创建
| API | 功能说明 |
|---|---|
torch.zeros(size) / torch.zeros_like(tensor) | 创建全 0 张量;创建与输入张量形状一致的全 0 张量 |
torch.ones(size) / torch.ones_like(tensor) | 创建全 1 张量;创建与输入张量形状一致的全 1 张量 |
torch.full(size, fill_value) / torch.full_like(tensor, fill_value) | 创建填充指定值的张量 |
代码示例:
t9 = torch.zeros(2,3) # 2行3列全0张量
print("t9:\n", t9)
t10 = torch.ones_like(t9) # 和t9形状一致的全1张量
print("t10:\n", t10)
t11 = torch.full((2,3), fill_value=5) # 2行3列,所有元素为5
print("t11:\n", t11)
3.2 张量元素类型修改
共有 3 种常用的张量类型修改方式,适用不同场景:
- 创建时指定类型:
torch.tensor(data, dtype=xxx),dtype 传入小写类型(如torch.float32、torch.int64) - type () 方法修改:
张量对象.type(dtype),dtype 可传入类型名(如torch.float32)或构造类(如torch.FloatTensor) - 快捷方法修改:
张量对象.half()/float()/double()/short()/int()/long(),直接转为对应精度类型
代码示例:
t = torch.tensor([1,2,3])
print("原始类型:", t.dtype)
# 1. 转为float32类型
t_float = t.float()
print("float32类型:", t_float.dtype)
# 2. 转为int64类型
t_long = t.type(torch.long)
print("int64类型:", t_long.dtype)
# 3. 转为半精度float16
t_half = t.half()
print("float16类型:", t_half.dtype)
3.3 张量类型转换
3.3.1 张量 ↔ Numpy 数组
| 转换方式 | 代码 | 内存共享说明 |
|---|---|---|
| 张量 → Numpy | 张量对象.numpy() | 共享内存,修改一个另一个同步变化 |
| 张量 → Numpy(不共享) | 张量对象.numpy().copy() | 不共享内存,相互独立 |
| Numpy → 张量 | torch.from_numpy(numpy数组) | 共享内存,修改一个另一个同步变化 |
| Numpy → 张量(不共享) | torch.tensor(numpy数组) | 不共享内存,相互独立 |
代码示例:
import numpy as np
# 张量转Numpy
t = torch.tensor([1,2,3])
np_arr = t.numpy()
print("张量转Numpy:", np_arr)
# Numpy转张量
np_arr2 = np.array([4,5,6])
t2 = torch.from_numpy(np_arr2)
print("Numpy转张量:", t2)
3.3.2 张量 ↔ 标量
| 转换方式 | 代码 | 注意事项 |
|---|---|---|
| 标量 → 张量 | torch.tensor(标量值) | 直接创建 0 维张量 |
| 张量 → 标量 | 张量对象.item() | 仅支持只有 1 个元素的张量,否则会报错 |
代码示例:
# 标量转张量
scalar = 10
t = torch.tensor(scalar)
print("标量转张量:", t)
# 张量转标量
t2 = torch.tensor(20)
scalar2 = t2.item()
print("张量转标量:", scalar2)
3.4 张量数值计算
3.4.1 基础四则运算
| 运算 | 非原地操作(不修改原张量) | 原地操作(修改原张量) | 推荐符号写法 |
|---|---|---|---|
| 加法 | add() | add_() | + |
| 减法 | sub() | sub_() | - |
| 乘法 | mul() | mul_() | * |
| 除法 | div() | div_() | / |
| 取反 | neg() | neg_() | - |
核心规则:PyTorch 中,方法名末尾带
_的均为原地操作,会直接修改原张量;不带_的会返回新张量,原张量不受影响。
代码示例:
a = torch.tensor([1,2,3])
b = torch.tensor([4,5,6])
# 推荐符号写法
print("加法:", a + b)
print("乘法:", a * b)
# 非原地操作
c = a.add(b)
print("非原地加法结果:", c)
print("原张量a不变:", a)
# 原地操作
a.add_(b)
print("原地加法后a被修改:", a)
3.4.2 点乘(对应元素相乘)
- 规则:两个张量形状必须完全一致,对应位置的元素相乘
- 实现方式:
张量1.mul(张量2)或张量1 * 张量2
代码示例:
a = torch.tensor([[1,2],[3,4]])
b = torch.tensor([[5,6],[7,8]])
print("点乘结果:\n", a * b)
3.4.3 矩阵乘法
- 规则:前一个张量的列数必须等于后一个张量的行数
- 实现方式:
torch.matmul(张量1, 张量2)或张量1 @ 张量2(推荐)
代码示例:
a = torch.tensor([[1,2,3], [4,5,6]]) # 形状(2,3)
b = torch.tensor([[1,2], [3,4], [5,6]]) # 形状(3,2)
print("矩阵乘法结果:\n", a @ b) # 输出形状(2,2)
3.5 张量常用运算函数
| 函数 | 功能说明 | 核心参数 |
|---|---|---|
min()/max() | 求张量的最小值 / 最大值 | dim 指定计算维度 |
log()/exp()/pow()/sqrt() | 对数、指数、幂、开方运算 | 逐元素计算 |
sum(dim)/mean(dim) | 求和 / 求均值 | dim=-1:以最内层维度为最小计算单元;不指定 dim 则对所有元素计算,返回标量 |
代码示例:
t = torch.tensor([[1,2,3], [4,5,6]])
# 对所有元素求和
print("所有元素求和:", t.sum())
# 按行求和(dim=1,最内层维度)
print("按行求和:", t.sum(dim=-1))
# 按列求均值
print("按列求均值:", t.mean(dim=0))
3.6 张量索引操作
3.6.1 基础行列索引
| 索引写法 | 功能说明 |
|---|---|
张量对象[i] | 取第 i 行 |
张量对象[:, j] | 取第 j 列 |
3.6.2 范围索引
- 语法:
张量对象[行起始:行结束:步长, 列起始:列结束:步长] - 核心规则:区间左闭右开,步长默认为 1,
:表示取该维度的所有元素
代码示例:
t = torch.tensor([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]])
# 取第一行
print("第一行:", t[0])
# 取第一列
print("第一列:", t[:, 0])
# 取前2行,第2-4列
print("范围索引:\n", t[0:2, 1:4])
3.7 张量形状调整
所有形状调整操作必须满足:调整前后张量的元素总个数不变。
| 方法 | 功能说明 | 核心注意事项 |
|---|---|---|
reshape(shape) | 通用形状调整,支持升维、降维、改形状 | -1表示让 PyTorch 自动计算该维度的大小,最多只能出现 1 次 |
unsqueeze(dim) | 升维,在指定 dim 位置增加一个形状为 1 的维度 | 常用于匹配批次维度、通道维度 |
squeeze(dim) | 降维,删除形状为 1 的维度 | 不指定 dim 则删除所有形状为 1 的维度;指定 dim 仅当该维度形状为 1 时才会删除 |
transpose(dim1, dim2) | 交换两个维度的位置 | 一次只能交换两个维度 |
permute(dims) | 重排所有维度的顺序 | 一次可以交换任意多个维度 |
view(shape) | 形状调整,功能与 reshape 类似 | 仅支持逻辑顺序与物理存储顺序一致的张量,否则会报错 |
代码示例:
t = torch.tensor([[1,2,3,4,5,6]])
print("原始形状:", t.shape) # (1,6)
# 1. reshape调整形状
t_reshape = t.reshape(2,3)
print("reshape后形状:", t_reshape.shape) # (2,3)
t_reshape2 = t.reshape(-1, 2) # -1自动计算为3
print("reshape带-1形状:", t_reshape2.shape) # (3,2)
# 2. 升维unsqueeze
t_unsqueeze = t.unsqueeze(dim=0)
print("升维后形状:", t_unsqueeze.shape) # (1,1,6)
# 3. 降维squeeze
t_squeeze = t.squeeze()
print("降维后形状:", t_squeeze.shape) # (6,)
# 4. 维度交换transpose
t2 = torch.randn(2,3,4) # (batch, channel, feature)
t_transpose = t2.transpose(1,2)
print("transpose后形状:", t_transpose.shape) # (2,4,3)
# 5. 维度重排permute
t_permute = t2.permute(2,0,1)
print("permute后形状:", t_permute.shape) # (4,2,3)
3.8 张量拼接操作
| 方法 | 功能说明 | 核心规则 |
|---|---|---|
torch.cat(tensors, dim) / concat | 张量拼接 | 1. 除了拼接的 dim 维度,其他维度形状必须完全一致;2. 拼接后不会升维,维度数不变 |
torch.stack(tensors, dim) | 张量堆叠 | 1. 所有参与拼接的张量形状必须完全一致;2. 拼接后会升维,维度数 + 1 |
代码示例:
a = torch.tensor([[1,2], [3,4]])
b = torch.tensor([[5,6], [7,8]])
# 1. cat按行拼接(dim=0)
cat_row = torch.cat([a,b], dim=0)
print("按行cat结果:\n", cat_row)
print("cat后形状:", cat_row.shape) # (4,2),维度数不变
# 2. cat按列拼接(dim=1)
cat_col = torch.cat([a,b], dim=1)
print("按列cat结果:\n", cat_col)
print("cat后形状:", cat_col.shape) # (2,4),维度数不变
# 3. stack堆叠
stack_result = torch.stack([a,b], dim=0)
print("stack结果:\n", stack_result)
print("stack后形状:", stack_result.shape) # (2,2,2),升维
4. PyTorch 自动微分机制 Autograd
自动微分是 PyTorch 的核心灵魂,是神经网络反向传播的底层基础,能够自动计算损失函数对模型参数的梯度,无需手动推导复杂的求导公式,大幅降低深度学习的开发门槛。
4.1 自动微分的核心概念
4.1.1 前向传播与反向传播
- 前向传播:输入数据经过神经网络的层层计算,得到预测结果,并根据预测结果与真实标签计算损失值的过程。核心是构建计算图、计算预测值与损失值。
- 反向传播:以损失值为起点,根据链式求导法则,反向计算损失函数对模型中每个可学习参数的梯度,再通过优化器更新参数,让损失值不断减小的过程。核心是梯度计算与参数更新。
4.1.2 计算图
计算图是用来描述运算过程的有向无环图(DAG),由节点和边组成:
- 节点:代表张量或运算操作
- 边:代表张量的流向与运算的依赖关系
计算图分为两种:
- 静态计算图:先定义完整计算图,再执行计算,代表框架为 TensorFlow 1.x
- 动态计算图:代码执行过程中动态构建计算图,代表框架为 PyTorch,调试更友好、语法更灵活,支持 Python 原生控制流。
4.2 自动微分核心属性与 API
4.2.1 核心属性
| 属性 | 功能说明 | 核心规则 |
|---|---|---|
requires_grad | 布尔值,标记张量是否需要计算梯度 | 1. 模型可学习参数(权重 w、偏置 b)默认requires_grad=True;2. 输入数据、标签默认requires_grad=False;3. 运算中只要有一个张量requires_grad=True,输出张量自动为 True |
grad | 存储张量的梯度值 | 反向传播后,损失函数对该张量的梯度会保存在这里,仅叶子张量的梯度会被永久保留 |
grad_fn | 记录张量的生成函数 | 是反向传播计算梯度的依据,用户手动创建的叶子张量grad_fn=None,运算得到的张量grad_fn为对应的运算函数 |
is_leaf | 标记是否为叶子张量 | 叶子张量是用户手动创建、不依赖其他张量的张量,模型可学习参数均为叶子张量;仅叶子张量的梯度会被保留,非叶子张量梯度反向传播后会被自动释放 |
4.2.2 核心 API
| API | 功能说明 | 适用场景 |
|---|---|---|
tensor.backward(gradient=None, retain_graph=None) | 触发反向传播,自动计算梯度 | 模型训练的反向传播步骤,必须由标量张量调用 |
torch.no_grad() | 上下文管理器,包裹的代码块关闭梯度计算 | 模型推理 / 评估阶段,节省显存与算力,避免不必要的梯度计算 |
tensor.detach() | 分离张量,返回与原张量共享数据但requires_grad=False的新张量 | 将张量脱离计算图,用于冻结模型参数、截断梯度传播 |
tensor.retain_grad() | 为非叶子张量保留梯度 | 调试时查看中间层的梯度,默认非叶子张量梯度会被释放 |
4.3 自动微分使用核心注意事项
- 反向传播触发条件:
backward()只能由标量张量调用;若为非标量张量,需传入gradient参数,形状与调用张量完全一致。 - 计算图释放规则:默认情况下,一次
backward()执行完成后,计算图会被自动释放;若需要多次反向传播,需设置retain_graph=True。 - 梯度累加特性:多次执行
backward()后,梯度会累加而非覆盖,因此每次训练迭代前必须手动执行optimizer.zero_grad()清零梯度,避免梯度污染。 - 推理阶段必须关闭梯度:模型评估 / 预测时,无需计算梯度,必须使用
torch.no_grad()关闭梯度计算,可大幅节省显存、提升推理速度。
4.4 自动微分完整代码实战
4.4.1 基础求导示例
求函数 y=x2+2x+1 在 x=3 处的导数,手动推导导数公式为 y′=2x+2,x=3 时导数为 8。
import torch
# 1. 创建叶子张量x,requires_grad=True表示需要计算梯度
x = torch.tensor(3.0, requires_grad=True)
# 2. 前向传播:定义函数y
y = x ** 2 + 2 * x + 1
# 3. 反向传播:自动计算梯度
y.backward()
# 4. 输出x的梯度值
print(f"x的梯度值为:{x.grad}") # 输出:x的梯度值为:8.0
4.4.2 非标量张量的反向传播
import torch
# 创建叶子张量x
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
# 前向传播:y = x * 2(y为非标量)
y = x * 2
# 反向传播:传入gradient=torch.ones_like(y)
y.backward(gradient=torch.ones_like(y))
# 输出x的梯度
print(f"x的梯度值为:{x.grad}") # 输出:x的梯度值为:tensor([2., 2., 2.])
4.4.3 梯度清零与多次反向传播
import torch
# 创建叶子张量x
x = torch.tensor(3.0, requires_grad=True)
# 第一次反向传播
y1 = x ** 2
y1.backward()
print(f"第一次梯度:{x.grad}") # 输出:6.0
# 梯度清零(必须操作!否则梯度会累加)
x.grad.zero_()
# 第二次反向传播
y2 = x * 3
y2.backward()
print(f"第二次梯度:{x.grad}") # 输出:3.0
4.4.4 推理阶段关闭梯度
import torch
model = torch.nn.Linear(10, 2)
x = torch.randn(5, 10)
# 训练模式:开启梯度计算
model.train()
y_train = model(x)
print(f"训练模式输出requires_grad:{y_train.requires_grad}") # True
# 推理模式:关闭梯度计算
model.eval()
with torch.no_grad():
y_eval = model(x)
print(f"推理模式输出requires_grad:{y_eval.requires_grad}") # False
5. ANN 人工神经网络
人工神经网络(Artificial Neural Network,ANN)是模拟人脑神经元结构的数学模型,是深度学习最基础的网络结构,也是所有复杂网络的核心基础。
5.1 神经元与网络结构
5.1.1 单个神经元的计算流程
单个神经元是神经网络的最小计算单元,计算分为两步:
- 线性求和:将输入特征与权重相乘,加上偏置项,得到线性组合z=w1x1+w2x2+...+wnxn+b=WX+b
- 激活函数:将线性组合输入激活函数,引入非线性关系,得到神经元的输出a=f(z)
5.1.2 神经网络的整体结构
神经网络由三层核心结构组成:
- 输入层:接收原始特征数据,神经元个数等于特征的维度
- 隐藏层:负责特征的学习与提取,层数和每层的神经元个数可自定义,网络的深度由隐藏层的层数决定
- 输出层:输出模型的预测结果,神经元个数等于任务的类别数(分类任务)或 1(回归任务)
5.2 激活函数详解
激活函数的核心作用是在神经网络中引入非线性关系。如果没有激活函数,无论网络有多少层,都只能等价于一个线性变换,无法处理复杂的非线性问题。
5.2.1 常用激活函数对比
| 激活函数 | 公式 | 输出区间 | 核心特点 | 适用场景 | 注意事项 |
|---|---|---|---|---|---|
| Sigmoid | f(x)=1+e−x1 | (0,1) | 可输出概率值,同时考虑正负样本 | 二分类输出层;浅层隐藏层 | 导数区间(0,0.25),深层网络极易出现梯度消失,隐藏层使用时层数≤4 |
| Tanh | f(x)=ex+e−xex−e−x | (−1,1) | 数据中心化,梯度消失问题轻于 Sigmoid | 浅层隐藏层 | 导数区间(0,1),隐藏层使用时层数≤10 |
| ReLU(优先推荐) | f(x)=max(0,x) | [0,+∞) | 计算简单、速度快,有效缓解梯度消失 | 所有隐藏层首选 | 只考虑正样本,可能出现 “神经元死亡”(梯度永久为 0) |
| Softmax | f(xi)=∑j=1nexjexi | (0,1) | 所有输出的概率和为 1 | 多分类任务的输出层 | 仅用于多分类输出层,不可用于隐藏层 |
5.2.2 激活函数使用总结
- 隐藏层:优先使用 ReLU;浅层网络可使用 Tanh(层数≤10)或 Sigmoid(层数≤4)
- 输出层:二分类任务可使用 Sigmoid 或 Softmax;多分类任务必须使用 Softmax
5.3 参数初始化策略
参数初始化直接影响模型的训练速度与最终效果,不当的初始化会导致梯度消失 / 爆炸,模型无法收敛。
5.3.1 偏置 b 初始化
推荐使用全 0 初始化,PyTorch 的nn.Linear层默认偏置为全 0 初始化。
5.3.2 权重 w 初始化
| 初始化方法 | 适用场景 |
|---|---|
| Kaiming 初始化(优先推荐) | ReLU 系列激活函数;深层神经网络 |
| Xavier 初始化 | Sigmoid/Tanh 激活函数;浅层神经网络(≤10 层) |
注意:PyTorch 的
nn.Linear层内部会自动执行默认初始化,若需自定义可手动覆盖。
5.4 损失函数详解
损失函数用于衡量模型预测值与真实标签的差距,是模型优化的目标,需根据任务类型选择对应的损失函数。
| 任务类型 | 损失函数 | 适用场景 | 核心注意事项 |
|---|---|---|---|
| 多分类 | CrossEntropyLoss(唯一选择) | 3 类及以上的分类任务 | 内部自带 Softmax 激活函数,输出层绝对不能重复调用 Softmax,否则会导致梯度异常 |
| 二分类 | BCELoss | 二分类任务 | 输出层必须先通过 Sigmoid 将输出转为概率值,再传入损失函数 |
| 二分类 | CrossEntropyLoss | 二分类任务 | 可直接用于二分类,无需 Sigmoid,输出层神经元个数为 2 |
| 回归 | L1Loss(MAE) | 回归任务,对异常值鲁棒 | 梯度恒定,训练后期收敛不稳定 |
| 回归 | MSELoss(L2) | 回归任务,数据无大量异常值 | 梯度稳定,对异常值极度敏感 |
| 回归 | SmoothL1Loss(优先推荐) | 所有回归任务 | 综合 L1 和 L2 的优点,对异常值鲁棒,梯度稳定 |
5.5 优化器与学习率衰减
5.5.1 常用优化器对比
优化器的作用是根据梯度更新模型的可学习参数,让损失值不断减小。
| 优化器 | 优化对象 | 核心特点 | 推荐优先级 |
|---|---|---|---|
| Adam | 梯度值 + 学习率 | 综合 Momentum 和 RMSProp 的优点,自适应学习率,收敛速度快,稳定性强 | 最高,绝大多数任务首选 |
| Momentum | 梯度值 | 引入动量,缓解 SGD 的震荡问题,加速收敛 | 中等,简单任务可使用 |
| RMSProp | 学习率 | 改进 AdaGrad,缓解学习率过早下降的问题,适合稀疏数据 | 中等,文本 / 稀疏数据可使用 |
| AdaGrad | 学习率 | 自适应学习率,适合稀疏数据,越往后学习率越小 | 低,仅用于特定稀疏场景 |
| SGD | 梯度值 | 随机梯度下降,无自适应能力,需要精细调参 | 低,仅用于简单任务或学术研究 |
5.5.2 手动学习率衰减策略
学习率衰减的作用是训练后期降低学习率,让模型更好地收敛到最优解。
表格
| 衰减策略 | API | 核心说明 |
|---|---|---|
| 等间隔衰减 | torch.optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.5) | 每隔step_size个 epoch,学习率乘以gamma |
| 指定间隔衰减 | torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[50,125,160], gamma=0.5) | 在milestones指定的 epoch 节点,学习率乘以gamma |
| 指数衰减 | torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.95) | 每轮学习率更新公式:lr=lr×gammaepoch |
5.6 正则化方法(缓解过拟合)
过拟合是指模型在训练集上效果极好,但在测试集 / 新数据上效果极差,泛化能力弱。正则化是缓解过拟合的核心手段。
5.6.1 Dropout 随机失活
- 核心原理:训练过程中,随机让部分神经元以概率 p 失活(输出置 0),未失活的神经元输出会放大1/(1−p)倍,避免模型过度依赖部分神经元,提升泛化能力。
- 使用规则:
- Dropout 层必须加在激活函数的后面
- 训练时必须执行
model.train(),开启 Dropout - 评估 / 推理时必须执行
model.eval(),关闭 Dropout - 失活概率 p 通常设置为 0.2-0.5
5.6.2 批量归一化 BN(BatchNorm)
- 核心原理:对每个批次的数据单独做标准化处理,让数据分布稳定,加速模型训练,缓解内部协变量偏移问题,同时有轻微的正则化效果。
- 使用规则:
- BN 层加在线性层 / 卷积层之后,激活函数之前
- 主要用于计算机视觉任务,训练时
model.train(),推理时model.eval()
5.7 ANN 网络搭建与完整训练代码实战
任务说明
构建一个 ANN 人工神经网络,解决二分类任务:输入特征维度为 10,2 层隐藏层,输出二分类概率,包含完整的训练、评估、模型保存流程。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# ====================== 1. 准备数据 ======================
# 生成模拟数据:1000个样本,10个特征,二分类标签
X = torch.randn(1000, 10) # 特征数据,形状(1000,10)
y = torch.randint(0, 2, (1000, 1)).float() # 标签,形状(1000,1),值为0或1
# 封装为Dataset和DataLoader,实现批次加载与打乱
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
# ====================== 2. 定义ANN网络结构 ======================
class ANN(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(ANN, self).__init__()
# 定义网络层
self.fc1 = nn.Linear(input_dim, hidden_dim) # 输入层→隐藏层1
self.bn1 = nn.BatchNorm1d(hidden_dim) # 批量归一化
self.relu1 = nn.ReLU() # 激活函数
self.dropout1 = nn.Dropout(0.3) # Dropout正则化
self.fc2 = nn.Linear(hidden_dim, hidden_dim) # 隐藏层1→隐藏层2
self.bn2 = nn.BatchNorm1d(hidden_dim)
self.relu2 = nn.ReLU()
self.fc3 = nn.Linear(hidden_dim, output_dim) # 隐藏层2→输出层
self.sigmoid = nn.Sigmoid() # 二分类输出层用Sigmoid,输出概率
def forward(self, x):
# 前向传播流程
x = self.fc1(x)
x = self.bn1(x)
x = self.relu1(x)
x = self.dropout1(x)
x = self.fc2(x)
x = self.bn2(x)
x = self.relu2(x)
x = self.fc3(x)
x = self.sigmoid(x)
return x
# 实例化模型
model = ANN(input_dim=10, hidden_dim=20, output_dim=1)
# ====================== 3. 定义损失函数、优化器、学习率衰减 ======================
criterion = nn.BCELoss() # 二分类损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001) # Adam优化器
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.5) # 每20轮学习率减半
# ====================== 4. 模型训练 ======================
epochs = 50
model.train() # 开启训练模式(Dropout、BN生效)
for epoch in range(epochs):
total_loss = 0.0
# 内层循环:遍历每个批次
for batch_X, batch_y in dataloader:
# 4.1 前向传播:得到预测值
predictions = model(batch_X)
# 4.2 计算损失值
loss = criterion(predictions, batch_y)
# 4.3 反向传播(固定三步,不可调换顺序)
optimizer.zero_grad() # 1. 梯度清零
loss.backward() # 2. 反向传播计算梯度
optimizer.step() # 3. 更新模型参数
total_loss += loss.item()
# 每轮结束更新学习率
scheduler.step()
# 打印训练日志
avg_loss = total_loss / len(dataloader)
current_lr = optimizer.param_groups[0]['lr']
print(f"Epoch [{epoch+1}/{epochs}], 平均损失: {avg_loss:.4f}, 当前学习率: {current_lr:.6f}")
# ====================== 5. 模型评估 ======================
model.eval() # 开启评估模式(Dropout、BN关闭)
with torch.no_grad(): # 关闭梯度计算,节省显存
# 生成模拟测试数据
test_X = torch.randn(100, 10)
test_y = torch.randint(0, 2, (100, 1)).float()
# 模型预测
test_predictions = model(test_X)
# 将概率转为类别:>0.5为1,否则为0
test_classes = (test_predictions > 0.5).float()
# 计算准确率
accuracy = (test_classes == test_y).sum().item() / len(test_y)
print(f"\n测试集准确率: {accuracy:.2%}")
print(f"前10个测试样本预测类别: {test_classes[:10].squeeze().numpy()}")
# ====================== 6. 模型保存 ======================
torch.save(model.state_dict(), "ann_binary_classification.pth")
print("\n模型已保存为 ann_binary_classification.pth")
6. CNN 卷积神经网络
卷积神经网络(Convolutional Neural Network,CNN)是专门为处理图像、视频等网格结构数据设计的神经网络,核心是通过卷积层自动提取图像的层级特征,是计算机视觉任务的基础模型。
6.1 CNN 的核心原理
CNN 之所以适合处理图像,核心是它具备两个关键特性:
- 局部感受野:卷积核只关注图像的局部区域,而非整张图,符合人类视觉的局部感知特性
- 参数共享:同一个卷积核在整张图像上滑动共享参数,大幅减少模型的参数量,避免过拟合
6.2 CNN 的整体结构
CNN 由三层核心结构组成:
- 输入层:接收图像张量,标准格式为
[N, C, H, W]- N:批次大小(一次输入的图片数量)
- C:通道数(彩色图 = 3,灰度图 = 1)
- H:图像高度
- W:图像宽度
- 隐藏层:
- 卷积层:核心层,从图像中提取层级特征(边缘→纹理→物体→场景)
- 激活函数:通常使用 ReLU,引入非线性
- 池化层:对特征图进行降维,减少参数量,提升感受野,缓解过拟合
- 输出层:将三维特征图展平为二维向量,送入全连接层(线性层),输出最终的分类 / 检测结果
6.3 卷积层详解
6.3.1 卷积层核心参数
| 参数 | 功能说明 | 常用取值 |
|---|---|---|
in_channels | 输入特征图的通道数 | 彩色图像输入为 3,后续层等于上一层的 out_channels |
out_channels | 输出特征图的通道数,等于卷积核的个数 | 16、32、64、128 等,通常逐层翻倍 |
kernel_size | 卷积核的大小 | 3(最常用)、5、7 |
stride | 卷积核在图像上滑动的步长 | 1(不改变尺寸)、2(尺寸减半) |
padding | 图像四周的填充圈数,填充值默认为 0 | 0、1、2,通常设置为kernel_size//2,让卷积后尺寸不变 |
6.3.2 特征图尺寸计算公式
卷积 / 池化后,特征图的尺寸计算公式为:
Hout=⌊strideHin+2×padding−kernel_size⌋+1Wout=⌊strideWin+2×padding−kernel_size⌋+1
示例:输入图像尺寸 32×32,卷积核 3×3,stride=1,padding=1,输出尺寸为:
Hout=⌊132+2×1−3⌋+1=32
即卷积后尺寸不变。
6.3.3 卷积层 API
import torch.nn as nn
# 定义卷积层:输入通道3,输出通道16,卷积核3×3,步长1,填充1
conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)
6.4 池化层详解
池化层的核心作用是特征降维,在保留关键特征的前提下,减少特征图的尺寸和参数量,同时扩大感受野。
6.4.1 常用池化方式
| 池化方式 | 核心原理 | 特点 | 推荐优先级 |
|---|---|---|---|
| 最大池化(MaxPooling) | 取池化窗口内的最大值作为输出 | 保留图像的显著特征,边缘、纹理等关键信息 | 最高,绝大多数场景首选 |
| 平均池化(AvgPooling) | 取池化窗口内的平均值作为输出 | 保留图像的整体特征,平滑特征图 | 低,仅用于特定场景 |
6.4.2 池化层 API
import torch.nn as nn
# 最常用的最大池化:窗口2×2,步长2,特征图尺寸直接减半
max_pool_layer = nn.MaxPool2d(kernel_size=2, stride=2)
6.5 卷积层与池化层的核心区别
| 对比维度 | 卷积层 | 池化层 |
|---|---|---|
| 核心功能 | 提取图像的层级特征,可同步实现降维 | 仅对特征图进行降维,不提取特征 |
| 可学习参数 | 卷积核内的权重 w 和偏置 b,是可学习参数 | 无任何可学习参数,仅做固定的最大值 / 平均值计算 |
| 计算方式 | 卷积核与图像局部区域做加权求和 | 取窗口内的最大值 / 平均值 |
6.6 CNN 网络搭建与完整图像分类代码实战
任务说明
构建一个 CNN 卷积神经网络,处理 3 通道彩色图像(输入尺寸 32×32),完成 10 分类任务,包含完整的训练、评估、模型保存流程。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# ====================== 1. 准备数据 ======================
# 生成模拟图像数据:1000张3通道32×32的彩色图像,10分类标签
X = torch.randn(1000, 3, 32, 32) # 形状[N, C, H, W]
y = torch.randint(0, 10, (1000,)) # 标签,0-9共10个类别
# 封装为Dataset和DataLoader
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
# ====================== 2. 定义CNN网络结构 ======================
class CNN(nn.Module):
def __init__(self, num_classes=10):
super(CNN, self).__init__()
# 第一组:卷积+BN+激活+池化
self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)
self.bn1 = nn.BatchNorm2d(16) # 批量归一化
self.relu1 = nn.ReLU()
self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) # 尺寸减半:32→16
# 第二组:卷积+BN+激活+池化
self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1)
self.bn2 = nn.BatchNorm2d(32)
self.relu2 = nn.ReLU()
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2) # 尺寸减半:16→8
# 第三组:卷积+BN+激活+池化
self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1)
self.bn3 = nn.BatchNorm2d(64)
self.relu3 = nn.ReLU()
self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2) # 尺寸减半:8→4
# 全连接层:分类输出
self.fc = nn.Linear(64 * 4 * 4, num_classes)
def forward(self, x):
# 第一组前向传播
x = self.conv1(x)
x = self.bn1(x)
x = self.relu1(x)
x = self.pool1(x)
# 第二组前向传播
x = self.conv2(x)
x = self.bn2(x)
x = self.relu2(x)
x = self.pool2(x)
# 第三组前向传播
x = self.conv3(x)
x = self.bn3(x)
x = self.relu3(x)
x = self.pool3(x)
# 展平:[N, 64, 4, 4] → [N, 64*4*4]
x = x.flatten(start_dim=1)
# 全连接层输出分类结果
x = self.fc(x)
return x
# 实例化模型
model = CNN(num_classes=10)
# ====================== 3. 定义损失函数、优化器 ======================
criterion = nn.CrossEntropyLoss() # 多分类损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001)
# ====================== 4. 模型训练 ======================
epochs = 30
model.train()
for epoch in range(epochs):
total_loss = 0.0
for batch_X, batch_y in dataloader:
# 前向传播
predictions = model(batch_X)
loss = criterion(predictions, batch_y)
# 反向传播固定三步
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
# 打印训练日志
avg_loss = total_loss / len(dataloader)
print(f"Epoch [{epoch+1}/{epochs}], 平均损失: {avg_loss:.4f}")
# ====================== 5. 模型评估 ======================
model.eval()
with torch.no_grad():
# 生成模拟测试数据
test_X = torch.randn(100, 3, 32, 32)
test_y = torch.randint(0, 10, (100,))
# 模型预测
test_predictions = model(test_X)
test_classes = torch.argmax(test_predictions, dim=1) # 取概率最大的类别
# 计算准确率
accuracy = (test_classes == test_y).sum().item() / len(test_y)
print(f"\n测试集准确率: {accuracy:.2%}")
print(f"前10个测试样本预测类别: {test_classes[:10].numpy()}")
# ====================== 6. 模型保存 ======================
torch.save(model.state_dict(), "cnn_image_classification.pth")
print("\n模型已保存为 cnn_image_classification.pth")
7. RNN 循环神经网络
循环神经网络(Recurrent Neural Network,RNN)是专门为处理序列数据设计的神经网络,核心是通过循环层保留序列的上下文信息,是自然语言处理、时间序列预测任务的基础模型。
7.1 RNN 的核心原理
序列数据是指数据之间存在先后顺序依赖关系的数据,比如文本、语音、股票价格、传感器数据等。RNN 的核心特性是:
- 隐藏状态传递:每个时间步的隐藏状态会传递到下一个时间步,让模型能够记住之前的上下文信息
- 参数共享:所有时间步共享同一套参数,大幅减少参数量,适配任意长度的序列数据
7.2 序列数据预处理:词嵌入层 Embedding
文本等非数字序列数据无法直接输入神经网络,需要先通过词嵌入层转为低维稠密的词向量。
7.2.1 文本数据处理流程
- 分词:将文本句子拆分为单个词语 / 字
- 构建词汇表:对所有词语去重,给每个词语分配唯一的数字索引
- 词嵌入:根据词语的索引,将其转为固定维度的低维稠密向量(替代 one-hot 的高维稀疏表示)
7.2.2 词嵌入层 API
import torch.nn as nn
# 定义词嵌入层:词汇表大小10000,词向量维度128
embedding_layer = nn.Embedding(num_embeddings=10000, embedding_dim=128)
7.3 循环层详解
7.3.1 循环层核心计算流程
每个时间步的计算分为两步:
- 输入:上一个时间步的隐藏状态 + 当前时间步的输入特征
- 输出:更新后的当前时间步隐藏状态 + 当前时间步的预测结果
隐藏状态是 RNN 的核心,它存储了序列从开头到当前时间步的所有上下文信息,实现了 “记忆” 能力。
7.3.2 循环层核心参数
| 参数 | 功能说明 |
|---|---|
input_size | 输入特征的维度(词向量的维度) |
hidden_size | 隐藏状态的维度 |
num_layers | 循环层的堆叠层数 |
batch_first | 若设置为 True,输入 / 输出的形状为[batch_size, seq_len, feature],更符合常规数据格式,推荐开启 |
7.3.3 张量形状说明(开启 batch_first=True)
| 张量 | 形状 | 说明 |
|---|---|---|
input | [batch_size, seq_len, input_size] | 输入序列数据 |
h0 | [num_layers, batch_size, hidden_size] | 初始隐藏状态,可省略,默认全 0 初始化 |
output | [batch_size, seq_len, hidden_size] | 每个时间步的输出结果 |
hidden | [num_layers, batch_size, hidden_size] | 最后一个时间步的隐藏状态,包含整个序列的上下文信息 |
7.3.4 循环层 API
import torch.nn as nn
# 定义RNN层:输入维度128,隐藏维度64,层数2,开启batch_first
rnn_layer = nn.RNN(input_size=128, hidden_size=64, num_layers=2, batch_first=True)
7.4 RNN 网络搭建与完整文本分类代码实战
任务说明
构建一个 RNN 循环神经网络,处理文本序列数据(词汇表大小 10000,序列长度 20),完成二分类任务,包含完整的训练、评估、模型保存流程。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# ====================== 1. 准备数据 ======================
# 生成模拟文本数据:1000个样本,每个样本序列长度20,词索引范围0-9999,二分类标签
X = torch.randint(0, 10000, (1000, 20)) # 形状[N, seq_len]
y = torch.randint(0, 2, (1000,)) # 标签,0或1
# 封装为Dataset和DataLoader
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
# ====================== 2. 定义RNN文本分类网络结构 ======================
class RNNTextClassifier(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_size, num_layers, num_classes):
super(RNNTextClassifier, self).__init__()
# 词嵌入层:词索引→词向量
self.embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embed_dim)
# RNN循环层
self.rnn = nn.RNN(
input_size=embed_dim,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True,
dropout=0.3 # 循环层Dropout
)
# 全连接层:分类输出
self.fc = nn.Linear(hidden_size, num_classes)
def forward(self, x):
# 1. 词嵌入:[N, seq_len] → [N, seq_len, embed_dim]
x = self.embedding(x)
# 2. RNN前向传播
# output:每个时间步的输出,形状[N, seq_len, hidden_size]
# hidden:最后一个时间步的隐藏状态,形状[num_layers, N, hidden_size]
output, hidden = self.rnn(x)
# 3. 取最后一个时间步的输出用于分类:[N, hidden_size]
last_output = output[:, -1, :]
# 4. 全连接层输出分类结果
x = self.fc(last_output)
return x
# 实例化模型
model = RNNTextClassifier(
vocab_size=10000,
embed_dim=128,
hidden_size=64,
num_layers=2,
num_classes=2
)
# ====================== 3. 定义损失函数、优化器 ======================
criterion = nn.CrossEntropyLoss() # 二分类损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001)
# ====================== 4. 模型训练 ======================
epochs = 20
model.train()
for epoch in range(epochs):
total_loss = 0.0
for batch_X, batch_y in dataloader:
# 前向传播
predictions = model(batch_X)
loss = criterion(predictions, batch_y)
# 反向传播固定三步
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
# 打印训练日志
avg_loss = total_loss / len(dataloader)
print(f"Epoch [{epoch+1}/{epochs}], 平均损失: {avg_loss:.4f}")
# ====================== 5. 模型评估 ======================
model.eval()
with torch.no_grad():
# 生成模拟测试数据
test_X = torch.randint(0, 10000, (100, 20))
test_y = torch.randint(0, 2, (100,))
# 模型预测
test_predictions = model(test_X)
test_classes = torch.argmax(test_predictions, dim=1)
# 计算准确率
accuracy = (test_classes == test_y).sum().item() / len(test_y)
print(f"\n测试集准确率: {accuracy:.2%}")
print(f"前10个测试样本预测类别: {test_classes[:10].numpy()}")
# ====================== 6. 模型保存 ======================
torch.save(model.state_dict(), "rnn_text_classification.pth")
print("\n模型已保存为 rnn_text_classification.pth")
8. 深度学习模型通用训练开发流程
所有深度学习模型的训练都遵循标准化的开发流程,掌握该流程可快速适配所有深度学习任务。
8.1 通用训练流程拆解
-
准备数据
- 数据预处理:归一化、标准化、数据增强、标签编码等
- 数据封装:
Tensor→ 自定义Dataset→DataLoader(实现批次加载、打乱、多线程读取) - 数据集划分:训练集、验证集、测试集
-
创建核心实例对象
- 模型实例:继承
nn.Module的网络类实例 - 损失函数实例:根据任务类型选择对应的损失函数
- 优化器实例:传入模型的可学习参数,设置学习率
- 【可选】学习率衰减器实例
- 模型实例:继承
-
双层循环训练
- 外层循环:控制训练轮次
epoch,遍历整个数据集的次数 - 内层循环:控制批次
batch,遍历DataLoader中的每个批次数据
- 外层循环:控制训练轮次
-
单批次训练核心四步
- 前向传播:将批次特征数据传入模型,自动调用
forward方法,得到预测结果 - 计算损失:将预测结果与真实标签传入损失函数,计算损失值
- 反向传播固定三步:
optimizer.zero_grad():梯度清零,避免梯度累加污染loss.backward():触发反向传播,自动计算所有可学习参数的梯度optimizer.step():根据梯度更新模型的可学习参数
- 【可选】日志打印、指标计算、模型验证
- 前向传播:将批次特征数据传入模型,自动调用
-
模型保存与推理
- 模型保存:
torch.save(model.state_dict(), "model.pth")(推荐保存参数,而非整个模型) - 模型加载:
model.load_state_dict(torch.load("model.pth")) - 推理阶段:必须执行
model.eval()+with torch.no_grad(),关闭梯度计算与训练专属层
- 模型保存:
9. 核心知识点重点总结
9.1 机器学习核心基础
- 线性回归的核心是梯度下降:wnew=wold−lr×grad,核心目标是让损失值逼近最小值,得到最优的 w 和 b 参数组合。
9.2 PyTorch 核心基础
- 张量 Tensor:深度学习唯一的底层数据结构,只能存储数字,所有计算都基于张量完成。
- 张量核心操作:创建、类型转换、四则运算、矩阵乘法、索引、形状调整、拼接,是所有模型开发的基础。
- 自动微分:前向传播计算预测值与损失值,反向传播自动计算梯度,是神经网络训练的核心。
9.3 三大核心网络
- ANN 人工神经网络:基础全连接网络,适合结构化数据的分类、回归任务。
- CNN 卷积神经网络:专为图像数据设计,核心是卷积层提取特征,是计算机视觉的基础。
- RNN 循环神经网络:专为序列数据设计,核心是循环层传递上下文信息,是 NLP、时间序列任务的基础。
9.4 模型训练核心准则
- 训练时必须执行
model.train(),推理 / 评估时必须执行model.eval()。 - 反向传播前必须执行梯度清零,避免梯度累加。
- 推理阶段必须用
torch.no_grad()关闭梯度计算,节省显存。 - 损失函数、激活函数、优化器必须与任务类型匹配,避免出现梯度异常、模型不收敛的问题。
更多推荐


所有评论(0)