【Pytorch神经网络理论篇】 05 Module类的使用方法+参数Parameters类+定义训练模型的步骤与方法

本文涉及的产品
模型训练 PAI-DLC,100CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
交互式建模 PAI-DSW,每月250计算时 3个月
简介: 通过指定名称的方式对该层的权重进行快速提取

同学你好!本文章于2021年末编写,获得广泛的好评!


故在2022年末对本系列进行填充与更新,欢迎大家订阅最新的专栏,获取基于Pytorch1.10版本的理论代码(2023版)实现,


Pytorch深度学习·理论篇(2023版)目录地址为:


CSDN独家 | 全网首发 | Pytorch深度学习·理论篇(2023版)目录


本专栏将通过系统的深度学习实例,从可解释性的角度对深度学习的原理进行讲解与分析,通过将深度学习知识与Pytorch的高效结合,帮助各位新入门的读者理解深度学习各个模板之间的关系,这些均是在Pytorch上实现的,可以有效的结合当前各位研究生的研究方向,设计人工智能的各个领域,是经过一年时间打磨的精品专栏!

https://v9999.blog.csdn.net/article/details/127587345


欢迎大家订阅(2023版)理论篇

以下为2021版原文~~~~

73ef90afdd0849519538ca2679ac3d88.png



1 Module类的使用方法


1.1 Module类的add_module()方法


1.1.1 概述


add_module():将XX层插入到模型结构中


1.1.2 add_module()----LogicNet_fun.py(第1部分)


import torch.nn as nn
import torch
import numpy as np
import matplotlib.pyplot as plt
class LogicNet(nn.Module):
    def __init__(self,inputdim,hiddendim,outputdim):
        super(LogicNet, self).__init__()
        ### 方法①
        self.Linear1 = nn.Linear(inputdim,hiddendim)
        self.Linear2 = nn.Linear(hiddendim,outputdim)
        ### 方法②
        self.add_module("Linear1",nn.Linear(inputdim,hiddendim))
        self.add_module("Linear2",nn.Linear(hiddendim,outputdim))
        self.criterion = nn.CrossEntropyLoss()
    def forward(self,x):
        x = self.Linear1(x)
model = LogicNet(inputdim=2,hiddendim=3,outputdim=2)
optimizer = torch.optim.Adam(model.parameters(),lr=0.01)


1.2 Module类的children()方法


1.2.1 children()概述


children()方法获取模型中的各层函数


1.2.2 children()代码实现----LogicNet_fun.py(第2部分)


### Module类的children()方法===》获取模型中的各层函数
for sub_module in model.children():
    print(sub_module)
    # 输出 Linear(in_features=2, out_features=3, bias=True)
    #     Linear(in_features=3, out_features=2, bias=True)
    #     CrossEntropyLoss()


1.3 Module类的named_children()方法


1.3.1named_children()概述


named_children()获取模型中的各层名字与结构信息


1.3.2 named_children()代码实现----LogicNet_fun.py(第3部分)


### Module类的named_children()===>获取模型中的各层名字与结构信息
for name,module in model.named_children():
    print(name,"is:",module)
    # 输出 Linear1 is: Linear(in_features=2, out_features=3, bias=True)
    #     Linear2 is: Linear(in_features=3, out_features=2, bias=True)
    #     criterion is: CrossEntropyLoss()


1.4 Module类的modules()方法


1.4.1 modules()概述


modules()获取整个网络的结构信息


1.4.2 modules()()代码实现----LogicNet_fun.py(第4部分)


### Module类的modules()===>获取整个网络的结构信息
for module in model.modules():
    print(module)
    # 输出 LogicNet(
    #               (Linear1): Linear(in_features=2, out_features=3, bias=True)
    #               (Linear2): Linear(in_features=3, out_features=2, bias=True)
    #               (criterion): CrossEntropyLoss()
    # )
    model.eval()
    # 输出 Linear(in_features=2, out_features=3, bias=True)
    #     Linear(in_features=3, out_features=2, bias=True)
    #     CrossEntropyLoss()


