[深度学习入门]PyTorch深度学习[数组变形、批量处理、通用函数、广播机制]

news2024/12/24 3:37:09

目录

  • 一、前言
  • 二、数组变形
    • 2.1 更改数组的形状
      • 2.1.1 reshape
      • 2.1.2 resize
      • 2.1.3 T(转置)
      • 2.1.4 ravel
      • 2.1.5 flatten
      • 2.1.6 squeeze
      • 2.1.7 transpose
    • 2.2 合并数组
      • 2.2.1 append
      • 2.1.2 concatenate
      • 2.1.3 stack
  • 三、批量处理
  • 四、通用函数
    • 4.1 math 与 numpy 函数的性能比较
    • 4.2 循环与向量运算比较
  • 五、广播机制
  • 六、小结


PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序

一、前言

  本文为PyTorch深度学习中[Numpy基础]的下篇,主要讲解数组变形、批量处理、通用函数和广播机制的相关知识。
  上期回顾:
  深度学习入门PyTorch深度学习——Numpy基础 (上)


二、数组变形

  在机器学习以及深度学习的任务中,通常需要将处理好的数据以模型能接收的格式输入给模型,然后由模型通过一系列的运算,最终返回一个处理结果
  然而,由于不同模型所接收的输人格式不一样,往往需要先对其进行一系列的变形和运算,从而将数据处理成符合模型要求的格式。在矩阵或者数组的运算中,经常会遇到需要 把多个向量或矩阵按某轴方向合并,或展平(如在卷积或循环神经网络中,在全连接层之前,需要把矩阵展平) 的情况。
  下面介绍几种常用的数据变形方法

2.1 更改数组的形状

  修改指定数组的形状是Numpy中最常见的操作之一,常见的方法有很多,下表列出了一些常用函数

函数描述
arr.reshape重新将向量arr维度进行改变,不修改向量本身
arr.resize重新将向量arr 维度进行改变,修改向量本身
arr.T对向量arr进行转置
arr.ravel对向量arr进行展平,即将多维数组变成1维数组,不会产生原数组的副本
arr.flatten对向量arr进行展平,即将多维数组变成1维数组,返回原数组的副本
arr.squeeze只能对维数为1的维度降维。对多维数组使用时不会报错,但是不会产生任何影响
arr.transpose对高维矩阵进行轴对换

  下面,我们来看一些实例。

2.1.1 reshape

  改变向量的维度(不修改向量本身):

import numpy as np
arr -np.arange(10)
print(arr)
#将向量arr维度变换为2行5列print(arr.reshape(2,5))
#指定维度时可以只指定行数或列数,其他用-1代替
print(arr.reshape(5,-1))
print(arr.reshape(-1,5))

  输出结果:

[0 1 2 3 4 5 6 7 8 9]
[[0 1 2 3 4]
[5 6 7 8 9]]
[[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]
[[0 1 2 3 4]
 [5 6 7 8 9]]

  值得注意的是,reshape函数不支持指定行数或列数,所以 -1在这里是必要的 。且所指定的行数或列数一定要能被整除,例如上面代码如果修改为arr.reshape(3,-1)即为错误的。


2.1.2 resize

  改变向量的维度(修改向量本身):

import numpy as np
arr=np.arange(10)
print(arr)
#将向量arr维度变换为2行5列arr.resize(2,5)
print(arr)

  输出结果:

[0 1 2 3 4 5 6 7 8 9]
[[0 1 2 3 4]
 [5 6 7 8 9]]

2.1.3 T(转置)

  向量转置:

import numpy as np
arr=np.arange(12).reshape(3,4)
#向量arr为3行4列
print(arr)
#将向量arr进行转置为4行3列
print(arr.T)

  输出结果:

[[0 1 2 3]
 [4 5 6 7]
 [8 9 10 11]]
[[0 4 8]
 [1 5 9]
 [2 6 10]
 [3 7 11]]

2.1.4 ravel

  向量展平:

import numpy as np
arr=np.arange(6).reshape(2,-l)
print(arr)
# 并按照列优先,展平
print("按照列优先,展平")
print (arr.ravel('F"))
# 按照行优先,展平
print("按照行优先,展平")
print(arr.ravel())

  输出结果:

[0 1 2 3 4 5]
# 按照列优先,展平
[ 0 3 1 4 2 5]
# 按照行优先,展平
[0 1 2 3 4 5]

2.1.5 flatten

  把矩阵转换为向量,这种需求经常出现在卷积网络与全连接层之间

import numpy as np
a=np.floor(10*np.random.random((3,4)))
print(a)
print(a.flatten())

  输出结果:

[[4. 0. 8. 5.]
 [1. 0. 4. 8.]
 [8. 2. 3. 7.]]
[4. 0. 8. 5. 1. 0. 4. 8. 8. 2. 3. 7.]

2.1.6 squeeze

  这是个主要用来降维的函数把矩阵中含1的维度去掉在PyTorch中还有一种与之相反的操作———torch.unsqueeze,这个后面再来介绍。

arr=np.arange(3).reshape(3,1)
print(arr.shape) #(3,1)
print(arr.squeeze().shape) #(3,)
arr1=np.arange(6).reshape(3,1,2,1)
print(arrl.shape) #(3,1,2,1)
print(arr1.squeeze().shape) #(3,2)

2.1.7 transpose

  对高维矩阵进行轴对换,这个在深度学习中经常使用,比如把图片中表示颜色顺序的RGB改为GBR

import numpy as np
arr2=np.arange(24).reshape(2,3,4)
print(arr2.shape) #(2,3,4)
print(arr2.transpose(1,2,0).shape) #(3,4,2)

2.2 合并数组

  合并数组也是最常见的操作之一,下表列举了常见的用于数组或向量合并的方法

函数描述
np.append内存占用大
np.concatenate没有内存问题
np.stack沿着新的轴加入一系列数组
np.hstack堆栈数组垂直顺序(行)
np.vstack堆栈数组垂直顺序(列)
np.dstack堆栈数组按顺序深入(沿第3维)
np.vsplit将数组分解成垂直的多个子数组的列表

  说明:
  (1)append、concatenate 以及 stack 都有一个 axis参数用于控制数组的合并方式是按行还是按列
  (2)对于appendconcatenate待合并的数组必须有相同的行数或列数(满足一个即可)。
  (3)stack 、hstack 、 dstack 要求待合并的数组必须具有相同的形状(shape)。下面选择一些常用函数进行说明

2.2.1 append

  合并一维数组

import numpy as np
a=np.array([1,2,3])
b=np.array([4,5,6])
c=np.append(a,b)
print(c)
#[1 2 3 4 5 6]

  合并多维数组

import numpy as np
a=np.arange(4).reshape(2,2)
b=np.arange(4).reshape(2,2)
# 按行合并
c=np.append(a,b,axis=0)
print('按行合并后的结果')
print(c)
print('合并后数据维度',c.shape) # 按列合并
d=np.append(a,b,axis=l)
print('按列合并后的结果')
print(d)
print('合并后数据维度',d.shape)

  输出结果:

按行合并后的结果
[[0 1]
 [2 3]
 [0 1]
 [2 3]]
合并后数据维度 (4,2)
按列合并后的结果
[[0 1 0 1]
 [2 3 2 3]]
合并后数据维度 (2,4)

2.1.2 concatenate

  沿指定轴链接数组或矩阵

import numpy as np
a=np.array([[1,2],[3,4]])
b=np.array([[5,6]])
c=np.concatenate((a,b),axis=0)
print(c)
d=np.concatenate((a,b.T),axis=1)
print(d)

  输出结果:

[[12]
 [3 4]
 [5 6]]
[[1 2 5]
 [3 4 6]]

2.1.3 stack

  沿指定轴堆叠数组或矩阵

import numpy as np
a=np.array([[1, 2],[3, 4]])
b=np.array([[5, 6],[7, 8]])
print(np.stack((a,b),axis=0))

  输出结果:

[[[1 2]
  [3 4]]
 [[5 6]
  [7 8]]]

三、批量处理

  在深度学习中,由于源数据都比较大,所以通常需要用到批处理如利用批量来计算梯度的随机梯度法(SGD)就是一个典型应用。深度学习的计算一般比较复杂,并且数据量一般比较大如果一次处理整个数据,较大概率会出现资源瓶颈
  为了更有效地计算,一般将整个数据集分批次处理。与处理整个数据集相反的另一个极端是每次只处理一条记录。这种方法也不科学一次处理一条记录无法充分发挥GPU、Numpy的平行处理优势
  因此,在实际使用中往往采用批量处理(Mini-Batch)的方法。
  如何把大数据拆分成多个批次呢? 可采用如下步骤:
  (1)得到数据集
  (2)随机打乱数据
  (3)定义批大小
  (4)批处理数据集
  下面我们通过一个示例来具体说明:

import numpy as np
# 生成10000个形状为2x3的矩阵
data_train=np.random.randn(10000,2,3)
#这是一个3维矩阵,第1个维度为样本数,后两个是数据形状print(data_train.shape)
# (10000,2,3)
# 打乱这10000条数据
np.random.shuffle(data_train)
# 定义批量大小
batch_size=100
# 进行批处理
for i in range(0,len(data_train),batch_size):
	x_batch_sum=np.sum(data_train[i:i+batch_size])
	print("第{}批次,该批次的数据之和:(}".format(i,x_batch_sum))

  最后5行结果:

9500批次,该批次的数据之和:17.637025804380929600批次,该批次的数据之和:-1.3609246073683879700批次,该批次的数据之和:-25.9122262392664459800批次,该批次的数据之和:32.0181369578358149900批次,该批次的数据之和:2.9002576614446935

  【说明】批次从0开始,所以最后一个批次是9900。


四、通用函数

  Numpy提供了两种基本的对象,即 ndarrayufunc 对象。前文已经介绍了ndarray,本节将介绍Numpy的另一个对象通用函数(ufunc)
  ufunc是universal function的缩写,它是一种能对数组的每个元素进行操作的函数。许多ufunc函数都是用C语言级别实现的,因此它们的计算速度非常快。此外,它们比 math 模块中的函数更灵活
  math模块的输入一般是标量,但Numpy中的函数可以是向量或矩阵,而利用向量或矩阵可以避免使用循环语句,这点在机器学习、深度学习中非常重要。
  下表为Numpy中常用的几个通用函数

函数使用方法
sqrt计算序列化数据的平方根
sin,cos三角函数
abs计算序列化数据的绝对值
dot矩阵运算
log,log10,log2对数函数
exp指数函数
cumsum,cumproduct累计求和、求积
sum对一个序列化数据进行求和
mean计算均值
median计算中位数
std计算标准差
var计算方差
corrcoef计算相关系数

4.1 math 与 numpy 函数的性能比较

import time
import math
import numpy as np

x=[i * 0.001 for i in np.arange (1000000)]
start=time.clock()
for i,t in enumerate(x):
x[i]=math.sin(t)
print("math.sin:",time.clock()-start)

x=[i*0.001 for i in np.arange (1000000)]=np.array(x)
start=time.clock()np.sin(x)
print("numpy.sin:",time.clock()-start)

  打印结果:

math.sin:0.5169950000000005
numpy.sin:0.05381199999999886

4.2 循环与向量运算比较

  充分使用Python的 Numpy库中的内建函数(Built-in Function),来实现计算的向量化,可大大地提高运行速度。Numpy库中的内建函数使用了SIMD指令。如下使用的向量化要比使用循环计算速度快得多。如果使用GPU,其性能将更强大,不过Numpy不支持GPU
  PyTorch支持GPU,后面有机会将介绍PyTorch 如何使用GPU来加速算法。

import time
import numpy as np
x1=np.random.rand(1000000)
x2=np.random.rand(1000000)
# 使用循环计算向量点积
tic=time.process_time()
dot=0
for i in range(len(xl)):
	dot+=x1[i]*x2[i]
toc=time.process_time()
print("dot="+str(dot)+"\n for loop----- Computation time = " +str(1000*(toc-tic))+""ms "" )
# 使用numpy函数求点积
tic=time.process_time()
dot=0
dot=np.dot(x1,x2)
toc=time.process_time()
print("dot="+str(dot)+"\n verctor version---- Computation time = "+str(1000*(toc-tic))+"ms")

  输出结果:

dot=250215.601995
  for loop----- Computation time=798.3389819999998 ms
  dot=250215.601995
verctor version---- Computation time=1.885051999999554 ms

  从运行结果上来看,使用for 循环的运行时间大约是向量运算的400倍。因此,在深度学习算法中,一般都使用向量化矩阵进行运算。


五、广播机制

  Numpy 的 Universal functions 中要求输人的数组shape是一致的当数组的shape不相等时,则会使用广播机制。不过,调整数组使得shape一样,需要满足一定的规则,否则将出错。这些规则可归纳为以下4条。
  (1)让所有输入数组都向其中 shape最长的数组看齐,不足的部分则通过在前面加1补齐,如:
  a: 2×3×2
  b:3×2
  则b向a看齐,在b的前面加1,变为:1×3×2
  (2)输出数组的shape是输入数组shape的各个轴上的最大值
  (3)如果输人数组的某个轴和输出数组的对应轴的长度相同或者某个轴的长度为1时,这个数组能被用来计算,否则出错
  (4)当输入数组的某个轴的长度为1时,沿着此轴运算时都用(或复制)此轴上的第一组值
  广播在整个Numpy中用于决定如何处理形状迥异的数组,涉及的算术运算包括(+,-,*,/…)。这些规则说得很严谨,但不直观,下面我们结合图形与代码来进一步说明。
  目的:A+B,其中A为4×1矩阵,B为一维向量( 3,)。
要相加,需要做如下处理:
  根据规则1,B需要向看齐,把B变为(1,3 )
  根据规则2,输出的结果为各个轴上的最大值,即输出结果应该为(4,3)矩阵,那么A如何由(4,1)变为(4,3)矩阵?B又如何由(1,3)变为(4,3)矩阵?
  根据规则4,用此轴上的第一组值(要主要区分是哪个轴),进行复制(但在实际处理中不是真正复制,否则太耗内存,而是采用其他对象如ogrid对象,进行网格处理)即可,详细处理过程如下图所示。
在这里插入图片描述
  代码实现:

import numpy as np
A=np.arange(0,40,10).reshape(4,1)
B=np.arange(0,3)
print("A矩阵的形状:{},B矩阵的形状:{}",format(A.shape,B.shape))
C=A+B
print("c矩阵的形状:{}".format(C.shape))
print(C)

  运行结果:

A矩阵的形状:(4,1),B矩阵的形状:(3,)
c矩阵的形状:(4,3)
[[0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]

六、小结

  本章主要介绍了Numpy模块的常用操作,尤其涉及对矩阵的操作,这些操作在后续程序中经常使用。Numpy内容很丰富,这里只列了一些主要内容,如果你想了解更多内容,可登录Numpy的官网(http://www.Numpy.org/)查看更多内容。
  最近在学习深度学习的优化算法,不知道大家想最先看哪一个…请在下方投个票吧!

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

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

相关文章

无涯教程-Perl - endhostent函数

描述 此函数告诉系统您不再希望使用gethostent从hosts文件读取条目。 语法 以下是此函数的简单语法- endhostent返回值 此函数不返回任何值。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perlwhile( ($name, $aliases, $addrtype, $length, addrs)gethostent() ) …

Android 网络协议与网络编程

一、TCP/IP协议 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联 协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP 协议组成。协议采用了4层的层级结构。…

ad+硬件每日学习十个知识点(24)23.8.4(时序约束,SignalTap Ⅱ)

文章目录 1.建立时间和保持时间2.为什么要建立时序约束?3.SignalTap Ⅱ4.SignalTap Ⅱ使用方法5.HDL的仿真软件(modelsim)6.阻抗匹配 1.建立时间和保持时间 答: 2.为什么要建立时序约束? 答: 3.Sign…

基于STM32CUBEMX驱动低压步进器电机驱动器STSPIN220(3)----定时器中断产生指定数量脉冲

基于STM32CUBEMX驱动低压步进器电机驱动器STSPIN220----3.定时器中断产生指定数量脉冲 概述样品申请视频教学STM32CUBEMX配置产生固定数量的PWM电机设置STSPIN220初始化主程序 概述 在步进电机控制过程中,为了实现精确的位置和速度控制,经常需要输出指定…

tomcat配置文件和web站点部署(zrlog)简介

一.tomcat/apache-tomcat-8.5.70/conf/server.xml组件类别介绍 1.类别 2.Connector参数 3.host参数 4.Context参数 二.web站点部署(以zrlog为例) 1.将zrlog的war包传到webapps下面 2.在mysql数据库中创建zrlog用户并赋予权限 3.完成安装向导,登录管理界面即可…

分布式链路追踪概述

分布式链路追踪概述 文章目录 分布式链路追踪概述1.分布式链路追踪概述1.1.什么是 Tracing1.2.为什么需要Distributed Tracing 2.Google Dapper2.1.Dapper的分布式跟踪2.1.1.跟踪树和span2.1.2.Annotation2.1.3.采样率 3.OpenTracing3.1.发展历史3.2.数据模型 4.java探针技术-j…

【福建事业单位-推理判断】08逻辑论证-加强-原因解释-日常总结

福建事业单位-推理判断】08逻辑论证-加强 一、加强题1.1 建立联系——搭桥1.2 补充论据必要条件(没它不行)补充论据(解释原因和举例论证) 总结 二、原因解释题三、日常结论复习建议 一、加强题 加强的题型,一般只加强…

【HMS Core】推送报错907135701、分析数据查看

【关键字】 HMS、推送服务、分析服务 【问题描述1】 集成推送服务,获取Token时报错 907135701: scope list empty 【解决方案】 907135701OpenGW没有配置Scope 1、您可以检查下网络是否有问题,手机是否可以正常连接互联网 2、查看推送服务开关是否正…

高压放大器芯片的作用和用途是什么呢

高压放大器芯片是一种应用于电子、通信、医疗等领域的电子元件,它可以将输入信号放大到足以驱动负载所需的电平,并具有高性能、高可靠性和高效率等特点。下面安泰电子将详细介绍高压放大器芯片的作用和用途: 图:ATA-7000系列高压放…

04-5_Qt 5.9 C++开发指南_QComboBox和QPlainTextEdit

文章目录 1. 实例功能概述2. 源码2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. 实例功能概述 QComboBox 是下拉列表框组件类,它提供一个下拉列表供用户选择,也可以直接当作一个QLineEdit 用作输入。OComboBox 除了显示可见下拉列表外,每个…

童年回忆——捕鱼达人(内含源码inscode一键运行)

前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄,vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

【GO】 33.go-zero 示例

1. 获取go-zero库 go get -u github.com/zeromicro/go-zero 2. 安装goctl brew install goctlgoctl -v #goctl version 1.5.4 darwin/amd64 3. 创建.api文件, greet.api goctl api -o greet.api syntax "v1"info (title: // TODO: add titledesc: //…

jupyter lab build失败,提示需要安装版本>=12.0.0的nodejs但其实已从官网安装18.17.0版本 的解决方法

出现的问题如题目所示,这个问题差点要把我搞死了。。。但还是在没有重装的情况下解决了😘。 问题来源 初衷是想安装lsp扩展,直接在jupyter lab网页界面的extensions中搜索lsp并点击install krassowski/jupyterlab-lsp,会提示需要…

缓存失效问题

目录 一、缓存穿透 二、缓存雪崩 三、缓存击穿 本地锁 分布式锁-使用redis存储key 阶段一 阶段二 阶段三 阶段四 一、缓存穿透 缓存穿透 是指 查询一个一定不存在的数据 ,由于缓存是不命中,将去查询数据库,但是数据库也无此记录&#xff0c…

matlab使用教程(10)—脚本和函数

1.概述 MATLAB 提供了一个强大的编程语言和交互式计算环境。您可以使用此语言在 MATLAB 命令行中一次输入一个命令,也可以向某个文件写入一系列命令,按照执行任何 MATLAB 函数的相同方式来执行这些命令。使用 MATLAB 编辑器或任何其他文件编辑器可以创建…

Swintransformer模型的优化

SwinTransformer模型优化 文章目录 SwinTransformer模型优化1.SwinTransformer概述2.性能瓶颈分析3.模型优化3.1.transpose消除3.2.更好的layergroup3.1.1.SliceOp3.1.2.SqueezeOp3.1.3.weight切分 4.优化效果 1.SwinTransformer概述 自从Transformer在NLP任务上取得突破性的进…

HikariDataSource类的作用和使用

HikariDataSource是一个Java数据库连接池的实现,它属于HikariCP连接池库。连接池是一个用于管理数据库连接的工具,它可以帮助优化数据库连接的创建和销毁过程,提高数据库操作的性能和效率。 HikariDataSource类的作用是创建和管理数据库连接…

为什么要选择文件传输软件?有哪些最佳高速文件传输软件?

是否经历过这样的场景,正在努力地完成工作任务,但是由于制作的数据无法及时传送给合作伙伴,工作流程被打断了?这听起来很令人沮丧,对吧?可是,这种情况在现实中并不罕见。 因此,需要…

微服务与Nacos概述

微服务概述 软件架构的演变:单体架构、垂直应用架构、流式计算架构 SOA、微服务架构和服务网格。 微服务是一种软件开发架构,它将一个大型应用程序拆分为一系列小型、独立的服务。每个服务都可以独立开发、部署和扩展,并通过轻量级的通信机…

C++ 派生类成员的标识与访问——虚基类及其派生类构造函数

虚基类的使用非常方便,简单,这是由于程序中所有类使用的都是自动生成的默认构造函数。如果虚基类声明有非默认的(即带参的)构造函数,并且没有声明默认形式的构造函数。这时,在整个继承关系中,直…