【AI知识】在 PyTorch 中设计和实现一个完整的模型训练和优化流程

在 PyTorch 中设计和实现一个完整的模型训练和优化流程

1. ​模型设计

模型的设计是训练流程的核心。PyTorch 提供了灵活的模块化设计方式,通常通过继承 nn.Module 来实现。

​模型设计步骤

1)​定义模型类:

继承 torch.nn.Module。

init 中定义模型的层(如全连接层、卷积层、RNN 层等)。

在 forward 中定义前向传播逻辑。

2)​选择模型组件:

​全连接层: nn.Linear ​

卷积层: nn.Conv2d ​

循环神经网络: nn.RNN, nn.LSTM, nn.GRU

​Transformer: nn.Transformer ​

激活函数: nn.ReLU, nn.Sigmoid, nn.Tanh

​归一化层: nn.BatchNorm1d, nn.LayerNorm ​

Dropout: nn.Dropout

以下是一个简单的全连接神经网络示例:

python 复制代码
import torch
import torch.nn as nn
from torch.utils.data import Dataset,DataLoader

# 定义一个简单的神经网络SimpleNN ,SimpleNN类继承自 nn.Module
class SimpleNN(nn.Module):
    # 在 __init__ 中定义模型的层(如全连接层、卷积层、RNN 层等)
    def __init__(self,input_dim,hidden_dim,output_dim):
        # 调用父类(即 nn.Module)的构造函数
        # nn.Module 的构造函数会初始化 PyTorch 模型所需要的内部状态
        super(SimpleNN,self).__init__()
        self.fc1=nn.Linear(input_dim,hidden_dim)
        self.relu=nn.ReLU()
        self.fc2=nn.Linear(hidden_dim,output_dim)

    # 在 forward 中定义前向传播逻辑
    def forward(self,x):
        x=self.fc1(x)
        x=self.relu(x)
        x=self.fc2(x)
        return x

# 实例化模型
model=SimpleNN(input_dim=10,hidden_dim=20,output_dim=2)
print(model)
python 复制代码
SimpleNN(
  (fc1): Linear(in_features=10, out_features=20, bias=True)
  (relu): ReLU()
  (fc2): Linear(in_features=20, out_features=2, bias=True)
)

2. ​数据准备

模型训练需要数据,通常使用 torch.utils.data.Dataset 和 torch.utils.data.DataLoader 来加载和处理数据。

​数据准备步骤

1)​自定义 Dataset:

继承 torch.utils.data.Dataset。

实现 lengetitem 方法。

2)​使用 DataLoader:

将 Dataset 包装为 DataLoader,支持批量加载、随机打乱和多线程加载。

​示例代码:

python 复制代码
# 通常使用 torch.utils.data.Dataset 和 torch.utils.data.DataLoader 来加载和处理数据
# CustomDataset继承 torch.utils.data.Dataset
class CustomDataset(Dataset):
    def __init__(self,data,labels):
        """
        初始化数据集。
        :param data: 数据样本,例如一个列表或数组。
        :param labels: 数据标签,与 data 一一对应。
        """
        self.data=data
        self.labels=labels
    def __len__(self):
        """
        返回数据集中样本的数量。
        """
        return len(self.data)
    def __getitem__(self, index) :
        """
        根据索引返回一个样本和对应的标签。
        :param idx: 样本的索引。
        :return: 样本和标签。
        """
        return self.data[index],self.labels[index]
    
# 1000个样本,每个样本10维度
data=torch.randn(1000,10)
# 1000个样本,二分类
labels=torch.randint(0,2,(1000,))

print(data.shape)
print(labels.shape)
python 复制代码
torch.Size([1000, 10])
torch.Size([1000])

3)创建 Dataset 和 DataLoader

python 复制代码
# 数据准备
dataset=CustomDataset(data,labels)
dataloader=DataLoader(dataset,batch_size=32,shuffle=True)

3. ​训练和优化

训练和优化是模型学习的核心过程,通常包括以下步骤:

​训练步骤

1)​定义损失函数:

常用损失函数:

分类任务: nn.CrossEntropyLoss

回归任务: nn.MSELoss

二分类任务: nn.BCELoss

2)定义优化器:

常用优化器:

torch.optim.SGD

torch.optim.Adam

torch.optim.RMSprop

3)定义损失函数和优化器

python 复制代码
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr=0.001)

​4)训练循环:

在每个 epoch 中遍历 DataLoader。计算损失、反向传播、更新参数。

