【动手学深度学习】--01.线性回归

news2024/12/23 8:41:56

文章目录

  • 线性回归
  • 1.原理
    • 1.1线性模型
    • 1.2衡量预估质量——平方损失
    • 1.3训练数据
    • 1.4参数学习
    • 1.5优化算法
  • 2.从零开始实现线性回归
    • 2.1生成数据集
    • 2.2批量读取数据集——Mini-batch思想
    • 2.3初始化模型参数
    • 2.4定义模型
    • 2.5定义损失函数
    • 2.6定义优化算法
    • 2.7训练模型
  • 3.借助深度学习框架实现线性回归模型
    • 3.1生成数据集
    • 3.2读取数据集
    • 3.3定义模型
    • 3.4初始化模型参数
    • 3.5定义损失函数
    • 3.6定义优化算法
    • 3.7训练

线性回归

学习视频:线性回归 + 基础优化算法【动手学深度学习v2】

1.原理

1.1线性模型

img

线性回归可以看成是一个单层神经网络

image-20230713230202391

1.2衡量预估质量——平方损失

img

使用平方损失来衡量预测值和真实值的差异

1.3训练数据

img

1.4参数学习

img

1.5优化算法

虽然线性回归有解析解,但是一般的模型都没有解析解,因此在此介绍更为普适的求解最优解的方法。当一个模型没有显示解的时候,可以使用梯度下降法来逼近最优解

梯度下降

img

小批量梯度下降

img

  • 批量不能太小,若计算量太小,不适合并行来最大利用计算资源

  • 批量不能太大,否则内存消耗增加,浪费计算

总结:

  • 梯度下降通过不断沿着反梯度方向更新参数求解

  • 小批量随机梯度下降是深度学习默认的求解算法

  • 两个重要的超参数是批量大小和学习率

2.从零开始实现线性回归

2.1生成数据集

  • 根据带有噪声的线性模型构造一个人造数据集

image-20230713220007922

torch.normal(means, std, size,require_grade)

means (Tensor) – 均值
std (Tensor) – 标准差
size (Tensor) – 可选的输出张量
require_grade :表示是否求梯度值

torch.matmul(input,other)

计算两个张量input和other的矩阵乘积
matmul函数没有强制规定维度和大小,可以用利用广播机制进行不同维度的相乘操作

import matplotlib.pyplot as plt
import random
import torch

def synthetic_data(w,b,num_examples):
    '''生成y = Xw + b + 噪声'''
    #X中的元素是均值为0,方差为1的随机值,是一个n*len(w)的二维张量
    X = torch.normal(0,1,(num_examples,len(w))) 
    #y是一个一维的张量
    y = torch.matmul(X,w) + b
    ##增加随机噪音,噪音是均值为0,方差为0.01的随机数
    y += torch.normal(0,0.01,y.shape)
    #y.reshape((-1, 1)) 的意思是将 y 数组重新排列成一个列向量。其中 -1 表示自动计算行数,1 表示列数为 1
    return X,y.reshape((-1,1))

X是一个n*len(w)的二维张量,而w是一个一维张量,根据向量相乘的规则,会得到一个n行一列的一维张量y

定义好w和b的值,利用上面的函数生成1000个数量的数据集

true_w = torch.tensor([2,-3.4])
true_b = 4.2
features,labels = synthetic_data(true_w,true_b,10000)

可以通过散点图的方式,看到两个特征关于y的线性关系,这里为了能使用matplotlib绘图,在pytorch中需要把张量通过detach函数,将tensor从计算图剥离,然后才能使用numpy函数转化为矩阵传入plt,它作为叶子节点仍指向之前tensor

torch.detach()函数

返回一个新的tensor,从当前计算图中分离下来。但是仍指向原变量的存放位置,不同之处只是requirse_grad为false.得到的这个tensor永远不需要计算器梯度,不具有grad.

即使之后重新将它的requires_grad置为true,它也不会具有梯度grad.这样我们就会继续使用这个新的tensor进行计算,后面当我们进行反向传播时,到该调用detach()的tensor就会停止,不能再继续向前进行传播.

plt.scatter(features[:, 0].detach().numpy(), labels.detach().numpy(), 1)
plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1)

image-20230713223013081

image-20230713222127531

