zoukankan      html  css  js  c++  java
  • 神经网络工具箱torch.nn -05

       torch.autograd库虽然实现了自动求导与梯度反向传播, 但如果我们要完成一个模型的训练, 仍需要手写参数的自动更新、 训练过程的控制等, 还是不够便利。 为此, PyTorch进一步提供了集成度更高的模块化接口torch.nn, 该接口构建于Autograd之上, 提供了网络模组、 优化器和初始化策略等一系列功能 。

    下面具体以一个由两个全连接层组成的感知机为例, 介绍如何使用nn.Module构造模块化的神经网络。 新建一个perception.py文件, 内容如
    下:

    perception.py

     1 import torch
     2 from torch import nn
     3 
     4 
     5 
     6 # 首先建立一个全连接的子module, 继承nn.Module
     7 class Linear(nn.Module):
     8     
     9     def __init__(self, in_dim, out_dim):
    10         super(Linear, self).__init__() # 调用nn.Module的构造函数
    11 
    12         # 使用nn.Parameter来构造需要学习的参数
    13         self.w = nn.Parameter(torch.randn(in_dim, out_dim))
    14         self.b = nn.Parameter(torch.randn(out_dim))
    15 
    16     def forward(self, x):
    17         x = x.matmul(self.w)        # 使用Tensor.matmul实现矩阵相乘
    18         y = x +self.b.expand_as(x)  # 使用Tensor.expand_as()来保证矩阵
    19 
    20         # 形状一致
    21         return y 
    22 
    23 # 构建感知机类, 继承nn.Module, 并调用了Linear的子module
    24 class Perception(nn.Module):
    25     def __init__(self, in_dim, hid_dim, out_dim):
    26         super(Perception, self).__init__()
    27         self.layer1 = Linear(in_dim, hid_dim)
    28         self.layer2 = Linear(hid_dim, out_dim)
    29 
    30     def forward(self, x):
    31         x = self.layer1(x)
    32         y = torch.sigmoid(x)
    33         
    34         y = self.layer2(y)
    35         y = torch.sigmoid(y)
    36 
    37         return y
    View Code

    同一目录下,调用perception.py 的测试文件:

    test.py

     1 import torch
     2 from perception import Perception
     3 
     4 # 实例化一个网络, 并赋值全连接中的维数, 最终输出二维代表了二分类
     5 p = Perception(2, 3, 2)
     6 # 可以看到perception中包含上述定义的layer1与layer2
     7 print(p)
     8 >> Perception(
     9   (layer1): Linear()
    10   (layer2): Linear()
    11 )
    12 
    13 # named_parameters()可以返回学习参数的迭代器, 分别为参数名与参数值
    14 for name, parameter in p.named_parameters():
    15     print(name, parameter)
    16 >> layer1.w Parameter containing:
    17     tensor([[ 1.2414,  0.9357, -0.6208],
    18             [ 0.4621,  1.0656,  0.2050]], requires_grad=True)
    19     layer1.b Parameter containing:
    20     tensor([-0.6094, -0.2722, -0.0099], requires_grad=True)
    21     layer2.w Parameter containing:
    22     tensor([[-2.8570,  0.8163],
    23             [-0.7686, -1.0082],
    24             [-0.9913,  0.1159]], requires_grad=True)
    25     layer2.b Parameter containing:
    26     tensor([ 1.7486, -0.9961], requires_grad=True)
    27 
    28 # 随机生成数据, 注意这里的4代表了样本数为4, 每个样本有两维
    29 data  = torch.randn(4, 2)
    30 print(data, data.size())
    31 >> tensor([[-0.8455, -0.7173],
    32         [ 0.9888, -1.4157],
    33         [-0.2249, -0.8835],
    34         [-0.1519, -0.7144]]) torch.Size([4, 2])
    35 
    36 # 将输入数据传入p, p()相当于调用perception中的forward()函数
    37 output = p(data)
    38 print(output)
    39 >> tensor([[0.6710, 0.2750],
    40         [0.4583, 0.2967],
    41         [0.6232, 0.2769],
    42         [0.5959, 0.2733]], grad_fn=<SigmoidBackward>)
    View Code

     可以看到, 利用nn.Module搭建神经网络简单易实现, 同时较为规范。 在实际使用时, 应注意如下5点。

    1nn.Parameter函数

     在类的__init__()中需要定义网络学习的参数, 在此使用nn.Parameter()函数定义了全连接中的ωb, 这是一种特殊的Tensor的构造方法, 默认需要求导, 即requires_gradTrue

    2forward()函数与反向传播

    forward()函数用来进行网络的前向传播, 并需要传入相应的Tensor, 例如上例的perception(data)即是直接调用了forward()。 在具体底层实现中, perception.__call__(data)将类的实例perception变成了可调用对象perception(data), 而在perception.__call__(data)中主要调用了forward()函数, 具体可参考官方代码。

    nn.Module可以自动利用Autograd机制实现反向传播, 不需要自己手动实现 。

    3. 多个Module的嵌套

    Module的搭建时, 可以嵌套包含子Module, 上例的Perception中调用了Linear这个类, 这样的代码分布可以使网络更加模块化, 提升代码的复用性。 在实际的应用中, PyTorch也提供了绝大多数的网络层,如全连接、 卷积网络中的卷积、 池化等, 并自动实现前向与反向传播。

     4nn.Modulenn.functional
          在PyTorch中, 还有一个库为nn.functional, 同样也提供了很多网络层与函数功能, 但与nn.Module不同的是, 利用nn.functional定义的网络层不可自动学习参数, 还需要使用nn.Parameter封装。 nn.functional的设计初衷是对于一些不需要学习参数的层, 如激活层、 BNBatchNormalization) 层, 可以使用nn.functional, 这样这些层就不需要在nn.Module中定义了。
         总体来看, 对于需要学习参数的层, 最好使用nn.Module, 对于无参数学习的层, 可以使用nn.functional, 当然这两者间并没有严格的好坏之分。

    5. nn.Sequential()模块
    当模型中只是简单的前馈网络时, 即上一层的输出直接作为下一层的输入, 这时可以采用nn.Sequential()模块来快速搭建模型, 而不必手动在forward()函数中一层一层地前向传播。 因此, 如果想快速搭建模型而不考虑中间过程的话, 推荐使用nn.Sequential()模块。
    在上面的例子中, Perception类中的layer1layer2是直接传递的,因此该Perception类可以使用nn.Sequential()快速搭建。 在此新建一个
    perception_sequential.py文件, 内容如下:

     1 from torch import nn
     2 
     3 class Perception(nn.Module):
     4 
     5     def __init__(self, in_dim, hid_dim, out_dim):
     6         super(Perception, self).__init__()
     7 
     8         # 利用nn.Sequential()快速搭建网络模块
     9         self.layer = nn.Sequential(
    10             nn.Linear(in_dim, hid_dim),
    11             nn.Sigmoid(),
    12             nn.Linear(hid_dim, out_dim),
    13             nn.Sigmoid()
    14         )
    15 
    16         def forward(self, x):
    17             y = self.layer(x)
    18             return y
    View Code

    同一目录下,调用perception_sequential.py 的测试文件:

    test.py

     1 import torch
     2 from perception_sequential import Perception
     3 
     4 
     5 model = Perception(100, 1000, 10).cuda()
     6 
     7 # 打印model结构, 会显示Sequential中每一层的具体参数配置
     8 print(model)
     9 >> Perception(
    10     (layer): Sequential(
    11         (0): Linear(in_features=100, out_features=1000, bias=True)
    12         (1): Sigmoid()
    13         (2): Linear(in_features=1000, out_features=10, bias=True)
    14         (3): Sigmoid()
    15     )
    16     )
    17 
    18 input = torch.randn(100).cuda
    19 # # 将输入传入实例化的模型
    20 output = model(input)
    21 
    22 print(output.shape)
    23 >> torch.Size([10])
    View Code
  • 相关阅读:
    五、Java对象和类
    四、JavaString字符串
    三、Java语句
    二、Java基本数据类型
    一、Java主类结构
    bat常用命令
    iOS 如何获得app的版本和系统的版本
    英语----时态---将来时态的四种对比
    英语----时态---将来时态的
    英语----时态---现在进行时与过去进行时
  • 原文地址:https://www.cnblogs.com/zhaopengpeng/p/13634429.html
Copyright © 2011-2022 走看看