当前位置: 首页 > news >正文

pytorch深度学习全流程:以简易数据、模型介绍

深度学习的大体包括下面几个阶段:

  1. 数据准备:从外部源加载数据,并转换为模型可以处理的数据格式和形式。
  2. 模型开发:设计一个神经网络模型,涉及自定义优化函数、神经网络模型等。
  3. 模型训练:包含模型的训练、验证与测试。
  4. 模型保存与部署:将训练好的模型参数进行保存,以用来应用。

数据准备

数据准备一般来自与私有数据或开源数据集。开源数据集往往已经适配pytorch,不需要再手动处理出正确的训练格式。私有数据需要手动适配成正确的训练格式。

通常需要手动派生自torch.utils.data.Dataset的映射型数据集类,覆盖getitem()len()方法。之后调用内置DataLoader为自定义的Dataset生成一个iterable迭代器。

一般,我们会保留一部分数据用于验证。验证数据不能用来训练神经网络,而是要用这部分数据测试模型在各个epoch结束时的性能。

测试集在模型训练和调参的整个过程中都应被严格隔离,只在最后评估时使用一次,以确保评估结果的公正性和无偏性。

数据集角色使用时机目的
训练集教材每个训练循环模型通过学习训练集来调整内部参数(权重和偏置)。
验证集模拟考每个训练循环结束后1. 调参:根据验证集的表现调整超参数(如学习率、网络层数)。 2. 早停:当模型在验证集上不再提升时,停止训练,防止过拟合。 3. 选模型:从多个候选模型中选择在验证集上表现最好的一个。
测试集最终大考所有训练和调参完成后,仅使用一次公正地评估最终模型的性能。这个结果代表了模型在全新、未见过的数据上的真实表现,也是你向他人汇报或发表论文时使用的最终指标。

模型开发

在PyTorch中,所有的自定义模型都应该继承torch.nn.Module基类。

实现两个关键方法:

  • __init__(self):构造函数。在这里,需要定义模型所需要的各个层,比如全连接层 (nn.Linear)、卷积层 (nn.Conv2d)、激活函数 (nn.ReLU) 等。
  • forward(self, x):前向传播。在这里,需要定义数据x如何流经你在 init 中定义的各个层,最终得到输出。不需要自己写反向传播,PyTorch 的 Autograd 引擎会自动处理。

pytorch的forward重定向于__callback__(),即:

# 之前实现了一个自定义模型 SelfModel
model = SelfModel() # 初始化,此时会调用 __init__,初始化各个层
# 有数据 x
outputs = model(x) # 这里等价于 model.forward(x) 进行前向传播。因为pytorch中Module基类实现了__callback__方法 model(x) = model.forward(x)

模型训练

定义损失函数(也称为[criterion])和优化器算法。

损失函数确定如何测量模型的性能,并计算预测结果和真实结果之间的损失或误差。优化器定义如何在训练中更新模型的参数。

pytorch优化器要求使用parameters()方法传入模型参数,也就是 model.parameters()。

这里假设声明的损失函数为criterion,优化器为optimizer。

整个流程大致为:优化器先清除梯度 -> 模型进行预测,期间进行前向传播 -> 损失函数计算损失(loss) -> 进行反向传播 -> 优化器更新参数。

for epoch in range(num_epochs): # 外循环# 训练model.train()  # 设置模型为训练模式# 遍历训练集for X_train, y_train in train_loader: # 内循环optimizer.zero_grad() # 将反向传播前的梯度清零outputs = model(X_train) # 前向传播loss = criterion(outputs, y_train) # 计算损失loss.backward() # 反向传播optimizer.step() # 更新参数

整个训练循环包括两个循环。在外循环中,我们要在每个迭代或epoch中处理整个训练数据集。在更新模型参数之前并不是等待处理整个数据集,而是会处理较小批量的数据,一次处理一个批次。内循环会循环处理每个批次。

对于每个小批次,将批次的X传入模型。模型将运行前向传播并返回计算得到的输出。之后损失函数比较模型和训练数据X的真实值y,来计算误差或损失。

