当我们使用autograd实现深度学习模型时,所实现的模型的抽象程度较低,如果用来实现深度学习模型,则我们需要编写的代码量极大,所以pytorch提供了torch.nn模块,是专门为深度学习设计的模块。
参考文章 深度学习框架——pytorch入门与实践,陈云
nn.Module
nn.Module是nn模块中的核心结构,它是一个抽象的概念,即可以表示神经网络中的某一层,也可以表示一个包含多个层的神经网络。在实际使用中,最常见的做法是继承nn.Module,来编写自己的网络层。
也就是说,nn.model是所有网络(net)层的父类,我们自己如果要实现层的话,需要继承该类。
下面,我们先用nn.Module实现全连接层,也就是输出y和输入x满足y=wx+b,w和b是可学习的参数。
import torch
from torch import nn
from torch.autograd import Variable
class Linear(nn.Module): #继承nn.Module
def __init__(self,in_features,out_features):
super(Linear, self).__init__()
self.w = nn.Parameter(torch.randn(in_features,out_features))
self.b = nn.Parameter(torch.randn((out_features)))
def forward(self, x):
x = x.mm(self.w)
return x+self.b.expand_as(x)
layer = Linear(4,3) #linear中w和b中用到的维度
input = Variable(torch.randn(2,4))
output = layer(input)
print(output)
for name ,parameter in layer.named_parameters():
print(name,parameter)
#### x:2*4 w:4*3 b:2*3
(1)这里,无需写反向传播,前向传播forward是对variable操作,nn.module能够利用autograd自动实现反向传播。
(2)使用时,可以直观的将layer理解为数学中的函数,等价于layer.call(input),在call函数中,主要调用forward函数,所以在实际使用中尽量使用layer(x)而不是layer.forward(x)。
(3)Module中的学习参数能通过named_parameters()返回迭代器,使其根据有辨识度,如下:
tensor([[ 4.9175, 2.3497, -2.6925],
[ 1.1180, 3.9969, 1.6693]], grad_fn=<AddBackward0>)
w Parameter containing:
tensor([[ 0.2551, -0.7882, -0.3602],
[ 0.8282, -0.8747, -1.5308],
[ 1.6235, 0.0266, -0.9119],
[ 2.1582, 0.2946, 0.2217]], requires_grad=True)
b Parameter containing:
tensor([-1.4613, 2.7254, 0.6014], requires_grad=True)
实现多层感知机:
import torch
from torch import nn
from torch.autograd import Variable
class Linear(nn.Module): #继承nn.Module
def __init__(self,in_features,out_features):
super(Linear, self).__init__()
self.w = nn.Parameter(torch.randn(in_features,out_features))
self.b = nn.Parameter(torch.randn((out_features)))
def forward(self, x):
x = x.mm(self.w)
return x+self.b.expand_as(x)
class Preceptron(nn.Module): #继承nn.Module
def __init__(self,in_features,hidden_features,out_features):
nn.Module.__init__(self)
self.layer1 = Linear(in_features,hidden_features)
self.layer2 = Linear(hidden_features,out_features)
def forward(self, x):
x = self.layer1(x)
x=torch.sigmoid(x)
return self.layer2
preceptron = Preceptron(3,4,1)
for name,param in preceptron.named_parameters():
print(name,param.size())
(1)构造函数__init__中,可利用前面自定义的Linear层(module),作为当前module对象的一个子module,它的可学习参数,也会成为当前module的可学习参数。
关于nn.Parameters
self.w = nn.Parameter(torch.randn(in_features,out_features))
参考博客:PyTorch里面的torch.nn.Parameter()
首先可以将这个函数理解为类型转换函数,将一个不可训练的tensor转换为可以训练的parameters,所以在参数训练的时候可以优化。转换后这个self.w变成了模型的一部分,成为了模型中根据训练可以改动的参数。
使用这个函数的目的是让某些变量在学习过程中达到最优值。
w被封装为一个parameter,Parameter是一种特殊的Variable,默认需要求导,即(requires_grad = True)