【鼠鼠学AI代码合集#8和9】线性神经网络

深度学习中的矢量化加速

在深度学习模型的训练过程中,处理大量数据的效率对模型性能至关重要。为此,我们通常希望能够在一次操作中处理整个小批量的样本,而不是逐一处理每个样本。这种优化方式称为矢量化。通过矢量化,我们可以充分利用底层硬件的并行处理能力,从而极大地加速计算过程。相较于传统的逐元素计算,矢量化能够减少开销,并使代码更加简洁。

为什么矢量化如此重要?

在Python中使用for循环进行逐元素操作虽然直观,但效率往往不高,尤其是在处理大规模数据时。Python本身是解释型语言,每次执行一条指令时,Python解释器会带来较大的开销。如果我们能利用底层的线性代数库(例如深度学习框架的内置库),就可以将这些高开销的操作批量化,从而极大提高运行效率。

通过示例对比矢量化与逐元素操作

为了说明矢量化的优势,我们通过一个简单的向量相加示例进行对比。我们将在两个全为1的10000维向量上进行逐元素相加,并分别采用for循环和矢量化两种方式来计算。

首先,我们引入所需的库,并定义一个简单的计时器类来测量不同方法的运行时间。

import time
import torch
import numpy as np# 计时器类
class Timer:"""记录多次运行时间"""def __init__(self):self.times = []self.start()def start(self):"""启动计时器"""self.tik = time.time()def stop(self):"""停止计时器并将时间记录在列表中"""self.times.append(time.time() - self.tik)return self.times[-1]def avg(self):"""返回平均时间"""return sum(self.times) / len(self.times)def sum(self):"""返回时间总和"""return sum(self.times)def cumsum(self):"""返回累计时间"""return np.array(self.times).cumsum().tolist()

接下来,我们定义两个大小为10000的全为1的张量向量,并分别通过for循环和矢量化进行相加计算。

n = 10000
a = torch.ones(n)
b = torch.ones(n)
方法一:使用for循环逐元素相加
c = torch.zeros(n)
timer = Timer()
for i in range(n):c[i] = a[i] + b[i]
print(f'For循环执行时间:{timer.stop():.5f} 秒')
方法二:使用矢量化操作
timer.start()
d = a + b
print(f'矢量化操作执行时间:{timer.stop():.5f} 秒')

性能对比

运行结果表明,矢量化操作比for循环快得多:

  • For循环执行时间:0.16749 秒
  • 矢量化执行时间:0.00042 秒

通过这组对比,可以看到矢量化代码的速度比for循环快了两个数量级。原因在于for循环只能逐元素进行加法操作,而矢量化操作则可以一次性批量处理整个向量的加法。深度学习框架(如PyTorch、MXNet、TensorFlow等)背后的线性代数库高度优化,通常会利用CPU或GPU的并行计算能力,这使得矢量化操作具有显著的速度优势。

矢量化的其他优势

  1. 并行计算:矢量化操作允许在现代CPU和GPU上进行高效的并行计算。与之相比,for循环只能串行处理元素。
  2. 减少解释器开销:for循环每次迭代都需要调用Python解释器,而矢量化操作将大量的计算交给底层优化的库完成,减少了解释器的频繁调用,进而提高效率。
  3. 简洁易读的代码:矢量化不仅加速了计算过程,还使代码更加简洁。复杂的循环逻辑可以被更简单的张量运算替代,代码可维护性和可读性均有所提升。
  4. 减少出错风险:矢量化代码减少了手动编写循环和逐元素操作的需求,从而降低了编写和调试代码时出错的几率。

总结

矢量化是一种通过批量处理数据来加速计算的技术,尤其在深度学习模型训练中至关重要。相比于逐元素的for循环,矢量化可以充分利用硬件的并行能力,大幅提高计算效率。在深度学习框架中(如PyTorch、MXNet、TensorFlow等),矢量化操作已经被广泛应用,以确保训练和推理的速度能够满足大规模数据的需求。

为了在日常开发中提升代码性能,务必养成使用矢量化操作的习惯。无论是矩阵运算、向量操作还是批量数据处理,矢量化都能带来显著的速度优势和代码质量提升。

参考代码

