第七章 Numpy介绍

1.Numpy介绍

1.介绍
Numpy是一个非常常见的库,之前我们学习过如何用它来表示矩阵。Numpy是非常的方便的一个库,可以通过它轻松地解决傅里叶变换,以及概率论还有线性代数的计算。如果你之前已经安装了Anaconda,那么理论上Numpy库已经被创建在你的Anaconda里面了,需要使用的时候直接import numpy就行,如果没有也只需要在终端pip install numpy(失败就用conda install numpy)即可。同时,我们总是习惯在import的时候,给numpy起个别称np,方便写代码,像这样:

import numpy as np

2.基本运算单位
就像我们之前学习的pytorch库的基本运算单位是tensor一样,凡是涉及到计算的库,我们如果想要学好它,就需要先学习它的基本单位是什么,我们才知道如何去定义变量进行计算。
在Numpy中,其基本运算单位是Ndarray,定义方法和python的数组没有什么区别,但是python数组允许每个数据的类型不一致,Ndarray则要求每个数据的类型必须是相同的。

3.创建Ndarray数组
创建方式一点都不难,简单到爆炸,因为和我们平时创建普通数组的方法没有任何区别。Ndarray数组的创建方式分为自定义和通过接口创建两种,我们依次介绍。
(1)自定义:自定义的话,我们需要先设置好自己的数组(或者元组)传入np.array()函数,但是要保证所有的数据类型都是一样的,不然会报错。例如

a = [0, 1, 2, 3, 4]		# 可以是数组
b = (0, 1, 2, 3, 4)		# 可以是元组
A = np.array(a)
B = np.array(b)

这里注意一下,无论你是用哪种形式创建的ndarray,最后类型都是一样的numpy.ndarray类型,所以A,B没有啥区别。

(2)通过接口来定义:
1 ◯ \textcircled{1} 1np.zeros()函数,需要传入的参数依次有维度(不填默认为1),行数x列数,(这三个一起用元组表示),以及数据类型detype。注意一点,定义维度时,维度是最前面那个,比如4x3x3定义了4个3x3矩阵。举例:

Z = np.zeros((33),dtype=int)	# 3x3的一个Int类型的0矩阵
Z2 = np.zeros((3,3,3),dtype=float) # 3个3x3float零矩阵(也可以说是3x3x3)

这里附上一个Z2的打印结果:

[
[[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]

 [[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]

 [[0. 0. 0.]
  [0. 0. 0.]
  [0. 0. 0.]]
  ]

可以看到是由三个3x3的0矩阵组成的数组,所以可以称为3x3x3的0矩阵

2 ◯ \textcircled{2} 2np.ones()生成单位矩阵,用法同上。

O = np.ones((2, 2, 2),dtype=int) #一个2x2x2类型为Int的单位矩阵

3 ◯ \textcircled{3} 3np,random随机数矩阵大家族,一共有四种,它们都不需要指定类型,因为它们的类型是固定的float(只有一个是int)。但是参数的传入方法不一样。
首先是np.random.rand()和np.random.randn()这两个函数。rand()生成(0,1)范围内的均匀分布随机数矩阵和randn()生成正太分布r的随机数矩阵。这两个的用法和上面不一样,它们只需要传入矩阵规模就行了(行数列数和每个单元数字的数目(每个单元数字的数目可以不填,默认为1))。这里解释一下,什么是每个单元的数字数目,其实前面的单位矩阵和零矩阵每个位置都只有一个数字,不是向量,但是随机矩阵这里是可以指定为向量来做单元的,这里给上例子和结果来理解:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a = np.random.rand(3, 3, 4)  # (0,1)均匀分布的随机数
b = np.random.randn(4, 4)    # 正太分布随机数

print(f"随机数矩阵1为:\n{a}")
print(f"正态分布的随机数矩阵为:\n{b}")

结果如下:

随机数矩阵1为:
[[[0.86652167 0.43213098 0.496585   0.14152115]
  [0.56226326 0.04437779 0.69080454 0.00303111]
  [0.96163042 0.35442079 0.13578848 0.69374048]]

 [[0.58851887 0.95796226 0.92340012 0.02522456]
  [0.0332563  0.22479247 0.69906303 0.95278404]
  [0.68927253 0.73203166 0.72147201 0.9109623 ]]

 [[0.81081839 0.98984553 0.3185658  0.42967656]
  [0.7839857  0.85217938 0.10993794 0.59476716]
  [0.32460013 0.98636237 0.29138712 0.44057259]]]
正态分布的随机数矩阵为:
[[ 0.79077707 -1.79275493  0.18175188  0.24232469]
 [-0.16919466 -0.80757122  1.16894734  0.01578053]
 [ 1.06789608 -0.13294504  0.79147516 -1.55178024]
 [ 2.02420851  1.51457941  1.17272312 -0.6959131 ]]

其次是np,random.random(),它生成(0,1)范围内的随机数,且该随机数组,不服从任何特定分布。它的参数也和之前的zeros还有ones没有区别,也是传入元组,且也是(维度x行x列的形式),例子:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np
a = np.random.random((3, 3, 3))  # (0,1)随机数
print(f"随机数矩阵为:\n+{a}")

输出结果为:

随机数矩阵为:
+[[0.86050578 0.63774575 0.02023288]
 [0.65343622 0.8246144  0.20655878]
 [0.98017708 0.91932295 0.08390556]]

最后一个是np.random.randint(),它可以生成指定范围的整数随机数矩阵,一共有三个参数,前两个指定整数范围,最后一个和之前一样是元组,且指定大小和维度。例如:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a = np.random.randint(1, 9, (3, 3))  # 生成一个3x3的随机数矩阵,范围在1-9
print(f"随机数矩阵为:\n{a}")

输出结果为:

随机数矩阵为:
[[7 1 3]
 [2 4 2]
 [1 1 6]]

4. 保存和加载数组
保存方式和之前保存神经网络稍微有一点不一样,神经网络保存时,网络名写前面,地址写后面,这里它地址写前面,数组名称写后面。
具体用法如下:

np.save('保存的路径/名称.后缀', 数组) # 保存为.npy文件
np.savetxt('保存的路径/名称.后缀',数组)	# 保存为.txt或者是.csv文件

这里的后缀有三种,分别是.npy 和.txt还有.csv,第一行save()函数,不管你有没有后缀,后缀是什么,都会给你保存成.npy文件,第二种需要指定csv,不然默认保存为txt文件
对应的加载方式也有三种:

np.load('名称')	# 加载.npy文件
np.loadtxt('名称')	# 加载.txt文件
np.genfromtxt('名称')	# 加载.csv文件(这代码其实先将其转为了txt再加载,因为它其实是用txt的方式保存的)

其中只有.npy是无损的,保存进去什么类型的数组,出来还是什么类型,所以我们也多用.npy来处理,至于.csv和.txt文件,它们在处理时都会自动的给转成浮点数。下面是一个实际的例子:
我们先把之前的随机数数组保存一下,记得它是整数型的

@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time2023/3/11 21:33
"""
import numpy as np

a = np.random.randint(1, 9, (3, 3))  # 生成一个3x3的随机数矩阵,范围在1-9

print(f"随机数矩阵为:\n+{a}")
np.save('a.npy', a)
np.savetxt('a.txt', a)
np.savetxt('a.csv', a)

运行结果是这个:

随机数矩阵为:
[[6 6 6]
 [8 7 3]
 [3 2 1]]

我们现在把它们加载进来看看:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a = np.load('a.npy')    # 加载.npy文件
a1 = np.loadtxt('a.txt')     # 加载.txt文件
a2 = np.genfromtxt('a.csv')  # 加载.csv文件

print(f"npy文件为:\n{a}")
print(f'txt文件为:\n{a1}')
print(f"csv文件为:\n{a2}")

输出结果如下:

npy文件为:
[[6 6 6]
 [8 7 3]
 [3 2 1]]
txt文件为:
[[6. 6. 6.]
 [8. 7. 3.]
 [3. 2. 1.]]
csv文件为:
[[6. 6. 6.]
 [8. 7. 3.]
 [3. 2. 1.]]

5.输出ndarray中想要的元素
我们有时候,并不要一个数组里面的全部元素,只要其中一部分,方法有两种,分别对应输出一个元素的索引法和输出多个连续元素的切片法:
(1)索引法: 数组名称[维度下标][行下标][列下标],如果只是二维的,那么:
数组名称[行数,列数]的方法也可以,同样的,上面的方法,如果只是一行,列就不用写。举个例子:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [1, 2, 3, 4]
a1 = [[1, 2], [3, 4]]
A0 = np.array(a0)  # 一维向量
A1 = np.array(a1)  # 2x2的矩阵
A2 = np.random.randint(1, 9, (4, 3, 3))  # 4个3x3的随机矩阵

print(f"A0是这样的:\n{A0}\n")
print(f"A1是这样的:\n{A1}\n")
print(f"A2是这样的:\n{A2}\n")

print(f"A0的第三个数字是: {A0[2]}\n")  # 注意,索引是从0开始的
print(f"A1的第二行,第一个元素是:{A1[1][0]}")    # 矩阵的第一种查看法
print(f"A1的第一行,第1个元素是:{A1[0, 0]}\n")      # 矩阵的第二种看法
print(f"A2的第3个矩阵的第二行第三个元素是:{A2[2][1][2]}")  # 注意看,这里维度是写在最前面的,符合我们的习惯
print(f"A2的第3个矩阵的第二行第三个元素是:{A2[2,1,2]}")  # 这样也是一样

输出结果为:

A0是这样的:
[1 2 3 4]

A1是这样的:
[[1 2]
 [3 4]]

A2是这样的:
[[[6 3 2]
  [6 1 5]
  [8 8 7]]

 [[5 3 5]
  [8 8 7]
  [6 7 5]]

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

 [[2 3 3]
  [5 6 5]
  [6 2 6]]]

A0的第三个数字是: 3

A1的第二行,第一个元素是:3
A1的第一行,第1个元素是:1

A2的第3个矩阵的第二行第三个元素是:7

(2)切片法: 切片法查找的是一定范围内的多个元素,用法如下:
数组名称 [ 开始的下标 ( 开始的索引 ) : 结束的下标(结束的索引 + 1 ) : 步长 ] 数组名称[开始的下标(开始的索引):结束的下标(结束的索引+1):步长] 数组名称[开始的下标(开始的索引):结束的下标(结束的索引+1:步长]
其中,开始下标不写默认是0,结束下标不写默认是列尾部元素的索引+1,步长不写,默认为1步。开始下标和结束下标为负数表示倒数,步长为负数表示倒退。上面介绍的是一维的,如果是二维的(矩阵),那我们给矩阵加上x和y坐标轴,查找范围的指定方法为分别指定x坐标上的范围和y坐标上的范围:
数组名称 [ x 开始下标 : x 结束下标: x 步长 , y 开始下标: y 结束下标, y 步长 ] 数组名称[x开始下标:x结束下标:x步长,y开始下标:y结束下标,y步长] 数组名称[x开始下标:x结束下标:x步长,y开始下标:y结束下标,y步长]
如果是三维及以上,我们就可以把它看着是一个长方形,可以用x,y,z坐标系来描述:
图是这样的:图片来自网络,侵权请联系1700098233@qq.com

多维切片的公式:
数组名称 [ x 开始 : x 结束 : x 步长 , y 开始 : y 结束 : y 步长 , z 开始 : z 结束 : z 步长 ] 数组名称[x开始:x结束:x步长,y开始:y结束:y步长,z开始:z结束:z步长] 数组名称[x开始:x结束:x步长,y开始:y结束:y步长,z开始:z结束:z步长]
如果没有步长没有开始和结束,只需要输入一个数字,和索引是一样的,全要是:,且::之间可以不要逗号,比如[1,::],就是只要x轴的第二行切出来的yz轴组成的平面的数据,如果三个都是数字,就可以退化为索引。举个例子:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [1, 2, 3, 4]
a1 = [[1, 2, 7], [3, 4, 8], [5, 6, 9]]
A0 = np.array(a0)  # 一维向量
A1 = np.array(a1)  # 2x2的矩阵
A2 = np.random.randint(1, 9, (4, 3, 3))  # 4个3x3的随机矩阵

print(f"A0是这样的:\n{A0}\n")
print(f"A1是这样的:\n{A1}\n")
print(f"A2是这样的:\n{A2}\n")

# 这里步长全是1
print(f"A0的2到3个元素是: {A0[1:4]}\n")  # 开始是从0开始,但是结尾是正常结尾,也就是索引加一
print(f"A1的x轴上的(2-3),y轴上的(1-2)组成的2x2的元素矩阵是:\n{A1[1:3, 0:3]}")  # 矩阵切片
print(f"A2的用x=0和x=1切出的两个矩阵是:\n{A2[0:2,::]}")  # 多维向量切片,切出的是前两个矩阵

输出结果为:

A0是这样的:
[1 2 3 4]

A1是这样的:
[[1 2 7]
 [3 4 8]
 [5 6 9]]

A2是这样的:
[[[4 3 7]
  [3 5 8]
  [3 6 7]]

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

 [[6 5 2]
  [8 2 6]
  [8 6 2]]

 [[1 2 3]
  [3 8 6]
  [1 8 1]]]

A0的2到3个元素是: [2 3 4]

A1的x轴上的(2-3),y轴上的(1-2)组成的2x2的元素矩阵是:
[[3 4 8]
 [5 6 9]]
A2的用x=0和x=1切出的两个矩阵是:
[[[4 3 7]
  [3 5 8]
  [3 6 7]]

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

6.重塑数组
我们可以用重塑数组的方式,来改变数组的性状,可以把一维变为二维,三维甚至是多维如图所示:
图片来自网络,侵权请联系1700098233@qq.com
重塑的代码也很简单,使用np.shape(数组名,(维度x行x列)) 就可以,但是要注意:原本数组的元素个数必须等于维度x行x列,也就是转换后元素不能多也不能少。举例:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [1, 2, 3, 4, 5, 6, 7, 8]

A = np.array(a0)
B = np.reshape(A, (2, 2, 2))	# 数组重塑为2个2x2矩阵
C = np.reshape(B, (1, 8))		# 变回去

print(f"原本的数组是:\n{A}\n")
print(f"把原本数组转为两个2x2的矩阵:\n{B}\n")
print(f"把转换后的又转回去成一维向量:\n{C}")

输出结果为:

原本的数组是:
[1 2 3 4 5 6 7 8]

把原本数组转为两个2x2的矩阵:
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

把转换后的又转回去成一维向量:
[[1 2 3 4 5 6 7 8]]

7.数组运算
数组的运算和矩阵的运算不一样,不然numpy也不会设置成两个模块,现在我们来说说ndnarray的计算方法:
(1)和常数的数乘运算: A ∗ x A*x Ax,其中, A A A是数组, x x x是常数,计算结果和矩阵是一样的,数组的每个元素的乘以 x x x,例如:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [1, 2, 3, 4, 5, 6, 7, 8]

A = np.array(a0)
B = A*3

print(f"原本的数组是:\n{A}\n")
print(f"数乘3以后的数组是:\n{B}")

输出结果为:

原本的数组是:
[1 2 3 4 5 6 7 8]

数乘3以后的数组是:
[ 3  6  9 12 15 18 21 24]

(2)数组和常数的加法计算用法和上面的数乘类似,只不过变成了加号: A + x A+x A+x,加x的意思就是每一个数组的元素都加上x,例子如下:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [1, 2, 3, 4, 5, 6, 7, 8]

A = np.array(a0)
B = A+3

print(f"原本的数组是:\n{A}\n")
print(f"加3以后的数组是:\n{B}")

输出结果为:

原本的数组是:
[1 2 3 4 5 6 7 8]

加3以后的数组是:
[ 4  5  6  7  8  9 10 11]

这种加一个常数或者乘以一个常数,会和全部的元素相加或者相乘的机制,叫做广播,利用这个特性,我们可以用数乘单位矩阵的方式,快速获得任意数字组成的矩阵(下面的数组间计算讲完一次举例)。

(3)数组和数组之间的计算,数组之间的计算和矩阵的计算规则不一样,矩阵有着加减乘除,且做法也更简单,首先要求做算法的两个矩阵的大小是一样的,之后就可以加减乘除了,计算的时候就是每一个对应的元素都进行加减或者乘除操作。具体操作见下面这个例子:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

A = np.array(a0)
B = np.ones((3, 3), dtype=int) * 3
C = A + B
D = A - B
E = A * B
F = A / B

print(f"A是一个三乘三的矩阵:\n{A}\n")
print(f"B是一个由3组成的矩阵:\n{B}\n")
print(f"A+B:\n{C}\n")
print(f"A-B:\n{D}\n")
print(f"A*B:\n{E}\n")
print(f"A/B:\n{F}")

输出如下:

A是一个三乘三的矩阵:
[[1 2 3]
 [4 5 6]
 [7 8 9]]

B是一个由3组成的矩阵:
[[3 3 3]
 [3 3 3]
 [3 3 3]]

A+B:
[[ 4  5  6]
 [ 7  8  9]
 [10 11 12]]

A-B:
[[-2 -1  0]
 [ 1  2  3]
 [ 4  5  6]]

A*B:
[[ 3  6  9]
 [12 15 18]
 [21 24 27]]

A/B:
[[0.33333333 0.66666667 1.]
 [1.33333333 1.66666667 2.]
 [2.33333333 2.66666667 3.]]

8.更高级的数组运算
更高级的数组运算包括数组的n次方、倒数、 e 数组 e^{数组} e数组 log ⁡ e 数组 \log_e^{数组} loge数组,分别对应的是:

# A是数组
# 次方:
A**n
# 倒数:
1/A
# e的数组次方
np.exp(A)
# e的对数
np.log(A)

它们的计算方式也遵循之前说的广播机制,就是会一个个地进行计算。
拿刚刚的矩阵举例:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

A = np.array(a0)
C = A**2
D = 1/A
E = np.exp(A)
F = np.log(A)

print(f"A是一个三乘三的矩阵:\n{A}\n")
print(f"A的平方:\n{C}\n")
print(f"A的倒数:\n{D}\n")
print(f"e^A:\n{E}\n")
print(f"ln(A):\n{F}")

输出为:

A是一个三乘三的矩阵:
[[1 2 3]
 [4 5 6]
 [7 8 9]]

A的平方:
[[ 1  4  9]
 [16 25 36]
 [49 64 81]]

A的倒数:
[[1.         0.5        0.33333333]
 [0.25       0.2        0.16666667]
 [0.14285714 0.125      0.11111111]]

e^A:
[[2.71828183e+00 7.38905610e+00 2.00855369e+01]
 [5.45981500e+01 1.48413159e+02 4.03428793e+02]
 [1.09663316e+03 2.98095799e+03 8.10308393e+03]]

ln(A):
[[0.         0.69314718 1.09861229]
 [1.38629436 1.60943791 1.79175947]
 [1.94591015 2.07944154 2.19722458]]

在学了这几个操作以后,我们也可以定义自己的SIgmoid,Thn还有交叉熵函数了。

9.比较运算:
Ndarray数组也支持比较运算,就是比大小或者是等于,符合是True,不符合是False,并且它是把数组中的元素一个个比过来。举例说明一下:

"""
@FileName:use_numpy.py
@Description:怎么用numpy的学习
@Author:段鹏浩
@Time:2023/3/11 21:33
"""
import numpy as np

a0 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
a1 = [[1, 3, 3], [7, 5, 6], [7, 10, 9]]
A = np.array(a0)
B = A == 2
C = A > 5
D = np.array(a1)
F = A == D
print(f"A是一个三乘三的矩阵:\n{A}\n")
print(f"A中的每一个元素和1的相等比较结果:\n{B}\n")
print(f'A中的每一个元素是不是比5大的比较结果:\n{C}\n')
print(f"D也是一个3x3的矩阵:\n{D}\n")
print(f"A和D中相等的元素的比较结果:\n{F}")

输出结果为:

A是一个三乘三的矩阵:
[[1 2 3]
 [4 5 6]
 [7 8 9]]

A中的每一个元素和1的相等比较结果:
[[False  True False]
 [False False False]
 [False False False]]

A中的每一个元素是不是比5大的比较结果:
[[False False False]
 [False False  True]
 [ True  True  True]]

D也是一个3x3的矩阵:
[[ 1  3  3]
 [ 7  5  6]
 [ 7 10  9]]

A和D中相等的元素的比较结果:
[[ True False  True]
 [False  True  True]
 [ True False  True]]

我们可以看到,数组和数字比大小,等于在和这个用这个数字为单位的等大小矩阵比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值