2.2批量读取数据集——Mini-batch思想

在下面的代码中,我们定义一个data_iter函数, 该函数接收批量大小、特征矩阵和标签向量作为输入,生成大小为batch_size的小批量。 每个小批量包含一组特征和标签。

def data_iter(batch_size, features, labels):
    #返回X数据量,即样本数量
    num_examples = len(features)
    #对正常数据的迭代器生成列表
    indices = list(range(num_examples))
    # 这些样本是随机读取的,没有特定的顺序,打乱顺序
    random.shuffle(indices)
    #从0到样本总数量进行迭代,步长为batch_size
    for i in range(0, num_examples, batch_size):
        #这里巧妙的min可以在最终组数据不够的时候返回的是最后一个节点的下标
        batch_indices = torch.tensor(
            indices[i: min(i + batch_size, num_examples)])
        #yield类似return 返回一个值,并且记住这个返回的位置,下次迭代从这个位置开始
        yield features[batch_indices], labels[batch_indices]

使用如下代码进行测试,得到批量读取的效果

batch_size = 10

for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break

image-20230713223528821

2.3初始化模型参数

在下面的代码中,我们通过从均值为0、标准差为0.01的正态分布中采样随机数来初始化权重, 并将偏置初始化为0

w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

2.4定义模型

要计算线性模型的输出, 我们只需计算输入特征X和模型权重w的矩阵-向量乘法后加上偏置b

def linreg(X, w, b):  #@save
    """线性回归模型"""
    return torch.matmul(X, w) + b

2.5定义损失函数

def squared_loss(y_hat, y):  #@save
    """均方损失"""
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

2.6定义优化算法

在每一步中,使用从数据集中随机抽取的一个小批量,然后根据参数计算损失的梯度。 接下来,朝着减少损失的方向更新我们的参数。 下面的函数实现小批量随机梯度下降更新。 该函数接受模型参数集合、学习速率和批量大小作为输入。每 一步更新的大小由学习速率lr决定。 因为我们计算的损失是一个批量样本的总和,所以我们用批量大小(batch_size) 来规范化步长,这样步长大小就不会取决于我们对批量大小的选择。

def sgd(params, lr, batch_size): 
    """小批量随机梯度下降"""
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()

2.7训练模型

整个训练过程主要分为:

  • 参数设置
  • 迭代轮次
  • 批量处理
  • 正向传播 (计算损失)
  • 反向传播
  • 更新参数
  • 梯度清零
  • 梯度更新

image-20230713224148249

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, labels):
        l = loss(net(X, w, b), y)  # X和y的小批量损失
        # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
        # 并以此计算关于[w,b]的梯度
        l.sum().backward()
        sgd([w, b], lr, batch_size)  # 使用参数的梯度更新参数
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

因为我们使用的是自己合成的数据集,所以我们知道真正的参数是什么。 因此,我们可以通过比较真实参数和通过训练学到的参数来评估训练的成功程度。 事实上,真实参数和通过训练学到的参数确实非常接近。

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')

3.借助深度学习框架实现线性回归模型

3.1生成数据集

#使用深度学习框架实现
import numpy as np
import torch
from torch.utils import data

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

3.2读取数据集

具体参考python之TensorDataset和DataLoader

torch,utils.data.TensorDataset(data_tensor,target_tensor)*

TensorDataset 可以用来对 tensor 进行打包,就好像 python 中的 zip 功能。
该类通过每一个 tensor 的第一个维度进行索引。
因此,该类中的 tensor 第一维度必须相等.
另外:TensorDataset 中的参数必须是 tensor

torch.utils.data.DataLoader(dataset,batch_size,shuffle)*

dataset:加载数据的数据集
batch_size:每批加载多少个样本
shuffle:表示是否希望数据迭代器对象在每个迭代周期内打乱数据

def load_array(data_arrays, batch_size, is_train=True): 
    """构造一个PyTorch数据迭代器"""
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train)

batch_size = 10
data_iter = load_array((features, labels), batch_size)

3.3定义模型

在PyTorch中,全连接层在Linear类中定义。 值得注意的是,我们将两个参数传递到nn.Linear中。 第一个指定输入特征形状,即2,第二个指定输出特征形状,输出特征形状为单个标量,因此为1。

