【Pytorch神经网络理论篇】 05 Module类的使用方法+参数Parameters类+定义训练模型的步骤与方法
1 Module類(lèi)的使用方法
1.1 Module類(lèi)的add_module()方法
1.1.1 概述
add_module():將XX層插入到模型結(jié)構(gòu)中
1.1.2 add_module()----LogicNet_fun.py(第1部分)
import torch.nn as nn import torch import numpy as np import matplotlib.pyplot as pltclass 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類(lèi)的children()方法
1.2.1?children()概述
children()方法獲取模型中的各層函數(shù)1.2.2 children()代碼實(shí)現(xiàn)----LogicNet_fun.py(第2部分)
### Module類(lèi)的children()方法===》獲取模型中的各層函數(shù) 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類(lèi)的named_children()方法
1.3.1named_children()概述
named_children()獲取模型中的各層名字與結(jié)構(gòu)信息1.3.2?named_children()代碼實(shí)現(xiàn)----LogicNet_fun.py(第3部分)
### Module類(lèi)的named_children()===>獲取模型中的各層名字與結(jié)構(gòu)信息 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類(lèi)的modules()方法
1.4.1?modules()概述
modules()獲取整個(gè)網(wǎng)絡(luò)的結(jié)構(gòu)信息1.4.2?modules()()代碼實(shí)現(xiàn)----LogicNet_fun.py(第4部分)
### Module類(lèi)的modules()===>獲取整個(gè)網(wǎng)絡(luò)的結(jié)構(gòu)信息 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 模型中的參數(shù)Parameters類(lèi)
2.1 概述
2.1.2 模型與參數(shù)的關(guān)系
訓(xùn)練過(guò)程中,模型通過(guò)公式的計(jì)算結(jié)果與目標(biāo)值進(jìn)行對(duì)比,通過(guò)調(diào)整參數(shù)來(lái)實(shí)現(xiàn)誤差的最小化。經(jīng)過(guò)多次調(diào)整后的參數(shù),可以使得整個(gè)模型的結(jié)果高度接近于目標(biāo)值,進(jìn)而得到有效的模型。
2.1.2 Parameter參數(shù)的屬性
Parameters是Variable類(lèi)的子類(lèi),但是存在以下兩點(diǎn)不同
①將Parameter參數(shù)賦值給Module的屬性時(shí)候,會(huì)將其自動(dòng)加到Module參數(shù)列表中
②將Variable變量賦值給Module的屬性時(shí)候,不會(huì)將其加到Module參數(shù)列表中
2.2模型添加參數(shù)
2.2.1 register_parameter(name,param) 為模型添加parameter參數(shù)
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 x2.2.2 register_buffer(name,param) 增加狀態(tài)參數(shù)
代碼:
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): passprint('cuda(GPU)是否可用:',torch.cuda.is_available()) print('torch的版本:',torch.__version__) model = Model() #.cuda()print('初始化之后模型修改之前'.center(100,"-")) print('調(diào)用named_buffers()'.center(100,"-")) for name, buf in model.named_buffers():print(name,'-->',buf.shape)print('調(diào)用named_parameters()'.center(100,"-")) for name, param in model.named_parameters():print(name,'-->',param.shape)print('調(diào)用buffers()'.center(100,"-")) for buf in model.buffers():print(buf.shape)print('調(diào)用parameters()'.center(100,"-")) for param in model.parameters():print(param.shape)print('調(diào)用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('調(diào)用named_buffers()'.center(100,"-")) for name, buf in model.named_buffers():print(name,'-->',buf.shape)print('調(diào)用named_parameters()'.center(100,"-")) for name, param in model.named_parameters():print(name,'-->',param.shape)print('調(diào)用buffers()'.center(100,"-")) for buf in model.buffers():print(buf.shape)print('調(diào)用parameters()'.center(100,"-")) for param in model.parameters():print(param.shape)print('調(diào)用state_dict()'.center(100,"-")) for k, v in model.state_dict().items():print(k, '-->', v.shape)輸出結(jié)果:
cuda(GPU)是否可用: True torch的版本: 1.10.0+cu113 --------------------------------------------初始化之后模型修改之前--------------------------------------------- -----------------------------------------調(diào)用named_buffers()------------------------------------------ register_buffer_in --> torch.Size([4, 6]) ----------------------------------------調(diào)用named_parameters()---------------------------------------- conv1.0.weight --> torch.Size([64, 1, 3, 3]) conv1.0.bias --> torch.Size([64]) --------------------------------------------調(diào)用buffers()--------------------------------------------- torch.Size([4, 6]) -------------------------------------------調(diào)用parameters()------------------------------------------- torch.Size([64, 1, 3, 3]) torch.Size([64]) -------------------------------------------調(diào)用state_dict()------------------------------------------- register_buffer_in --> torch.Size([4, 6]) conv1.0.weight --> torch.Size([64, 1, 3, 3]) conv1.0.bias --> torch.Size([64]) --------------------------------------------模型初始化以及修改之后--------------------------------------------- -----------------------------------------調(diào)用named_buffers()------------------------------------------ register_buffer_in --> torch.Size([4, 6]) register_buffer_out --> torch.Size([15, 15]) ----------------------------------------調(diào)用named_parameters()---------------------------------------- conv1.0.weight --> torch.Size([64, 1, 3, 3]) conv1.0.bias --> torch.Size([64]) --------------------------------------------調(diào)用buffers()--------------------------------------------- torch.Size([4, 6]) torch.Size([15, 15]) -------------------------------------------調(diào)用parameters()------------------------------------------- torch.Size([64, 1, 3, 3]) torch.Size([64]) -------------------------------------------調(diào)用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 對(duì)比
緩沖buffer和參數(shù)Parameter的區(qū)別是前者不需要訓(xùn)練優(yōu)化,而后者需要訓(xùn)練優(yōu)化.在創(chuàng)建方法上也有區(qū)別,前者必須要將一個(gè)張量使用方法register_buffer()來(lái)登記注冊(cè),后者比較靈活,可以直接賦值給模塊的屬性,也可以使用方法register_parameter()來(lái)登記注冊(cè).
3 從模型中獲取參數(shù)
3.1 使用parameters()方法獲取模型的Parameter參數(shù)
3.1.1?parameters()方法獲取模型的Parameter參數(shù)的代碼----LogicNet_fun.py(第5部分)
### 使用parameters()方法獲取模型的Parameter參數(shù) 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()獲取模型中的參數(shù)和參數(shù)名字
3.2.1?使用named_parameters()獲取模型中的參數(shù)和參數(shù)名字----LogicNet_fun.py(第6部分)
### 使用named_parameters()獲取模型中的參數(shù)和參數(shù)名字 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.bias3.3 state_dict()獲取模型的全部參數(shù)
3.3.1?state_dict()概述
state_dict()可以將模型中的Parameter和buffer參數(shù)取出,但不可取出Variable變量
3.3.2?tate_dict()代碼實(shí)現(xiàn)
import torch from torch.autograd import Variable import torch.nn as nnclass 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 為模型中的參數(shù)指定名稱(chēng),并查看權(quán)重
即:通過(guò)指定名稱(chēng)的方式對(duì)該層的權(quán)重進(jìn)行快速提取
3.4.1 代碼實(shí)現(xiàn)
import torch import torch.nn as nn from collections import OrderedDictmodel = 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 保存模型+載入模型+將模型載入指定的硬件設(shè)備
4.1.1 代碼實(shí)現(xiàn) ----LogicNet_fun.py(第7部分)
### 保存模型 torch.save(model.state_dict(),'./model.path') ### 載入模型 model.load_state_dict(torch.load('./model.path')) ### 將模型載入到指定的硬件設(shè)備中===>該方法并不常用 ### 為實(shí)現(xiàn)細(xì)粒度控制 通常將其分解為 1、將模型載入內(nèi)存。2、使用模型的to()方法,將模型復(fù)制到指定的設(shè)備中 model.load_state_dict(torch.load('./model.path',map_location={'cuda:1','cuda:0'}))5 模型結(jié)構(gòu)中的鉤子函數(shù)
5.1 正向鉤子函數(shù)概述
5.1.1 模型正向結(jié)構(gòu)中的鉤子
模型正向結(jié)構(gòu)中的鉤子函數(shù)定義:
register_forward_hook(hook)hook(module,input,output) #不可修改input和output的數(shù)值,返回一個(gè)句柄 #調(diào)用handle的remove()方法可以將hook從module中去除在module上注冊(cè)一個(gè)forward_hook,使得每次調(diào)用forward()計(jì)算輸出的時(shí)候,這個(gè)hook函數(shù)就會(huì)被調(diào)用。
5.1.2 正向結(jié)構(gòu)中的鉤子函數(shù)的代碼實(shí)現(xiàn)
import torch from torch import nn from torch.autograd import Variabledef for_hook(module,input,output): # 定義鉤子函數(shù)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+1model = Model() #實(shí)例化模型 x = Variable(torch.FloatTensor([1]),requires_grad=True) handle = model.register_forward_hook(for_hook) # 注冊(cè)鉤子 print("模型結(jié)果",model(x)) # 運(yùn)行模型 # 輸出 模型: Model() # 輸入: tensor([1.], requires_grad=True) # 輸出: tensor(2., grad_fn=<UnbindBackward0>) # 模型結(jié)果 tensor([2.], grad_fn=<AddBackward0>)###刪除鉤子 handle.remove() print("模型結(jié)果",model(x)) # 運(yùn)行模型 # 輸出 模型結(jié)果 tensor([2.], grad_fn=<AddBackward0>)5.2?反向鉤子函數(shù)概述
5.2.1 反向結(jié)構(gòu)中的鉤子函數(shù)
模型反向結(jié)構(gòu)中的鉤子函數(shù)定義:
register_backward_hook(hook) ### 在module上注冊(cè)一個(gè)backward_hook,每次計(jì)算module的input的梯度時(shí),這個(gè)hook就會(huì)被調(diào)用hook(module,grad_input,grad_output) #不可修改grad_input和grad_outpu的數(shù)值,返回一個(gè)句柄 # 但可以選擇性的返回關(guān)于輸入的梯度,返回的梯度會(huì)在后續(xù)的計(jì)算中替換grad_input #多個(gè)輸入輸出時(shí),grad_input,grad_output會(huì)是個(gè)元組#調(diào)用handle的remove()方法可以將hook從module中去除在module上注冊(cè)一個(gè)backward_hook,使得每次計(jì)算module的input的梯度時(shí),調(diào)用hook()
6?LogicNet_fun.py匯總
import torch.nn as nn import torchclass 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類(lèi)的children()方法===》獲取模型中的各層函數(shù) 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類(lèi)的named_children()===>獲取模型中的各層名字與結(jié)構(gòu)信息 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類(lèi)的modules()===>獲取整個(gè)網(wǎng)絡(luò)的結(jié)構(gòu)信息 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參數(shù) 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()獲取模型中的參數(shù)和參數(shù)名字 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')) ### 將模型載入到指定的硬件設(shè)備中===>該方法并不常用 ### 常將其分解為 1、將模型載入內(nèi)存。2、使用模型的to()方法,將模型復(fù)制到指定的設(shè)備中 model.load_state_dict(torch.load('./model.path',map_location={'cuda:1','cuda:0'}))總結(jié)
以上是生活随笔為你收集整理的【Pytorch神经网络理论篇】 05 Module类的使用方法+参数Parameters类+定义训练模型的步骤与方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Pycharm使用matplotlib绘
- 下一篇: 数据结构链表之单链表的快慢指针——3