这个专栏名为《Numpy从入门到精通》,顾名思义,是记录自己学习numpy的学习过程,也方便自己之后复盘!为深度学习的进一步学习奠定基础!希望能给大家带来帮助,爱睡觉的咋祝您生活愉快! 这一篇介绍《Numpy从入门到精通——随机生成数组|特定生成数组|规则生成数组

文章目录

  • 0、写在前面
  • 一、Numpy基础知识
  • 二、数组属性
  • 三、random模块生成数组
  • 四、生成特定形状的多维数组的函数
  • 五、利用arange、linspace函数生成数组 

0、写在前面

之前虽然做过不少项目,但是感觉都是跑的demo,其中的语法,模型修改,算法重构自己一点也不清楚,所以准备系统的学习Pytorch,真正理解模型的创建和训练和修改。我打算对着我之前推荐的那本书来学,一步一步学习,在六月之前学习完。在寒假的时候,我就决定在正式开始深度学习,先把numpy学习完。因为在之前接触numpy和少量深度学习的知识之后,发现numpy中的矩阵和深度学习中的张量tensor十分相似,这两个之间常常会发生转化。所以我认为,学好numpy对于深度学习来说是必不可少的。

一、Numpy基础知识

我们都知道在计算机视觉中,图像的本质就是像素矩阵。说是对图像进行处理,但其实是对矩阵进行处理。而Numpy是数据科学的通用语言,它是科学计算、矩阵运算、深度学习的基石。numpy中的对象称为矩阵对象(ndarray对象),它直接保存数值,与C语言中的一维数组比较类似。

numpy主要有以下主要特点:

  1. 快速、节省空间,提供数组化的算术运算和高级的广播功能
  2. 使用标准数学函数对整个数组的数据进行快速操作,而不需要编写循环。
  3. 提供读写/写入磁盘上的阵列数据和操作存数器映像文件的工具(存储读取功能)
  4. 提供线型代数、随机数生成和傅里叶变换的能力
  5. 提供集成C、C++、Fortran代码的工具

我们使用Opencv库对图像进行深入探索,首先我们写一段最基本的Opencv读取图片显示的代码:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :numpy学习 
@File    :task_1.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/4/16 18:22 
"""
import cv2
image = cv2.imread("image.jpg")
cv2.imshow("image",image)
cv2.waitKey(0)
cv2.destroyAllWindows()

用type函数查看image的类型:

print(type(image))
# <class 'numpy.ndarray'>

从上面例子可以看出来,image图片的本质其实就是一个矩阵,np.ndarray。

二、数组属性

在Numpy中,维度被称为轴。np.ndarray有三个重要属性:

  • nd.array.ndim:数组的维度(轴)的个数
  • nd.array.shape:数组的维度,值为一个整数元组,元组的值代表对应的轴的长度。(x,y)中的x代表这个数组有几行,y代表这个数组有几列。
  • nd.array.dtpye:数据类型,描述数组中元素的类型。

同样,我们以具体的例子进行讲解:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :numpy学习 
@File    :task_1.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/4/16 18:22 
"""
import numpy as np
import cv2
image = cv2.imread("image.jpg")
image_gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # 转成灰度图
print("image的维度为:",image.ndim)
print("image_gray的维度为:",image_gray.ndim)
print("image的大小为:",image.shape)
print("image_gray的大小为:",image_gray.shape)
print("image的数据类型为:",image.dtype)
print("image_gray的数据类型为:",image_gray.dtype)
# image的维度为: 3
# image_gray的维度为: 2
# image的大小为: (1080, 1920, 3)
# image_gray的大小为: (1080, 1920)
# image的数据类型为: uint8
# image_gray的数据类型为: uint8

ndim为维度,彩色图片通道数为3,维度为3;灰度图片通道数为1,维度为2。转化前后图片的大小不变,都为1080*1920,数据类型也不变,都为uint8。