之后要调整参数来降低损失。损失值调用反向传播计算梯度,优化器根据所计算的梯度更新参数。

pytorch在调用反向传播时会积累梯度,在训练RNN时可能有用,但是在CNN中并不需要积累梯度。大多数情况下,需要在完成反向传播前使梯度置零,这样优化器可以正确地更新模型参数。

在每一轮训练时,可能有训练和验证。pytorch提供模型训练模式和评估(也叫推理)模式,它们分布是model.train()model.eval()。这是因为pytorch框架地模型在训练和推理阶段地行为不同。

训练过程中,Dropout层会按照概率随机将一部分神经元的输出置为0,BatchNorm层会使用当前mini-batch的均值和方差来对数据进行归一化。

但是在评估过程中,不希望模型的输出具有随机性,即希望所有的神经元参与计算。同时输入的可能是小部分数据,这时候计算的均值和方差会不准确。因此评估时会冻结Dropout、BatchNorm的相关参数。

如果训练过程中,只含有训练,没有评估,那么不声明model.train()往往也能得到正确的结果。但是如果两者都有,但是没有显示声明model.train()model.eval()则会学到非最优的模型参数。因此,强烈建议,在训练中显示声明model.train()model.eval()

for epoch in range(epochs):model.train()# 训练 ...model.eval()# 评估 ...

在评估时,也常常结合with torch.no_grad()来使用。model.eval()开启后不会影响各层的梯度计算行为,即梯度计算和存储与model.train()模式一样,只是不进行反向传播。

with torch.no_grad()则主要是用于停止Autograd模型的工作,停止梯度计算来加速推理和节省显存。

所有常常是这样:

for epoch in range(epochs):model.train()# 训练 ...model.eval()with torch.no_grad():# 评估 ...

模型保存与部署

pytorch中常使用.pt.pth文件扩展名保存模型。推荐的方法是将模型训练后的参数进行保存,部署时将参数进行加载。

以下是相关代码(.ipynb格式经脚本转换为.py格式)

