zoukankan      html  css  js  c++  java
  • PyTorch【4】-神经网络API_nn

    Autograd 虽然提供了自动微分,但是如果用 autograd 自行搭建神经网络,也是比较麻烦的;

    本教程环境 pytorch 1.3以上

    pytorch 提供了更高级的 API,即 torch.nn 模块,该模块构建于 Autograd 上,其中 nn.Module 是最重要的类,如下

    class Module(object):
        r"""Base class for all neural network modules.
        Your models should also subclass this class.
    
            import torch.nn as nn
            import torch.nn.functional as F
    
            class Model(nn.Module):
                def __init__(self):
                    super(Model, self).__init__()
                    self.conv1 = nn.Conv2d(1, 20, 5)
                    self.conv2 = nn.Conv2d(20, 20, 5)
    
                def forward(self, x):
                    x = F.relu(self.conv1(x))
                    return F.relu(self.conv2(x))
        """
    
        dump_patches = False
        _version = 1
        def __init__(self):
            torch._C._log_api_usage_once("python.nn_module")def forward(self, *input):
            raise NotImplementedError
        def register_buffer(self, name, tensor):def register_parameter(self, name, param):

    从中可以看到构建网络的大致步骤

    搭建网络流程 

    在 PyTorch 中搭建神经网络的基本步骤如下:

    1. 网络需要继承自 nn.Module

    2. 在构造函数中声明可学习参数  

      // 不需要学习的参数可声明,可不声明

    3. 重写 forward 方法,记录前向计算过程

      // 只要在 nn.Module 子类中构造了 forward 方法,backward 方法就会基于 Autograd 自动实现

    以 LeNet 为例

    代码如下

    import torch as t
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    class Net(nn.Module):
        ### 必须1:构建网络需要继承 nn.Module
        def __init__(self):
            super(Net, self).__init__()
    
            ### 必须2:需要学习的参数必须放在 构造函数 中
            # 不需要学习的参数可放可不放
            ###输入 32x32 单通道
            self.conv1 = nn.Conv2d(1, 6, 5)         ###卷积层1: 1,输入通道数, 6,输出通道数,5,卷积核 size 5*5    输出 28x28 6通道
                                                    ###后面接了2x2的池化,步长 2                                     输出 14x14 6通道
            self.conv2 = nn.Conv2d(6, 16, 5)        ###卷积层2:                                                    输出 10x10 16通道
                                                    ###后面接了2x2的池化,步长 2                                     输出 5x5 16通道
    
            ### 全连接层  wx+b
            self.fc1 = nn.Linear(16*5*5, 120)       ###第一层全连接  120 自定义
            self.fc2 = nn.Linear(120, 84)           ### 第二层     84 自定义
            self.fc3 = nn.Linear(84, 10)            ### 第三层     10 个分类
    
        def forward(self, x):
            ### 必须3:构造 forward 前向计算函数
            ### 只要在 nn.Module 的子类中定义了 forward,backward 函数就会被自动实现(利用 Autograd)
            ### 卷积--激活--池化
            x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) ###池化层1:
            x = F.max_pool2d(F.relu(self.conv2(x)), 2)
            print(x.size()[0])      # 1
            x = x.view(x.size()[0], -1)     # -1 表示自适应,拉伸成 1 维
            x = F.relu(self.fc1(x))         # relu(wx+b)
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
    
    net = Net()
    print(net)      ### 打印可学习参数名称列表
    # Net(
    #   (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
    #   (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
    #   (fc1): Linear(in_features=400, out_features=120, bias=True)
    #   (fc2): Linear(in_features=120, out_features=84, bias=True)
    #   (fc3): Linear(in_features=84, out_features=10, bias=True)
    # )

    网络的可学习参数通过 net.parameters() 获取,也可以通过 net.named_parameters 同时获取参数名称和参数值

    params = list(net.parameters())     ### 可学习参数
    # print(params)
    print(net.named_parameters)         ### 可学习参数及其名称
    for name, parameter in net.named_parameters():
        print(name, parameter.size())

    API

    nn 提供了构建神经网络的各种方法

    nn. 的方法都是一个类

    loss function

    均方差 nn.MSELoss

    用法大致如下,其他函数也类似

    predict = net(input)
    criterion = nn.MSELoss()
    loss = criterion(predict, label)

    交叉熵 nn.CrossEntropyLoss

    优化器

    torch.optim 中实现了大多数的优化方法,如 SGD,Adam,RMSProp

    用法如下

    from torch.optim import SGD
    criterion = nn.CrossEntropyLoss()
    optimizer = SGD(net.parameters(), lr=0.001, momentum=0.9)
    for epoch in range(2):
        running_loss = 0.
        for i, data in enumerate(trainloader, 0):
            (inputs, labels) = data
    
            ### 梯度清零,与 net.zero_grad() 效果一样
            optimizer.zero_grad()
            outputs = net(inputs)
            loss = criterion(outputs, labels)   ### 计算损失
            loss.backward()         ### 反向传播
            optimizer.step()        ### 参数更新
            
            ### 打印 loss,可有可无
            running_loss += loss[0]
            if i % 2000 == 1999:
                print(epoch+1, i+1, running_loss/2000)
            running_loss = 0.

    激活函数

    ReLu:有两个 API

    nn.ReLu:这是一个类,用法如下

    import torch
    import torch.nn as nn
    m = nn.ReLU()
    input = torch.randn(2)
    output = m(input)
    print(output)

    relu:这是一个函数,用法如下

    import torch.nn.functional as F
    x = F.relu(input)

    relu 的底层应该是 nn.ReLu

    Sigmoid:也是两个 API

    用法完全同 ReLu

    其他激活函数同理

    卷积与池化

    nn.Conv2d :一个类

    class Conv2d(_ConvNd):
        def __init__(self, in_channels, out_channels, kernel_size, stride=1,
                     padding=0, dilation=1, groups=1,
                     bias=True, padding_mode='zeros'):

    nn.functional.max_pool2d:一个函数

    def _max_pool2d(input, kernel_size, stride=None, padding=0, dilation=1,
                    ceil_mode=False, return_indices=False)

    nn.MaxPool2d:一个类

    CLASS torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

    其他

    nn.Linear:线性函数,他是一个类

    class Linear(Module):
        __constants__ = ['bias', 'in_features', 'out_features']
    
        def __init__(self, in_features, out_features, bias=True):

    参考资料:

  • 相关阅读:
    hello world
    first demo
    Mac出现Operation not permitted
    java 获取一个数字中,各个数字出现的次数
    java 判断回文数字
    202001031
    20200103
    华为手机的系列
    java 反向打印一个数字
    java 生成两个数之间的素数
  • 原文地址:https://www.cnblogs.com/yanshw/p/12200064.html
Copyright © 2011-2022 走看看