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)

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

start=time()
c=torch.zeros(1000)
for i in range(1000):
c[i]=a[i] + b[i]
print(time() - start)

***output***
0.02039504051208496

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

start=time()
d=a+b
print(time()-start)

***output***
0.0008330345153808594

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

a=torch.ones(3)
b=10
print(a+b)

***output***
tensor([11.,11.,11.])

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

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()))

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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明月醉窗台

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值