import time
import torch
import numpy as npclass Timer:"""记录多次运行时间"""def __init__(self):self.times = []self.start()def start(self):"""启动计时器"""self.tik = time.time()def stop(self):"""停止计时器并将时间记录在列表中"""self.times.append(time.time() - self.tik)return self.times[-1]n = 10000
a = torch.ones(n)
b = torch.ones(n)# For循环实现逐元素加法
c = torch.zeros(n)
timer = Timer()
for i in range(n):c[i] = a[i] + b[i]
print(f'For循环执行时间:{timer.stop():.5f} 秒')# 矢量化加法
timer.start()
d = a + b
print(f'矢量化操作执行时间:{timer.stop():.5f} 秒')

通过这一示例,希望您能更加直观地理解矢量化带来的巨大加速效果,并在实践中应用这一技术提升深度学习模型的训练效率。

正态分布

import math
import numpy as np
import matplotlib.pyplot as pltdef normal(x, mu, sigma):p = 1 / math.sqrt(2 * math.pi * sigma**2)return p * np.exp(-0.5 / sigma**2 * (x - mu)**2)x = np.arange(-7, 7, 0.01)
params = [(0, 1), (0, 2), (3, 1)]for mu, sigma in params:plt.plot(x, normal(x, mu, sigma), label=f'mean {mu}, std {sigma}')plt.xlabel('x')
plt.ylabel('p(x)')
plt.legend()
plt.show()

线性回归的从零开始实现

引言

线性回归是一种基础而重要的机器学习算法,通过建立特征与目标变量之间的线性关系进行预测。尽管现代深度学习框架可以简化实现过程,从零开始构建线性回归模型有助于深入理解其工作原理。

1. 生成数据集

为了测试我们的线性回归模型,我们首先需要生成一个带噪声的线性数据集。以下是生成数据集的函数:

import torchdef synthetic_data(w, b, num_examples):"""生成y=Xw+b+噪声w: 模型的权重参数b: 模型的偏置num_examples: 生成的样本数量"""# 生成特征矩阵X,服从标准正态分布X = torch.normal(0, 1, (num_examples, len(w)))# 计算标签y,添加线性噪声y = torch.matmul(X, w) + b  # 计算线性关系y += torch.normal(0, 0.01, y.shape)  # 添加噪声return X, y.reshape((-1, 1))  # 返回特征和标签

我们设置真实的权重和偏置,并生成1000个样本:

true_w = torch.tensor([2, -3.4])  # 真实权重
true_b = 4.2  # 真实偏置
features, labels = synthetic_data(true_w, true_b, 1000)  # 生成数据集

2. 可视化数据集

为了直观观察特征与标签之间的关系,我们可以绘制散点图:

import matplotlib.pyplot as pltplt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), s=1)
plt.xlabel('Feature 1')  # X轴标签
plt.ylabel('Label')  # Y轴标签
plt.title('Scatter plot of Features vs Labels')  # 图表标题
plt.show()  # 显示图表

3. 读取数据集

训练模型时,我们需要以小批量的方式读取数据。以下是实现这一功能的 data_iter 函数:

import randomdef data_iter(batch_size, features, labels):"""生成小批量数据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]  # 返回当前批量的特征和标签

4. 初始化模型参数

接下来,我们需要初始化模型的参数。权重从均值为0、标准差为0.01的正态分布中随机初始化,而偏置初始化为0:

w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)  # 权重参数
b = torch.zeros(1, requires_grad=True)  # 偏置参数

5. 定义模型

线性回归模型的输出由输入特征与权重的矩阵乘法后加上偏置计算而来:

def linreg(X, w, b):"""线性回归模型X: 输入特征w: 权重参数b: 偏置参数"""return torch.matmul(X, w) + b  # 返回预测结果

6. 定义损失函数

我们使用均方损失函数来评估模型的预测能力:

def squared_loss(y_hat, y):"""均方损失y_hat: 预测值y: 真实值"""return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2  # 计算损失

7. 定义优化算法

我们实现小批量随机梯度下降(SGD)来更新模型参数:

def sgd(params, lr, batch_size):"""小批量随机梯度下降params: 要更新的参数列表lr: 学习率batch_size: 批量大小"""with torch.no_grad():  # 不需要计算梯度for param in params:param -= lr * param.grad / batch_size  # 更新参数param.grad.zero_()  # 清除梯度

8. 训练模型

最后,我们将所有组件结合起来,进行模型训练。以下是主要的训练循环:

lr = 0.03  # 学习率
num_epochs = 3  # 训练轮数
batch_size = 10  # 设置批量大小
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)  # 计算当前批量的损失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}')  # 打印损失

9. 评估结果

通过比较真实参数与训练得到的参数,我们可以评估训练的效果:

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')  # 打印权重误差
print(f'b的估计误差: {true_b - b}')  # 打印偏置误差

完整代码

import torch
import matplotlib.pyplot as pltdef synthetic_data(w, b, num_examples):"""生成y=Xw+b+噪声w: 模型的权重参数b: 模型的偏置num_examples: 生成的样本数量"""# 生成特征矩阵X,服从标准正态分布X = torch.normal(0, 1, (num_examples, len(w)))# 计算标签y,添加线性噪声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)  # 生成数据集plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), s=1)
plt.xlabel('Feature 1')  # X轴标签
plt.ylabel('Label')  # Y轴标签
plt.title('Scatter plot of Features vs Labels')  # 图表标题
plt.show()  # 显示图表import randomdef data_iter(batch_size, features, labels):"""生成小批量数据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]  # 返回当前批量的特征和标签w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)  # 权重参数
b = torch.zeros(1, requires_grad=True)  # 偏置参数def linreg(X, w, b):"""线性回归模型X: 输入特征w: 权重参数b: 偏置参数"""return torch.matmul(X, w) + b  # 返回预测结果def squared_loss(y_hat, y):"""均方损失y_hat: 预测值y: 真实值"""return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2  # 计算损失def sgd(params, lr, batch_size):"""小批量随机梯度下降params: 要更新的参数列表lr: 学习率batch_size: 批量大小"""with torch.no_grad():  # 不需要计算梯度for param in params:param -= lr * param.grad / batch_size  # 更新参数param.grad.zero_()  # 清除梯度lr = 0.03  # 学习率
num_epochs = 3  # 训练轮数
batch_size = 10  # 设置批量大小
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)  # 计算当前批量的损失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}')  # 打印偏置误差

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

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

相关文章

【开源免费】基于SpringBoot+Vue.JS网上超市系统(JAVA毕业设计)

本文项目编号 T 037 ,文末自助获取源码 \color{red}{T037,文末自助获取源码} T037,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

研发运营一体化(DevOps)能力成熟度模型

目录 应用设计 安全风险管理 技术运 持续交付 敏捷开发管理 基于微服务的端到端持续交付流水线案例 应用设计 安全风险管理 技术运 持续交付

Android 判断手机放置的方向

#1024程序员节|征文# 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 需求 老板:我有个手持终端,不能让他倒了,当他倒或者倾斜的时候要发出报警; 程序猿:我这..... 老板…

2024-09-28 地址空间与进程控制

一、进程地址空间 Pt.2 同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址 1. 页表 内存保护与页表标志位 在操作系统中,页表用于管理内存的访问权限。每个页表项通常包含一组标志位&…

二:Python学习笔记--基础知识(1) 变量,关键字,数据类型,赋值运算符,比较运算符

目录 1. 变量 2. python关键字 3. python数据类型 3.1 数字类型 整型 int 浮点型 float 内置函数-type 3.2 字符串类型 3.3 布尔类型 3.4 空类型 3.5 列表类型 3.6 元组类型 3.7 字典类型 4. python赋值运算 5. python比较运算符 1. 变量 组成:必须是数…

基于SSM的BBS社区论坛系统源码

运行环境:ideamysql5.7jdk8maven 使用技术:ssmmysqlshirolayui 功能模块:用户管理、模板管理、帖子管理、公告管理、权限管理等

yolov9目标检测/分割预测报错AttributeError: ‘list‘ object has no attribute ‘device‘常见汇总

这篇文章主要是对yolov9目标检测和目标分割预测测试时的报错,进行解决方案。 在说明解决方案前,严重投诉、吐槽一些博主发的一些文章,压根没用的解决方法,也不知道他们从哪里抄的,误人子弟、浪费时间。 我在解决前&…

Lampiao靶机入侵实战

07-Lampiao靶机入侵实战 一、扫描采集信息 1、获取IP地址 nmap -sn 192.168.81.0/24获得IP地址为:192.168.81.1282、获取端口信息 由于nmap默认情况下只扫描常用的1000个端口,覆盖面并不全,所以建议全端口扫描 nmap -p 1-65535 192.168.…

DiffusionDet: Diffusion Model for Object Detection—扩散模型检测论文解析

