【深度学习基础】NumPy数组库的使用

news2024/11/11 18:31:00

目录

写在开头

 一、数组的类型与维度

数组的类型

数组的维度

二、数组的创建

递增数组 

同值数组

随机数数组 

三、数组的索引

访问/修改单个元素 

花式索引 

数组的切片

四、数组的变形

数组的转置

数组的翻转

数组的形状改变

数组的拼接

五、数组的运算 

 数组与常数的运算

数组与数组的运算 

六、数组的函数

线性代数中的矩阵乘法

数学函数 

聚合函数 

七、布尔型数组 

布尔型数组的生成  

布尔型数组的常用函数 

八、从NumPy数组到PyTorch张量 

写在最后 

写在开头

   近期好久不写博客了,主要是心态略有浮躁,同时对于自己的网络安全专业和未来方向也略显怀疑,可能还会迷茫一段时间,但我已经决定尽可能让自己忙碌起来,心态尽量平和,少受互联网信息的影响,避免过多思考人生与未来。至于这个新开的深度学习专栏的来由,主要是本人近期要开始研究写论文的东西,要选取一些深度学习模型对某种网络攻击类型进行检测,而我本人又对于深度学习的领域仅限于了解一些基础原理,实践能力(当调参侠)基本没有,因此我也从头开始慢慢学习,用博客做个记录。不过我相信慢就是快,一步一步脚踏实地慢慢来,也终将会有所进步。

   此处还特别感谢B站爆肝杰哥的视频,详解了配置pytorch环境的每一步。这里放上其视频链接(本文并不涉及到pytorch的内容,后续博客可能会用到):

Python深度学习:安装Anaconda、PyTorch(GPU版)库与PyCharm_哔哩哔哩_bilibili

  本文使用的NumPy库的版本为1.21,不过相近版本的语法都大差不差,基本可以通用。在进入深度学习具体算法的学习之前我们先介绍NumPy数组库,这是因为NumPy包为Python提供了数组变量的类型,弥补了Python本身数据类型的不足。虽然Python中的列表数据类型也可以实现数组的功能,但对于列表,其每个元素的数据类型是可以不同的,因此列表在存储元素的值的同时也要存储该元素的数据类型,这在一定程度上浪费了内存。而NumPy数组中的元素仅可容纳一种数据类型,存储时可以节约内存,加快运算速度,更方便深度学习的相关处理。下面我们做一个简单的引入:

import numpy as np

arr1 = np.array([10, 20, 30])  # 创建整数型数组
arr2 = np.array([1, 2, 3.])   # 创建浮点型数组,内涵浮点数,即为浮点型数组
list1 = ["hello", 100, 3.14]   # 创建列表,元素的数据类型可以不同
print(arr1)
print(arr2)
print(list1)

 可看到NumPy数组与Python列表的不同:

1. Numpy数组的元素数据类型一致(可分为整数型数组和浮点型数组),而列表可以不一致。

2. Numpy数组用print输出后元素之间是没有逗号','的,而列表的元素之间有逗号','作为分隔。

 一、数组的类型与维度

数组的类型

    Numpy数组就两种类型,整数型/浮点型。其中可以用.astype()方法相互转换,示例如下:

arr1 = np.array([10, 20, 30])  # 创建整数型数组
arr2 = arr1.astype(float)    # 整数型转浮点型
arr3 = arr2.astype(int)      # 浮点型转整数型
print(arr1)
print(arr2)
print(arr3)

   另外通常情况下,整数型数组在运算过程中很容易升级为浮点型数组,只要与浮点数(组)做运算即可:

int_arr = np.array([10, 20, 30])   # 创建整数型数组
float_arr = np.array([1.0, 2, 3])  # 创建浮点型数组
print(int_arr + 0.0)  # 整数型数组与浮点数进行运算
print(int_arr * 1.0)
print(int_arr / 1)    # 除以整数也会升级为浮点型数组
print(int_arr + float_arr)

  这里特别注意整数型数组遇到除法(即使是➗整数),都会升级为浮点数组 

数组的维度

  基本上不会遇到三维以上的,数组的中括号层数反应了该数组的维度。这里列个表描述一维到三维数组的表示:

数组的维度及其表示
数组维数形状表示举例说明
一维x 或 (x,)一维数组[1 2 3]的形状是3 或 (3,)
二维(x, y)二维数组[[1 2 3]]的形状是(1, 3)
三维(x, y, z)三维数组[[[1 2 3]]]的形状是(1, 1, 3)

  可以使用.shape属性(注意没有括号,不是方法!)查看数组的形状,举例如下

   数组之间的相互转化,使用.reshape()方法即可,参数填写想要转换的维数,例如想把(2,3)的数组转化为(3, 2)的数组:

arr1 = np.array([[1, 2, 3], [4, 5, 6]])
print("转换前:\n",arr1)
arr2 = arr1.reshape((3, 2))
print("转化后:\n", arr2)

 特别注意的是,reshape()方法有个方便之处,就是给定了每个维度之后,它可以自动算出最后一个维度是多少,最后的这个维度可以填写-1,举例如下:

# 将2*15的二维数组(矩阵)转换为5*6
arr1 = np.arange(30).reshape(2,15)   # 生成2*15的整数递增数组 
print("转换前:\n",arr1)
arr2 = arr1.reshape(5, -1)  # 填写-1时,reshape会自动计算出此处应该是6
print("转化后:\n", arr2)

二、数组的创建

递增数组 

  直接用np.array()函数可以将Python列表转化为Numpy数组,这个方法我们已经实现过。另外还可以用np.arange()函数创建递增数组格式如下:

arr = np.arange([起始位置x], 终止位置y, [步长s] )

这个和python中的range函数类似,生成[x, y)范围内的数组。print()

同值数组

创建同值数组可以用np.zeros()创建全为0.0的数组,用np.ones()创建全为1.0的数组。

arr1 = np.ones(3)
print(arr1)
arr2 = 3.14 * np.ones((2,4))  # 创建全为3.14的2*4的矩阵
print(arr2)

随机数数组 

   创建随机数组成的数组,需要使用np.random系列的函数,下面举例说明:

   首先是0-1均匀分布,方法为np.random.random(形状),举例如下:

# 创建0-1范围均匀分布的矩阵
arr1 = np.random.random(5)
print(arr1)
# 创建90-100范围均匀分布
arr2 = (100-90)*np.random.random((2, 3)) + 90
print(arr2)

   

如果想生成整数型随机数组,则通过np.random.randint(min,max, shape)实现: 

# 创建[1, 10)范围内的整数随机数组,矩阵形状为2*3
arr3 = np.random.randint(1, 10, (2,3))
print(arr3)

 另外,服从正太分布的随机数组的创建方法是np.random.normal(μ, σ, shape):

# 创建均值为80,标准差为5的正太分布随机数组,矩阵形状为3*3
arr4 = np.random.normal(80, 5, (3,3))
print(arr4)

   特别地,如果只需要标准正太分布,则可直接使用np.random.randn(shape)即可,只需要传入形状参数。

三、数组的索引

访问/修改单个元素 

   这个和Python列表一致,正索引从0开始,倒索引从-1开始,就懒得具体描述了。注意对单一元素修改时,不会改变原本矩阵的类型(整数型/浮点型)即可

arr = np.arange(1, 10).reshape((3,-1))
print(arr)
arr[1,1] = 100.123  # 修改整形数组中的某个元素,数组依然为整形,该元素的浮点会被截断。
print(arr)

花式索引 

   用两层中括号可以进行花式索引,同时取出矩阵中的多个元素,输出仍然是个向量,举例如下:

arr = np.arange(1, 17).reshape((4,4))
print(arr)
# 花式索引,取出并修改副对角线的元素
print(arr[[0,1,2,3],[3,2,1,0]])

  利用这种方法,可以同时修改矩阵中的多个元素:

arr = np.arange(1, 17).reshape((4,4))
print(arr)
# 花式索引,取出并修改副对角线的元素
arr[[3,2,1,0],[0,1,2,3]] = (100,200,300,400)
print("修改后:\n", arr)

数组的切片

 这快其实完全可以类比Python中列表的切片,就简单举个例子略过好了:

# 生成10*10的矩阵
arr = np.arange(1, 101).reshape((10,-1))
print(arr)
# 取出第4-5行,4-5列
print("取出最中间的2*2:\n", arr[4:6, 4:6])

  这里还需要特别注意:数组的切片仅仅是视图,数组的赋值也仅仅是绑定,并没有产生新的数组! 

# 生成10*10的矩阵
arr = np.arange(1, 101).reshape((10,-1))
print(arr)
# 取出第4-5行,4-5列
arr2 = arr[4:6, 4:6]
arr3 = arr
arr2[:,:] = 999
print(arr)
print(arr2)
print(arr3)

  由上图可知,改了arr2后,arr和arr2也会改变,这是因为不论是切片还是赋值,其实都不会创建新的数组,本质上都是相同的内存!要想创建新的变量,需要用到.copy方法才可(实际用到的很少,此处略)。

四、数组的变形

数组的转置

  使用.T即可实现转置,注意转置操作仅对矩阵有效,如果是向量(一维数组)需要升级为矩阵(二维数组)

arr1 = np.arange(1, 5)
print("初始向量:\n", arr1)
# 升级为矩阵
arr2 = arr1.reshape((1,-1))
print("矩阵:\n", arr2)
print("转置后的结果\n", arr2.T)

数组的翻转

     一共两个函数,分别是上下(up-down)翻转np.flipud()和左右(left-right)翻转np.fliplr()。注意对于向量(一维数组),只能进行上下翻转。这是因为在数学中,向量是以列向量的形式存在。下面举例说明即可:

# 向量的翻转
vec = np.arange(10)
print("初始向量:\n", vec)
vec_ud = np.flipud(vec)
print("向量翻转后:\n", vec_ud)

   矩阵的翻转如下:

# 矩阵的翻转
mat = np.arange(25).reshape((5, -1))
print("初始矩阵:\n", mat)
mat_lr = np.fliplr(mat)
print("左右翻转:\n", mat_lr)
mat_ud = np.flipud(mat)
print("上下翻转:\n", mat_ud)

数组的形状改变

  使用.reshape()方法即可,前面用到多次了,这里不再举例。

数组的拼接

  使用函数np.concatenate([arr1, arr2])即可实现拼接,如果是向量(一维),直接拼接即可。如果是矩阵,默认情况按照axis=0进行拼接(要求列的维度相同),也可以指定按照另一个维度进行拼接,注意对应维度元素个数相等。向量不能和矩阵进行拼接,需要先升级为矩阵。

# 向量的拼接
vec1 = np.array([1,2,3])
vec2 = np.array([7,8,9])
vec3 = np.concatenate([vec1, vec2])
print(vec3)

  矩阵拼接要注意对齐相应维数:

# 矩阵的拼接
mat1 = np.array([[1,2,3], [4,5,6]])
mat2 = np.array([[7,8,9], [10,11,12]])
mat3 = np.concatenate([mat1, mat2])   #默认情况,axis=0
mat4 = np.concatenate([mat1, mat2], axis=1)   #非默认情况, 指定axis=1
print("axis=0拼接:\n", mat3)
print("axis=1拼接:\n", mat4)

五、数组的运算 

 数组与常数的运算

 这个其实没啥好说的,就是Python中的那些常见运算符,加减乘除幂余取整啥的,常见运算符如下:

+  =  *  /  **  //  % 

   这些运算就是对矩阵中的元素逐个运算,特别注意除法会生成浮点型数组即可。随便举两个例子

数组与数组的运算 

  这里也没太多可讲的,如果数组的维度相同,则数组间的运算就是对应元素的运算(并不是线性代数中的运算方式)。

  如果进行运算的数组的维数不同,则会出现某一方被广播的情况,例如:

1. 向量与矩阵运算,则向量自动升级为行矩阵。即如果是 (y,) 与 (x,y)运算,则(x,)会先升级为(1,y),然后再运算

2. 如果某矩阵是行矩阵或列矩阵,则该矩阵被广播,以适配另一个矩阵的形状。

   与这个例子类似,列矩阵也可以被广播:

   行矩阵和列矩阵也可以同时被广播,即(1,y)的行矩阵与(x,1)的列矩阵运算,相当于先把各自广播为(x, y),再进行运算:

六、数组的函数

线性代数中的矩阵乘法

  就是函数np.dot(arr1,arr2)。当arr1和arr2均为向量时,相当于是向量点积,其他情况都可视为线性代数中的矩阵乘法:

数学函数 

 有一大堆,这里列一下好了

函数说明
np.abs()绝对值
np.sin()正弦
np.cos()余弦
np.tan()

正切

np.exp()指数e*x
np.log()对数ln(x)

  举例说明一下对数函数吧,默认是以e为底,以其他为底的话需要用换底公式:

聚合函数 

  就是按照对应维度的方向求最大最小值,求和、平均值、标准差啥的。向量也可以,但向量没有axis参数,矩阵需要哪个用axis参数指明是哪个维度(当axis=0,最终结果的个数与每一行的元素个数相同。反之axis=1,最终结果的个数与每一列的元素个数相同)。列个表格:

函数说明
np.max(arr, axis=0),  np.min(arr, axis=1)按维度求最大或最小值
np.sum(arr, axis=0)按维度求和
np.mean(arr, axis=0), np.std(arr, axis=1)按维度最均值或标准差
# 聚合函数
arr = np.arange(1, 11).reshape((2, 5))
print(arr)
print("按照维度0求均值: ", np.mean(arr, axis=0))
print("按照维度1求均值: ", np.mean(arr, axis=1))
print("整体求均值: ", np.mean(arr))

特别注意:考虑到大型数组难免有缺失值,以上聚合函数碰到缺失值时会报错,因此出现了聚合函数的安全版本,即计算时忽略缺失值:np.nansum( )、 np.nanprod( ) 、np.nanmean( )、np.nanstd( )、np.nanmax( )、np.nanmin( )。

七、布尔型数组 

布尔型数组的生成  

顾名思义,就是每个元素都是布尔类型的数组,可以通过一些比较运算符产生(>, <, ==, !=, >=, <=)。这些于是奶奶是还可以多个条件同时使用(用与,或,非对应&, |, ~)下面举例说明:

# 布尔类型的产生
arr = np.arange(25).reshape(5,-1)
print(arr)
# 将值在(10, 18)范围内的位置置为True
print((arr>10)&(arr<18))
print("满足条件的个数为:", np.sum((arr>10)&(arr<18)))

布尔型数组的常用函数 

使用np.sum()函数可以统计布尔数组里True的个数,如上。另外还有两个常用函数,如下:

函数说明
np.sum(arr)统计布尔数组arr里True的个数
np.any(arr)arr中有一个是True,则为True,否则为False
np.all(arr)arr中所有的都是True, 才为True,否则为False
np.where(arr)返回arr中是True的位置

   这里可以举个例子,假设某次英语六级考试,10000人参加考试,所有人均分是425,标准差为70,进行一次模拟,判断是否所有的考生分数都>200,并找出高分的位置:

# 模拟六级成绩样本
arr = np.random.normal(425, 70, 10000)
# 判断是否所有人都高于200分
print(np.all(arr>200))
# 寻找高于650分的位置
print(np.where(arr>650))

八、从NumPy数组到PyTorch张量 

  PyTorch作为当前最常用的深度学习库,融合了NumPy数组的语法,作为处理张量的基本语法,且运算可用GPU加速,具有很大速度优势。NumPy数组和PyTorch张量有一定的对应关系:

1.np 对应 torch
2.数组 array 对应张量 tensor
3.NumPy n 维数组对应着 PyTorch n 阶张量
NumPy数组和PyTorch张量可用相互转化:
ts = torch.tensor(arr) 或  arr = np.array(ts)

   NumPy数组和PyTorch张量相关处理的不同点,基本上将np改为torch,array改为tensor,即可对应Pytorch的处理方法。不过也有少量不同,此处根据B站爆肝杰哥的总结,列举不同点(表格源于B站:爆肝杰哥)。