# Converted from Jupyter Notebook on 2025-08-03 19:23:48
# Conversion tool: convert_ipynb2py
# Author: Golemon# cell [1]
import torch
import torch.nn as nn
import torch.optim as optim# cell [2]################################################
# 数据构造
################################################# cell [3]
from torch.utils.data import TensorDataset, DataLoader, random_split# 用于线性回归模型训练或测试的模拟数据集。
a, b, c, d, e, f, g = 1,2,3,4,5,6,7# 生成随机数据 x1, x2, x3, x4, x5, x6
# 假设我们生成1000个数据点
num_points = 1000
x1 = torch.randn(num_points)
x2 = torch.randn(num_points)
x3 = torch.randn(num_points)
x4 = torch.randn(num_points)
x5 = torch.randn(num_points)
x6 = torch.randn(num_points)y = a * x1 + b * x2 + c * x3 + d * x4 + e * x5 + f * x6 + g + torch.normal(0, 0.2, (num_points,))
y = y.view((-1,1))
x = torch.stack([x1, x2, x3, x4, x5, x6], dim=1)
print(f"Data shape: {x.shape}, y shape: {y.shape}")# 将数据转换为TensorDataset
train_data = TensorDataset(x, y)train_set, val_set = random_split(train_data, [800, 200])
train_loader = DataLoader(train_set, batch_size=32, shuffle=True)
val_loader = DataLoader(val_set, batch_size=32, shuffle=False)# 查看数据集和批次信息
print(f"Train set size: {len(train_set)}, Validation set size: {len(val_set)}")
train_set_batch, train_labels_batch = next(iter(train_loader))
print(f"Train batch shape: {train_set_batch.shape}, Train labels batch shape: {train_labels_batch.shape}")# cell [4]################################################
# 模型定义
################################################# cell [5]
class MultiLayerMLP(nn.Module):def __init__(self, input_size, hidden_size, output_size, num_hidden_layers, dropout_prob):super().__init__()# 创建多个隐藏层self.hidden_layers = nn.ModuleList()# 第一个隐藏层self.hidden_layers.append(nn.Linear(input_size, hidden_size))# 中间隐藏层for _ in range(num_hidden_layers - 1):self.hidden_layers.append(nn.Linear(hidden_size,hidden_size))# 输出层self.fc_out = nn.Linear(hidden_size, output_size)# 激活函数self.relu = nn.ReLU()# 正则化self.dropout = nn.Dropout(dropout_prob)def forward(self, x):# 依次通过每一层隐藏层for layer in self.hidden_layers:x = self.relu(layer(x))x = self.dropout(x)# 输出层x = self.fc_out(x)return x# cell [6]################################################
# 初始化模型参数
################################################# cell [7]
# 初始化模型
input_size = 6
hidden_size = 64
output_size = 1
num_hidden_layers = 3
dropout_prob = 0.0
model = MultiLayerMLP(input_size, hidden_size, output_size, num_hidden_layers, dropout_prob)
print(model)# cell [8]################################################
# 定义损失函数和优化器
################################################# cell [9]
# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# cell [10]################################################
# 训练模型
################################################# cell [11]
# 训练循环
num_epochs = 1000
for epoch in range(num_epochs):# 训练model.train()  # 设置模型为训练模式# 遍历训练集for X_train, y_train in train_loader:optimizer.zero_grad() # 将反向传播前的梯度清零outputs = model(X_train) # 前向传播loss = criterion(outputs, y_train) # 计算损失loss.backward() # 反向传播optimizer.step() # 更新参数# 验证model.eval()  # 设置模型为评估模式with torch.no_grad():  # 在验证时不需要计算梯度val_loss = 0.0for X_val, y_val in val_loader:outputs = model(X_val)loss = criterion(outputs, y_val)val_loss += loss.item()val_loss /= len(val_loader)if (epoch + 1) % 100 == 0:print(f'Epoch [{epoch+1}/{num_epochs}],Train Loss: {loss.item():.4f}, Val Loss: {val_loss:.4f}')# cell [12]################################################
# 保存和加载模型
################################################# cell [13]
# 保存模型
# 保存模型中只需要保存模型已学习的参数,已经在模型类中定义了模型的设计,所以并不需要保存架构
torch.save(model.state_dict(), 'model.pt')# 加载模型
model = MultiLayerMLP(input_size, hidden_size, output_size, num_hidden_layers, dropout_prob)
# 加载模型参数 
# load_state_dict需要一个字典对象,而不是保存的state_dict的目录,因此在传入load时需要使用torch.load将已保存的文件逆串行化
model.load_state_dict(torch.load('model.pt'))
http://www.dtcms.com/a/313636.html

相关文章:

  • linux火焰图
  • vuhub Noob靶场攻略
  • 雪花算法重复id问题
  • Maxscript在选择的可编辑多边形每个面上绘制一个内部圆形
  • 自动驾驶中的传感器技术19——Camera(10)
  • OS21.【Linux】环境变量
  • CMake 命令行参数完全指南(5)
  • graph TD的规则
  • Linux Deepin深度操作系统应用商店加载失败,安装星火应用商店
  • io_getevents 和 io_pgetevents 系统调用及示例
  • [硬件电路-145]:模拟电路 - 常见的电源芯片、用途、管脚定义
  • 深度学习-读写模型网络文件
  • 大模型设计
  • 学习方法论
  • 智能化设备维护:开启高效运维新时代
  • 前端异步任务处理总结
  • Maven - 依赖的生命周期详解
  • 服务端技术栈分类总结
  • 模型预估打分对运筹跟踪的影响
  • 数据结构:单向链表的函数创建
  • [硬件电路-141]:模拟电路 - 源电路,信号源与电源,能自己产生确定性波形的电路。
  • 高质量数据集|大模型技术正从根本上改变传统数据工程的工作模式
  • RapidIO/SRIO 入门之什么是SRIO
  • 环绕字符串中的唯一子字符串-动态规划
  • [2025ICCV-目标检测方向]DuET:通过无示例任务算术进行双增量对象检测
  • 1.内核模块
  • C语言基础03——数组——习题
  • 工作笔记-----IAP的相关内容
  • 8大图床高速稳定网站,值得长期选用
  • 【最长公共前缀】