【Python代码】以线性模型为例,详解深度学习算法流程,包括数据生成、定义模型、损失函数、优化算法和训练

news2025/1/15 22:42:41

**使用带有噪声的线性模型构造数据集,并根据有限的数据恢复该线性模型的参数。**其中包括数据集构造、模型参数初始化、损失函数定义、定义优化算法和训练等过程。是大多数算法实现过程的一个缩影,理解此过程有助于在开发或改进算法时更深刻了解其算法的构造和框架。

  • 过程详解
    • 生成数据
    • 小批量划分数据集
    • 模型参数初始化
    • 模型定义
    • 损失函数定义
    • 定义优化算法
    • 模型训练
  • 运行示例
    • 整体代码
  • 示例中部分函数详解
    • torch.normal()
    • .backward()

过程详解

生成数据

此时以简单的线性模型为例,生成1000个2维的数据,作为样本集。每个样本都符合均值为0,标准差为1的正态分布。具体代码如下所示。

import torch

def synthetic_data(w,b,num_examples):
    """生成y=Wx+b+噪声"""
    ##X是一个1000行2列的数据,符合0,1的正态分布
    X=torch.normal(0,1,(num_examples,len(w)))#特征
    y=torch.matmul(X,w)+b
    y+=torch.normal(0,0.01,y.shape)#添加噪声
    return X,y.reshape((-1,1))
true_w=torch.tensor([2,-3.4])
true_b=4.2
features,labels=synthetic_data(true_w,true_b,1000)
print()
print('features',features[0],'\nlabels:',labels[0])
print('features.shape',features.shape,'\nlabels.shape:',labels.shape)

输出:

features tensor([0.1724, 0.8911]) 
labels: tensor([1.5308])
features.shape torch.Size([1000, 2]) 
labels.shape: torch.Size([1000, 1])

可以看出,已经生成了1000个2维的样本集X,大小为1000行2列。添加完噪声的标签labels,为1000行1列,即一个样本对应一个标签。
对生成数据的第一维和标签的结果可视化:

import matplotlib.pyplot as plt
plt.scatter(features[:,0].detach().numpy(),labels.detach().numpy(),1)
plt.savefig('x1000.jpg')
plt.show()

在这里插入图片描述

小批量划分数据集

把生成的数据打乱,并根据设置的批量大小,根据索引提取样本和标签。

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):
        batch_indices=torch.tensor(
        indices[i:min(i+batch_size,num_examples)]
        )#确定索引
        ##根据索引值提取相应的特征和标签
        yield features[batch_indices],labels[batch_indices]

选择其中的一个批量样本和标签可视化进行展示。

batch_size=10#批量设置为10
for X,y in data_iter(batch_size,features,labels):
    print(X,'\n',y)
    break##读取一次就退出,即选择其中的一个批量

输出:

tensor([[-0.6141, -0.9904],
        [ 2.2592, -1.2401],
        [ 0.3217, -2.0419],
        [ 2.6761,  1.6293],
        [-0.3886,  1.4958],
        [-1.4074,  0.2157],
        [-1.9986, -0.1091],
        [ 0.3808,  0.3756],
        [-0.6877,  0.3499],
        [ 1.5450, -1.0313]]) 
 tensor([[ 6.3528],
        [12.9585],
        [11.7972],
        [ 4.0089],
        [-1.6630],
        [ 0.6698],
        [ 0.5591],
        [ 3.6852],
        [ 1.6348],
        [10.7883]])

样本是10个1行2列的数据,标签是10个1行1列的数据。

模型参数初始化

这里设置权重w为符合均值为0,标准差为0.01的正态分布的随机生成数据,偏置b设置为0。也可以根据自己情况设置初始参数。

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

输出:

w: tensor([[-0.0164],
        [-0.0022]], requires_grad=True) 
b: tensor([0.], requires_grad=True)

初始参数设置之后,接下来就是更新这些参数,直到这些参数满足我们的数据拟合。
在更新时,需要计算损失函数关于参数的梯度,再根据梯度向减小损失的方向更新参数。

模型定义

定义一个模型,将输入和输出关联起来。前面生成的数据是线性的,所以定义的模型也是一个线性的 y=Wx+b

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

损失函数定义

这里简单的定义一个损失函数,计算预测结果和真实结果的平均平方差。

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

定义优化算法

使用小批量随机梯度下降算法作为优化算法。这里要确定超参数批量大小和学习率。

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