2 模型中的参数Parameters类


2.1 概述


2.1.2 模型与参数的关系


训练过程中,模型通过公式的计算结果与目标值进行对比,通过调整参数来实现误差的最小化。经过多次调整后的参数,可以使得整个模型的结果高度接近于目标值,进而得到有效的模型。


2.1.2 Parameter参数的属性


Parameters是Variable类的子类,但是存在以下两点不同


①将Parameter参数赋值给Module的属性时候,会将其自动加到Module参数列表中


②将Variable变量赋值给Module的属性时候,不会将其加到Module参数列表中


2.2模型添加参数


2.2.1 register_parameter(name,param) 为模型添加parameter参数


class Example(nn.Module):
    def __init__(self):
        super(Example, self).__init__()
        print('看看我们的模型有哪些parameter:\t', self._parameters, end='\n')
        # 输出 mymodel = Example()
        # '''
        # 看看我们的模型有哪些parameter:   OrderedDict()
        self.W1_params = nn.Parameter(torch.rand(2,3))
        print('增加W1后看看:',self._parameters, end='\n')
        # 增加W1后看看: OrderedDict([('W1_params', Parameter containing:
        # tensor([[0.0479, 0.9264, 0.1193],
        #         [0.5004, 0.7336, 0.6464]], requires_grad=True))])
        self.register_parameter('W2_params' , nn.Parameter(torch.rand(2,3)))
        print('增加W2后看看:',self._parameters, end='\n')
        # 增加W2后看看: OrderedDict([('W1_params', Parameter containing:
        # tensor([[0.0479, 0.9264, 0.1193],
        #         [0.5004, 0.7336, 0.6464]], requires_grad=True)), ('W2_params',         Parameter containing:
        # tensor([[0.1028, 0.2370, 0.8500],
        #         [0.6116, 0.0463, 0.4229]], requires_grad=True))])
        # '''
    def forward(self, x):
        return x


2.2.2 register_buffer(name,param) 增加状态参数


代码:


import torch 
import torch.nn as nn
torch.manual_seed(seed=20200910)
class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.conv1=torch.nn.Sequential(  # 输入torch.Size([64, 1, 28, 28])
                torch.nn.Conv2d(1,64,kernel_size=3,stride=1,padding=1),
                torch.nn.ReLU(),  # 输出torch.Size([64, 64, 28, 28])
        )
        self.attribute_buffer_in = torch.randn(3,5)
        register_buffer_in_temp = torch.randn(4,6)
        self.register_buffer('register_buffer_in', register_buffer_in_temp)
    def forward(self,x): 
        pass
print('cuda(GPU)是否可用:',torch.cuda.is_available())
print('torch的版本:',torch.__version__)
model = Model() #.cuda()
print('初始化之后模型修改之前'.center(100,"-"))
print('调用named_buffers()'.center(100,"-"))
for name, buf in model.named_buffers():
    print(name,'-->',buf.shape)
print('调用named_parameters()'.center(100,"-"))
for name, param in model.named_parameters():
    print(name,'-->',param.shape)
print('调用buffers()'.center(100,"-"))
for buf in model.buffers():
    print(buf.shape)
print('调用parameters()'.center(100,"-"))
for param in model.parameters():
    print(param.shape)
print('调用state_dict()'.center(100,"-"))
for k, v in model.state_dict().items():
    print(k, '-->', v.shape)
model.attribute_buffer_out = torch.randn(10,10)
register_buffer_out_temp = torch.randn(15,15)
model.register_buffer('register_buffer_out', register_buffer_out_temp)
print('模型初始化以及修改之后'.center(100,"-"))
print('调用named_buffers()'.center(100,"-"))
for name, buf in model.named_buffers():
    print(name,'-->',buf.shape)
print('调用named_parameters()'.center(100,"-"))
for name, param in model.named_parameters():
    print(name,'-->',param.shape)
