pytorch-torch.nn介绍
torch介绍
目录
torch.nn
Parameters
Parameter继承自torch.tesor。其和tensor的区别如下:
torch.tensor的requires_grad属性默认为False, 但是parameters的requires_grad属性默认为TrueParameter()可以理解为类型转换函数。将一个不可训练类型的tensor转化为可以训练的parameter。当定义网络的时候,使用Parameter赋值给module的参数的时候,该参数会自动的被加入到module的参数列表中(会自动的出现在parameters()的迭代器中),如果使用torch.tesor来定义网络参数的时候(requires_grad=True可以将tensor变成可训练的),则不会自动加入parameter有两个参数:nn.Parameter(data=None, requires_grad=True)data输入tensorrequires_grad = True: 默认为True
- 参数访问一般是通过如下,
torch.Mdule定义的两个方法和一个属性.parameters(): 返回一个包含模型所有参数的迭代器.named_parameters():返回包含参数名称和参数的迭代器._parameters:torch.Module属性,包含模型所有参数
import torch.nn.functional as F
import os
import numpy as np
import math
import random
from torch.utils import data
class LR1(nn.Module):
def __init__(self, dim):
super(LR1, self).__init__()
self.weight = torch.randn(dim, requires_grad=True)
self.bias = torch.randn(1, requires_grad=True)
def forward(self, X):
out = torch.matmul(X,self.weight) + self.bias
return 1 / (torch.exp(out)+1)
class LR2(nn.Module):
def __init__(self, dim):
super(LR2, self).__init__()
self.weight = torch.nn.Parameter(torch.randn(dim))
self.bias = torch.nn.Parameter(torch.randn(1))
def forward(self, X):
out = torch.matmul(X,self.weight) + self.bias
return 1 / (torch.exp(out)+1)
net1 = LR1(3)
net2 = LR2(3)
print(net1._parameters) # OrderedDict()
rint(net2._parameters) # 输出weight和bias
# 读取模型参数
for param in net1.parameters(): # 输出None
print('net1: param: ',param)
for param in net2.parameters():
print('net2:param:', param)
# 输出
net2:param: Parameter containing:
tensor([-0.1286, 1.6369, 1.8213], requires_grad=True)
net2:param: Parameter containing:
tensor([-0.8231], requires_grad=True)
# 输出参数名字和具体参数
for name,param in net2.named_parameters():
print('name={}'.format(name), param)
# 输出
name=weight Parameter containing:
tensor([-0.1286, 1.6369, 1.8213], requires_grad=True)
name=bias Parameter containing:
tensor([-0.8231], requires_grad=True)
Containers(容器)
nn.Module
任何一个layer、block、netword都是nn.Module的子类。该基类很多重要的方法和属性,分别如下所示。
1. modules相关方法和属性
属性:
self._modules: 返回值结构:Dict[str, Optional['Module']]- 字典类型,作用:用来保存定义网络的children模块。所谓children模块,是直接基于
nn.Modules定义的模块,只针对一阶派生,即儿子,不会对儿子再进行深度遍历
- 字典类型,作用:用来保存定义网络的children模块。所谓children模块,是直接基于
第一类方法:
- children(): 返回当前网络中,所有children模块的迭代器。只返回“儿子”一层
- modules():返回所有模块的迭代器。将整个模型的所有构成(包含layer,自定义层,block)等由浅入深的依次遍历出来。
- 作用:某一些行为需要获取模型的各个最小layer,比如初始化,模型加载参数等
- named_modules(): 也是对网络中定义的模块进行深度优先遍历,返回所有模块。其和
modules基本等价,不同的地方在于,其返回的是一个元祖,第一个是名称,第二个是对象。 - get_submodule(target):返回特定的模块,注意target是子模块的名字,如果没有命名,那么就从‘0’开始
4个函数源码如下:
def children(self) -> Iterator['Module']: #
"""Return an iterator over immediate children modules."""
for name, module in self.named_children():
yield module
def named_children(self) -> Iterator[Tuple[str, 'Module']]:
memo = set()
for name, module in self._modules.items(): # 从self._modules字典中获取layer和相对应的名字
if module is not None and module not in memo:
memo.add(module)
yield name, module
def modules(self) -> Iterator['Module']:
for _, module in self.named_modules(): # 调用的是named_modules()
yield module
def named_modules(self, memo: Optional[Set['Module']] = None, prefix: str = '', remove_duplicate: bool = True):
if memo is None:
memo = set()
if self not in memo:
if remove_duplicate:
memo.add(self)
yield prefix, self
for name, module in self._modules.items():
if module is None:
continue
submodule_prefix = prefix + ('.' if prefix else '') + name
yield from module.named_modules(memo, submodule_prefix, remove_duplicate) # 递归调用了
案例1: self._modules
net = nn.Sequential(nn.Linear(2,2),nn.Linear(2,1))
print(net._modules) # 1
print(net._modules['0']) # 2
# 1号输出
OrderedDict({'0': Linear(in_features=2, out_features=2, bias=True), '1': Linear(in_features=2, out_features=1, bias=True)})
# 2号输出
Linear(in_features=2, out_features=2, bias=True)
案例2. modules和named_modules的区别
print(net.get_submodule('1'))
# 输出:Linear(in_features=2, out_features=1, bias=True)
for idx,module in enumerate(net.modules()):
print(idx,'-->',module)
# 输出
0 --> Sequential(
(0): Linear(in_features=2, out_features=2, bias=True)
(1): Linear(in_features=2, out_features=1, bias=True)
)
1 --> Linear(in_features=2, out_features=2, bias=True)
2 --> Linear(in_features=2, out_features=1, bias=True)
for idx,module in enumerate(net.children()):
print(idx,'-->',module)
# 输出
Linear(in_features=2, out_features=2, bias=True)
0 --> Linear(in_features=2, out_features=2, bias=True)
1 --> Linear(in_features=2, out_features=1, bias=True)
第二类方法
- add_module(name, module): 增加模块。由如下源码可以看出,和 register_module完全等价。
def add_module(self, name: str, module: Optional['Module']) -> None:
..... # 其他源码没啥用,删除
self._modules[name] = module
def register_module(self, name: str, module: Optional['Module']) -> None:
r"""Alias for :func:`add_module`."""
self.add_module(name, module)
2. parameters相关方法和属性
属性
._parameters功能:输出模型的所有注册的参数,没有注册的是无法输出的- 其是一个
OrderDict
- 其是一个
方法
.parameters()功能: 输出模型注册的所有参数.get_parameter(target: str)功能:根据参数的名字,调用具体的参数- ex
print(net2.get_parameter('bias'))
- ex
.named_parameters()功能:输出参数名字和具体参数.register_parameter(name, param)功能:将参数添加到模型的参数属性中去(加入到._parameters)- 注意:参数param 必须是Parameter类型
def register_parameter(self, name: str, param: Optional[Parameter]) -> None:
self._parameters[name] = param # 核心就下面一句话
案例:
class LR1(nn.Module):
def __init__(self, dim):
super(LR1, self).__init__()
self.weight = torch.randn(dim, requires_grad=True)
self.bias = torch.randn(1, requires_grad=True)
def forward(self, X):
out = torch.matmul(X,self.weight) + self.bias
return 1 / (torch.exp(out)+1)
class LR2(nn.Module):
def __init__(self, dim):
super(LR2, self).__init__()
self.weight = torch.nn.Parameter(torch.randn(dim))
self.bias = torch.nn.Parameter(torch.randn(1))
def forward(self, X):
out = torch.matmul(X,self.weight) + self.bias
return 1 / (torch.exp(out)+1)
net1 = LR1(3)
net2 = LR2(3)
print(net1._parameters) # OrderedDict()
print(net2._parameters) # 输出weight和bias
for param in net2.parameters():
print('net2:param:', param)
print(net2.get_parameter('bias'))
# 输出
Parameter containing:
tensor([-1.2585], requires_grad=True)
print(type(net2._parameters)) #输出:<class 'collections.OrderedDict'>
案例:注册参数
class LR1(nn.Module):
def __init__(self, dim):
super(LR1, self).__init__()
self.weight = torch.randn(dim, requires_grad=True)
self.bias = torch.randn(1, requires_grad=True)
for i,param in enumerate([self.weight, self.bias]):
# self._parameters['{}'.format(i)] = param
self.register_parameter(name='{}'.format(i), param=nn.Parameter(param))
def forward(self, X):
out = torch.matmul(X,self.weight) + self.bias
return 1 / (torch.exp(out)+1)
print(net1._parameters)
# 输出
OrderedDict({'0': Parameter containing:
tensor([ 0.5769, -0.5915, 1.6764], requires_grad=True), '1': Parameter containing:
tensor([1.1855], requires_grad=True)})
3. buffer模型缓存相关方法和属性
模型中的参数分成两类:
- 一种是反向传播,需要被更新的,称之为
parameter - 一种是反向传播,不需要被更新的,称之为buffer
如上两类变量,都会保存在模型的state_dict() 的返回值中。(其返回值是OrderDict)
buffers模型缓存主要是将一些不训练的张量保存进state_dict中,如果普通张量没有使用set_buffers()接口进行注册,那么我们保存加载就不会有这个变量。
属性:
.buffers(): 输出模型所有注册的buffer- 结果也是
OrderDict类型
- 结果也是
方法:
- get_buffer(target):获取特定的buffer对象,target是bffer的名字
- named_buffers()::输出buffer的名字和具体数值
register_buffer(name, tensor, persistent=True)# 将一些buffer进行注册
class LR1(nn.Module):
def __init__(self, dim):
super(LR1, self).__init__()
self.weight = nn.Parameter(torch.randn(dim, requires_grad=True))
self.bias = torch.randn(1, requires_grad=True) # 其不会更新
self.bias2 = torch.randn(1, requires_grad=True)
self.register_buffer('b', self.bias)
def forward(self, X):
out = torch.matmul(X,self.weight) + self.bias
return 1 / (torch.exp(out)+1)
net1 = LR1(3)
print(net1._parameters) # OrderedDict({'weight': Parameter containing: tensor([-0.9199, -0.5809, -1.4698], requires_grad=True)})
print(net1._buffers) # 输出 OrderedDict({'b': tensor([-1.7809], requires_grad=True)}
print(net1.state_dict()) # 输出不带self.bias2 因为其既没有加入到self._parameters中,又没有加入到self._buffer中
# OrderedDict({'weight': tensor([-0.9199, -0.5809, -1.4698]), 'b': tensor([0.2081])})
4. apply
函数体定义在基类torch.Module中,递归的调用slef.children()将函数f应用于网络的子模块。其和pandas中的apply作用类似。
功能:递归的将函数f应用到网络的各个子模块。常用于参数初始化
def init_weight(m):
if type(m) == nn.Linear:
m.weight.data.fill_(1.0)
m.bias.data.fill_(0.0)
model = nn.Sequential(nn.Linear(2,2), nn.Linear(2,1))
model.apply(init_weight)
for param in model.parameters():
print(param)
# 输出
Parameter containing:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
Parameter containing:
tensor([0., 0.], requires_grad=True)
Parameter containing:
tensor([[1., 1.]], requires_grad=True)
Parameter containing:
eval()
forward
load_stat_dict(state_dict)
parameters()
返回一个包含模型所有参数的迭代器
register_buffer(name, tensor)
给模型添加一个persistent buffer。
使用场景:在一些场景中,我们需要保存一些模型参数,但是这些参数不是模型的优化
属性变量:training
apply函数: 将所有子模块传给函数f进行处理。
https://www.cnblogs.com/dan-baishucaizi/p/16082456.html#21-module

浙公网安备 33010602011771号