写在最后 

   这一章节是PyTorch深度学习的基础,内容还挺多的。后续我可能还会更新一些DNN,CNN,RNN,GNN相关的博客,由于我的研究课题是要选取一些深度学习模型对某种网络攻击类型进行检测,可能会用到图神经网络相关的内容,后续学习的过程也会重点总结一下。

   今年感觉状态稀碎,不过慢慢来,相信慢就是快!不要太过在意短期的得失。如果各位读者有什么问题也欢迎评论区指出,也可以私信与我讨论(也可以是技术无关的问题),我一定知无不言。

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

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

相关文章

心电信号处理算法(包括基线漂移消除技术,高通、低通和陷波滤波,等值线校正和QRS等波群标记等,MATLAB代码)

由于心电信号是心脏活动产生的电位差变化并在人体皮肤表面采集得到的微弱信号&#xff0c;频率大致为0.05Hz~100Hz&#xff0c;波形幅值在10μV~5mV内。与其他生理信号不同之处是&#xff0c;心电信号的频率较低且波形幅值小&#xff0c;在采集时容易被各种噪声干扰。心电信号由…

HTML橙色爱心

目录 写在前面 准备开始 完整代码 运行结果 系列文章 写在后面 写在前面 本期小编给大家分享一颗热烈且浪漫的爱心&#xff0c;快来看看吧&#xff01; 准备开始 在开始之前&#xff0c;我们需要先简单的了解一下这颗爱心的原理哦~ 本期将用html实现这颗跳动的爱心&a…

5.26机器人基础-空间描述和变换-总结

非目录 方便我找 重点 逆解 位姿矩阵的几何意义 实际坐标需要除以比例因子才能得到 比例因子的好处&#xff1a;在计算机的储存更加简单方便&#xff0c;例如x,y,x原先很大时&#xff0c;等比例改变 位姿坐标的齐次变换&#xff1a;左乘齐次坐标 从端点到末端&#xff0c…

rtthread 堆空间申请

#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) //定义堆开始的地址 程序仿真查看 begin_align rw_size; 堆开始地址 最大栈地址 堆的结束地址 ram1最大地址&#xff0c;128kbytes 处。 上述就是rtthread 申请的堆空间大小。

民国漫画杂志《时代漫画》第25期.PDF

时代漫画25.PDF: https://url03.ctfile.com/f/1779803-1248635084-fd4794?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

【数据结构(邓俊辉)学习笔记】图01——图的表示与实现

文章目录 1. 概述1.1 邻接 关联1.2 无向 有向1.3 路径 环路 2. 邻接矩阵2.1 接口2.2 邻接矩阵 关联矩阵2.3 实例2.4 顶点和边2.5 邻接矩阵2.6 顶点静态操作2.7 边操作2.7 顶点动态操作2.8 综合评价 1. 概述 1.1 邻接 关联 相对于此前的线性以及半线性结构&#xff0c;图…

【Python】 XGBoost模型的使用案例及原理解析

原谅把你带走的雨天 在渐渐模糊的窗前 每个人最后都要说再见 原谅被你带走的永远 微笑着容易过一天 也许是我已经 老了一点 那些日子你会不会舍不得 思念就像关不紧的门 空气里有幸福的灰尘 否则为何闭上眼睛的时候 又全都想起了 谁都别说 让我一个人躲一躲 你的承诺 我竟然没怀…

内存函数详解,包含部分字符串函数

目录 一&#xff0c;memcpy内存函数的介绍 二memmove函数的介绍 三&#xff0c;memset的函数使用 四&#xff0c;memcmp的介绍 五&#xff0c;内存函数的模拟实现&#xff0c;以及一个字符串函数strstr的模拟实现 5.1memcpy函数的实现 5.2memmove的模拟实现 5.3memcmp的模拟…

19 QinQ技术(Vlan两层封装)

1 什么是QinQ&#xff1f; QinQ&#xff08;802.1Q-in-802.1Q&#xff09;&#xff0c;也叫做VLAN Stacking或Double VLAN&#xff0c;由IEEE 802.1ad标准定义&#xff0c;**是一项扩展VLAN空间的技术&#xff0c;**通过在802.1Q标签报文的基础上再增加一层802.1Q的Tag来达到扩…

Stream流常用操作

