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()
6LogicNet_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'}))
版权声明:本文为博主LiBiGor原创文章,版权归属原作者,如果侵权,请联系我们删除!
原文链接:https://blog.csdn.net/qq_39237205/article/details/123226991