模型训练

有了数据、损失函数、初始参数和优化算法,我们就可以开始训练,更新参数。

lr=0.01
num_epochs=10
net=linreg
loss=squared_loss

for epoch in range(num_epochs):
    for X,y in data_iter(batch_size,features,labels):
        y_pred=net(X,w,b)
        l=loss(y_pred,y)
        l.sum().backward()
        sgd([w,b],lr,batch_size)
    with torch.no_grad():
        train_l=loss(net(features,w,b),labels)#使用更新后的参数计算损失

运行示例

整体代码


import torch
import random

##生成数据
def synthetic_data(w,b,num_examples):
    """生成y=Wx+b+噪声"""
    ##X是一个1000行2列的数据,符合0,1的正态分布
    X=torch.normal(0,1,(num_examples,len(w)))
    y=torch.matmul(X,w)+b
    y+=torch.normal(0,0.01,y.shape)
    return X,y.reshape((-1,1))
#真实的权重和偏置
true_w=torch.tensor([2,-3.4])
true_b=4.2
##调用生成数据函数,生成数据
features,labels=synthetic_data(true_w,true_b,1000)
# print('features',features[0],'\nlabels:',labels[0])
# print('features.shape',features.shape,'\nlabels.shape:',labels.shape)

# import matplotlib.pyplot as plt
# #set_figsize()
# plt.scatter(features[:,0].detach().numpy(),labels.detach().numpy(),1)
# plt.savefig('x1000.jpg')
# plt.show()

##读取数据,根据设置的批量大小
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):
        batch_indices=torch.tensor(
        indices[i:min(i+batch_size,num_examples)]
        )
        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

##初始化参数
w=torch.normal(0,0.01,size=(2,1),requires_grad=True)
b=torch.zeros(1,requires_grad=True)

##定义模型、损失函数和优化算法
def linreg(X,w,b):
    """线性回归模型"""
    return torch.matmul(X,w)+b
def squared_loss(y_hat,y):
    """均方损失"""
    return (y_hat-y.reshape(y_hat.shape))**2/2

def sgd(params,lr,batch_size):
    """小批量随机梯度下降优化法"""
    with torch.no_grad():
        for param in params:
            param-=lr*param.grad/batch_size
            param.grad.zero_()
#设置参数
lr=0.01
num_epochs=10
net=linreg
loss=squared_loss
##开始训练
for epoch in range(num_epochs):
    for X,y in data_iter(batch_size,features,labels):
        y_pred=net(X,w,b)
        l=loss(y_pred,y)
        l.sum().backward()
        sgd([w,b],lr,batch_size)
    with torch.no_grad():
        train_l=loss(net(features,w,b),labels)#使用更新后的参数计算损失
        print('w:',w,'\nb',b)
        print(f'epoch{epoch+1},loss{float(train_l.mean()):f}')

输出结果:

w: tensor([[ 1.1745],
        [-2.1489]], requires_grad=True) 
b tensor([2.6504], requires_grad=True)
epoch1,loss2.268522
w: tensor([[ 1.6670],
        [-2.9392]], requires_grad=True) 
b tensor([3.6257], requires_grad=True)
epoch2,loss0.318115
w: tensor([[ 1.8670],
        [-3.2300]], requires_grad=True) 
b tensor([3.9866], requires_grad=True)
epoch3,loss0.044844
w: tensor([[ 1.9472],
        [-3.3373]], requires_grad=True) 
b tensor([4.1204], requires_grad=True)
epoch4,loss0.006389
w: tensor([[ 1.9793],
        [-3.3768]], requires_grad=True) 
b tensor([4.1701], requires_grad=True)
epoch5,loss0.000951
w: tensor([[ 1.9920],
        [-3.3914]], requires_grad=True) 
b tensor([4.1888], requires_grad=True)
epoch6,loss0.000178
w: tensor([[ 1.9970],
        [-3.3968]], requires_grad=True) 
b tensor([4.1958], requires_grad=True)
epoch7,loss0.000069
w: tensor([[ 1.9991],
        [-3.3988]], requires_grad=True) 
b tensor([4.1984], requires_grad=True)
epoch8,loss0.000053
w: tensor([[ 1.9997],
        [-3.3995]], requires_grad=True) 
b tensor([4.1993], requires_grad=True)
epoch9,loss0.000051
w: tensor([[ 1.9999],
        [-3.3998]], requires_grad=True) 