print('调用buffers()'.center(100,"-"))
for buf in model.buffers():
    print(buf.shape)
print('调用parameters()'.center(100,"-"))
for param in model.parameters():
    print(param.shape)
print('调用state_dict()'.center(100,"-"))
for k, v in model.state_dict().items():
    print(k, '-->', v.shape)


输出结果:


cuda(GPU)是否可用: True
torch的版本: 1.10.0+cu113
--------------------------------------------初始化之后模型修改之前---------------------------------------------
-----------------------------------------调用named_buffers()------------------------------------------
register_buffer_in --> torch.Size([4, 6])
----------------------------------------调用named_parameters()----------------------------------------
conv1.0.weight --> torch.Size([64, 1, 3, 3])
conv1.0.bias --> torch.Size([64])
--------------------------------------------调用buffers()---------------------------------------------
torch.Size([4, 6])
-------------------------------------------调用parameters()-------------------------------------------
torch.Size([64, 1, 3, 3])
torch.Size([64])
-------------------------------------------调用state_dict()-------------------------------------------
register_buffer_in --> torch.Size([4, 6])
conv1.0.weight --> torch.Size([64, 1, 3, 3])
conv1.0.bias --> torch.Size([64])
--------------------------------------------模型初始化以及修改之后---------------------------------------------
-----------------------------------------调用named_buffers()------------------------------------------
register_buffer_in --> torch.Size([4, 6])
register_buffer_out --> torch.Size([15, 15])
----------------------------------------调用named_parameters()----------------------------------------
conv1.0.weight --> torch.Size([64, 1, 3, 3])
conv1.0.bias --> torch.Size([64])
--------------------------------------------调用buffers()---------------------------------------------
torch.Size([4, 6])
torch.Size([15, 15])
-------------------------------------------调用parameters()-------------------------------------------
torch.Size([64, 1, 3, 3])
torch.Size([64])
-------------------------------------------调用state_dict()-------------------------------------------
register_buffer_in --> torch.Size([4, 6])
register_buffer_out --> torch.Size([15, 15])
conv1.0.weight --> torch.Size([64, 1, 3, 3])
conv1.0.bias --> torch.Size([64])


2.2.3 对比


缓冲buffer和参数Parameter的区别是前者不需要训练优化,而后者需要训练优化.在创建方法上也有区别,前者必须要将一个张量使用方法register_buffer()来登记注册,后者比较灵活,可以直接赋值给模块的属性,也可以使用方法register_parameter()来登记注册.


3 从模型中获取参数


3.1 使用parameters()方法获取模型的Parameter参数


3.1.1 parameters()方法获取模型的Parameter参数的代码----LogicNet_fun.py(第5部分)


### 使用parameters()方法获取模型的Parameter参数
for param in model.parameters():
    print(type(param.data),param.size())
    # 输出 <class 'torch.Tensor'> torch.Size([3, 2])
    #     <class 'torch.Tensor'> torch.Size([3])
    #     <class 'torch.Tensor'> torch.Size([2, 3])
    #     <class 'torch.Tensor'> torch.Size([2])


3.2 使用named_parameters()获取模型中的参数和参数名字


3.2.1 使用named_parameters()获取模型中的参数和参数名字----LogicNet_fun.py(第6部分)


### 使用named_parameters()获取模型中的参数和参数名字
for name, param in model.named_parameters():
    print(type(param.data),param.size(),name)
    # 输出 <class 'torch.Tensor'> torch.Size([3, 2]) Linear1.weight
    #     <class 'torch.Tensor'> torch.Size([3]) Linear1.bias
    #     <class 'torch.Tensor'> torch.Size([2, 3]) Linear2.weight
    #     <class 'torch.Tensor'> torch.Size([2]) Linear2.bias


3.3 state_dict()获取模型的全部参数


3.3.1 state_dict()概述


state_dict()可以将模型中的Parameter和buffer参数取出,但不可取出Variable变量


3.3.2 tate_dict()代码实现


