PyTorch基础:神经网络工具箱torch.nn(nn.Module类)

nn.Module类:

nn.Module是PyTorch提供的神经网络类,并在类中实现了网络各层的定义及前向计算与反向计算机制。在初始化中定义模型结构与参数,在函数forward()中编写网络前向过程即可。

  1. 一般把网络中具有可学习参数的层(如全连接层、卷积层等)放在构造函数__init__()中,当然我也可以吧不具有参数的层也放在里面;
  2. 一般把不具有可学习参数的层(如ReLU、dropout、BatchNormanation层)可放在构造函数中,也可不放在构造函数中,如果不放在构造函 数__init__里面,则在forward方法里面可以使用nn.functional来代替
  3. forward()方法是必须要重写的,它是实现模型的功能,实现各个层之间的连接关系的核心。

nn.Parameter:
torch.nn.Parameter是继承自torch.Tensor的子类,其主要作用是作为nn.Module中的可训练参数使用。它与torch.Tensor的区别就是nn.Parameter会自动被认为是module的可训练参数,即加入到parameter()这个迭代器中去;而module中非nn.Parameter()的普通tensor是不在parameter中的。注意到,nn.Parameter的对象的requires_grad属性的默认值是True,即是可被训练的,这与torch.Tensor对象的默认值相反。在nn.Module类中,Pytorch也是使用nn.Parameter来对每一个module的参数进行初始化的。
perception.py:

import torch
from torch import nn


#首先建立一个全连接的子module,继承nn.Module
class Linear(nn.Module):
    def __init__(self, in_dim, out_dim):  #初始化实例的值,这些值一般要供其他方法调用
       #首先找到Linear的父类(父类是类nn.Module);
       #然后把类Linear的对象self转换为类nn.Module的对象;
       #当需要继承父类构造函数中的内容,并且子类需要在父类的基础上补充时,使用super().__init__()方法
       #这里的补充则是参数in_dim、out_dim
        super(Linear, self).__init__()  
        #使用nn.Parameter来构造需要学习的参数
        self.w = nn.Parameter(torch.randn(in_dim, out_dim))    #全连接层中的w 维度(in_dim,out_dim)
        self.b = nn.Parameter(torch.randn(out_dim))            #全连接层中的b 维度out_dim

    #在forward中实现向前传播过程
    def forward(self, x):
        x = x.matmul(self.w)            #使用Tensor.matmul实现矩阵相乘 
        y = x + self.b.expand_as(x)     #使用Tensor.expand_as()来保证矩阵形状一致
        return y


#构建感知机类,继承nn.Module,并调用了Linear的子module
class Perception(nn.Module):
    def __init__(self, in_dim, hid_dim, out_dim):
        super(Perception, self).__init__()
        self.layer1 = Linear(in_dim, hid_dim)    #维度是(in_dim,hid_dim)   (2,3)
        self.layer2 = Linear(hid_dim, out_dim)   #维度是(hid_dim,out_dim)  (3,2)

    def forward(self, x):
        x = self.layer1(x)      
        y = torch.sigmoid(x)    #使用torch中的sigmoid作为激活函数
        y = self.layer2(y)
        y = torch.sigmoid(y)
        return y
        #in_dim=2、hid_dim=3、out_dim=2

终端:

>>> import torch
>>> from perception import Perception    #调用上述模块
>>> #实例化一个网络,并赋值全连接中的维数,最终输出二维代表了二分类
>>> perception = Perception(2,3,2)
>>> #可以看到perception中包含上述定义的layer1与layer2
>>> perception
Perception(
  (layer1): Linear()
  (layer2): Linear()
)
>>> #named_parameters()可以返回学习参数的迭代器,分别为参数名与参数值
>>> for name,parameter in perception.named_parameters():
...      print(name,parameter)
...
layer1.w Parameter containing:
tensor([[ 1.4509, -0.6111, -0.5108],
        [-0.3818, -2.0542,  0.3184]], requires_grad=True)
layer1.b Parameter containing:
tensor([-1.5274,  0.1767, -0.5369], requires_grad=True)
layer2.w Parameter containing:
tensor([[ 0.1622, -0.3417],
        [ 0.7079, -1.1008],
        [-1.4995,  0.1793]], requires_grad=True)
