torch.nn是专门为神经网络设计的模块化接口。模块化。
# 引入torch.nn并指定别名,一般别名命名为nn
import torch.nn as nn
PyTorch中已经为我们准备好了现成的网络模型,只要继承nn.Module,并实现它的forward方法,PyTorch会根据autograd,自动实现backward函数,在forward函数中可使用任何tensor支持的函数,还可以使用if、for循环、print、log等Python语法,写法和标准的Python写法一致。
torch.nn只支持mini-batches,不支持一次只输入一个样本,即一次必须是一个batch。也就是说,就算我们输入一个样本,也要增加一维变成批。
可学习参数:
网络的可学习参数通过net.parameters()返回,返回值是一个可迭代对象,或者说列表,列表里面放的是参数对象Parameter,参数对象里面主要就包含了一个tensor。
net.named_parameters可同时返回可学习的参数及名称。这个就相当于返回的dict,可以方便的知道名字。
Net(
(fc1): Linear(in_features=2, out_features=4, bias=True)
)
('fc1.weight', Parameter containing:
tensor([[-0.5767, 0.1687],
[ 0.0383, -0.0288],
[ 0.1512, 0.3680],
[ 0.2099, -0.4599]], requires_grad=True))
('fc1.bias', Parameter containing:
tensor([-0.3643, -0.6344, 0.2378, 0.5576], requires_grad=True))
这是一个只有一个2*4 linear层的,可见线性层的参数分为了两部分,本身的参数和偏置参数, 偏置参数和输出层的数量相同,就是每个单元对应到一个参数。a = wx+b
比较奇怪的是,并没有明确的指明模型每层是什么样的,pytorch却知道了可学习参数是什么。它应该是通过类包含的属性来获取的,就是通过self.xxx = xxx 中给类指定的属性来知道了参数。
这里面有几个点要了解的
1、属性中创建的层的顺序必须和前向传播的顺序一样吗?这应该是因为反向时会按照层被调用的顺序计算梯度,所以创建顺序对反向传播梯度值计算没有影响。然后,根据梯度更新参数,是否受到参数顺序影响,这个不知道。不过按照pytorch这种架构,应该就是不会影响了,也就是说更新参数只会利用到改层参数和他的梯度,不会利用前后层的参数和梯度。由上,更新梯度时,可以和调用顺序不一样。
2、通过属性创建的层,和前向传播中用到的层,必须保持一致吗,也就是说创建的层都必须在前向传播中使用吗?或者没创建的层能在前向传播中使用吗?根据梯度更新的方式,如果没有被使用,那么改层的梯度不存在或者为0,不会对其参数产生影响。所以,应该是可以不是用的。然后没创建的层在前向传播中使用那是语法错误,不存在这种情况。所以这两个地方不比保持一致。
加载保存好的参数
para = torch.load(r’xxx.pth’))
myResnet.load_state_dict(para)
注意这里可以看到,参数是以字典形式保存的,其key就是参数名称,也就是代码里面的变量名称,如果变量名称改了,就会加载出错
优化器
在反向传播计算完所有参数的梯度后,还需要使用优化方法来更新网络的权重和参数。
在torch.optim中实现大多数的优化方法,例如RMSProp、Adam、SGD等,下面我们使用SGD做个简单的样例
小点,利用API,随机梯度SGD,使用这样简单几行代码就能实现了。
learning_rate = 0.01
for f in net.parameters():
f.data.sub_(f.grad.data * learning_rate)