import torch
from torch.autograd import Variable
import torch.nn as nn
class ModelPar(nn.Module):
    def __init__(self):
        super(ModelPar, self).__init__()
        self.Line1 = nn.Linear(1,2) # 定义全连接层
        self.var1 = Variable(torch.rand([1])) # 定义Variable变量
        self.par = nn.Parameter(torch.rand([1])) # 定义Parameter变量
        self.register_buffer("buffer",torch.randn([2,3])) # 定义buffer变量
model = ModelPar()
for par in model.state_dict():
    print(par,':',model.state_dict()[par])
    # 输出 par : tensor([0.0285])
    #     buffer : tensor([[-0.7736,  0.7613,  0.5444],[ 1.0695,  0.7132, -0.3575]])
    #     Line1.weight : tensor([[0.7708],[0.6926]])
    #     Line1.bias : tensor([-0.0628, -0.6818])


3.4 为模型中的参数指定名称,并查看权重


即:通过指定名称的方式对该层的权重进行快速提取


3.4.1 代码实现


import torch
import torch.nn as nn
from collections import  OrderedDict
model = nn.Sequential(
    OrderedDict(
        [
            ('conv1',nn.Conv2d(1,20,5)),
            ('rule1',nn.ReLU()),
            ('conv2',nn.Conv2d(20,64,5)),
            ('relu2',nn.ReLU())
        ]
    )
)
print(model)
# 输出 Sequential(
#       (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
#       (rule1): ReLU()
#       (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
#       (relu2): ReLU()
#     )
params = model.state_dict()
print(params['conv1.weight'])
print(params['conv1.bias'])


4 保存与载入模型


4.1 保存模型+载入模型+将模型载入指定的硬件设备


4.1.1 代码实现 ----LogicNet_fun.py(第7部分)


### 保存模型
torch.save(model.state_dict(),'./model.path')
### 载入模型
model.load_state_dict(torch.load('./model.path'))
### 将模型载入到指定的硬件设备中===>该方法并不常用
### 为实现细粒度控制 通常将其分解为  1、将模型载入内存。2、使用模型的to()方法,将模型复制到指定的设备中
model.load_state_dict(torch.load('./model.path',map_location={'cuda:1','cuda:0'}))


5 模型结构中的钩子函数


5.1 正向钩子函数概述


5.1.1 模型正向结构中的钩子


模型正向结构中的钩子函数定义:


register_forward_hook(hook)
hook(module,input,output) #不可修改input和output的数值,返回一个句柄
#调用handle的remove()方法可以将hook从module中去除


在module上注册一个forward_hook,使得每次调用forward()计算输出的时候,这个hook函数就会被调用。


5.1.2 正向结构中的钩子函数的代码实现


import torch
from torch import nn
from torch.autograd import  Variable
def for_hook(module,input,output): # 定义钩子函数
    print("模型:",module)
    for val in input:
        print("输入:",val)
    for out_val in output :
        print("输出:",out_val)
class Model(nn.Module): #定义模型
    def __init__(self):
        super(Model, self).__init__()
    def forward(self,x):
        return x+1
model = Model() #实例化模型
x = Variable(torch.FloatTensor([1]),requires_grad=True)
handle = model.register_forward_hook(for_hook) # 注册钩子
print("模型结果",model(x)) # 运行模型
# 输出 模型: Model()
#     输入: tensor([1.], requires_grad=True)
#     输出: tensor(2., grad_fn=<UnbindBackward0>)
#     模型结果 tensor([2.], grad_fn=<AddBackward0>)
###删除钩子
handle.remove()
print("模型结果",model(x)) # 运行模型
# 输出 模型结果 tensor([2.], grad_fn=<AddBackward0>)


5.2 反向钩子函数概述


5.2.1 反向结构中的钩子函数


模型反向结构中的钩子函数定义:


register_backward_hook(hook)
### 在module上注册一个backward_hook,每次计算module的input的梯度时,这个hook就会被调用
hook(module,grad_input,grad_output) #不可修改grad_input和grad_outpu的数值,返回一个句柄
# 但可以选择性的返回关于输入的梯度,返回的梯度会在后续的计算中替换grad_input
#多个输入输出时,grad_input,grad_output会是个元组
#调用handle的remove()方法可以将hook从module中去除


在module上注册一个backward_hook,使得每次计算module的input的梯度时,调用hook()


6 LogicNet_fun.py汇总


import torch.nn as nn
import torch
class LogicNet(nn.Module):
    def __init__(self,inputdim,hiddendim,outputdim):
        super(LogicNet, self).__init__()
        ### 方法①
        self.Linear1 = nn.Linear(inputdim,hiddendim)
        self.Linear2 = nn.Linear(hiddendim,outputdim)
        ### 方法②
        self.add_module("Linear1",nn.Linear(inputdim,hiddendim))
        self.add_module("Linear2",nn.Linear(hiddendim,outputdim))
        self.criterion = nn.CrossEntropyLoss()
    def forward(self,x):
        x = self.Linear1(x)
model = LogicNet(inputdim=2,hiddendim=3,outputdim=2)
optimizer = torch.optim.Adam(model.parameters(),lr=0.01)
### Module类的children()方法===》获取模型中的各层函数
for sub_module in model.children():
    print(sub_module)
    # 输出 Linear(in_features=2, out_features=3, bias=True)
    #     Linear(in_features=3, out_features=2, bias=True)
    #     CrossEntropyLoss()
### Module类的named_children()===>获取模型中的各层名字与结构信息
for name,module in model.named_children():
    print(name,"is:",module)
    # 输出 Linear1 is: Linear(in_features=2, out_features=3, bias=True)
    #     Linear2 is: Linear(in_features=3, out_features=2, bias=True)
    #     criterion is: CrossEntropyLoss()
### Module类的modules()===>获取整个网络的结构信息
for module in model.modules():
    print(module)
    # 输出 LogicNet(
    #               (Linear1): Linear(in_features=2, out_features=3, bias=True)
    #               (Linear2): Linear(in_features=3, out_features=2, bias=True)
    #               (criterion): CrossEntropyLoss()
    # )
    model.eval()
    # 输出 Linear(in_features=2, out_features=3, bias=True)
    #     Linear(in_features=3, out_features=2, bias=True)
    #     CrossEntropyLoss()
### 使用parameters()方法获取模型的Parameter参数
for param in model.parameters():
    print(type(param.data),param.size())
    # 输出 <class 'torch.Tensor'> torch.Size([3, 2])
    #     <class 'torch.Tensor'> torch.Size([3])
    #     <class 'torch.Tensor'> torch.Size([2, 3])
    #     <class 'torch.Tensor'> torch.Size([2])
### 使用named_parameters()获取模型中的参数和参数名字
for name, param in model.named_parameters():
    print(type(param.data),param.size(),name)
    # 输出 <class 'torch.Tensor'> torch.Size([3, 2]) Linear1.weight
    #     <class 'torch.Tensor'> torch.Size([3]) Linear1.bias
    #     <class 'torch.Tensor'> torch.Size([2, 3]) Linear2.weight
    #     <class 'torch.Tensor'> torch.Size([2]) Linear2.bias
### 保存模型
torch.save(model.state_dict(),'./model.path')
### 载入模型
model.load_state_dict(torch.load('./model.path'))
### 将模型载入到指定的硬件设备中===>该方法并不常用
### 常将其分解为  1、将模型载入内存。2、使用模型的to()方法,将模型复制到指定的设备中
model.load_state_dict(torch.load('./model.path',map_location={'cuda:1','cuda:0'}))