layer2.b Parameter containing:
tensor([-0.2565,  0.8857], requires_grad=True)
>>> #随机生成数据,注意这里的4代表了样本数为4,每个样本有两维
>>> data = torch.randn(4,2)
>>> data
tensor([[ 1.2537,  0.3754],
        [-0.6795,  1.6050],
        [-0.3249,  0.1087],
        [-2.7153, -0.6721]])
>>> #将输入数据传入perception,perception()相当于调用perception中的forward()函数
>>> output = perception(data)
>>> output
tensor([[0.3986, 0.6280],
        [0.2546, 0.7122],
        [0.3818, 0.5815],
        [0.3646, 0.4857]], grad_fn=<SigmoidBackward>)

  1. Perception输入参数(2,3,2)
  2. layer1 = linear(2,3) layer2 = linear(3,2)
  3. layer1:w = (2,3) b = 3 layer2:w = (3,2) b = 2
  4. forward输入参数(4,2)
  5. layer1:y = xw + b = (4,2) * (2,3) + (4,3) = (4,3) layer1 : y = layer2 :x
  6. layer2:y = xw + b = (4,3) * (3,2) + (4,2) = (4,2)
    括号内代表矩阵维数

forward()
forward()函数用来进行网络的前向传播,并需要传入相应的Tensor,例如在上面的代码中perception(data)即是直接调用了forward()。在具体底层实现中,perception.call(data)将类的实例perception变成了可调用对象perception(data),而在perception.call(data)中主要调用了forward()函数
nn.Module可以自动利用Autograd机制实现反向传播,不需要自己手动实现
多个Module嵌套
在Module的搭建时,可以嵌套包含子Moudle,上例的Perception中调用了Linear这个类。PyTorch也提供了绝大多数的网络层,如全连接、卷积网络中的卷积、池化等,并自动实现前向与反向传播
nn.Module与nn.functional库
在PyTorch中,还有一个库为nn.functional,同样也提供了很多网络层与函数功能,但与nn.Module不同的是,利用nn.functional定义的网络层不可自动学习参数,还需要使用nn.Parameter封装。nn.functional的设计初衷是对于一些不需要学习参数的层,如激活函数层、BN(Batch Normalization)层,可以使用nn.functional,这样这些层就不需要在nn.Module中定义了
nn.Sequential()模块
当模型中只是简单的前馈网络时,即上一层的输出直接作为下一层的输入,这是可以采用nn.Sequential()模块来快读搭建模型,而不必手动在forward()函数中一层一层地前向传播。因此,如果想快速搭建模型而不考虑中间过程的话,推荐使用nn.Sequential
在上面的例子中,Perception类中的layer1与layer2是直接传递的,因此该Perception类可以使用nn.Sequential()快速搭建
perception_sequential.py:

from torch import nn


class Perception(nn.Module):
    def __init__(self, in_dim, hid_dim, out_dim):
        super(Perception, self).__init__()
        #利用nn.Squential()快速搭建网络模块
        self.layer = nn.Sequential(
          nn.Linear(in_dim, hid_dim),
          nn.Sigmoid(),
          nn.Linear(hid_dim, out_dim),
          nn.Sigmoid()
                                  )

    def forward(self, x):
        y = self.layer(x)
        return y

终端

>>> import torch
>>> #从上述文件中引入Perception类
>>> from perception_sequential import Perception
>>> model = Perception(100,1000,10)    #构建类的实例,可以在尾部加上.cuda(),表明在CUDA上
>>> #打印model结构,会显示Sequential中每一层的具体参数配置
>>> model
Perception(
  (layer): Sequential(
    (0): Linear(in_features=100, out_features=1000, bias=True)
    (1): Sigmoid()
    (2): Linear(in_features=1000, out_features=10, bias=True)
    (3): Sigmoid()
  )
)
>>> input = torch.randn(100)    #可以在尾部加上.cuda(),表明在CUDA上
>>> output = model(input)    #将输入传入实例化的模型
>>> output.shape
torch.Size([10])

你可能感兴趣的:(PyTorch基础)