python 复制代码
def train(model,dataloader,criterion,optimizer,num_epochs=100):
    model.train()
    for epoch in range(num_epochs):  # 进行 num_epochs 轮训练
        total_loss = 0  # 记录每个 epoch 的总损失
        for input, label in dataloader:  # 逐个 mini-batch 训练
            optimizer.zero_grad()  # 清空上一批次的梯度
            output = model(input)  # 前向传播(计算预测值)
            loss = criterion(output, label)  # 计算当前 mini-batch 的损失
            loss.backward()  # 反向传播(计算梯度)
            optimizer.step()  # 更新模型参数
            total_loss += loss.item()  # 累加损失
        print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {total_loss/len(dataloader):.4f}")

train(model,dataloader,criterion,optimizer,num_epochs=100)
python 复制代码
Epoch [1/100], Loss: 0.7028
Epoch [2/100], Loss: 0.6962
Epoch [3/100], Loss: 0.6940
Epoch [4/100], Loss: 0.6910
Epoch [5/100], Loss: 0.6884
Epoch [6/100], Loss: 0.6861
Epoch [7/100], Loss: 0.6832
Epoch [8/100], Loss: 0.6824
Epoch [9/100], Loss: 0.6814
Epoch [10/100], Loss: 0.6790
Epoch [11/100], Loss: 0.6798
Epoch [12/100], Loss: 0.6804
Epoch [13/100], Loss: 0.6770
Epoch [14/100], Loss: 0.6757
Epoch [15/100], Loss: 0.6744
Epoch [16/100], Loss: 0.6763
Epoch [17/100], Loss: 0.6736
Epoch [18/100], Loss: 0.6744
Epoch [19/100], Loss: 0.6763
Epoch [20/100], Loss: 0.6728
Epoch [21/100], Loss: 0.6704
Epoch [22/100], Loss: 0.6704
Epoch [23/100], Loss: 0.6684
Epoch [24/100], Loss: 0.6673
Epoch [25/100], Loss: 0.6678
...
Epoch [97/100], Loss: 0.6305
Epoch [98/100], Loss: 0.6300
Epoch [99/100], Loss: 0.6316
Epoch [100/100], Loss: 0.6284

4. 模型评估

在训练完成后,通常需要在验证集或测试集上评估模型的性能。

​评估步骤

1)​禁用梯度计算:

使用 torch.no_grad() 来避免不必要的计算和内存消耗。

2)​计算指标:

分类任务: 准确率、F1 分数等。

回归任务: 均方误差(MSE)、平均绝对误差(MAE)等。

python 复制代码
def evaluate(model,test_dataloader):
    model.eval()
    correct=0
    total=0
    # 禁用 PyTorch 的自动梯度计算,使得前向传播不计算梯度,从而节省显存,提高计算效率
    with torch.no_grad():
        for input,label in test_dataloader:
            output=model(input)
            # 在 outputs 中找到每个样本的最大类别索引(预测类别)
            # 第一个返回值(_):最大值,即 outputs 中每个样本的最大 logit 值(但我们不需要它)。
            # 第二个返回值(predicted):最大值的索引,即模型的预测类别。
            _,predicted=torch.max(output,1)
            # labels.size(0) 返回当前 batch 的样本数,比如 batch_size=32,则 labels.size(0) = 32
            total+=label.size(0)
            # .sum(): 统计 True 的个数,即预测正确的样本数量  tensor(3) → 正确预测了 3 个样本
            # .item(): 将张量转换为 Python 标量,方便加到 correct 变量中  3 → Python 标量 3
            correct += (predicted == label).sum().item()
    print(f"Accuracy: {100 * correct / total:.2f}%")

# 1000个样本,每个样本10维度
testdata=torch.randn(100,10)
# 1000个样本,二分类
testlabels=torch.randint(0,2,(100,))

# 在测试集上评估
test_dataset = CustomDataset(testdata,testlabels)
test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)
evaluate(model, test_loader)
python 复制代码
Accuracy: 55.00%

5. ​模型保存和加载

训练好的模型可以保存到磁盘,以便后续使用或部署。

1)​保存模型:

使用 torch.save 保存模型的状态字典(state_dict)。

2)​加载模型:

使用 torch.load 加载模型的状态字典,并将其加载到模型中。

python 复制代码
# 保存模型
torch.save(model.state_dict(), "model.pth")

# 加载模型
model = SimpleNN(input_dim=10, hidden_dim=20, output_dim=2)
model.load_state_dict(torch.load("model.pth"))

6. ​总结

模型设计: 继承 nn.Module,定义模型结构。

