模型构造
1. 继承Module类来构造模型:
Module类是nn模块里提供的一个模型构造类,是所有神经网络模块的基类,可以继承它来定义我们想要的模型
继承了Module类后要选择性重载Module类的函数。
格式:
class Module_name(torch.nn.Module): 只有继承时类才有参数
def __init__(self,**kwargs): 声明带有模型参数的层
调用Module_name父类Module的构造函数来进行必要的初始化
这样在构造实例时还可以指定其他函数
super(Module_name,self).__init__(**kwargs)
定义模型的具体网络层以及激活函数,等待被其他函数调用
self.hidden=nn.Linear(784,256) 隐藏层
self.act=nn.ReLU() 激活函数
self.output=nn.Linear(256,10) 输出层
def forward(self,x): 定义模型前向计算,根据输入的样本数据x计算返回所需要的模型输出
a=self.act(self.hidden(x))
return self.output(a)
Module类是一个通用的部件,实际上,pytorch还实现了继承自Module的可以方便构建模型的类,如
Sequential、ModuleList、ModuleDict等类
Sequential类:适用于前向计算为简单的串联各个层的计算的情况
可以接收一个子模块的有序字典(ObjectDict)或者一系列模块作为参数来逐一添加Module实例
ModuleList接受一个子模块的列表作为输入,然后也可以类似Lsit那样进行append和extend操作
net=nn.ModuleLIst([nn.Linear(784,256),nn.ReLU()])
net.append(nn.Linear(256,10))
net[-1]
以上两者的区别:
1. ModuleList类仅仅是一个存储各种模块的列表,这些模块之间没有联系也没有顺序
(所以不需要保证相邻层的输入和输出维度匹配,比较灵活)
没有实现forward功能,需要自己实现。
所以无法执行net(X)这种语句。
2. Sequential内的模块需要按照顺序进行排列,要保证相邻层的输入输出大小相匹配,内部
forward功能也已经实现
ModuleList只是让网络定义前向传播时更灵活:
class MyModule(nn.Module):
def __init__(self):
super(MyModule,self).__init__()
self.linears=nn.ModuleList([nn.Linear(10,10) for i in range(10)])
def forward(self,x):
for i , l in enumerate(self.linears):
x=self.linears[i//2] (x)+ l(x)
return x
具体详看 李沐深度学习pytorch2020版本 模型构造篇
模型参数的访问、初始化和共享
在多个层之间共享同一份模型参数是什么意思
访问模型参数:
tensor.data
tensor.grad
初始化模型参数:
init.normal_(param,mean=,std=) 正态分布随机初始化参数
init.constant_(param,val=) 常数初始化参数
def init_weight_(tensor):
with torch.no_grad():
tensor.uniform_(a,b) tensor在-10和10之间随机取值填充
logic... 定义初始化逻辑
这里传进来的就是param,不需要return,和c语言中的(忘记是形参还是实参了)参数传递很像
for name,param in net[0].name_parameters():
if 'weight' in name:
init_weight_(param)