大数跨境

构建网络:一站式实现模型搭建与训练

构建网络:一站式实现模型搭建与训练 知识代码AI
2026-09-03
2

构建网络:一站式实现模型搭建与训练


一、模型搭建整体流程

使用 PyTorch 构建和训练模型的基本流程分为以下 5 个步骤:[pdf_16]

步骤
说明
① 定义网络结构
继承 nn.Module 类,在 __init__() 中定义可学习参数,在 forward() 中定义前向传播
② 实例化模型
创建模型对象,如 model = LinearModel()
③ 定义损失函数与优化器
如 MSE 损失 + SGD 优化器
④ 训练循环
迭代多个 Epoch,执行前向传播→计算损失→梯度清零→反向传播→优化器更新参数
⑤ 保存/查看训练结果
使用 named_parameters() 或 state_dict() 查看参数,用 torch.save() 保存模型

二、自定义网络结构——nn.Module 详解

1. 三条核心规则

继承 nn.Module 类后,必须遵守以下规则:[pdf_16]

规则
说明
必须继承 nn.Module nn.Module
 是所有神经网络模块的基类,Torchvision 中的模型也都是通过继承它构建的
重写 __init__()
把需要学习参数的层放到构造函数中(如 weight、bias、卷积层)。**必须调用 super().__init__()**,否则会报错:AttributeError: cannot assign parameters before Module.__init__() call
重写 forward()
定义模型如何计算输出(前向传播)。不需要学习参数的层(如 BN 层、激活函数、Dropout)一般可放在这里

模块是 callable 的:调用 model(x) 相当于执行 forward 函数。[pdf_16]

2. 线性回归模型示例

import torch
from torch import nn

classLinearModel(nn.Module):
def__init__(self):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(1))
        self.bias = nn.Parameter(torch.randn(1))

defforward(self, input):
return (input * self.weight) + self.bias

# 使用
model = LinearModel()
x = torch.tensor(3)
y = model(x)

nn.Parameter() 的作用是作为 nn.Module 中可训练的参数使用。[pdf_16]

3. 模块化组合——将重复结构封装

对于深层网络,可以将重复结构封装为单独模块,如将 3×3 卷积与 2×2 卷积组合封装为 CustomLayer:[pdf_16]

classCustomLayer(nn.Module):
def__init__(self, input_channels, output_channels):
        super().__init__()
        self.conv1_1 = nn.Conv2d(in_channels=input_channels, out_channels=3, kernel_size=3)
        self.conv1_2 = nn.Conv2d(in_channels=3, out_channels=output_channels, kernel_size=2)

defforward(self, input):
        x = self.conv1_1(input)
        x = self.conv1_2(x)
return x

然后在主模型中直接调用 CustomLayer

classCustomModel(nn.Module):
def__init__(self):
        super().__init__()
        self.layer1 = CustomLayer(11)
# ... 重复使用
        self.layern = CustomLayer(11)

defforward(self, input):
        x = self.layer1(input)
# ...
        x = self.layern(x)
return x

残差块、Inception 块等多层组合结构,都可以采用上述模块化方式实现。[pdf_16]


三、模型训练完整过程

1. 准备训练数据

回归模型为  ,其中 x 与 y 对应 x_train 与 y_train,w 与 b 是要学习的参数:[pdf_16]

import numpy as np
import random
from matplotlib import pyplot as plt

W = 2
b = 3
xlim = [-1010]
x_train = np.random.randint(low=xlim[0], high=xlim[1], size=30)
y_train = [W * x + b + random.randint(02for x in x_train]
plt.plot(x_train, y_train, 'bo')

2. 训练代码(MSE 损失 + SGD 优化器)

model = LinearModel()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, weight_decay=1e-2, momentum=0.9)

y_train = torch.tensor(y_train, dtype=torch.float32)
for _ in range(1000):
    input = torch.from_numpy(x_train)
    output = model(input)
    loss = nn.MSELoss()(output, y_train)
    model.zero_grad()
    loss.backward()
    optimizer.step()

3. 查看训练后的参数

for parameter in model.named_parameters():
    print(parameter)
# 输出:
# ('weight', Parameter containing: tensor([2.0071], requires_grad=True))
# ('bias', Parameter containing: tensor([3.1690], requires_grad=True))

