pytorch之模型保存与加载(五)

1、保存和加载模型

当保存和加载模型时,需要熟悉三个核心功能:

  1. torch.save:将序列化对象保存到磁盘。此函数使用Python的pickle模块进行序列化。使用此函数可以保存如模型、tensor、字典等各种对象。
  2. torch.load:使用pickle的unpickling功能将pickle对象文件反序列化到内存。此功能还可以有助于设备加载数据。
  3. torch.nn.Module.load_state_dict:使用反序列化函数 state_dict 来加载模型的参数字典。

2.什么是状态字典:state_dict?

在PyTorch中,torch.nn.Module模型的可学习参数(即权重和偏差)包含在模型的参数中,(使用model.parameters()可以进行访问)。 state_dict是Python字典对象,它将每一层映射到其参数张量。注意,只有具有可学习参数的层(如卷积层,线性层等)的模型 才具有state_dict这一项。目标优化torch.optim也有state_dict属性,它包含有关优化器的状态信息,以及使用的超参数。

因为state_dict的对象是Python字典,所以它们可以很容易的保存、更新、修改和恢复,为PyTorch模型和优化器添加了大量模块。

下面通过从简单模型训练一个分类器中来了解一下state_dict的使用。

3、CNN介绍

3.1、各层作用

  1. 卷积层 – 主要作用是保留图片的特征

  2. 池化层 – 主要作用是把数据降维,可以有效的避免过拟合

  3. 全连接层 – 根据不同任务输出我们想要的结果

3.2、CNN优缺点

3.2.1 优点

  • 共享卷积核,处理高维数据无压力;
  • 可以自动进行特征提取
  • 卷积层可以提取特征, 卷积层中的卷积核(滤波器)真正发挥作用,通过卷积提取需要的特征,详细解释参考牛人博文 CNN入门讲解:卷积层是如何提取特征的?

3.2.2 缺点

  • 当网络层次太深时,采用BP传播修改参数会使靠近输入层的参数改动较慢;
  • 采用梯度下降算法很容易使训练结果收敛于局部最小值而非全局最小值;
  • 池化层会丢失大量有价值信息,忽略局部与整体之间关联性;
  • 由于特征提取的封装,为网络性能的改进罩了一层黑盒

     

3.3、卷积层尺寸计算

3.4、具体计算实例

4、实例

import torch
import torch.autograd as autograd
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
torch.manual_seed(1)


#cnn参数计算详解https://zhuanlan.zhihu.com/p/29119239
'''
in_channels:输入通道
out_channels:输出通道
kernel_size:核大小
stride:Default: 1
padding:Default: 0
nn.Conv2d(in_channels:int, out_channels:int, kernel_size:Union[int, Tuple[int, int]], 
stride:Union[int, Tuple[int, int]]=1, padding:Union[int, Tuple[int, int]]=0, dilation:Union[int, Tuple[int, int]]=1,
groups:int=1, bias:bool=True, padding_mode:str='zeros')

Shape:
Input: :math:`(N, C_{in}, H_{in}, W_{in})`
Output: :math:`(N, C_{out}, H_{out}, W_{out})`
'''
class CNN(nn.Module):
    def __init__(self):
        super(CNN,self).__init__()
        """
        in_channels:5,out_channels:6,kernel_size:3
        conv1.weight 	 torch.Size([6, 5, 3, 3])
        conv1.bias 	 torch.Size([6])
        """
        self.conv1=nn.Conv2d(5,6,3)  
        self.pool=nn.MaxPool2d(2,2)
        self.conv2=nn.Conv2d(6,5,2)
        """
        fc1.weight 	 torch.Size([7, 10])
        fc1.bias 	 torch.Size([7])
        """
        self.fc1=nn.Linear(5*1*2,7)
    
    def forward(self,x):
        
        x=self.conv1(x) #输入x:(1, 5, 10, 12) 输出:(1, 6, 8, 10) 
        x=F.relu(x)     #输入x:(1, 6, 8, 10)  输出:(1, 6, 8, 10)
        x=self.pool(x)  #输入x:(1, 6, 8, 10)  输出:(1, 6, 4, 5)
        x=self.conv2(x) #输入x:(1, 6, 4, 5)  输出:(1, 5, 3, 4)
        x=self.pool(x)  #输入x:(1, 5, 3, 4)  输出:(1, 5, 1, 2)
        x=x.view(1,-1,5*1*2) #输入x:(1, 5, 1, 2)  输出:(1, 1, 7)
        x=self.fc1(x)
        return x
    
def test_in_out(cnn):
    '''简单测试模型输入输出大小'''
    cnn=CNN()
    x= torch.randn(1,5,10,12)
    fea=cnn(x)
    print(x.size(),fea.size())

def print_param(cnn):
    '''
    打印模型相关参数
    '''
    opt=optim.SGD(cnn.parameters(),lr=0.1,momentum=0.9)

    #打印模型的状态字典
    for param_tensor in cnn.state_dict():
        print("模型字典:",param_tensor,'\t',cnn.state_dict()[param_tensor].size())

    #优化器的词典状态
    for var_name in opt.state_dict():
        print("优化器词典:",var_name,'\t',opt.state_dict()[var_name])

def save_load(model,model_path):
    '''
    保存加载模型
    方式1:当保存好模型用来推断的时候,只需要保存模型学习到的参数,使用 torch.save() 函数来保 
    存模型 state_dict ,它会给模型恢复提供 最大的灵活性,这就是为什么要推荐它来保存的原因。

    在 PyTorch 中最常见的模型保存使‘.pt’或者是‘.pth’作为模型文件扩展名。
    '''
    torch.save(cnn.state_dict(),model_path)
    print_param(cnn)
    cnn2.load_state_dict(torch.load(model_path))
    print_param(cnn2)
    return cnn

cnn=CNN()
model_path='model_path/cnn.pt'
test_in_out(cnn)
save_load(cnn,model_path)

CNN相关网址:

https://zhuanlan.zhihu.com/p/29119239(CNN尺寸计算)

https://blog.csdn.net/lrglgy/article/details/88764906(CNN优缺点)

看到的模型保存是以CNN为基础的,故对CNN的尺度变换及优缺点做一个简单的介绍

http://pytorch123.com/ThirdSection/SaveModel/(保存模型)

猜你喜欢

转载自blog.csdn.net/u013069552/article/details/112850972