b tensor([4.1997], requires_grad=True)
epoch10,loss0.000051

示例中部分函数详解

此部分,对代码中的部分函数进行解释和说明,以帮助大家理解和使用。

torch.normal()

torch.normal 是 PyTorch 中的一个函数,用于从正态分布(也称为高斯分布)中生成随机数。返回一个与输入张量形状相同的张量,其中的元素是从均值为 mean,标准差为 std 的正态分布中随机采样的

import torch

x = torch.normal(0, 1, (3, 3))
print(x)

输出:

tensor([[-1.5393,  0.2281,  1.2181],
        [ 0.7260, -1.4805,  0.5720],
        [ 0.0170, -0.9961, -0.2761]])

.backward()

在PyTorch中,a.backward() 是一个用于自动微分的方法。它通常用于计算一个张量(tensor)相对于其操作数(即输入和参数)的梯度。当你使用 PyTorch 的 autograd 模块时,可以通过调用 backward() 方法来自动计算梯度。

import torch

# 创建一个张量并设置requires_grad=True来跟踪其计算历史
a = torch.tensor([5.0], requires_grad=True)
print('a:',a)
# 定义一个简单的操作
b = a * 2

# 调用backward()来自动计算梯度
b.backward()

# 输出梯度
print(a.grad)  

输出:

a: tensor([5.], requires_grad=True)
tensor([2.])

其中,requires_grad属性是为了使PyTorch跟踪张量的计算历史并自动计算梯度。

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

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

相关文章

C#,实用新型加强版的整数数组

疫苗要打加强针!数组要用加强版! 三连发 加强版整数数组源代码https://mp.csdn.net/mp_blog/creation/editor/124151056 加强版实数数组源代码https://mp.csdn.net/mp_blog/creation/editor/124151110 加强版泛型数组源代码https://mp.csdn.net/mp_bl…

软件资源管理下载系统全新带勋章功能 + Uniapp前端

测试环境:php7.1。ng1.2,MySQL 5.6 常见问题: 配置好登录后转圈圈,检查环境及伪静态以及后台创建好应用 上传图片不了,检查php拓展fileinfo 以及public文件权限 App个人主页随机背景图,在前端uitl文件…

Java 面向对象02 封装 (黑马)

人画圆:画圆这个方法应该定义在园这个类里面。 人关门:是人给了门一个作用力,然后门自己关上了门,所以关门的方法是在门的类里面 封装对象的好处: 调用Java自带的方法举例实现: 在测试类中,对其…

Java中验证码功能的解决方案

目录​​​​​​​ 1、前言 2、随机数字验证码 2.1 使用Java的Random类生成随机数字 2.2 使用Java的Graphics2D类在图片上绘制验证码 3、字符验证码 3.1 生成包含随机字符的字符串 3.2 使用Java的Graphics2D类在图片上绘制验证码 ​​​​​​​​​​​​​​4、数学…

【设计模式】代理模式例子解析

代理模式,顾名思义,就是我们在需要访问一个类时,并不直接调用这个类,而是通过一个"代理"来间接地实现这个过程。 这个“代理”就像是真实对象的一个接口,所有的对于真实对象的操作都需要通过这个“代理”来…

IP劫持的危害分析及应对策略

在当今数字化时代,网络安全问题备受关注,其中IP劫持是一种常见而危险的威胁。本文将深入探讨IP劫持的危害,并提供一些有效的应对策略。 第一部分:IP劫持的定义 IP劫持是指黑客通过各种手段获取并篡改目标IP地址的控制权&#xf…

怎么提升搜狗网站排名

在当今数字化时代,网站排名对于品牌、企业以及个人都至关重要。而对于许多网站来说,搜狗搜索引擎是一个重要的流量来源。为了在搜狗上取得更好的排名,不仅需要优化网站内容,还需要巧妙运用一些工具和技巧。在本文中,我…

gitee码云如何提交pr

步骤 fork 源码到自己的仓库 git clone 自己的仓库 git clone xxxxxxxxxxxxxxx查看自己是否与本地仓库建立了连接 git remote -v如果没有关联,先关联本地仓库 git remote add origin xxxxxxxxxx //例 git remote add origin https://gitee.com/YZRDEG/DLT6…

DevEco Studio4.0/3.1预览器报错综合整理