目录
相关文章
|
2月前
|
算法 PyTorch 算法框架/工具
Pytorch学习笔记(九):Pytorch模型的FLOPs、模型参数量等信息输出(torchstat、thop、ptflops、torchsummary)
本文介绍了如何使用torchstat、thop、ptflops和torchsummary等工具来计算Pytorch模型的FLOPs、模型参数量等信息。
388 2
|
4天前
|
机器学习/深度学习 人工智能 PyTorch
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
本文将系统阐述DPO的工作原理、实现机制,以及其与传统RLHF和SFT方法的本质区别。
50 22
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
|
23天前
|
机器学习/深度学习 人工智能 PyTorch
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
本文探讨了Transformer模型中变长输入序列的优化策略,旨在解决深度学习中常见的计算效率问题。文章首先介绍了批处理变长输入的技术挑战,特别是填充方法导致的资源浪费。随后,提出了多种优化技术,包括动态填充、PyTorch NestedTensors、FlashAttention2和XFormers的memory_efficient_attention。这些技术通过减少冗余计算、优化内存管理和改进计算模式,显著提升了模型的性能。实验结果显示,使用FlashAttention2和无填充策略的组合可以将步骤时间减少至323毫秒,相比未优化版本提升了约2.5倍。
42 3
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
|
2月前
|
机器学习/深度学习 自然语言处理 监控
利用 PyTorch Lightning 搭建一个文本分类模型
利用 PyTorch Lightning 搭建一个文本分类模型
76 8
利用 PyTorch Lightning 搭建一个文本分类模型
|
2月前
|
机器学习/深度学习 自然语言处理 数据建模
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力
本文深入探讨了Transformer模型中的三种关键注意力机制:自注意力、交叉注意力和因果自注意力,这些机制是GPT-4、Llama等大型语言模型的核心。文章不仅讲解了理论概念,还通过Python和PyTorch从零开始实现这些机制,帮助读者深入理解其内部工作原理。自注意力机制通过整合上下文信息增强了输入嵌入,多头注意力则通过多个并行的注意力头捕捉不同类型的依赖关系。交叉注意力则允许模型在两个不同输入序列间传递信息,适用于机器翻译和图像描述等任务。因果自注意力确保模型在生成文本时仅考虑先前的上下文,适用于解码器风格的模型。通过本文的详细解析和代码实现,读者可以全面掌握这些机制的应用潜力。
131 3
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力
|
3月前
|
并行计算 PyTorch 算法框架/工具
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
文章介绍了如何在CUDA 12.1、CUDNN 8.9和PyTorch 2.3.1环境下实现自定义数据集的训练,包括环境配置、预览结果和核心步骤,以及遇到问题的解决方法和参考链接。
169 4
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
|
3月前
|
机器学习/深度学习 PyTorch 调度
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
在深度学习中,学习率作为关键超参数对模型收敛速度和性能至关重要。传统方法采用统一学习率,但研究表明为不同层设置差异化学习率能显著提升性能。本文探讨了这一策略的理论基础及PyTorch实现方法,包括模型定义、参数分组、优化器配置及训练流程。通过示例展示了如何为ResNet18设置不同层的学习率,并介绍了渐进式解冻和层适应学习率等高级技巧,帮助研究者更好地优化模型训练。
215 4
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
|
3月前
|
机器学习/深度学习 监控 PyTorch
PyTorch 模型调试与故障排除指南
在深度学习领域,PyTorch 成为开发和训练神经网络的主要框架之一。本文为 PyTorch 开发者提供全面的调试指南,涵盖从基础概念到高级技术的内容。目标读者包括初学者、中级开发者和高级工程师。本文探讨常见问题及解决方案,帮助读者理解 PyTorch 的核心概念、掌握调试策略、识别性能瓶颈,并通过实际案例获得实践经验。无论是在构建简单神经网络还是复杂模型,本文都将提供宝贵的洞察和实用技巧,帮助开发者更高效地开发和优化 PyTorch 模型。
56 3
PyTorch 模型调试与故障排除指南
|
2月前
|
存储 并行计算 PyTorch
探索PyTorch:模型的定义和保存方法
探索PyTorch:模型的定义和保存方法
|
9天前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
47 17

热门文章

最新文章