# nn是神经网络的缩写
from torch import nn

net = nn.Sequential(nn.Linear(2, 1))

我们这里使用到了Sequential函数,它的作用类似于封装一个我们自定义的模型,可以将我们写好的网络一层一层连接实例化 torch.nn.Sequential()讲解

3.4初始化模型参数

normal和fill加下划线都是将原本data的值进行填充替换的作用,们通过net[0]选择网络中的第一个图层, 然后使用weight.databias.data方法访问参数

net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

3.5定义损失函数

计算均方误差使用的是MSELoss类,也称为平方L2范数

loss = nn.MSELoss() 

3.6定义优化算法

小批量随机梯度下降算法是一种优化神经网络的标准工具, PyTorch在optim模块中实现了该算法的许多变种。 当我们实例化一个SGD实例时,我们要指定优化的参数 (可通过net.parameters()从我们的模型中获得)以及优化算法所需的超参数字典。 小批量随机梯度下降只需要设置lr值,这里设置为0.03。

trainer = torch.optim.SGD(net.parameters(), lr=0.03)

3.7训练

对于每一个小批量,我们会进行以下步骤:

  • 通过调用net(X)生成预测并计算损失l(前向传播)。
  • 通过进行反向传播来计算梯度。
  • 通过调用优化器来更新模型参数。
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X) ,y)
        trainer.zero_grad()
        l.backward()
        trainer.step()
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')

下面我们比较生成数据集的真实参数和通过有限数据训练获得的模型参数

w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/751414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于nginx学习记录(一)

系列文章目录 第一章 Nginx 学习入门——Nginx的概述及安装 系列文章目录 一、Nginx 概述 二、安装步骤 1.下载pcre安装包,并放入linux中,进行解压: 2.pcre解压完成后,进入解压后的文件,执行./configure命令 3.在当前目录执行命令:make && make install 4.由于到…

【并发编程的艺术读书笔记】创建线程的四种方式