数据准备: 使用 Dataset 和 DataLoader 加载数据。

​训练和优化: 定义损失函数和优化器,编写训练循环。 ​

模型评估: 在测试集上评估模型性能。 ​

模型保存和加载: 使用 torch.save 和 torch.load 保存和加载模型。

7. 一些用法备注

1)super().init()

super(SimpleNN, self).init () 是 Python 中用于调用父类(基类)init 方法的语法。

在 PyTorch 里,所有自定义的神经网络都应该继承自 torch.nn.Module,并在 init 方法中调用 super(),以确保 torch.nn.Module 的初始化逻辑被正确执行,例如参数注册、模块管理等。

如果不调用 super(SimpleNN, self).init():父类 nn.Module 的初始化代码不会执行,这可能导致:

参数不会被正确注册,影响 model.parameters() 和优化器的使用。

一些 PyTorch 内部机制可能无法正常工作,如 model.to(device) 可能会出错。

模型在 torch.save() 或 torch.load() 时可能出现问题。

2)model.parameters()

作用:返回模型的所有可训练参数,以便优化器更新参数。
parameters() 是 torch.nn.Module 类的一个方法,它会递归地获取模型所有 nn.Module 层的可训练参数(nn.Parameter 类型),传递给优化器,比如 torch.optim.Adam(model.parameters(), lr=0.001),用于更新权重。

3)model.train()

作用:将模型切换到训练模式,启用某些特定的层(例如 Dropout 和 BatchNorm),确保它们在训练时正确工作。
Dropout(随机丢弃一部分神经元)在训练模式下会生效,在评估模式下会关闭。

BatchNorm(批量归一化)在训练时会更新均值和方差,而在评估时使用固定的均值和方差。

4)model.eval()

作用:在测试和推理(inference)阶段使用,将模型切换到评估模式,禁用 Dropout 和 BatchNorm 的更新,确保测试结果稳定,避免训练时的随机行为影响模型预测结果。

5)optimizer.zero_grad()

作用:清空梯度
PyTorch 采用 自动微分(Automatic Differentiation)机制,每次调用 loss.backward()

时,梯度会累积(而不是覆盖)。因此,在每次更新参数前,需要先清空上一次的梯度,否则梯度会不断累积,影响优化效果。

6)loss.backward()

作用:反向传播
反向传播用于计算梯度,本质上是基于 自动微分(Autograd)实现的链式法则(Chain Rule)。PyTorch 通过 loss.backward() 计算所有参数的梯度。每个 requires_grad=True 的张量都会存储其 .grad,这些梯度会存入 param.grad,以供下一步 optimizer.step() 更新参数。

7)optimizer.step()

作用:更新参数

优化器(如 Adam、SGD)使用存储的 param.grad 来更新模型参数。

8)with torch.no_grad()

作用:禁用 PyTorch 的自动梯度计算,使得前向传播不计算梯度,从而节省显存,提高计算效率。

为什么使用?

测试阶段不需要反向传播,不需要计算梯度。

节省显存:如果不加 torch.no_grad(),PyTorch

仍会存储计算图以备反向传播使用,占用额外显存。 加速计算:因为不计算梯度,计算过程更快。

相关推荐
管理前沿3 分钟前
如何避免Bug跟踪系统混乱
大数据·运维·人工智能
搏博8 分钟前
本地基于Ollama部署的DeepSeek详细接口文档说明
人工智能·python·深度学习·神经网络
无级程序员12 分钟前
简单理解机器学习中top_k、top_p、temperature三个参数的作用
人工智能·机器学习
m0_6658151026 分钟前
全面解读 联核科技四向穿梭车的常见功能介绍
大数据·人工智能
小白的高手之路39 分钟前
Pytorch中的torch.utils.data.Dataset 类
pytorch·python·深度学习
cv2016_DL1 小时前
多模态大模型常见问题
人工智能·机器学习·语言模型·自然语言处理·transformer
csdn5659738501 小时前
当DeepSeek走进生活:一场颠覆日常的智能革命
人工智能·生活·智能交通·deepseek·智能生活
Alpha汇股志1 小时前
基于 EMA12 指标结合 iTick 外汇报价 API 、股票报价API、指数报价API的量化策略编写与回测
人工智能·经验分享·开源·业界资讯
STRUGGLE_3991 小时前
【论文笔记】Transformer
人工智能·深度学习·transformer
共享ui设计和前端开发人才1 小时前
UI前端与数字孪生:打造智慧城市的双引擎
人工智能·智慧城市