题外话:额,这篇文章的由来,是在这篇文章DevEco Studio3.1报错...发布后,仍有人没解决预览不了的问题,然后就有小伙伴让我看看到底哪个地方出错了,为什么按照文章上的去做了,还是无法使用&#x…

在Qt中通过控制按钮实现登录界面密码与明码的转换

创建控件: 首先,在Qt设计师界面界面上创建QLineEdit类文本框,用于输入密码,并且实现密码与明码相互转化。 设置初始状态: 默认情况下,输入密码的文本框应该是可见的并允许用户输入。 添加切换按钮&…

计算机网络——面试问题

1 从输⼊ URL 到⻚⾯展示到底发⽣了什么? 1. 先检查浏览器缓存⾥是否有缓存该资源,如果有直接返回;如果没有进⼊下⼀ 步⽹络请求。 2. ⽹络请求前,进⾏ DNS 解析 ,以获取请求域名的 IP地址 。 3. 浏览器与服务器…

代码随想录二刷 |回溯 | 组合

代码随想录二刷 |回溯 | 组合 题目描述解题思路代码实现 题目描述 77.组合 给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。 示例: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 解题思路 递归…

浅析:HarmonyOS 一次开发多端部署

万物互联时代,应用的设备底座将从几十亿手机扩展到数百亿设备。全新的全场景设备体验,正深入改变消费者的使用习惯, 同时应用开发者也面临设备底座从手机单设备到全场景多设备的转变,通过全场景多设备作为全新的底座,为…

Vue3+ElementUI 多选框中复选框和名字点击方法效果分离

现在的需求为 比如我点击了Option A &#xff0c;触发点击Option A的方法&#xff0c;并且复选框不会取消勾选&#xff0c;分离的方法。 <el-checkbox-group v-model"mapWork.model_checkArray.value"> <div class"naipTypeDom" v-for"item …

【GitHub项目推荐--最简洁的人脸识别库】【转载】

本项目是世界上最简洁的人脸识别库&#xff0c;你可以使用 Python 和命令行工具提取、识别、操作人脸。本项目的人脸识别是基于业内领先的 C 开源库 dlib 中的深度学习模型&#xff0c;用Labeled Faces in the Wild 人脸数据集进行测试&#xff0c;有高达 99.38% 的准确率。 …

年味渐近 其乐龍龍!2024四川省网联会年货节闪亮来袭!

1月19日&#xff0c;“其乐龍龍2024四川省网联会年货节”正式启动&#xff0c;此次活动由四川省网联会主办&#xff0c;以直播、短视频多种形式在抖音、微博、小红书等多平台同步呈现&#xff0c;旨在为广大消费者带来一场别开生面的年货盛宴&#xff0c;助力激发消费活力。 年…

1985-2022年企业级数字经济核心产业专利数据库

1985-2022年企业级数字经济核心产业专利数据库 1、时间&#xff1a;1985-2022年 2、指标&#xff1a;分类号类型、发明人、专利公开号、分类号、专利名称、主分类号、专利类型、代理机构、专利摘要、分案原申请号、申请人、优先权、专利申请号、国际申请、申请日、国际公布、…

ChatGPT时代对大数据应用的展望

前言&#xff1a; 2022年底&#xff0c;科技圈有个爆炸性新闻&#xff0c;ChatGPT的诞生&#xff0c;引发了世界范围内的震惊&#xff1b;人工智能在与人交流上有了划时代的技术突破&#xff0c;可以和人深入的理解交流&#xff0c;让许多公司和领域对这项技术有了更多遐想。对…

day25 组合总和Ⅲ 电话号码的字母组合

题目1&#xff1a;216 组合总和Ⅲ 题目链接&#xff1a;216 组合总和Ⅲ 题意 找出相加之和为n的k个数的组合 数字只可使用1~9之间的数&#xff08;包括 1 9&#xff09;且每个数字只能使用1遍 题目中有两个限制条件&#xff1a;1&#xff09;k个数 2&#xff09;k个…

HNU-数据挖掘-实验2-数据降维与可视化

数据挖掘课程实验实验2 数据降维与可视化 计科210X 甘晴void 202108010XXX 文章目录 数据挖掘课程实验<br>实验2 数据降维与可视化实验背景实验目标实验数据集说明实验参考步骤实验过程1.对数据进行初步降维2.使用无监督数据降维方法&#xff0c;比如PCA&#xff0c;I…