深度学习模型训练核心流程(5 步)

  1. 数据准备
    加载数据集 → 划分训练集 / 测试集 → 创建数据加载器(批处理)。

  2. 模型定义
    设计网络结构(如 CNN) → 初始化模型参数。

  3. 训练配置
    选择损失函数(如交叉熵) → 选择优化器(如 SGD) → 设置超参数(学习率、Epoch)。

  4. 训练循环

    for epoch in range(epochs):
        # 训练
        for data in train_dataloader:
            前向传播 → 计算损失 → 反向传播 → 优化器更新参数
        
        # 测试(每轮结束后)
        with torch.no_grad():
            for data in test_dataloader:
                前向传播 → 计算损失(不更新参数)
    
  5. 模型保存与监控
    保存模型(每轮或最优) → 使用 TensorBoard 等工具记录训练指标(损失、准确率)。


 模型:

# 搭建神经网络
import torch
from torch import nn


class MyModule(nn.Module):
    def __init__(self):
        super().__init__()
        self.module = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64 * 4 * 4, 64),
            nn.Linear(64, 10)
        )

    def forward(self, x):
        x = self.module(x)
        return x


# 测试网络
if __name__ == '__main__':
    model = MyModule()
    input = torch.ones((64, 3, 32, 32))
    output = model(input)
    print(output.shape)

训练: 

import torch

import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

from model import *

