NumPy(Numerical Python)是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix)),支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

以下记录自己学习NumPy的笔记。

numpy.array基础

1
2
3
import numpy as np
##查看版本
np.__version__

python list的特点

不对类型做具体的限定

1
2
3
4
L = [i for i in range(10)]
L --> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
L[5] = 'test'
L --> [0, 1, 2, 3, 4, 'test', 6, 7, 8, 9]

python中限定只能存储一种类型的数组如下:

1
2
3
import array
arr = array.array('i', [i for i in range(10)])
arr --> array('i', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

numpy.array

基础操作

1
2
3
4
5
6
7
# 列表初始化
nparr = np.array([i for i in range (10)])
npar --> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 查看存储类型
nparr.dtype --> dtype('int32')
nparr[5] = 10.5
nparr --> array([ 0, 1, 2, 3, 4, 10, 6, 7, 8, 9])

int定义浮点会自动去位

创建0数组或0矩阵

1
2
3
4
5
6
7
8
9
10
11
12
13
np.zeros(10).dtype
--> array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) --> dtype('float64')
np.zeros(10, dtype=int)
## 创建全为0矩阵
np.zeros((3, 5))
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
## 创建全为1矩阵
np.ones(shape=(3, 5))
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])

创建指定数字的矩阵

1
2
3
4
np.full(shape=(3, 5), fill_value=666.)
array([[666., 666., 666., 666., 666.],
[666., 666., 666., 666., 666.],
[666., 666., 666., 666., 666.]]

arange 调用list创建矩阵

1
[i for i in range(0, 10, 2)]

起始,终止(左闭右开),步长

1
2
np.arange(0, 1, 0.2) 
--> array([0. , 0.2, 0.4, 0.6, 0.8])

linspace 在范围内(包含前后),截取x个数

1
2
3
np.linspace(0, 20, 10)
--> array([ 0. , 2.22222222, 4.44444444, 6.66666667, 8.88888889,
11.11111111, 13.33333333, 15.55555556, 17.77777778, 20. ])

生成随机数(左闭右开)

1
2
3
4
np.random.randint(4, 8, 10)
--> array([4, 6, 6, 7, 4, 4, 4, 6, 4, 4])
## 随机矩阵
np.random.randint(4, 8, size=(3,5))

指定随机种子

1
2
3
4
5
6
np.random.seed(666) 
np.random.randint(4, 8, size=10)
--> array([4, 6, 5, 6, 6, 6, 5, 6, 4, 5])
np.random.seed(666)
np.random.randint(4, 8, size=10)
--> array([4, 6, 5, 6, 6, 6, 5, 6, 4, 5])

随机浮点数

1
np.random.random((3,5))

符合正态分布的随机数

1
np.random.normal()

数组的基本属性

1
2
3
4
X = np.arange(15).reshape(3, 5)
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

查看数组维度

1
2
3
X.ndim --> 2
X.shape --> (3, 5)
X.size --> 15

数组读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
X[2,2] --> 12
X[:2, :3] ##前两行前三列
--> array([[0, 1, 2],
[5, 6, 7]])
X[::-1] --> ## 倒行
array([[10, 11, 12, 13, 14],
[ 5, 6, 7, 8, 9],
[ 0, 1, 2, 3, 4]])
X[::, ::-1] --> ##倒列
array([[ 4, 3, 2, 1, 0],
[ 9, 8, 7, 6, 5],
[14, 13, 12, 11, 10]])
X[::-1, ::-1] --> ##行列都倒
array([[14, 13, 12, 11, 10],
[ 9, 8, 7, 6, 5],
[ 4, 3, 2, 1, 0]])
X[::-2] --> ##倒着输出两行
array([[10, 11, 12, 13, 14],
[ 0, 1, 2, 3, 4]])

numpy分片没有创建新矩阵,修改子矩阵会修改原矩阵

构造不相关的子矩阵,如下

1
subX = X[:2, :3].copy()

Reshape升维

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
x = np.arange(10)
x.shape --> (10,)
x.reshape(2, 5)
-->array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
B = x.reshape(1, 10) --> array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
B.shape --> (1, 10)
x.reshape(10, -1) ## 只划分10行,不关心每行几个元素
--> array([[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
x.reshape(-1, 5) ## 只划分5列,不关心有几行

矩阵的合并与分割

合并

1
2
x = np.array([1,2,3])
y = np.array([3,2,1])

向量合并

1
2
np.concatenate([x,y])
--> array([1, 2, 3, 3, 2, 1])

二维数组合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
A = np.array([[1,2,3],
[4,5,6]])

--> array([[1, 2, 3],
[4, 5, 6],
[1, 2, 3],
[4, 5, 6]])
# 一个样本增加一个样本
np.concatenate([A,A])
# 一个样本增加一个特征
np.concatenate([A, A], axis=1)
--> array([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])

axis默认为0,表示竖着拼接;axis=1 表示沿着第二个维度进行拼接(横着拼接)

跨维度合并

1
2
z = np.array([666,666,666])
A2 = np.concatenate([A, z.reshape(1,-1)])

垂直方向进行叠加

1
2
3
4
np.vstack([A,z])
--> array([[ 1, 2, 3],
[ 4, 5, 6],
[666, 666, 666]])

水平方向进行叠加

1
2
3
4
B = np.full((2,2), 100)
-->
array([[100, 100],
[100, 100]])
1
2
3
4
np.hstack([A, B])
-->
array([[ 1, 2, 3, 100, 100],
[ 4, 5, 6, 100, 100]])

分割操作

1
2
3
4
x = np.arange(0, 10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
x1, x2, x3 = np.split(x, [3,7])
(array([0, 1, 2]), array([3, 4, 5, 6]), array([7, 8, 9]))

多维默认以行分割

1
2
3
4
5
A = np.arange(16).reshape(4,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
1
2
3
4
5
6
A1, A2 = np.split(A, [2])
(array([[0, 1, 2, 3],
[4, 5, 6, 7]]),
array([[ 8, 9, 10, 11],
[12, 13, 14, 15]]))
upper, lower = np.vsplit(A, [2])

以列分割

1
2
3
4
5
6
7
8
9
10
A1, A2 = np.split(A, [2], axis=1)
(array([[ 0, 1],
[ 4, 5],
[ 8, 9],
[12, 13]]),
array([[ 2, 3],
[ 6, 7],
[10, 11],
[14, 15]]))
left, right = np.hsplit(A, [2])

矩阵的运算

给定一个向量,让向量中每一个数乘以2

a = (0,1,2)

a*2 = (0,2,4)

1
2
n = 10
L = [i for i in range(n)]

方法1:list

1
2
3
A = [2*e for e in L]
-->
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

方法2:numpy

1
2
3
4
import numpy as np
L = np.arange(n)
A = np.array(e*2 for e in L) #或者
A = 2 * L

Universal Functions

1
2
3
4
X = np.arange(1,16).reshape((3,5))
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
1
运算+-*/(浮点除)//(整数除)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 求余
X % 2
# 取倒数
1 / X
array([[1. , 0.5 , 0.33333333, 0.25 , 0.2 ],
[0.16666667, 0.14285714, 0.125 , 0.11111111, 0.1 ],
[0.09090909, 0.08333333, 0.07692308, 0.07142857, 0.06666667]])
# 取绝对值
np.abs(X)
# 取正弦函数cos,tan同
np.sin(X)
# 取e的X方
np.exp(X)
# 取3的X次方
np.power(3,X)
# 取log以e为底
np.log(X)
# 取log以2为底

矩阵对应元素做运算

加减乘除

1
2
3
4
5
6
7
8
9
10
A = np.arange(4).reshape(2, 2)
B = np.full((2,2),10)
A,B
(array([[0, 1],
[2, 3]]),
array([[10, 10],
[10, 10]]))
A * B
array([[ 0, 10],
[20, 30]])

标准矩阵乘法

1
2
3
A.dot(B)       
array([[10, 10],
[50, 50]])

矩阵的转置

1
2
3
A.T
array([[0, 2],
[1, 3]])

向量和矩阵之间的运算

1
2
3
4
5
v = np.array([1,2])
v-->array([1, 2])
A-->
(array([[0, 1],
[2, 3]])

加法:向量和矩阵中的每个行做加法

1
2
3
4
5
v+A
array([[1, 3],
[3, 5]])
#等同
np.vstack([v] * A.shape[0]) +A

向量堆叠tile

1
np.tile(v,[2,1])

乘法:矩阵的每个元素和向量每个元素相乘再相加

1
2
3
4
v.dot(A)
array([4, 7])
A.dot(v) #将v转换2x1的矩阵
array([2, 8])

矩阵的逆

1
2
3
4
5
6
7
8
9
invA = np.linalg.inv(A)
array([[-1.5, 0.5],
[ 1. , 0. ]])
A.dot(invA) #得到单位矩阵
array([[1., 0.],
[0., 1.]])
invA.dot(A)
array([[1., 0.],
[0., 1.]])

矩阵一定要是方阵才有逆矩阵

伪逆矩阵

1
2
3
4
5
6
7
8
9
10
11
12
13
x = np.arange(16).reshape(2, 8)
np.linalg.pinv(x)
array([[-1.35416667e-01, 5.20833333e-02],
[-1.01190476e-01, 4.16666667e-02],
[-6.69642857e-02, 3.12500000e-02],
[-3.27380952e-02, 2.08333333e-02],
[ 1.48809524e-03, 1.04166667e-02],
[ 3.57142857e-02, -4.96086088e-18],
[ 6.99404762e-02, -1.04166667e-02],
[ 1.04166667e-01, -2.08333333e-02]])
x.dot(pinvx)
array([[ 1.00000000e+00, -2.60208521e-16],
[ 9.71445147e-17, 1.00000000e+00]])

聚合操作

把一组值变成一个值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
x = np.arange(16).reshape(4,-1)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
# 最大值
np.max(x)
# 最小值
np.min(x)
# 求乘积
np.prod(x)
# 平均值
np.mean(x)
# 中位数
np.median(x)
# 方差
np.var(x)
# 标准差
np.std(x)

求和

1
np.sum(x)

求每一列的和

1
2
np.sum(x, axis=0) -->
array([24, 28, 32, 36])

求每一行的和

1
2
np.sum(x, axis=1) -->
array([ 6, 22, 38, 54])

百分位点求值

1
2
3
4
5
6
7
8
9
np.percentile(x,q=50)
7.5
for percent in [0,25,50,75,100]:
print(np.percentile(x,q=percent))
0.0
3.75
7.5
11.25
15.0

索引

1
2
3
4
5
6
7
new = np.random.normal(0,1, size=10)
np.min(new)
--> -1.2581554274500057
np.argmin(new)
--> 1
new[1]
--> -1.2581554274500057

排序使用索引

1
2
3
4
5
6
x = np.arange(16)
np.random.shuffle(x)
# 返回排序后结果
np.sort(x)
# 将x排序
x.sort()

按照索引有序排列

1
np.argsort(x)

标定点(标定点前都比他小,后都比他大)

1
2
3
np.partition(x,7)
array([ 1, 3, 4, 2, 6, 0, 5, 7, 15, 13, 12, 8, 9, 10, 14, 11])
np.argpartition(x,7) 索引对应的值比7小或者比7

矩阵排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#x = np.random.randint(16,size=(4,4))
array([[ 8, 10, 11, 14],
[13, 2, 9, 11],
[ 5, 10, 8, 7],
[11, 11, 0, 6]])
#沿着列排序(默认)
np.sort(x, axis=1)
array([[ 8, 10, 11, 14],
[ 2, 9, 11, 13],
[ 5, 7, 8, 10],
[ 0, 6, 11, 11]])
np.argsort(x, axis=1)
array([[0, 1, 2, 3],
[1, 2, 3, 0],
[0, 3, 2, 1],
[2, 3, 0, 1]], dtype=int64)
#沿着行排序
np.sort(x, axis=0)
array([[ 5, 2, 0, 6],
[ 8, 10, 8, 7],
[11, 10, 9, 11],
[13, 11, 11, 14]])
np.argsort(x, axis=0)
array([[2, 1, 3, 3],
[0, 0, 2, 2],
[3, 2, 1, 1],
[1, 3, 0, 0]], dtype=int64)
np.argpartition(x,2,axis=1)
array([[0, 1, 2, 3],
[1, 2, 3, 0],
[0, 3, 2, 1],
[2, 3, 0, 1]], dtype=int64)

Fancy Indexing