• 『PyTorch』第四弹_通过LeNet初识pytorch神经网络_上


    总结一下相关概念:

    • torch.Tensor - 一个近似多维数组的数据结构
    • autograd.Variable - 改变Tensor并且记录下来操作的历史记录。和Tensor拥有相同的API,以及backward()的一些API。同时包含着和张量相关的梯度
    • nn.Module - 神经网络模块,便捷的数据封装,能够将运算移往GPU,还包括一些输入输出的东西
    • nn.Parameter - 一种变量(Variable),当将任何值赋予Module时自动注册为一个参数
    • autograd.Function - 实现了使用自动求导方法的前馈和后馈的定义。每个Variable的操作都会生成至少一个独立的Function节点,与生成了Variable的函数相连之后记录下操作历史

    导入库:

    # Author : Hellcat
    # Time   : 2018/2/10
    
    import torch as t
    import torch.nn as nn
    import torch.optim as optim
    import torch.nn.functional as F
    from torch.autograd import Variable
    

     torch.nn:网络层

    torch.nn.functional:激活函数、池化函数归于此模块

    pytorch中的网络层是class,而tensorflow

    print(t.nn.Conv2d)
    <class 'torch.nn.modules.conv.Conv2d'>
    print(tf.nn.conv2d)
    <function conv2d at 0x000001A33CC44510>

     

    网络主体:

    net网络要使用class并继承父类才行,因而有一些自带的方法

     net.parameters():返回全部的参数值,迭代器

    net.named_parameters():返回参数名称和值,迭代器

    net.参数名:就是参数变量,Variable,可以直接查看data和grad等等

    class Net(nn.Module):
        def __init__(self):
            # nn.Module子类的函数必须在构造函数中执行父类的构造函数
            # 等价于nn.Model.__init__(self)
            super(Net,self).__init__()
    
            # 输入1通道,输出6通道,卷积核5*5
            self.conv1 = nn.Conv2d(1, 6, 5)
            # 定义卷积层:输入6张特征图,输出16张特征图,卷积核5x5
            self.conv2 = nn.Conv2d(6,16,5)
            # 定义全连接层:线性连接(y = Wx + b),16*5*5个节点连接到120个节点上
            self.fc1 = nn.Linear(16*5*5,120)
            # 定义全连接层:线性连接(y = Wx + b),120个节点连接到84个节点上
            self.fc2 = nn.Linear(120,84)
            # 定义全连接层:线性连接(y = Wx + b),84个节点连接到10个节点上
            self.fc3 = nn.Linear(84,10)
    
        # 定义向前传播函数,并自动生成向后传播函数(autograd)
        def forward(self,x):
            # 输入x->conv1->relu->2x2窗口的最大池化->更新到x
            x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))
            # 输入x->conv2->relu->2x2窗口的最大池化->更新到x
            x = F.max_pool2d(F.relu(self.conv2(x)),2)
            # view函数将张量x变形成一维向量形式,总特征数不变,为全连接层做准备
            x = x.view(x.size()[0], -1)
            # 输入x->fc1->relu,更新到x
            x = F.relu(self.fc1(x))
            # 输入x->fc2->relu,更新到x
            x = F.relu(self.fc2(x))
            # 输入x->fc3,更新到x
            x = self.fc3(x)
            return x
    
    
    if __name__ == "__main__":
    
        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)
        (fc2): Linear(in_features=120, out_features=84)
        (fc3): Linear(in_features=84, out_features=10)
        )
        """
    
        # 返回参数值:顺序和下面的named一致
        params = list(net.parameters())
        print(len(params))
        """
        10
        """
    
        # net.named_parameters(): ((参数名称,参数属性),……)
        for name, parameters in net.named_parameters():
            print(name, ":", parameters.size())
            """
            conv1.weight : torch.Size([6, 1, 5, 5])
            conv1.bias : torch.Size([6])
            conv2.weight : torch.Size([16, 6, 5, 5])
            conv2.bias : torch.Size([16])
            fc1.weight : torch.Size([120, 400])
            fc1.bias : torch.Size([120])
            fc2.weight : torch.Size([84, 120])
            fc2.bias : torch.Size([84])
            fc3.weight : torch.Size([10, 84])
            fc3.bias : torch.Size([10])
            """
    

    模拟单次向前&向后传播:

    # #########网络传播过程模拟#########
        # 输入如果没有batch数,则少一维度,Tensor,unsqueeze()可以为张量扩维
        input_ = Variable(t.randn(1, 1, 32, 32))
        out = net(input_)
        print(out.size())
        """
        torch.Size([1, 10])
        """
        # net.zero_grad()
        # 输出值为10个标量(一个向量),所以需要指定每个标量梯度的权重
        # out.backward(t.ones(1,10))
    

    注意: torch.nn 只接受小批量的数据

    整个torch.nn包只接受那种小批量样本的数据,而非单个样本。 例如,nn.Conv2d能够结构一个四维的TensornSamples x nChannels x Height x Width。

    如果你拿的是单个样本,使用input.unsqueeze(0)来加一个假维度就可以了

    维度是[batch,channel,height,width]。

    Loss函数构建

     # #########Loss设计#########
        target = Variable(t.arange(0,10))
        # Loss需要先实例化,然后是callable的实例
        loss_fn = nn.MSELoss()  # 均方误差
        loss = loss_fn(out, target)
        print(loss)
    
        net.zero_grad()
        print("反向传播之前:", net.conv1.bias.grad)
        loss.backward()
        print("反向传播之后:", net.conv1.bias.grad)
    

    反向传播之前: None


    反向传播之后: Variable containing:
            -0.1330
            -0.0888
            -0.0101
            -0.0186
             0.0462
             0.0317
           [torch.FloatTensor of size 6]

    优化器构建

    # #########优化器设计#########
        print(net.parameters())
        """
        <generator object Module.parameters at 0x0000021B525BE888>
        """
        # 初始化优化器
        optimizer = optim.SGD(net.parameters(), lr=0.01)
    
        optimizer.zero_grad()  # 效果等同net.zero_grad()
    
        output = net(input_)
        loss = loss_fn(output, target)
    
        loss.backward()
        print("反向传播之前:", net.conv1.bias.data)
        optimizer.step()
        print("反向传播之后:", net.conv1.bias.data)
    

     反向传播之前:
        -0.1702
         0.1192
         0.1349
         0.1307
        -0.0141
        -0.0558
      [torch.FloatTensor of size 6]


    反向传播之后:
        -0.1689
         0.1201
         0.1350
         0.1309
        -0.0146
        -0.0561
      [torch.FloatTensor of size 6]

  • 相关阅读:
    mysql存儲過程+游標的應用實例5/17
    mysql存儲過程+遊標應用之:找缺號5/19
    轉:愚公移山
    c++中的头文件
    栈和堆:生存空间
    java中的类加载
    c++中的连接
    访问static变量和方法
    子类调用构造函数的过程
    c++中变量的存储种类
  • 原文地址:https://www.cnblogs.com/hellcat/p/6858125.html
Copyright © 2020-2023  润新知