将列表转为矩阵使用array函数:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :numpy学习 
@File    :task_2.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/4/16 19:48
"""
import numpy as np
import cv2
# 将列表转化为ndarray
list_1 = [0,1,2,3,4,5]
image_1 = np.array(list_1)
print(image_1.ndim)
print(image_1.shape)
# 将嵌套列表转化为ndarray
list_2 = [[0,1,2,3,4],[5,6,7,8,9]]
image_2 = np.array(list_2)
print(image_2.ndim)
print(image_2.shape)
# 将嵌套列表转化为ndarray,并用cv2显示
list_3 = [[[1,2,3],[1,2,3],[1,2,3]],
          [[1,2,3],[1,2,3],[1,2,3]],
          [[1,2,3],[1,2,3],[1,2,3]]]
image_3 = np.array(list_3,dtype="uint8")
print(image_3.ndim)
print(image_3.shape)
print(image_3.dtype)
cv2.imshow("image",image_3)
cv2.waitKey(0)
cv2.destroyAllWindows()

用array函数能够将list列表转为ndarray格式,注意如果想用opencv进行图片显示的话,注意array转化是,将dtpye设置成“uint8”,这样才能够用opencv正常显示。

三、random模块生成数组

在深度学习时,我们常常要对参数进行初始化,这就涉及到np.random进行生成数组。接下来用一个表和一段代码介绍np.random生成数组:

函数 描述
np.random.random 生成从0到1之间的随机数
np.random.uniform 生成均匀分布的随机数
np.random.randn 生成标准正态分布的随机数
np.random.randint 生成随机的整数
np.random.normal 生成正态分布的整数
np.random.shuffle 随机打乱顺序
np.random.seed 设置随机数种子
random_sampel 生成随机的浮点数
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :numpy学习 
@File    :task_3.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/4/17 9:06 
"""

import numpy as np

print('生成形状(4, 4),值在0-1之间的随机数:')
print(np.random.random((4, 4)), end='\n\n')

# 产生一个取值范围在[1, 50)之间的数组,数组的shape是(3, 3)
# 参数起始值(low)默认为0, 终止值(high)默认为1。
print('生成形状(3, 3),值在low-high之间的随机整数::')
print(np.random.randint(low=1, high=50, size=(3, 3)), end='\n\n')
print('产生的数组元素是均匀分布的随机数:')
print(np.random.uniform(low=1, high=3, size=(3, 3)), end='\n\n')

print('生成满足正态分布的形状为(3, 3)的矩阵:')
print(np.random.randn(3, 3))

结果为:

生成形状(4, 4),值在0-1之间的随机数:
[[1.09478767e-01 8.28542687e-01 2.29063164e-01 6.74524184e-01]
 [3.95004570e-01 2.21405468e-01 7.33547514e-02 1.52782087e-01]
 [9.89312618e-01 2.67019311e-01 6.23058383e-01 2.03517166e-01]
 [9.67375188e-01 4.01401820e-04 8.69373856e-01 4.89925436e-01]]

生成形状(3, 3),值在low-high之间的随机整数::
[[48 29 41]
 [17 29 17]
 [12 30 13]]

产生的数组元素是均匀分布的随机数:
[[2.53303787 1.30406591 1.73541217]
 [1.45465375 2.78644509 1.58166964]
 [2.7118102  2.50493356 1.31396379]]

生成满足正态分布的形状为(3, 3)的矩阵:
[[ 1.18399228 -0.17099359 -2.02865943]
 [-0.86478027 -0.68082124  0.84941314]
 [-0.03038969  2.32215063 -0.57330676]]

下面进一步阐述随机数种子的含义:
用上面随机方式产生的矩阵是无法重现的,如果想两次生成相同的矩阵,就用到了随机数种子,np.random.seed()

import numpy as np
np.random.seed(10) 
print("按指定随机种子,第1次生成随机数:")
print(np.random.randint(1, 5, (2, 2)))
 
# 想要生成同样的数组,必须再次设置相同的种子
np.random.seed(10)
print("按相同随机种子,第2次生成的数据:")
print(np.random.randint(1, 5, (2, 2)))

输出:

按指定随机种子,第1次生成随机数:
[[2 2]
 [1 4]]
按相同随机种子,第2次生成的数据:
[[2 2]
 [1 4]]

