《老鸟python 系列》视频上线了,全网稀缺资源,涵盖python人工智能教程,爬虫教程,web教程,数据分析教程以及界面库和服务器教程,以及各个方向的主流实用项目,手把手带你从零开始进阶高手之路!点击 链接 查看详情

numpy

阅读:123984245    分享到

numpy 是第三方模块,如果我们想使用它,必须先安装上该模块。安装方法: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy。

numpy 模块内有很多类库,这些类库里面实现了存储数据的属性和对数据进行运算的函数。其实 numpy 模块里面的类和我们 python 内置的 list 一样,都是对数据进行存储和运算的类,只是 numpy 模块里面的类要比 list 要丰富的多,现在开始我们就来学习 numpy 的主要 API。

数据结构和初始化

numpy 是一个模块,它主要功能是做数据处理,既然是做数据处理,首先要有数据存储的功能,numpy 给我们提供一个 ndarray 类可以存储要处理的数据。

ndarray 类是 numpy 创造的一个数据类型,在使用之前,我们首先想到的是如何初始化它。numpy 的 array 函数负责初始化 numpy 的数据,我们可以给该函数传入用 list 或 tuple 进行初始化。

import numpy as np

nparr = np.array((2, 3, 4))  # 可以用 tuple 来创建 ndarray 对象
print(nparr)
print(type(nparr))

nparr = np.array([2, 3, 4])  # 可以用 list 来创建 ndarray 对象
print(nparr)
print(type(nparr))

上面代码中,我们发现 ndarray 类型的数据和 list 很像,ndarray 和 list 对象相比,ndarray 数据的成员之间只是没有用逗号隔开。

运行结果如下:

[2 3 4]
<class 'numpy.ndarray'>
[2 3 4]
<class 'numpy.ndarray'>

我们也可以使用 numpy 提供的 arange 函数对 numpy 进行初始化,或者使用 ndarray 对象本身初始化。

import numpy as np

nparr = np.arange(0, 10)  # 用np提供的arange函数
print(nparr)
print(type(nparr))

nparr2 = np.array(nparr)   # 用nparr对象本身
print(nparr2)
print(type(nparr2))

运行结果如下:

[0 1 2 3 4 5 6 7 8 9]
<class 'numpy.ndarray'>
[0 1 2 3 4 5 6 7 8 9]
<class 'numpy.ndarray'>

numpy 支持切片功能,切片规则和 list 一样。通过切片取得的结果同样为 ndarray 类型。

import numpy as np

nparr = np.arange(0, 10)
print(nparr[:4])
print(nparr[3: 7])
print(nparr[:7: 2])

运行结果如下:

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

和 list 比较

numpy 提供的运算函数的效率比其它数据结构提供的运算函数高效(比如 list 等等)。下面的案例中,我们分别创建一个 ndarray 类型的对象和 list 类型的对象,对象中存储的数据的内容都是一样的,存储了 0-9999999 的整数,然后我们对使用 numpy 提供的 sum 函数和 list 提供的 sum 函数对这些数据求和运算,我们发现 numpy 要比 list 快得多。

import time
import numpy as np

nparr = np.array(np.arange(10000000))  # [0  1  2  ...10000000 - 1]
bgtime = time.time()
nparr.sum()  # 对numpy中的所有数据求和
endtime = time.time()
print("numpy计算耗时:", endtime - bgtime)

mylist = range(10000000)  # [0, 1, 2  ...10000000 - 1]
bgtime = time.time()
sum(mylist)  # 对list中的所有数据求和
endtime = time.time()
print("list计算耗时", endtime - bgtime)

运行结果如下:

numpy计算耗时: 0.006000518798828125
list计算耗时 0.711040735244751

我们有时候需要把复杂的数据结构转为我们常用的数据结构,方便我们的使用,numpy 提供了 tolist 函数,可以把 ndarray 类型的数据转为list类型的数据。

import numpy as np

nparr = np.arange(0, 10)
print(nparr)
larr = nparr.tolist()
print(larr)

运行结果如下:

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

numpy 和 list 一样支持下标访问里面的元素,同样下标是从零开始计算。

import numpy as np

nparr = np.array(0, 10)
print(nparr[2])

运行结果如下:

2

科学计算

numpy 的 ndarray 对象可以进行四则运算。注意:进行四则运算的数组元素个数必须一致。

import numpy as np

npdata_one = np.array([1, 2, 3])
npdata_two = np.array([4, 5, 6])
print("相加结果:", npdata_one + npdata_two)
print("相减结果:", npdata_one - npdata_two)
print("相乘加结果:", npdata_one * npdata_two)
print("相除加结果:", npdata_one / npdata_two)

上面代码中我们分别定义两个 ndarray 对象,对象为一维数组,在 tensorflow 或者数学概念上一维数组表示向量,这两个向量的 shape为(3,),表示 1 维度含 3 个元素。然后对其进行四则运算。

运行结果如下:

相加结果: [5 7 9]
相减结果: [-3 -3 -3]
相乘加结果: [ 4 10 18]
相除加结果: [0.25 0.4  0.5 ]