DiffusionDet: Diffusion Model for Object Detection—扩散模型检测论文解析 这是一篇发表在CVPR 2023的一篇论文,因为自己本身的研究方向是目标跟踪,之前看了一点使用扩散模型进行多跟踪的论文,里面提到了DiffusionDet因此学习一下。 论文…

读数据工程之道:设计和构建健壮的数据系统21数据获取

1. 数据获取 1.1. 数据获取是将数据从一个地方移动到另一个地方的过程 1.1.1. 数据获取与系统内部获取是不同的 1.2. 数据获取是数据工程生命周期中将数据从源系统移入存储的一个中间步骤 1.3. 数据集成则是将来自不同来源系统的数据组合到一个新的数据集 1.4. 数据获取的…

数字后端零基础入门系列 | Innovus零基础LAB学习Day6

今天没有具体的数字IC后端lab实验。今天的重点是熟悉掌握静态时序分析STA中的几类timing path以及setup和hold检查机制(包含setup和hold计算公式)。 芯片流片失败的那些故事 数字后端零基础入门系列 | Innovus零基础LAB学习Day5 等大家把今天内容学习…

QT获取本机所有IP地址以及修改本机IP(注意区分Windows和Linux环境)

QT 获取本机所有 IP 地址 Chapter1 QT 获取本机所有 IP 地址获取本机所有 IP 地址,包括 IPV6的地址,需要引用 QNetworkInterface1.检索所有网络接口:2.获取接口的详细信息:3.获取接口的 IP 地址:4.用于网络诊断和监控&…

KEYSIGHT E4980A是德E4980AL 精密LCR表

Keysight E4980A 精密 LCR 表为各种元件测量提供了精度、速度和多功能性的最佳组合。 E4980A 在低阻抗和高阻抗范围内提供快速测量速度和出色的性能,是元件和材料的一般研发和制造测试的终极工具。 LAN、USB 和 GPIB PC 连接可提高您的设计和测试效率。 Keysight E4…

大语言模型的Scaling Law【Power Low】

NLP-大语言模型学习系列目录 一、注意力机制基础——RNN,Seq2Seq等基础知识 二、注意力机制【Self-Attention,自注意力模型】 三、Transformer图文详解【Attention is all you need】 四、大语言模型的Scaling Law【Power Low】 文章目录 NLP-大语言模型学习系列目录一、什么是…

练习LabVIEW第十九题

学习目标: 刚学了LabVIEW,在网上找了些题,练习一下LabVIEW,有不对不好不足的地方欢迎指正! 第十九题: 创建一个程序把另外一个VI的前面板显示在Picture控件中 开始编写: 在前面板放置一个二…

iOS AVAudioSession 详解【音乐播放器的配置】

前言 在 iOS 音频开发中,AVAudioSession 是至关重要的工具,它控制着应用的音频行为,包括播放、录音、后台支持和音频中断处理等。对于音乐播放器等音频需求强烈的应用,设计一个合理的 AVAudioSession 管理体系不仅能保证音频播放…

一文详解高光谱数据python处理包spectral(SPy)

一、基本操作 读取高光谱数据文件 import spectral # 读取ENVI格式的高光谱图像 # image的后缀可以是.raw、.spe、.lan等 # 代码里img对象,类似于rasterio库的dataset对象,可以用它来读取高光谱数据 img spectral.envi.read_envi(filemy_data.hdr, im…

【LeetCode】修炼之路-0008- String to Integer (atoi)【python】

题目 基本思路 其实题目已经说了如何实现了,我们按照给定的思路实现即可 1. 问题四大要求详解 1.1 处理空格 (Whitespace) 忽略字符串开头的任何空格字符 (" ")例如: " 123" 应该被处理为 “123”Python实现: 可以使用 strip() 方法或循环处…

Python浪漫之星星与文字构造的错位图

效果图: 完整代码: import tkinter as tk import random import math from tkinter.constants import *width 888 height 500 heartx width / 2 hearty height / 2 side 11class Star:def __init__(self, canvas, x, y, size):self.canvas canvas…

精准医疗沟通新体验:开源语音识别(ASR)如何提升医生与患者对话

需求背景:一家远程医疗公司在为偏远地区提供在线医疗服务的过程中,发现传统手动记录方式效率太低,无法满足需求,影响就诊的效率。 解决方案:使用思通数科的ASR平台,公司可以实现多话者对话转录和自动病历生…