训练后 weight ≈ 2.0071,bias ≈ 3.1690,与真实值 w=2、b=3 非常接近,模型成功学习了数据的规律。[pdf_16]


四、模型保存与加载

方式一:只保存训练好的参数(推荐)

# 保存
torch.save(model.state_dict(), './linear_model.pth')

# 加载(需先定义网络结构)
linear_model = LinearModel()
linear_model.load_state_dict(torch.load('./linear_model.pth'))
linear_model.eval()

state_dict 是一个字典,在模型定义后自动生成,存储模型的可训练参数:[pdf_16]

model.state_dict()
# 输出:OrderedDict([('weight', tensor([[2.0071]])), ('bias', tensor([3.1690]))])

方式二:保存网络结构与参数

# 保存整个模型
torch.save(model, './linear_model_with_arc.pth')

# 加载(不需要创建网络了)
linear_model_2 = torch.load('./linear_model_with_arc.pth')
linear_model_2.eval()

⚠️ 重要提醒

  • **加载模型后必须执行 model.eval()**:因为 Dropout 与 BN 等层在训练时与评估时状态不同,模型进入评估或上线前必须调用。[pdf_16]
  • 模型后缀名 .pt 或 .pth 只是命名习惯,没有特殊要求。[pdf_16]

五、迁移学习——使用 Torchvision 预训练模型微调(AlexNet 示例)

1. 什么是微调

Torchvision 提供的模型最大的作用是当作预训练模型,用来加速模型收敛速度,这就是微调(fine-tuning)。文章介绍了两种微调方式:[pdf_16]

  • 固定整个网络参数,只训练最后全连接层
  • 修改全连接层之后,整个网络重新训练(使用预训练模型的参数作为初始化参数)—— 这是更常用的方式

2. 使用预训练模型的两个重点

重点
要求
输入数据格式
三通道数据,shape 为   的 Tensor,使用均值 [0.485, 0.456, 0.406] 和标准差 [0.229, 0.224, 0.225] 进行正规化
输入尺寸
经典卷积网络最后的全连接层导致输入尺寸固定,但 Torchvision 模型可接受任意尺寸输入(有的网络用全局平均或全卷积网络)

3. 导入与验证预训练模型

import torchvision.models as models

# 方式一:在线下载
alexnet = models.alexnet(pretrained=True)

# 方式二:手动下载后加载
alexnet = models.alexnet()
alexnet.load_state_dict(torch.load('./model/alexnet-owt-4df8aa71.pth'))

验证模型加载是否成功——用一张狗图片预测,输出 263 对应 ImageNet 中的柯基狗:[pdf_16]

from PIL import Image
import torchvision.transforms as transforms

im = Image.open('dog.jpg')
transform = transforms.Compose([
    transforms.RandomResizedCrop((224224)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.4850.4560.406], std=[0.2290.2240.225])
])
input_tensor = transform(im).unsqueeze(0)
alexnet(input_tensor).argmax()
# 输出:263 ← 对应 ImageNet 中的 Pembroke(柯基狗)

4. 打印网络结构确定修改位置

print(alexnet)

AlexNet 结构包含:[pdf_16]

  • features:卷积层部分
  • avgpoolAdaptiveAvgPool2d(output_size=(6, 6))
  • classifier:Sequential 分类器(含 Dropout、Linear、ReLU 等层)

5. 使用 CIFAR-10 数据集进行微调

CIFAR-10 数据集:[pdf_16]

  • 共 60000 张 32×32 RGB 图片,10 个类别
  • 每类 6000 张,50000 张训练集,10000 张测试集
cifar10_dataset = torchvision.datasets.CIFAR10(
    root='./data',
    train=False,
    transform=transforms.ToTensor(),
    target_transform=None,
    download=True
)

展示 CIFAR-10 图片数据:

from torch.utils.data import DataLoader
tensor_dataloader = DataLoader(dataset=cifar10_dataset, batch_size=32)
data_iter = iter(tensor_dataloader)
img_tensor, label_tensor = data_iter.next()
print(img_tensor.shape)  # torch.Size([32, 3, 32, 32])

grid_tensor = torchvision.utils.make_grid(img_tensor, nrow=16, padding=2)
grid_img = transforms.ToPILImage()(grid_tensor)
display(grid_img)