所以,想要生成的随机数是一样的,只需要在前面添加一个随机数种子,种子里面的代号就代表着随机数是什么,这里是10,你也可以换成其他数,代表着不同的随机数种子!

四、生成特定形状的多维数组的函数

有时,在对参数初始化时,会要求生成一些特殊的矩阵,比如全是1或者全是0的矩阵,在numpy中同样给我们留下了对应的函数,

函数 描述
np.zeros((3,.4)) 生成3x4的数组,元素全是0
np.ones((3,4)) 生成3x4的数组,元素全是1
np.empty((2,3)) 生成2x3的空数组,空数组中的值是未初始化的垃圾值
np.zeros_like(ndarr) 以ndarr相同维度生成元素全是0的数组
np.ones_like(ndarr) 以ndarr相同维度生成元素全是1的数组
np.empty_like(ndarr) 以ndarr相同维度生成空数组
np.eye(5) 生成一个5x5的矩阵,对角线全为1,其余全是0
np.full((3,5),666) 生成3x5的数组,元素全是666
np.diag([1, 2, 3]) 对角线为1,2,3的矩阵

下面我们看具体的代码:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :numpy学习 
@File    :task_5.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/4/17 9:19 
"""
import numpy as np

# 生成全是 0 的 3x3 矩阵
nd5 = np.zeros([3, 3])
# 生成与nd5形状一样的全0矩阵
# np.zeros_like(nd5)
# 生成全是 1 的 3x3 矩阵
nd6 = np.ones([3, 3])
# 生成 3 阶的单位矩阵
nd7 = np.eye(3)
# 生成 3 阶对角矩阵
nd8 = np.diag([1, 2, 3])
print("*" * 6 + "nd5" + "*" * 6)
print(nd5)
print("*" * 6 + "nd6" + "*" * 6)
print(nd6)
print("*" * 6 + "nd7" + "*" * 6)
print(nd7)
print("*" * 6 + "nd8" + "*" * 6)
print(nd8)

输出结果为:

******nd5******
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]
******nd6******
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
******nd7******
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
******nd8******
[[1 0 0]
 [0 2 0]
 [0 0 3]]

五、利用arange、linspace函数生成数组

在一些特定的情况中,我们还希望生成一系列有规律的矩阵,学过Python基础的同学对range函数一定不陌生,在numpy中,我们可以用arange和linspace生成特定规律的数组。

np.arange([start,]stop[,step,],dtype=None)

  • start:起始数
  • stop:终止数,不包括
  • step:步长,可以是小数

np.linspace(start,stop,num,endpoint=True,retstep=False,dtype=None)

  • start:起始数
  • stop:终止数
  • num:分割成多少份
  • endpoint:是否包含终点
  • retstep:是否带步长
  • dtype:数据类型
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :numpy学习 
@File    :task_6.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/4/17 9:57 
"""
import numpy as np

print(np.arange(10))
# [0 1 2 3 4 5 6 7 8 9]
print(np.arange(0, 10))
# [0 1 2 3 4 5 6 7 8 9]
print(np.arange(1, 4, 0.5))
# [1.  1.5 2.  2.5 3.  3.5]
print(np.arange(9, -1, -1))
# [9 8 7 6 5 4 3 2 1 0]

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :numpy学习 
@File    :task_7.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/4/17 9:58 
"""
import numpy as np

print(np.linspace(0, 1, 10))
# [0.         0.11111111 0.22222222 0.33333333 0.44444444 0.55555556
# 0.66666667 0.77777778 0.88888889 1.        ]
print(np.linspace(0,1,10,retstep=True))
# ([0.        , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
       0.55555556, 0.66666667, 0.77777778, 0.88888889, 1.        ]), 0.1111111111111111)

注意,np.linspace(0, 1, 10)生成 的是步长为0.11111111的矩阵,因为0也占了一位,步长计算为(1-0)/9=0.11111,如果想要步长为0.1,只需要将start=0改为0.1即可。
除了上面学习的arange、linspace函数,numpy还提供了logspace函数,大家也可以自己写一写代码,自行尝试一下效果!