train_data = torchvision.datasets.CIFAR10(root="D:\\Python\\learn_pytorch\\torchvision_dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)

test_data = torchvision.datasets.CIFAR10(root="D:\\Python\\learn_pytorch\\torchvision_dataset", train=True,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=False)

# 数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

# 利用DataLoader来加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

# 创建网络模型
model = MyModule()

# 损失函数
loss_fn = nn.CrossEntropyLoss()

# 优化器
learning_rate = 1e-2
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 训练次数
total_train_step = 0
# 测试次数
total_test_step = 0
# 训练轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("logs")
for i in range(epoch):
    print("---------第{}轮训练开始---------".format(i + 1))

    # 训练
    for data in train_dataloader:
        imgs, targets = data
        outputs = model(imgs)
        loss = loss_fn(outputs, targets)

        # 优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step = total_train_step + 1
        if total_train_step % 100 == 0:
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss", loss.item(), total_train_step)
    # 评估模型训练效果 - 跑一个测试数据查看正确率

    # 测试过程中,参数不需要调整了,临时把梯度去除
    total_test_loss = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            outputs = model(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()

    print("整体测试集上的loss:{}", format(total_test_loss))
    writer.add_scalar("test_sum_loss", total_test_loss, total_test_step)
    total_test_step = total_test_step + 1

    # 保存每一次训练的结果
    torch.save(model, "model_{}.pth".format(i))
    print("模型已保存")

writer.close()

强调流程: 

import torch

import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

from model import *

准备数据集

train_data = torchvision.datasets.CIFAR10(root="D:\\Python\\learn_pytorch\\torchvision_dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)

test_data = torchvision.datasets.CIFAR10(root="D:\\Python\\learn_pytorch\\torchvision_dataset", train=True,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=False)

# 数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

# 利用DataLoader来加载数据集

加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

# 创建网络模型
model = MyModule()

# 损失函数
loss_fn = nn.CrossEntropyLoss()

# 优化器
learning_rate = 1e-2
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 训练次数
total_train_step = 0
# 测试次数
total_test_step = 0
# 训练轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("logs")
for i in range(epoch):
    print("---------第{}轮训练开始---------".format(i + 1))

    # 训练
    for data in train_dataloader:
        imgs, targets = data   数据准备
        outputs = model(imgs) 训练结果
        loss = loss_fn(outputs, targets) 计算损失

        # 优化器优化模型
        optimizer.zero_grad() 梯度清空
        loss.backward() 反向传播
        optimizer.step() 优化器工作(链式法则 计算梯度 优化参数)
        total_train_step = total_train_step + 1
        if total_train_step % 100 == 0:
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # 测试
    # 评估模型训练效果 - 跑一个测试数据查看正确率

    # 测试过程中,参数不需要调整了,临时把梯度去除
    total_test_loss = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data  数据准备
            outputs = model(imgs)  训练结果
            loss = loss_fn(outputs, targets)  计算损失
            total_test_loss = total_test_loss + loss.item() 计算损失和

    print("整体测试集上的loss:{}", format(total_test_loss))
    writer.add_scalar("test_sum_loss", total_test_loss, total_test_step)
    total_test_step = total_test_step + 1

    # 保存每一次训练的结果
    torch.save(model, "model_{}.pth".format(i))  保存训练结果
    print("模型已保存")

writer.close()
 

运行后的目录列表: 

 

 Tensorboard的记录结果:

上述是通过 计算测试数据的损失函数的值的和,来判断训练的效果

适合 回归任务,生成任务等

若是分类等任务,用正确率来判断较合适:

分类问题的测试(看预测的准确率):

如输入两张图片

1.先把 输出的概率tensor形式变成预测对应的结果preds(用Argmax函数

2.在和各个的targets进行比较,得到true/false的列表

3.求这个列表的和 true=1,false=0

 


Argmax 函数:

argmax 函数(argument of the maximum)是一种常用的数学函数,核心作用是返回数组(或序列)中最大值所在的 “位置索引”,而非最大值本身。

  • “arg” 表示 “参数”(即位置索引),“max” 表示 “最大值”,合起来就是 “最大值对应的参数(索引)”。

  • 例如:对于数组 [3, 1, 5, 2],最大值是 5,它在数组中的索引是 2(从 0 开始计数),因此 argmax([3, 1, 5, 2]) = 2

关键细节:索引规则与多维数组

索引从 0 开始
在编程(如 Python、NumPy)中,数组索引默认从 0 开始,argmax 返回的索引也遵循这一规则。
例:arr = [10, 20, 5] → argmax(arr) = 1(因为 20 是最大值,位于索引 1

argmax 函数:定义与核心作用

argmax 函数(argument of the maximum)是一种常用的数学函数,核心作用是返回数组(或序列)中最大值所在的 “位置索引”,而非最大值本身。

  • “arg” 表示 “参数”(即位置索引),“max” 表示 “最大值”,合起来就是 “最大值对应的参数(索引)”。

  • 例如:对于数组 [3, 1, 5, 2],最大值是 5,它在数组中的索引是 2(从 0 开始计数),因此 argmax([3, 1, 5, 2]) = 2

关键细节:索引规则与多维数组

  1. 索引从 0 开始
    在编程(如 Python、NumPy)中,数组索引默认从 0 开始,argmax 返回的索引也遵循这一规则。
    例:arr = [10, 20, 5] → argmax(arr) = 1(因为 20 是最大值,位于索引 1)。

  2. 多维数组的处理
    对于二维及以上的数组,argmax 可以指定 “轴(axis)”,返回对应轴上最大值的索引。
    例:二维数组 [[3, 7], [2, 8]]

    • 若按行(axis=1)计算:每行的最大值索引分别是 1(第一行 7 在索引 1)和 1(第二行 8 在索引 1),结果为 [1, 1]

    • 若按列(axis=0)计算:每列的最大值索引分别是 0(第一列 3>2)和 1(第二列 8>7),结果为 [0, 1]


代码案例: 

 上述代码修改为用准确率看训练效果:

# 测试过程中,参数不需要调整了,临时把梯度去除
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
    for data in test_dataloader:
        imgs, targets = data
        outputs = model(imgs)
        loss = loss_fn(outputs, targets)
        total_test_loss = total_test_loss + loss.item()
        accuracy = (outputs.argmax(1) == targets).sum()
        total_accuracy = total_accuracy + accuracy  # 预测对的总数量

print("整体测试集上的loss:{}", format(total_test_loss))
print("整体测试集上的准确率:{}", format(total_accuracy / test_data_size)) # 准确率
writer.add_scalar("test_sum_loss", total_test_loss, total_test_step)
writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step)
total_test_step = total_test_step + 1

  Tensorboard的记录结果:


一个要点

 在一些训练时候会用model.train() 和 model.eval()两个方法表示阶段

for i in range(epoch):
    print("---------第{}轮训练开始---------".format(i + 1))

    # 训练
    model.train()
    for data in train_dataloader:
        imgs, targets = data
        outputs = model(imgs)
        loss = loss_fn(outputs, targets)

        # 优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step = total_train_step + 1
        if total_train_step % 100 == 0:
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss", loss.item(), total_train_step)
    # 评估模型训练效果 - 跑一个测试数据查看正确率
    # 测试过程中,参数不需要调整了,临时把梯度去除
    model.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            outputs = model(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy = total_accuracy + accuracy  # 预测对的总数量

在 PyTorch 中,model.train() 和 model.eval() 是用于切换模型 “训练模式” 和 “评估模式” 的核心方法。它们的本质作用是控制模型中特定层的行为(如 Dropout、BatchNorm),以适配 “训练” 和 “评估” 两个不同阶段的需求。

但不是必须的,在有需要管理的层时候必须要有

如:

一、依赖训练 / 评估模式的层

  • Dropout 层(含 Dropout1d、Dropout2d 等)

  • Batch Normalization 层(含 BatchNorm1d、BatchNorm2d 等)

  • DropPath 层(随机路径丢弃)

二、有 “记忆” 或状态的层

  • RNN 层(循环神经网络)

  • LSTM 层(长短期记忆网络)

  • GRU 层(门控循环单元)

三、其他特殊计算逻辑的层

  • Layer Normalization 层(LayerNorm)

  • Instance Normalization 层(InstanceNorm)

  • Group Normalization 层(GroupNorm)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