numpy 还提供其它常用的科学计算函数,比如有求均值,求方差,找最大值和最小值以及生成随机数等等。

import numpy as np

nparr = np.arange(0, 10)
print("均值:", nparr.mean())    # 求取均值
print("方差:", nparr.std())     # 求方差
print("最小值:", nparr.min())   # 找出最小值
print("最大值:", nparr.max())   # 找出最大值
print(np.random.rand(5))        # 生成5个随机数

上面代码中我们定义一个一维数组(向量)。

运行结果如下:

均值: 4.5
方差: 2.8722813232690143
最小值: 0
最大值: 9
[0.54464551 0.61172934 0.91811861 0.93888077 0.23287131]

当然我们也可以对二维数组(矩阵)或者多维数组(标量)做相应的科学计算,向量和矩阵数据计算在人工智能的数据使用中非常常见。

多维数组

前面我们一直都在学习 numpy 的一维数组(向量)相关的定义和函数以及应用,下面我们就来学习关于 numpy 多维数组的定义和使用。

numpy 的多维数组初始化方法和一维数组初始化方法一样,我们常用使用 list 或 tuple 的多维数组对 numpy 进行初始化。下面我们定义一个 2 行 3 列的多维数组(矩阵),然后打印出结果。

import numpy as np

nparrs = np.array([[2, 3, 4],
                   [5, 6, 7]])  # 创建2行3列的多维数组(矩阵)
print("数据:", nparrs)
print("维度:", nparrs.shape)  # (2, 3)
print("类型", type(nparrs))

运行结果如下:

数据: [[2 3 4]
        [5 6 7]]
维度: (2, 3)
类型 <class 'numpy.ndarray'>

numpy 数组可以进行维度变换,可以把多维数组展平成一维数组,numpy 提供的 ravel 函数可以完成多数组展平为一维数组的功能,当然也可以对一维数组本身展平为一维数组(这没什么意义)。

import numpy as np

nparrs = np.array([[2, 3, 4],
                   [5, 6, 7]])  # 创建2行3列的多维数组(矩阵)
nparr = nparrs.ravel()          # 对多维数组进行展平成一位数组,赋值给nparr
print("展平后的值:", nparr)
print("原本的值不变:", nparrs)  # 注意nparrs本身的值不会变

运行结果如下:

展平后的值: [2 3 4 5 6 7]
原本的值不变: [[2 3 4]
                [5 6 7]]

注意:ravel 不改变被展平数组本身,它会把展平后的一维数组作为一个结果返回。

numpy 还提供一个 reshape 函数,该函数可以变换数组的维度,也就是说它可以把高维数组转为低维度数组,同样也可以把低维度数组转为高纬度数组。

import numpy as np

nparra = np.arange(8)          # 定义一个一维数组(向量)
print("一维数组:", nparra)

nparrb = nparra.reshape(2, 4)  # 把一维数组转为二维数组(矩阵)
print("改变维度后的二维数组:", nparrb)
print("被改变数组本身的维度不变:", nparra)

nparrc = nparrb.reshape(8)     # 把二维数组转为一维数组(向量)
print("一维数组:", nparrc)
print("被改变数组本身的维度不变:", nparrb)

运行结果如下:

一维数组: [0 1 2 3 4 5 6 7]
改变维度后的二维数组: [[0 1 2 3]
                       [4 5 6 7]]
被改变数组本身的维度不变: [0 1 2 3 4 5 6 7]
一维数组: [0 1 2 3 4 5 6 7]
被改变数组本身的维度不变: [[0 1 2 3]
                           [4 5 6 7]]

注意:reshape 函数同样不会改变被转为数组本身,它和 ravel 函数一样会返回新的结果。

numpy 提供 shape 函数不但可以随意变换数组的维度(高纬度和低纬度互相转换),它也改变数组本身。

import numpy as np

nparr = np.arange(8)  # 定义一个1维数组(向量)
nparr.shape = (2, 4)  # 把nparr本身转为2行4列的2维数组(矩阵)
print("改变本身:", nparr)

nparr.shape = (8,)    # 把nparr本身转为1维数组(向量)
print("改变本身:", nparr)

运行结果如下:

改变本身: [[0 1 2 3]
            [4 5 6 7]]
改变本身: [0 1 2 3 4 5 6 7]

同样 numpy 的多维数组也支持四则运算,下面我们定义两个二维数组(矩阵),然后对其做四则运算,注意:numpy 的二维数组(矩阵)同样必须符合数学上的运算规则。

import numpy as np

nparra = np.array([[2, 3], [4, 5]])
nparrb = np.array([[3, 4], [5, 6]])

print("矩阵相加:", nparra + nparrb)
print("矩阵相减:", nparra - nparrb)
print("矩阵相乘:", nparra * nparrb)
print("矩阵相除:", nparra / nparrb)

运行结果如下:

矩阵相加: [[ 5  7]
[ 9 11]]
矩阵相减: [[-1 -1]
            [-1 -1]]