一、中间操作 中间操作是返回一个新的流&#xff0c;并在返回的流中包含所有之前的操作结果。它们总是延迟计算&#xff0c;这意味着它们只会在终止操作时执行&#xff0c;这样可以最大限度地优化资源使用。 1. filter(过滤) filter()方法接受一个谓词&#xff08;一个返回boo…

Vue.js条件渲染与列表渲染指南

title: Vue.js条件渲染与列表渲染指南 date: 2024/5/26 20:11:49 updated: 2024/5/26 20:11:49 categories: 前端开发 tags: VueJS前端开发数据绑定列表渲染状态管理路由配置性能优化 第1章&#xff1a;Vue.js基础与环境设置 1.1 Vue.js简介 Vue.js (读音&#xff1a;/vju…

每日一问-如何设置VS Code 中 Markdown粘贴图片的位置

VS Code内的markdown编辑器应该算是比较好用的&#xff0c;但是有一个问题一直困扰着我&#xff0c;就是在编辑markdown文件时&#xff0c;粘贴图片的位置问题。默认情况下&#xff0c;VS Code会将粘贴的图片放在markdown文件的同级目录下&#xff0c;这样会导致markdown文件的…

【代码随想录——回溯算法二周目】

1. 组合总和 var (path []intres [][]int )func combinationSum(candidates []int, target int) [][]int {path make([]int, 0)res make([][]int, 0)dfs(candidates,target,0,0)return res }func dfs(candidates []int, target int,tempTarget int,start int) {if tempTarg…

1、Introduction to Python【Python简介】

主要目的是回顾一下主要的Python基础知识&#xff0c;当作复习。 1、使用Type查看变量属性 a 10 print(type(a)) 2、向列表中加入元素 fam [lisa, 1.74] fam [emma, 1.79]# fam [lisa, 1.74, emma, 1.79] 3、删除列表中某个元素 del(fam[index]) 4、列表具有唯一性 …

ASP.NET MVC 快速入门(图文版)

今年是2024年了&#xff0c;没有多少人在ASP.NET 去做开发&#xff0c;都使用ABP框架 &#xff0c;不过我们仍然需要了解ASP.NET MVC 的一个开发流程 MVC概述 MVC是当前比较流行的WEB程序开发模式之一&#xff0c;ASP.NET MVC是.Net对MVC的一种实现。MVC&#xff08;Model View…

CobaltStrike渗透框架进阶之扩展脚本和MSF联动

CobaltStrike扩展脚本 扩展是Cobaltstrike一个极为重要的模块&#xff0c;它有效地丰盈了cobaltstrike的功能 选择菜单栏的CobaltStrike–>脚本管理器&#xff0c;点击load&#xff0c;然后选择cna扩展文件即可&#xff0c;旁边的unload为去除该扩展&#xff0c;&#xff…

【iOS开发】—— KVC

【iOS开发】—— KVC 一. KVC的定义key和keyPath的区别用法&#xff1a; 批量复制操作字典模型相互转化KVC的其他方法 KVC原理赋值原理取值原理 一. KVC的定义 KVC&#xff08;Key-value coding&#xff09;键值编码&#xff0c;就是指iOS的开发中&#xff0c;可以允许开发者通…

3D牙科网格分割使用基于语义的特征学习与图变换器

文章目录 3D Dental Mesh Segmentation Using Semantics-Based Feature Learning with Graph-Transformer摘要方法实验结果 3D Dental Mesh Segmentation Using Semantics-Based Feature Learning with Graph-Transformer 摘要 本文提出了一种新颖的基于语义的牙科网格分割方…

小程序怎么改名

经常有商家想要对自己的小程序进行重命名&#xff0c;改名可能是为了更好地与品牌形象以及业务相匹配&#xff0c;也可能是为了更好地吸引用户。那么如何才能更名呢&#xff1f; 一、准备几个新名字。 在决定改名之前&#xff0c;首先要确定几个新的小程序名字。为什么要准备…

CCF20231201——仓库规划

CCF20231201——仓库规划 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n,m,a[1001][11],b[1001]{0};cin>>n>>m;for(int i1;i<n;i){for(int j1;j<m;j)cin>>a[i][j];}for(int i1;i<n;i){bool foundfals…