zoukankan      html  css  js  c++  java
  • 动手学深度学习4-线性回归的pytorch简洁实现

    本节利用pytorch中的模块,生成一个更加简洁的代码来实现同样的功能

    导入同样导入之前的包或者模块
    %matplotlib inline
    import torch
    from IPython import display
    from matplotlib import pyplot as plt
    import numpy as np
    import random
    
    生成数据集
    num_inputs =2   ## 特征数量
    num_examples=1000   # 样本量
    true_w=[2,-3.4]  # 真实的权重系数
    true_b=4.2  # 真实的偏置量
    features = torch.randn(num_examples,num_inputs,dtype=torch.float32)   # 生成随机的特征
    labels = true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b  # 生成随机的标签
    labels += torch.tensor(np.random.normal(0,0.01,size=labels.size()),dtype=torch.float32)  #在标签上加上随机噪声项
    
    通过pytorch读取数据

    pytotch 提供了data包来读取数据。由于data常用作变量名,我们将data导入的data模块用Data代替。在每一次的迭代中,我们将随机读取包含10个样本的小批量

    import torch.utils.data as Data
    batch_size=10
    dataset= Data.TensorDataset(features,labels)
    data_iter = Data.DataLoader(dataset,batch_size,shuffle=True)
    for X,y in data_iter:
        print(X,y)
        break
    
    tensor([[ 1.9769,  1.5576],
            [-0.4743,  0.8653],
            [ 0.2641,  1.9682],
            [-2.3385,  0.3753],
            [ 0.3972, -0.6515],
            [ 1.1317, -0.2586],
            [ 1.6896,  1.0102],
            [-0.6803,  0.7734],
            [-0.3525, -0.7764],
            [ 0.3199,  0.9397]]) tensor([ 2.8727,  0.3198, -1.9711, -1.7576,  7.2187,  7.3517,  4.1360,  0.2171,
             6.1193,  1.6434])
    
    定义模型
    • 从上一节从零开始的实现中,我们需要定义模型参数,并使用他们一步步描述模型是怎样计算的。当模型结果变得复杂时,这些步骤变得更加繁琐。其实pytorch提供了大量的预定义的层,这使我, 只需要关注使用哪些层来构造模型。下面介绍pytorch更加简洁的定义线性回归。

    • 首先导入torch.nn 模块,实际上,nn是neural network的缩写。该模块定义了大量神经网络的层,之前使用过的autograd,而nn就是利用autograd来定义模型。

    • nn的核心数据结构是Module,它是一个抽象概念,既可以表示神经网络中的某个层,也可以表示包含很多层的神经网络。

    • 在实际使用中,通过会继承torch.Module,撰写自己的网络/层。一个nn.Module实例应该包含一些曾以及返回输出的前向传播(forward)方法.

    from torch import nn
    
    class LinearNet(nn.Module):
        def __init__(self,n_features):
            super(LinearNet,self).__init__()
            self.linear = nn.Linear(n_features,1)   # 这里的1是指out_features
        def forward(self,x):
            y = self.linear(x)
            return y
    net = LinearNet(num_inputs)  # 输入特维度为2,输出结果维度为1
    print(net)
    
    LinearNet(
      (linear): Linear(in_features=2, out_features=1, bias=True)
    )
    

    事实上,我们还可以用nn.Sequential来更加方便的搭建网络,Sequential是一个有序的容器,网络层将按照在传入的Sequential的顺序依次被添加到计算图中。

    # 写法1
    net= nn.Sequential(nn.Linear(num_inputs,1)
                      # 此处还可以传入其他的层
                      )
    # 写法2
    net = nn.Sequential()
    net.add_module('linear',nn.Linear(num_inputs,1))
    # net.add_module .....
    
    
    # 写法3
    
    from collections import OrderedDict
    
    net = nn.Sequential(
    OrderedDict([
        ('linear',nn.Linear(num_inputs,1))
        # 其他的层
        
    ])
    )
    
    print(net)
    print(net[0])
    
    
    Sequential(
      (linear): Linear(in_features=2, out_features=1, bias=True)
    )
    Linear(in_features=2, out_features=1, bias=True)
    
     for param in net.parameters():
            print(param)
    
    Parameter containing:
    tensor([[-0.4229, -0.0282]], requires_grad=True)
    Parameter containing:
    tensor([0.0852], requires_grad=True)
    

    作为一个单层神经网络,线性回归输出层中的神经元和输入层中各输入完成全连接,因此线性回归的输出层有叫作全连接层

    初始化模型

    在使用net前,我们需要初始化模型参数,如线性回归模型中的权重和偏差。pytorch在init模型中提供了多种参数初始化方法。这里的init是initializer的缩写形式。我们通过init.normal_将权重参数每个元素初始化为随机采样的均值为0,标准差为0.01的正态分布。偏差会初始化为0

    from torch.nn import init
    init.normal_(net[0].weight,mean=0,std=0.01)
    init.constant_(net[0].bias,val=0)
    # 该写法与后面的三种写法才可以使用,如果使用一开始的写法,net[0].weight 因改为net.linear.weight bias亦然。
    #因为net[0]这样的写法只有当net是ModuleList或者Sequential实例时才可以。
    # 
    
    Parameter containing:
    tensor([0.], requires_grad=True)
    
    定义损失函数
    # pytorch在nn模块中提供了各种损失函数,这些损失函数可以看做是一种特殊的层,pytorch也将这些损失函数实现为nn.Module的子类。这里我们使用
    # pytorch提供的均方误差损失作为模型的损失函数
    loss = nn.MSELoss()
    
    定义优化算法

    同样我们也无需自己实现小批量随机梯度下降算法,torch.optim 模块提供了很多常用的优化算法,SGD,Adam,RMSPorp等。下面我们创建了一个用于优化net所有参数的优化器实例,并指定学习率为0.03的小批量随机梯度下降(SGD)为优化算法。

    import torch.optim as optim
    optimizer = optim.SGD(net.parameters(),lr=0.03)
    print(optimizer)
    
    SGD (
    Parameter Group 0
        dampening: 0
        lr: 0.03
        momentum: 0
        nesterov: False
        weight_decay: 0
    )
    

    我们可以为不同的子网络设置不同的学习率,这在finetune时经常用到。

    optimizer = optim.SGD(
    [
        {'params':net.subset1.parameters()},  # lr 默认用最外层的学习率
        {'params':net.subset2.parameters(),'lr':0.01}
    ],
        lr= 0.03
    )
    
    训练模型

    在使用pytorch训练模型时,我们通过调用optim实例的step函数来迭代模型参数。按照小批量随机梯度下降的定义,我们在step函数中指明批量大小
    从而而批量中中样本梯度求平均

    num_epochs =3
    for epoch in range(1,num_epochs+1):
        for X,y in data_iter:
            output = net(X)
            l = loss(output,y.view(-1,1))
            optimizer.zero_grad()  # 梯度清零,等价于net.zero_grad()
            l.backward()
            optimizer.step()
        print('epoch %d loss: %f'%(epoch,l.item()))
            
    
    epoch 1 loss: 0.000286
    epoch 2 loss: 0.000199
    epoch 3 loss: 0.000072
    

    下面我们分别比较学到的模型参数和真实的模型参数。我们从net获得的需要的层,并访问其权重(weight)和偏差(bias)。学到的参数和真实的参数很接近

    dense=net[0]
    print(true_w,dense.weight)
    print(true_b,dense.bias)
    
    [2, -3.4] Parameter containing:
    tensor([[ 2.0010, -3.3996]], requires_grad=True)
    4.2 Parameter containing:
    tensor([4.2005], requires_grad=True)
    
    小结
    • 使用pytorch可以更加简洁的实现模型
    • torch.utils.data 模块提供了有关数据处理的工具,torch.nn 模块定义了大量神经网络的层,torch.nn.init 模块定义了各种初始化的方法,torch.optim模块提供了模型参数初始化的各种方法
  • 相关阅读:
    WebDriverAgent入门篇-安装和使用
    5分钟了解TypeScript
    “软到不行”的WWDC2018
    IntelliJ idea 撤回(已经commit未push的)操作
    【java并发核心一】Semaphore 的使用思路
    Spring Boot 如何干掉 if else?
    到底什么是重入锁,拜托,一次搞清楚!
    mysql 递归查找菜单节点的所有子节点
    sql语句递归查询(start with)
    js实现对上传图片的路径转成base64编码,并且对图片进行压缩,实现预览功能1
  • 原文地址:https://www.cnblogs.com/onemorepoint/p/11774588.html
Copyright © 2011-2022 走看看