目录
目录

Numpy入门

Numpy是一个python库,能够为高维数组的运算提供支持。

1
2
3
4
5
6
7
8
import numpy as np

a = np.array([1, 2, 3]) # 创建一维向量
print(type(a))
print(a.shape) # 以元组形式返回各维度的大小
print(a[0], a[1], a[2]) # 访问内容
a[0] = 5
print(a)
1
2
3
4
<class 'numpy.ndarray'>
(3,)
1 2 3
[5 2 3]

1
2
3
4
b = np.array([[1, 2, 3], [4, 5, 6]]) # 创建二维矩阵
print(b)
print(b.shape)
print(b[0, 0], b[0][1]) # 访问内容
1
2
3
4
[[1 2 3]
[4 5 6]]
(2, 3)
1 2

Numpy提供多种函数用于创建特殊的数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a = np.zeros((2, 2)) # 创建shape为(2, 2)的全零数组
print(a)

b = np.ones((1, 2))
print(b)

c = np.full((2,2), 7) # 全为7的常数数组
print(c)

d = np.eye(2) # 单位矩阵
print(d)

e = np.random.random((2, 2)) # 随机矩阵
print(e)
1
2
3
4
5
6
7
8
9
[[0. 0.]
[0. 0.]]
[[1. 1.]]
[[7 7]
[7 7]]
[[1. 0.]
[0. 1.]]
[[0.45092272 0.87624057]
[0.01306848 0.73089519]]

Numpy同样为Array提供了方便的切片和索引。但需要注意的是Numpy中Array的切片是引用方式的,修改切片后的内容同样会修改原内容。

1
2
3
4
5
6
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = a[:2, 1:3]
print(a)
print(b)
b[0, 0] = 77
print(a)
1
2
3
4
5
6
7
8
[[ 1  2  3  4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[2 3]
[6 7]]
[[ 1 77 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]

Integer array indexing和Boolean array indexing提供了另外两种索引方式:

1
2
3
4
a = np.array([[1,2], [3, 4], [5, 6]])

print(a[[0, 1, 2], [0, 1, 0]])
print(np.array([a[0, 0], a[1, 1], a[2, 0]]))
1
2
[1 4 5]
[1 4 5]

1
2
3
4
5
6
a = np.array([[1,2], [3, 4], [5, 6]])

bool_idx = (a > 2)
print(bool_idx)

print(a[bool_idx]) # 可以使用布尔值索引直接创建列表,等价于print(a[a > 2])
1
2
3
4
[[False False]
[ True True]
[ True True]]
[3 4 5 6]

Numpy中的基本算数运算都是element-wise,即同位置元素运算的。矩阵乘法需要使用dot函数。

1
2
3
4
5
6
7
8
9
10
11
12
x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)

print(x + y) # 等价于np.add(x, y)

print(x - y) # 等价于np.subtract(x, y)

print(x * y) # 等价于np.multiply(x, y)

print(x / y) # 等价于np.divide(x, y)

print(np.sqrt(x))
1
2
3
4
5
6
7
8
9
10
[[ 6.  8.]
[10. 12.]]
[[-4. -4.]
[-4. -4.]]
[[ 5. 12.]
[21. 32.]]
[[0.2 0.33333333]
[0.42857143 0.5 ]]
[[1. 1.41421356]
[1.73205081 2. ]]

1
2
3
4
5
6
7
8
9
10
x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])
v = np.array([9,10])
w = np.array([11, 12])

print(v.dot(w)) # 向量内积,等价于np.dot(v, w)

print(x.dot(v)) # 矩阵向量相乘,等价于np.dot(x, v)

print(x.dot(y)) # 矩阵相乘,等价于np.dot(x, y)
1
2
3
4
219
[29 67]
[[19 22]
[43 50]]

sum函数可以方便地对矩阵元素求和,axis参数指示累加的方向。

1
2
3
4
5
x = np.array([[1,2],[3,4],[5,6]])

print(np.sum(x))
print(np.sum(x, axis = 0)) # 按行求和
print(np.sum(x, axis = 1)) # 按列求和
1
2
3
21
[ 9 12]
[ 3 7 11]

.T属性标识矩阵的转置,reshape函数可以改变矩阵的shape

1
2
3
4
x = np.array([[1,2], [3,4]])
print(x)
print(x.T)
print(x.reshape((-1, 1))) # -1表示自动推断,等价于np.reshape(x, (-1, 1))
1
2
3
4
5
6
7
8
[[1 2]
[3 4]]
[[1 3]
[2 4]]
[[1]
[2]
[3]
[4]]

一维数组的转置不会产生效果。

1
2
3
v = np.array([1, 2, 3])
print(v.shape)
print(v.T.shape)
1
2
(3,)
(3,)

广播(Broadcasting)是Numpy中非常重要的概念,它在一些情况下能使shape不同的矩阵进行运算。

Broadcasting two arrays together follows these rules:

  1. If the arrays do not have the same rank, prepend the shape of the lower rank array
    with 1s until both shapes have the same length.
  2. The two arrays are said to be compatible in a dimension if they have the same size in
    the dimension, or if one of the arrays has size 1 in that dimension.
  3. The arrays can be broadcast together if they are compatible in all dimensions.
  4. After broadcasting, each array behaves as if it had shape equal to the elementwise
    maximum of shapes of the two input arrays.
  5. In any dimension where one array had size 1 and the other array had size greater
    than 1, the first array behaves as if it were copied along that dimension

简单而言,参与广播的两个矩阵在每一维上的shape要么为一个相同值,要么为1。运算时会对某一维数不足的矩阵在这一维度上进行重复堆叠,使运算的矩阵大小相同,可以进行element-wise运算。

使用广播可以减少循环,在很大程度上节约运算时间,应当尽量使用。

1
2
3
4
5
6
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = np.empty_like(x) # 创建一个shape与x相同的空矩阵
for i in range(4):
y[i, :] = x[i, :] + v # 给每一行分别加上v
print(y)
1
2
3
4
[[ 2  2  4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]

1
2
3
4
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = x + v
print(y) # 使用广播
1
2
3
4
[[ 2  2  4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]

1
2
3
vv = np.tile(v, (4, 1)) # 广播操作的实际堆叠
print(vv)
print(x + vv)
1
2
3
4
5
6
7
8
[[1 0 1]
[1 0 1]
[1 0 1]
[1 0 1]]
[[ 2 2 4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]