矩阵相乘: [[ 6 12]
            [20 30]]
矩阵相除: [[0.66666667 0.75      ]
            [0.8        0.83333333]]

我们知道二维数组在数学上代表矩阵,我们知道矩阵支持叉乘运算。下面我们定义两个二维数组(矩阵),分别为 1 行 2 列和 2 行 3 列,根据矩阵叉乘规则,叉乘结果为 1 行 3 列的矩阵。

import numpy as np

nparra = np.array([[1, 2]])    # (1, 2)
nparrb = np.array([[1, 2, 3],  # (2, 3)
                   [4, 5, 6]])
data = np.matmul(nparra, nparrb)

print("矩阵叉乘:", data)

运行结果如下:

矩阵叉乘: [[ 9 12 15]]

numpy 的 hstack 函数可以对数组进行水平组合,注意:被水平组合的两个数组的行数必须相同。

import numpy as np

nparra = np.array([[1, 2],
                  [3, 4]])
nparrb = np.array([[4, 5, 6],
                  [7, 8, 9]])

print("水平组合:\n", np.hstack((nparra, nparrb)))

运行结果如下:

水平组合:
[[1 2 4 5 6]
[3 4 7 8 9]]

numpy 的 vstack 函数可以对数组进行垂直组合,注意:被垂直组合的两个数组的列数必须相同。

import numpy as np

nparra = np.array([[1, 2, 3]])
nparrb = np.array([[4, 5, 6],
                  [7, 8, 9]])

print("垂直组合:\n", np.vstack((nparra, nparrb)))

运行结果如下:

垂直组合:
[[1 2 3]
 [4 5 6]
 [7 8 9]]

numpy 的 random.RandomState.rand (维度)函数返回一个 [0, 1) 之间的随机数,维度为空返回一个标量。

import numpy as np

rdm = np.random.RandomState(seed=1)  # 同一个种子生成的随机数相同
a = rdm.rand()      # 维度为0,返回一个标量
b = rdm.rand(2, 3)  # 维度为2,返回2行3列的矩阵

print("a:", a)
print("b", b)

运行结果如下:

a: 0.417022004702574
b [[7.20324493e-01 1.14374817e-04 3.02332573e-01]
   [1.46755891e-01 9.23385948e-02 1.86260211e-01]]

注意,区间 [0, 1) 代表左闭右开,也就是生成的随机数可以包含 0 但不能包含 1。

numpy 的 mgrid [起始值:结束值:步长, 起始值:结束值:步长,…]可以生产网格坐标点,该函数经常和 numpy 的 ravel 函数以及 numpy 的 c_[] 一起使用。

numpy 的 c_[数组1,数组2,…]使返回的间隔数值点配对。

import numpy as np

x, y = np.mgrid[1: 3: 1, 2: 4: 0.5]
print("x:", x)
print("y:", y)

grid = np.c_[x.ravel(), y.ravel()]  # 生成图状数据(网格化数据)
print("grid:\n", grid)

运行结果如下:

x: [[1. 1. 1. 1.]
[2. 2. 2. 2.]]
y: [[2.  2.5 3.  3.5]
[2.  2.5 3.  3.5]]
grid:
[[1.  2. ]
[1.  2.5]
[1.  3. ]
[1.  3.5]
[2.  2. ]
[2.  2.5]
[2.  3. ]
[2.  3.5]]

文件读写

我们的数据经常来自于文件中,numpy 具有读取文件的功能,同样也可以把数据存储到文件中。

numpy 的 loadtxt 函数可以从文件中读取数据,我们有个 nparr.txt 文件,里面存储了 3 行 3 列的数据,我们把该文件中的数据读取到 numpy 中,然后打印出来。

如下图是文件里面存储的内容

import numpy as np

data = np.loadtxt('nparr.txt', dtype=int)
print(data)

运行结果如下:

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

如上代码,其中 dtype=int 是说明把文件中读取的内容以整数的形式存储到 numpy 中,否则默认以 float 的形式读取到 numpy 中。

numpy 的 savetxt 函数可以把 numpy 中的数据存储到文件中。

import numpy as np

nparr = np.array([[4, 5, 6],
[7, 8, 9]])
np.savetxt('nparr.txt', nparr, fmt="%d")

如上代码中,我们定义一个二维数组 nparr,然后把它存储到文件 nparr.txt 中,其中 fmt="%d", 是指把数据以整数类型存储到文件中,否则默认是以 float 类型存储到文件中。

执行代码后,文件里面存储的内容

numpy 还提供 load 和 save 函数同样可以读写文件,只是读写文件的后缀名必须是 npy。大家可以自行使用 load 函数读文件,使用 save 函数写文件做测试,在此不在赘述。

本节重要知识点

了解numpy的数据结构

熟练使用numpy常用的函数

会使用numpy进行文件读写操作


如果以上内容对您有帮助,请老板用微信扫一下赞赏码,赞赏后加微信号 birdpython 领取免费视频。


登录后评论