创建线程的四种方式 继承Thread类 public class MyThread extends Thread {Overridepublic void run() {System.out.println("MyThread...run...");}public static void main(String[] args) {// 创建MyThread对象MyThread t1 new MyThread() ;MyThread t2 new M…

神经网络模型在深度学习中的作用

神经网络模型是一种模拟人脑神经元之间连接和相互作用的数学模型。它由多个神经元(节点)以层次结构相互连接而成,每个神经元通过学习权重和偏置,根据输入数据产生相应的输出。 在深度学习中,神经网络模型被广泛应用于…

基于ZYNQ阵列涡流检测系统硬件设计(一)

为实现阵列涡流检测系统总体功能,需研制一套多通道信号采集硬件系统,以搭配 软件编程实现分时激励和分时采集。基于以上要求,本章介绍了阵列涡流检测系统的硬 件模块设计。 3.1 阵列涡流检测系统总体设计 阵列涡流检测系统需要利用 DA …

PADS Logic元件库创建的管脚如何快速复制

在绘制原器件封装的时候,如果对管脚一个一个去进行放置会影响效率,因此可以通过对管脚进行复制来实现快速放置管脚。 第一步:在元件界面点击添加端点图标,先进行一个管脚的放置,如图1所示 图1 放置管脚示意图 第二步&…

2.Vue3中Cesium地图初始化及地图控件配置

前言 本文中,我们主要介绍 Cesium 在 Vue 3运行环境的配置,以及 Cesium 实例中控件的显隐设置,本文是后续文章内容的基础,项目代码在此查看;通过本文,我们可以得到一个纯净的 cesium 项目,后续的…

ptrace修改进程数据

ptrace可以修改和读取一个进程的数据 long ptrace(enum __ptrace_request request,pid_t pid,void *addr,void *data); PTRACE_TRACEME, 本进程被其父进程所跟踪。其父进程应该希望跟踪子进程 PTRACE_PEEKTEXT, 从内存地址中读取一个字节,内存地址由addr给出 PT…

基于docker搭建gitea私服仓库,并开启https访问、ssh访问和邮箱验证通知功能

系列文章目录 git常用命令大锦囊 文章目录 系列文章目录前言一、gitea安装1. 安装docker compose2. 安装gitea 二、给gitea配置https访问三、gitea配置ssh方式拉取代码四、给gitea配置可发送的邮箱五、gitea注册开启邮箱验证和邮箱通知六、限制所有仓库只有登录后才能访问七、…

Windows git bash输入vim报错,不能使用vim-plug插件管理器

Windows系统下的git bash在安装时自带了默认的vim&#xff0c;我自己也下了个gvim&#xff0c;并且配置了.vimrc&#xff0c;其中使用了vim-plug管理nerdtree这些插件。但是在bash中vim <file>时&#xff0c;就会蹦出来几行报错&#xff1a; 处理 /c/Users/<username…

pyqt 实现计算器

1.由designer设计实现的计算器类 文件名为&#xff1a;untitled.py # -*- coding: utf-8 -*-# Form implementation generated from reading ui file untitled.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will b…

浅谈无线温度监控系统在低功耗开关柜中的应用

安科瑞 华楠 摘要&#xff1a;为了能够实现实时监测高压开关柜的温度状况&#xff0c;提出一种基于无线传感器网络的开关柜温度在线监测系统。设计的无线温度在线监测系统不仅解决了开关柜内高温、高压、强电磁感应等在恶劣环境下不易检测的问题&#xff0c;而且从硬件选择和软…

谷粒商城篇章4 ---- P102-P172【分布式高级篇一】

目录 1. Elasticsearch 1.1 基本概念 1.1.1 Index&#xff08;索引&#xff09; 1.1.2 Type&#xff08;类型&#xff09; 1.1.3 Document&#xff08;文档&#xff09; 1.1.4 倒排索引机制 1.2 Docker安装 ES 1.2.1 下载镜像文件 1.2.2 运行 Elasticsearch 1.3 初步…

mongodb,redis,mysql 区别

一、MySQL 关系型数据库。 在不同的引擎上有不同 的存储方式。 查询语句是使用传统的sql语句&#xff0c;拥有较为成熟的体系&#xff0c;成熟度很高。 开源数据库的份额在不断增加&#xff0c;mysql的份额页在持续增长。 缺点就是在海量数据处理的时候效率会显著变慢。 二、Mo…

C基础day8(2023.7.10)

一、Xmind整理&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;基本类型参数 #include <stdio.h> #include <string.h> #include <stdlib.h> //传参&#xff1a;被调函数需要使用主调函数的局部变量&#xff0c;传参 void Sum(char a,char b);//被…

模拟电路(PHY)的端接电阻(terminator)

电气终端&#xff08;英语&#xff1a;electrical termination&#xff09;&#xff0c;是使传输线的末端的负载与传输线特性阻抗相匹配&#xff0c;以避免信号在末端反射的措施。实现电气终端的装置是端接器&#xff08;英语&#xff1a;terminator&#xff09;&#xff0c;有…

《向量数据库指南》——向量数据库的技术挑战和优势

目录 技术挑战 向量数据库的优势 技术挑战 在前面,我列出了向量数据库应该具有的理想功能,然后将向量数据库与向量搜索库和向量搜索插件进行比较。现在,让我们简单来了解一下向量数据库的技术挑战。未来的教程中,我们将介绍 Milvus 是如何解决这些问题的,以及这些技术是…

一个月学通Python(十六):Django模型深入理解(Web开发)

专栏介绍 结合自身经验和内部资料总结的Python教程&#xff0c;每天3章&#xff0c;1个月就能全方位的完成Python的学习并进行实战开发&#xff0c;学完了定能成为大佬&#xff01;加油吧&#xff01;卷起来&#xff01; 全部文章请访问专栏&#xff1a;《Python全栈教程&…

Openlayers实战:加载高德地图

在国内地图市场上,高德地图占据了重要的地位。Openlayers可以加载高德地图,这其中根据不同的参数,可以显示遥感地图,矢量地图等,可以显示中文,英文。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还是大剑师兰特(CSDN) * @此源代码版权归大剑师兰特所有…

flutter页面添加透明遮罩

路由工具 import package:test/main.dart; import package:flutter/material.dart;import circle_page_route.dart;class NavigatorUtil {static push(Widget page, {BuildContext context}) {return Navigator.push(context ?? navigatorKey.currentContext,MaterialPageRo…

津津乐道设计模式 - 迭代器模式详解(以购物车的场景来演示迭代器模式)

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…