• Pytorch总结二之线性回归算法原理与实现


    线性回归

    • [1] 线性回归输出是⼀个连续值,因此适⽤于回归问题。回归问题在实际中很常⻅,如预测房屋价格、⽓温、销售额等连续值的问题。与回归问题不同,分类问题中模型的最终输出是⼀个离散值。我们所说的图像分类、垃圾邮件识别、疾病检测等输出为离散值的问题都属于分类问题的范畴。softmax回归则适⽤于分类问题。
    • [2] 由于线性回归和softmax回归都是单层神经⽹络,它们涉及的概念和技术同样适⽤于⼤多数的深度学习模型。⾸先以线性回归为例,介绍⼤多数深度学习模型的基本要素和表示⽅法。

    1.线性回归的基本要素

    1.1 模型定义

    在这里插入图片描述

    1.2 模型训练

    接下来我们需要通过数据来寻找特定的模型参数值,使模型在数据上的误差尽可能⼩。这个过程叫作模型训练(model training)。下⾯我们介绍模型训练所涉及的3个要素。

    • 训练数据
      在这里插入图片描述
    • 损失函数
      在这里插入图片描述
    • 优化算法
      在这里插入图片描述
      在这里插入图片描述

    1.3 模型预测

    在这里插入图片描述

    2.线性回归的表示方法

    2.1 神经网络图

    在这里插入图片描述
    在这里插入图片描述

    2.2 矢量计算表达式

    在模型训练或预测时,我们常常会同时处理多个数据样本并⽤到⽮量计算。在介绍线性回归的⽮量计算表达式之前,让我们先考虑对两个向量相加的两种⽅法。

    先定义两个1000维的向量

    import torch
    from time import time
    
    a=torch.ones(1000)
    b=torch.ones(1000)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    向量相加的一种方式是将两个向量按照元素逐一相加

    start=time()
    c=torch.zeros(1000)
    for i in range(1000):
    c[i]=a[i] + b[i]
    print(time() - start)
    
    ***output***
    0.02039504051208496
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    向量相加的另⼀种⽅法是,将这两个向量直接做⽮量加法。

    start=time()
    d=a+b
    print(time()-start)
    
    ***output***
    0.0008330345153808594
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    结果很明显,后者⽐前者更省时。因此,我们应该尽可能采⽤⽮量计算,以提升计算效率。
    在这里插入图片描述
    对3个房屋样本预测价格的⽮量计算表达式为 其中的加法运算使⽤了⼴播机制(可参考:广播机制)。例如

    a=torch.ones(3)
    b=10
    print(a+b)
    
    ***output***
    tensor([11.,11.,11.])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    在这里插入图片描述

    3. 线性回归的从零开始实现

    # time:20220810
    # writer:yohn
    #Pytorch实现线性回归
    from decimal import Decimal
    
    import matplotlib
    import torch
    from matplotlib import pyplot as plt
    import numpy as np
    import random
    
    #1.构造一个简单的人工训练数据集
    num_inputs = 2   #输入特征个数
    num_examples = 1000  #训练数据集样本数
    true_w = [2, -3.4]  #线性回归模型真实权重
    true_b = 4.2  #偏差
    features = torch.from_numpy(np.random.normal(0, 1, (num_examples,num_inputs)))
    labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
    labels += torch.from_numpy(np.random.normal(0, 0.01,size=labels.size()))
    
    print(features[0], labels[0])
    #tensor([ 0.5589, -0.2146], dtype=torch.float64) tensor(6.0320, dtype=torch.float64)
    
    plt.scatter(features[:, 1].numpy(), labels.numpy(), 1)  #显示样本数据
    # plt.title("data")
    # plt.show()
    
    #2.读取数据
    def data_iter(batch_size, features, labels):
        num_examples = len(features)
        indices = list(range(num_examples))
        random.shuffle(indices) # 样本的读取顺序是随机的
        for i in range(0, num_examples, batch_size):
            j = torch.LongTensor(indices[i: min(i + batch_size,num_examples)]) # 最后⼀次可能不⾜⼀个batch
            yield features.index_select(0, j), labels.index_select(0, j)
    
    batch_size = 10  #读取第一个小批量数据并打印,形状特征为(10,2)
    for X, y in data_iter(batch_size, features, labels):
        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)
    w.requires_grad_()
    b.requires_grad_()
    
    #4.定义模型,用mm做矩阵乘法
    def linreg(X, w, b):  # 本函数已保存在d2lzh_pytorch包中⽅便以后使⽤
        #X.to(torch.float32)  #数据类型转换失败
        X_=X.float()
        #print(X_.type())
        return torch.mm(X_, w) + b
    
    #5.定义损失函数
    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):
        for param in params:
            param.data-=lr*param.grad/batch_size
    
    #7.训练模型
    # 在训练中,我们将多次迭代模型参数。在每次迭代中,我们根据当前读取的⼩批量数据样本(特征 X 和
    # 标签 y ),通过调⽤反向函数 backward 计算⼩批量随机梯度,并调⽤优化算法 sgd 迭代模型参数。
    # 由于我们之前设批量⼤⼩ batch_size 为10,每个⼩批量的损失 l 的形状为(10, 1)。回忆⼀下⾃动求
    # 梯度⼀节。由于变量 l 并不是⼀个标量,所以我们可以调⽤ .sum() 将其求和得到⼀个标量,再运
    # ⾏ l.backward() 得到该变量有关模型参数的梯度。注意在每次更新完参数后不要忘了将参数的梯度清零。
    
    lr = 0.03
    num_epochs = 3
    net = linreg
    loss = squared_loss
    for epoch in range(num_epochs):  # 训练模型⼀共需要num_epochs个迭代周期
        # 在每⼀个迭代周期中,会使⽤训练数据集中所有样本⼀次(假设样本数能够被批量⼤⼩整除)。X
        # 和y分别是⼩批量样本的特征和标签
        for X, y in data_iter(batch_size, features, labels):
            l = loss(net(X, w, b), y).sum()  # l是有关⼩批量X和y的损失
            l.backward()  # ⼩批量的损失对模型参数求梯度
            sgd([w, b], lr, batch_size)  # 使⽤⼩批量随机梯度下降迭代模型参数
    
            # 不要忘了梯度清零
            w.grad.data.zero_()
            b.grad.data.zero_()
        train_l = loss(net(features, w, b), labels)
        print('epoch %d, loss %f' % (epoch + 1, train_l.mean().item()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    output:

    PS F:\Pytorch>  f:; cd 'f:\Pytorch'; & 'D:\program\Anaconda3\envs\Opencv\python.exe' 'c:\Users\Administrator\.vscode\extensions\ms-python.python-2022.12.1\pythonFiles\lib\python\debugpy\adapter/../..\debugpy\launcher' '60042' '--' 'f:\Pytorch\test_LinearRegression.py' 
    tensor([-0.7717, -0.7120], dtype=torch.float64) tensor(5.0800, dtype=torch.float64)
    tensor([[-0.5386,  0.5189],
            [ 0.1192,  0.2583],
            [ 1.5698,  0.1282],
            [ 0.2097,  0.1574],
            [ 0.3357, -1.2421],
            [-1.2881,  0.9988],
            [ 1.1337,  0.7982],
            [ 0.0722, -1.5144],
            [-0.7096,  0.0702],
            [ 0.4494, -0.3630]], dtype=torch.float64) tensor([ 1.3563,  3.5482,  6.9283,  4.0891,  9.0797, -1.7926,  3.7620,  9.4906,
             2.5574,  6.3390], dtype=torch.float64)
    epoch 1, loss 0.026653
    epoch 2, loss 0.000089
    epoch 3, loss 0.000048
    PS F:\Pytorch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    一阶系统阶跃响应实现规划方波目标值
    数组篇 第一题:删除排序数组中的重复项
    Hadoop问题:start-all.sh显示未找到命令
    unity打包webgl 部署到本地Web服务器
    C++ Reference: Standard C++ Library reference: C Library: cwchar: wcspbrk
    「Verilog学习笔记」实现3-8译码器①
    Markdown还能这么玩?这款开源神器绝了
    独立按键控制LED亮灭、独立按键控制LED状态、独立按键控制LED显示二进制、独立按键控制LED移位——“51单片机”
    R语言将指定函数应用于一组数据、使用dplyr包的group_by函数和summarize函数计算分组的均值、加和、样本个数
    基于JAVA天津城建大学教室查询预约管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
  • 原文地址:https://blog.csdn.net/yohnyang/article/details/126477835