zoukankan      html  css  js  c++  java
  • 深度学习之线性回归从零实现

        本节将介绍如何只利⽤ Tensorautograd 来实现⼀个线性回归的训练。
        ⾸先,导⼊本节中实验所需的包或模块,其中的matplotlib包可⽤于作图,且设置成嵌⼊显示。

    ⾸先,导⼊本节中实验所需的包或模块:

    import torch
    from IPython import display
    from matplotlib import pyplot as plt #matplotlib包可用于作图,且设置成嵌入显示
    import numpy as np
    import random
    

    一、生成数据集

    我们构造⼀个简单的⼈⼯训练数据集,它可以使我们能够直观⽐较学到的参数和真实的模型参数的区
    别。设训练数据集样本数为1000,输⼊个数(特征数)为2。给定随机⽣成的批量样本特征 (X in R^{1000 imes 2}),我们使⽤线性回归模型真实权 (w = [2,-3.4]^T) 和偏差 (b = 4.2) ,以及⼀个随机噪声项 (epsilon) 来⽣成标签

    [y = Xw + b + epsilon ]

    其中噪声项 (epsilon) 服从均值为0、标准差为0.01的正态分布。噪声代表了数据集中⽆意义的⼲扰。下⾯,让我们⽣成数据集。

    
    # 1.生成数据集
    num_inputs = 2 #2个特征
    num_examples = 1000 #训练集1000个样本数量
    true_w = [2,-3.4] #两个特征的权重值
    true_b = 4.2 # 偏差
    features = torch.from_numpy(np.random.normal(0,1,(num_examples,num_inputs)))
    # 下面两行是使用一个随机噪声生成标签$y = Xw+b+ epsilon$
    lables = true_w[0] = features[:,0] + true_w[1] * features[:,1] + true_b
    lables += torch.from_numpy(np.random.normal(0,0.01,size=lables.size()))
    
    #注意:`features`的每一行是一个长度为2的向量,而`lables`的每一行是一个长度为1的向量(标量)。
    print(features[0],lables[0])
    

    输出结果:

    tensor([0.8702, 1.1407], dtype=torch.float64) tensor(1.2039, dtype=torch.float64)
    

        绘制线性关系图:

    # 通过生成第二个特征`features[:,1]和标签`lables`的散点图,可以更直观观察两者间的线性关系
    # 若没有导入`/d2lzh_pytorch`包里添加下面两个函数,则需要在此添加
    def use_svg_display():
        # 用矢量图显示
        display.set_matplotlib_formats('svg')
    
    def set_figsize(figsize = (3.5,2.5)):
        use_svg_display()
        # 设置图的尺寸
        plt.rcParams['figure.figsize'] = figsize
    """
    # 在d2lzh_pytorch里面添加上面两个函数后就可以这样导入
    import sys
    sys.path.append("..")
    from d21zh_pytorch import *
    """
    
    set_figsize()
    plt.scatter(features[:,1].numpy(),lables.numpy(),1);
    

    输出结果:

    二、读取数据

        在训练模型的时候,我们需要遍历数据集并不断读取⼩批量数据样本。这⾥我们定义⼀个函数:它每次返回 batch_size(批量⼤⼩)个随机样本的特征和标签。

    batch_size = 10
    #`data_iter`保存在d2lzh包中。
    # 们读取第一个批量数据样本并打印。每个批量的特征形状为(10, 2),分别对应批量大小和输入个数;标签形状为批量大小。
    for x,y in data_iter(batch_size,features,lables):
        print("输出x,y在data_iter中的数据")
        print(x,y)
        break
    

    输出结果:

    完整代码:

    # -*- coding: utf-8 -*-
    """
    Created on Fri Feb 21 01:30:34 2020
    
    @author: Google
    """
    
    # 导入所需模块或者包
    import torch
    from IPython import display
    from matplotlib import pyplot as plt #matplotlib包可用于作图,且设置成嵌入显示
    import numpy as np
    import random
    #import sys
    #sys.path.append("..")
    from d2lzh_pytorch import *
    
    # 1.生成数据集
    num_inputs = 2 #2个特征
    num_examples = 1000 #训练集1000个样本数量
    true_w = [2,-3.4] #两个特征的权重值
    true_b = 4.2 # 偏差
    features = torch.from_numpy(np.random.normal(0,1,(num_examples,num_inputs)))
    # 下面两行是使用一个随机噪声生成标签$y = Xw+b+ epsilon$
    lables = true_w[0] = features[:,0] + true_w[1] * features[:,1] + true_b
    lables += torch.from_numpy(np.random.normal(0,0.01,size=lables.size()))
    
    #注意:`features`的每一行是一个长度为2的向量,而`lables`的每一行是一个长度为1的向量(标量)。
    print(features[0],lables[0])
    
    # 通过生成第二个特征`features[:,1]和标签`lables`的散点图,可以更直观观察两者间的线性关系
    # 若没有导入`/d2lzh_pytorch`包里添加下面两个函数,则需要在此添加
    def use_svg_display():
        # 用矢量图显示
        display.set_matplotlib_formats('svg')
    
    def set_figsize(figsize = (3.5,2.5)):
        use_svg_display()
        # 设置图的尺寸
        plt.rcParams['figure.figsize'] = figsize
    """
    # 在d2lzh_pytorch里面添加上面两个函数后就可以这样导入
    import sys
    sys.path.append("..")
    from d21zh_pytorch import *
    """
    
    set_figsize()
    plt.scatter(features[:,1].numpy(),lables.numpy(),1);
    
    
    """
    2.读取数据:
    在训练模型的时候,我们需要遍历数据集并不断读取⼩批量数据样本。这⾥我们定义⼀个函数:它每次
    返回 batch_size (批量大小)个随机样本的特征和标签。
    """
    batch_size = 10
    
    #`data_iter`保存在d2lzh包中。
    # 们读取第一个批量数据样本并打印。每个批量的特征形状为(10, 2),分别对应批量大小和输入个数;标签形状为批量大小。
    for x,y in data_iter(batch_size,features,lables):
        print("输出x,y在data_iter中的数据")
        print(x,y)
        break
    
    """
    3. 初始化模型参数
    """
    # 我们将权重初始化成均值为0、标准差为0.01的正态随机数,偏差则初始化成0
    w = torch.tensor(np.random.normal(0,0.01,(num_inputs,1)),dtype = torch.float32)
    b = torch.zeros(1,dtype = torch.float32)
    
    # 后续的模型训练中,需要对这些参数梯度求迭代参数的值,因此要使`requires_grad=True`
    w.requires_grad_(requires_grad = True)
    b.requires_grad_(requires_grad = True)
    
    
    """
    4.定义模型
    """
    # 下面是线性回归的矢量计算表达式的实现,使用`mm`函数做矩阵乘法
    def linreg(z,w,b): # 本函数已保存在d2lzh_pytorch包中方便以后使用
        z = torch.tensor(z, dtype=torch.float32)
        return torch.mm(z,w)+b
    
    """
    5.定义损失函数
    """
    # 使用`平方损失`做线性回归的损失函数。将真实值`y`变形成预测值`y_hat`的形状。
    #以下函数的返回结果也将和`y_hat`的形状相同
    def squared_loss(y_hat,y): # 本函数已保存在d2lzh_pytorch包中方便以后使用
        # 注意:此处返回的是向量,并且pytorch中的MSELoss并没有除以2
        return (y_hat - y.view(y_hat.size())) ** 2/2
    
    """
    6.定义优化算法
    """
    # 以下的`sgd`函数实现小批量随机梯度下降算法,通过不断迭代来优化损失函数。
    # 这里自动求梯度模块计算得来的梯度是一个批量样本的梯度和,通过将它除以批量大小来得到平均值
    def sgd(params,lr,batch_size): # 本函数已保存在d2lzh_pytorch包中方便以后使用
        for param in params:
            param.data -= lr * param.grad / batch_size #更改param时用的param.data
    
    
    """
    7.训练模型
    """
    lr = 0.03
    num_epochs = 3
    net = linreg
    loss = squared_loss
    
    for epoch in range(num_epochs):
        for x,y in data_iter(batch_size,features,lables):
            l = loss(net(x,w,b),y).sum()
            l.backward()
            sgd([w,b],lr,batch_size)
            
            # 进行梯度清零
            w.grad.data.zero_()
            b.grad.data.zero_()
        train_l = loss(net(features,w,b),lables)
        print('epoch %d,loss %f' % (epoch + 1,train_l.mean().item()))
    

    运行结果:

    三、自我总结:

        在第4步:定义模型中,原代码:

    """
    4.定义模型
    """
    # 下面是线性回归的矢量计算表达式的实现,使用`mm`函数做矩阵乘法
    def linreg(z,w,b): # 本函数已保存在d2lzh_pytorch包中方便以后使用
        return torch.mm(z,w)+b
    

        运行过程中,会报错:

    Traceback (most recent call last):
    
      File "<ipython-input-9-386f60e0227d>", line 1, in <module>
        runfile('F:/CodeStore/DL_Pytorch/3.2PracticeOfLinerRegression.py', wdir='F:/CodeStore/DL_Pytorch')
    
      File "D:InstallSoftwareAnacondaenvsspyder_py3.5libsite-packagesspyder_kernelscustomizespydercustomize.py", line 678, in runfile
        execfile(filename, namespace)
    
      File "D:InstallSoftwareAnacondaenvsspyder_py3.5libsite-packagesspyder_kernelscustomizespydercustomize.py", line 106, in execfile
        exec(compile(f.read(), filename, 'exec'), namespace)
    
      File "F:/CodeStore/DL_Pytorch/3.2PracticeOfLinerRegression.py", line 114, in <module>
        l = loss(net(x,w,b),y).sum()
    
      File "F:/CodeStore/DL_Pytorch/3.2PracticeOfLinerRegression.py", line 83, in linreg
        return torch.mm(z,w)+b
    
    RuntimeError: Expected object of scalar type Double but got scalar type Float for argument #2 'mat2' in call to _th_mm
    

    问题:类型错误,于是添加z = torch.tensor(z, dtype=torch.float32),将数据类型统一。改后的代码:

    """
    4.定义模型
    """
    # 下面是线性回归的矢量计算表达式的实现,使用`mm`函数做矩阵乘法
    def linreg(z,w,b): # 本函数已保存在d2lzh_pytorch包中方便以后使用
        z = torch.tensor(z, dtype=torch.float32)
        return torch.mm(z,w)+b
    
    """
    
  • 相关阅读:
    拦截器接口(IActionFilter,IExceptionFilter,IResultFilter,IAuthorizationFilter)
    Linq学习
    keycode值大全
    C#使用Cookie方法
    领域驱动设计学习
    mvc3 razor语法学习
    O/R Mapping 阻抗失衡
    文档格式批量转换(doc,txt,pdf等)
    统计sql语句
    如何确定文件编码格式的方法??
  • 原文地址:https://www.cnblogs.com/somedayLi/p/12333796.html
Copyright © 2011-2022 走看看