6. 微调完整流程代码

修改全连接层(将最后一层替换为适配 10 类输出的 Linear 层):[pdf_16]

fc_in_features = alexnet.classifier[6].in_features
alexnet.classifier[6] = torch.nn.Linear(fc_in_features, 10)

定义优化器与 DataLoader:[pdf_16]

from torch.utils.data import DataLoader

dataloader = DataLoader(dataset=cifar10_dataset,
                        batch_size=32,
                        shuffle=True,
                        num_workers=2)

optimizer = torch.optim.SGD(alexnet.parameters(), lr=1e-4, weight_decay=1e-2, momentum=0.9)

训练循环:[pdf_16]

for epoch in range(3):
for item in dataloader:
        output = alexnet(item[0])
        target = item[1]
        loss = nn.CrossEntropyLoss()(output, target)
        print('Epoch {}, Loss {}'.format(epoch + 1, loss))

        alexnet.zero_grad()
        loss.backward()
        optimizer.step()

六、核心要点总结

知识点
要点
自定义网络
继承 nn.Module,重写 __init__() 和 forward(),注意 super().__init__()
nn.Parameter
作为 nn.Module 中可训练的参数使用
模块化封装
将重复结构(残差块、Inception 块等)封装为单独模块,可复用组合
训练五步
梯度清零 → 前向传播 → 计算损失 → 反向传播 → 优化更新
模型保存方式一 torch.save(model.state_dict(), ...)
 只保存参数,加载需先定义网络结构
模型保存方式二 torch.save(model, ...)
 保存整个模型,加载无需重定义网络
model.eval()
评估或上线前必须调用,使 Dropout 和 BN 层切换为评估模式
迁移学习
使用预训练模型参数作为初始化,修改全连接层适配新任务,重新训练
AlexNet 结构
包含 features(卷积层)、avgpool、classifier(全连接层)三部分
CIFAR-10
10 类 60000 张 32×32 RGB 图片,50000 训练 / 10000 测试

七、每课一练

问题:请你自己构建一个卷积神经网络,基于 CIFAR-10,训练一个图像分类模型。因为还没有学习图像分类原理,我先帮你写好了网络的结构,需要你补全数据读取、损失函数(交叉熵损失)与优化方法(SGD)等部分。[pdf_16]

解题思路

  1. 数据读取:使用 torchvision.datasets.CIFAR10 加载数据集,配合 DataLoader 设置 batch size
  2. 损失函数:使用 nn.CrossEntropyLoss()
  3. 优化方法:使用 torch.optim.SGD(model.parameters(), lr=..., momentum=...)
  4. 训练循环:参考上面的五步框架——梯度清零 → 前向传播 → 计算损失 → 反向传播 → 优化更新

八、小结

  1. 模型搭建三步:继承 nn.Module、重写 __init__()、重写 forward()
  2. 模块化封装:将重复结构(如残差块)封装为子模块,便于复用。
  3. 训练五步:梯度清零 → 前向传播 → 计算损失 → 反向传播 → 优化更新。
  4. 模型保存与加载:两种方式——只保存参数或保存整个模型;加载后记得调用 model.eval()
  5. 迁移学习:使用预训练模型初始化参数,修改全连接层适配新任务,整体重新训练,可加速收敛。
  6. AlexNet + CIFAR-10:修改最后一层全连接层输出为 10 类,使用 SGD 优化器和交叉熵损失函数进行训练。
  7. 核心原则model.eval() 是评估和上线前必须调用的步骤,确保 Dropout 和 BN 层行为正确。


【声明】内容源于网络
0
0
知识代码AI
技术基底 机器视觉全栈 × 光学成像 × 图像处理算法 编程栈 C++/C#工业开发 | Python智能建模 工具链 Halcon/VisionPro工业部署 | PyTorch/TensorFlow模型炼金术 | 模型压缩&嵌入式移植
内容 403
粉丝 0
知识代码AI 技术基底 机器视觉全栈 × 光学成像 × 图像处理算法 编程栈 C++/C#工业开发 | Python智能建模 工具链 Halcon/VisionPro工业部署 | PyTorch/TensorFlow模型炼金术 | 模型压缩&嵌入式移植
总阅读6.6k
粉丝0
内容403