news 2026/10/22 13:02:57

FA_CNN卷积神经网络九_模型保存与加载PyTorch

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FA_CNN卷积神经网络九_模型保存与加载PyTorch

FA:Formulas and Algorithm,CNN:Convolutional Neural Network

1. 引言

在深度学习项目中,训练好的模型需要保存到磁盘,以便后续部署或继续训练。PyTorch 提供了两种主流的模型保存方式,各有优劣。本文将结合 VGG16 实例,详细介绍这两种方式的保存与加载方法,并剖析一个常见的「网络陷阱」——为什么有时加载模型会失败。

2. 准备工作

在开始之前,请确保已安装 PyTorch 和 torchvision:

pipinstalltorch torchvision

本文所有代码均基于 PyTorch 框架,使用 VGG16 作为示例网络。

3. 网络模型保存(方式一):模型结构 + 模型参数

方式一通过torch.save(model, path)将整个模型对象(包括网络结构和参数)序列化保存到磁盘。

importtorchvisionimporttorch vgg16=torchvision.models.vgg16(pretrained=False)# 保存方式一:模型结构 + 模型参数torch.save(vgg16,"./model/vgg16_method1.pth")print(vgg16)

运行后,控制台会打印出 VGG16 的完整网络结构,包括特征提取层(features)、池化层(avgpool)和分类器(classifier):

VGG( (features): Sequential( (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): ReLU(inplace=True) (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (3): ReLU(inplace=True) (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (6): ReLU(inplace=True) (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (8): ReLU(inplace=True) (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (11): ReLU(inplace=True) (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (13): ReLU(inplace=True) (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (15): ReLU(inplace=True) (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (18): ReLU(inplace=True) (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (20): ReLU(inplace=True) (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (22): ReLU(inplace=True) (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (25): ReLU(inplace=True) (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (27): ReLU(inplace=True) (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (29): ReLU(inplace=True) (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) ) (avgpool): AdaptiveAvgPool2d(output_size=(7, 7)) (classifier): Sequential( (0): Linear(in_features=25088, out_features=4096, bias=True) (1): ReLU(inplace=True) (2): Dropout(p=0.5, inplace=False) (3): Linear(in_features=4096, out_features=4096, bias=True) (4): ReLU(inplace=True) (5): Dropout(p=0.5, inplace=False) (6): Linear(in_features=4096, out_features=1000, bias=True) ) )

4. 网络模型导入(方式一)

方式一保存的模型,加载时同样使用torch.load(path),直接返回完整的模型对象:

importtorch# 保存方式一对应的加载模型model=torch.load("./model/vgg16_method1.pth")print(model)

加载成功后,model即为完整的 VGG16 网络,可直接用于推理或继续训练。

5. 网络模型保存(方式二):仅保存模型参数(官方推荐)

方式二只保存模型的状态字典(state_dict),即网络各层的权重和偏置参数,不保存网络结构。这也是 PyTorch 官方推荐的做法。

importtorchvisionimporttorch vgg16=torchvision.models.vgg16(pretrained=False)# 保存方式二:模型参数(官方推荐),不再保存网络模型结构torch.save(vgg16.state_dict(),"./model/vgg16_method2.pth")print(vgg16)

打印的仍是 VGG16 的网络结构,但保存到磁盘的.pth文件只包含参数字典。

6. 网络模型导入(方式二)

方式二保存的模型,加载时不能直接得到完整的网络对象,需要分两步:

6.1 直接加载参数(仅得到参数字典)

importtorchimporttorchvision# 导入模型参数model=torch.load("./model/vgg16_method2.pth")print(model)

此时model是一个OrderedDict,包含各层的权重和偏置,例如:

OrderedDict([('features.0.weight', tensor([...])), ('features.0.bias', tensor([...])), ...])

6.2 将参数导入模型结构

要得到完整的网络,需要先创建网络结构,再通过load_state_dict将参数导入:

importtorchimporttorchvision vgg16=torchvision.models.vgg16(pretrained=False)print(vgg16)# 将模型参数导入到模型结构中vgg16.load_state_dict(torch.load("./model/vgg16_method2.pth"))print(vgg16)

加载成功后,vgg16即为带有训练参数的完整网络。

7. 网络陷阱:为什么有时加载模型会失败?

下面通过一个自定义网络Tudui来演示常见的加载陷阱。

7.1 创建自定义模型并保存

importtorchfromtorchimportnnclassTudui(nn.Module):def__init__(self):super(Tudui,self).__init__()self.conv1=nn.Conv2d(3,64,kernel_size=3)defforward(self,x):x=self.conv1(x)returnx tudui=Tudui()torch.save(tudui,"./model/tudui_method1.pth")

7.2 失败场景:直接加载方式一保存的模型

如果在新的、未定义Tudui类的环境中直接加载方式一保存的模型,会报错:

importtorch# 无法直接加载方式一保存的网络结构model=torch.load("./model/tudui_method1.pth")print(model)

原因分析:方式一保存的是整个模型对象,其中包含网络结构定义。加载时,PyTorch 需要反序列化这个类,但当前环境中没有Tudui类的定义,因此无法还原网络结构。

提示:在 Jupyter Notebook 中,如果先运行了定义Tudui的代码块,再运行加载代码,可能不会报错。但重启 Kernel 后(点击 Kernel → Restart),再单独运行加载代码,就会失败。

7.3 成功场景:加载前先定义网络结构

要成功加载方式一保存的模型,必须在加载前重新定义相同的网络结构:

importtorchfromtorchimportnn# 确保网络模型是我们想要的网络模型,要在加载前写明网络模型classTudui(nn.Module):def__init__(self):super(Tudui,self).__init__()self.conv1=nn.Conv2d(3,64,kernel_size=3)defforward(self,x):x=self.conv1(x)returnx# 不需要创建网络模型实例,直接加载model=torch.load("./model/tudui_method1.pth")print(model)

加载成功后,输出:

Tudui( (conv1): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1)) )

7.4 成功场景:通过 import 引入网络定义

更规范的做法是,将网络定义放在独立的.py文件中,通过import引入:

importtorchfrommodel_saveimport*# 相当于把 model_save.py 里的网络模型定义写到这里# 不需要创建网络模型实例,直接加载model=torch.load("tudui_method1.pth")print(model)

8. 两种方式对比总结

对比项方式一:保存整个模型方式二:仅保存参数(官方推荐)
保存内容网络结构 + 参数仅参数(state_dict)
保存代码torch.save(model, path)torch.save(model.state_dict(), path)
加载代码torch.load(path)先建网络,再load_state_dict(torch.load(path))
加载依赖需要网络类定义需要网络结构定义
文件体积较大较小
可移植性较差(依赖类定义)较好
适用场景快速实验、临时保存正式部署、模型发布

9. 总结

  • 方式一(保存整个模型)使用简单,但加载时依赖网络类的定义,容易踩坑。
  • 方式二(仅保存参数)是官方推荐做法,文件更小、更灵活,加载时只需先构建网络结构再导入参数。
  • 无论哪种方式,加载模型前都要确保网络结构定义可用,这是避免「网络陷阱」的关键。

希望本文能帮助你正确掌握 PyTorch 模型的保存与加载,避开常见的坑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 13:02:54

HDLbits 1.4 学习笔记

always 块、if/case 语句与优先编码器(Procedures)1.Always blocks(组合)由于数字电路由逻辑门通过导线连接组成,任何电路都可以表示为模块的组合并赋予语句。然而,有时这并不是描述电路最方便的方式。过程…

作者头像 李华
网站建设 2026/10/22 13:00:23

普通一本计算机毕业,求职大模型开发需要补齐哪5项能力?

普通一本计算机毕业,求职大模型开发需要补齐哪5项能力? “会Python、会LangChain、会向量数据库,还缺什么?”如果这些“会”只代表跟着教程运行过,清单再长,也可能经不起项目追问。 **大模型开发求职更需…

作者头像 李华
网站建设 2026/10/22 12:59:19

Python aiida-kkr 包完全指南与实战案例

1. 引言aiida-kkr 是一个基于 AiiDA 工作流框架开发的 Python 包,用于自动化管理和运行 KKR(Korringa-Kohn-Rostoker)多重散射方法的电子结构计算。它把复杂的 KKR 计算流程封装成可复现、可追踪的工作流,让科研人员能够以声明式的…

作者头像 李华
网站建设 2026/10/22 12:54:23

代理模式与@Transactional失效场景详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 12:44:41

Vue3——第 10 篇:插槽(Slot)——打造高复用组件的利器

本篇定位:插槽是 Vue 组件化体系中最强大的扩展机制之一,它让组件变得高度可定制化。本篇将系统讲解插槽的三种类型——默认插槽、具名插槽和作用域插槽,以及它们的高级用法。读完本篇,你将能够设计出灵活、可复用、语义清晰的组件…

作者头像 李华