Numpy与线性代数(Linear Algebra)

Numpy是基于python的一个常用库,利用它来方便地操纵数组。

在python中使用numpy这个库需要提前导入,并起个别名为np

1
import numpy as np

1 numpy数组与python列表

定义python列表:

1
alist = [1, 2, 3, 4]
利用numpy定义数组:
1
narray = np.array([1, 2, 3, 4])
输出进行观察和对比两者:
1
2
3
4
5
print('alist:', alist)
print('narray:', narray)

print('Type of alist:', type(alist))
print('Type of narray:', type(narray))
[1, 2, 3, 4]

[1 2 3 4]

<class 'list'>

<class 'numpy.ndarray'>

2 numpy数组与python列表的运算符

numpy数组与python列表的+*含义不同,其中numpy数组是真正在进行代数运算。

+的不同:

1
print(narray + narray)
[2 4 6 8]

1
print(alist + alist)

[1, 2, 3, 4, 1, 2, 3, 4]

*的不同:

1
print(narray * 3)
[ 3 6 9 12]

1
print(alist * 3)

[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]

3 矩阵(Matrix)

在线性代数中,矩阵是指一种由n行m列的结构,它是一个矩形,所以每一行都有相同的列数。利用numpy创建矩阵:

numpy可以用数组(array)或者列表来初始化一个矩阵,但最后都是数组(array)的类型。

1
2
3
matrix1 = np.array([narray, narray, narray])
matrix2 = np.array([alist, alist, alist])
matrix3 = np.array([narray, [1, 1, 1, 1], narray])
1
2
3
print('matrix1:', matrix1)
print('matrix2:', matrix2)
print('matrix3', matrix3)
1
2
3
4
5
6
7
8
9
10
11
12
matrix1:
[[1 2 3 4]
[1 2 3 4]
[1 2 3 4]]
matrix2:
[[1 2 3 4]
[1 2 3 4]
[1 2 3 4]]
matrix3:
[[1 2 3 4]
[1 1 1 1]
[1 2 3 4]]
一定要注意每行的列数要相同,不然会出现问题。
1
2
3
badmatrix = np.array([[1, 2], [3, 4], [5, 6, 7]]) # Define a matrix. Note the third row contains 3 elements
print(badmatrix) # Print the malformed matrix
print(badmatrix * 2) # It is supposed to scale the whole matrixz
[list([1, 2]) list([3, 4]) list([5, 6, 7])] [list([1, 2, 1, 2]) list([3, 4, 3, 4]) list([5, 6, 7, 5, 6, 7])]

3.1 矩阵的四则运算

定义一个矩阵:

1
okmatrix = np.array([[1, 2], [3, 4]])
#### 加法和减法

矩阵进行加减时要逐渐两个矩阵是拥有相同结构的,即行和列数要对应相同。

1
2
3
4
5
resutlt1 = okmatrix + okmatrix
result2 = okmatrix - okmatrix

print(result1)
print(result2)
1
2
3
4
5
[[2 4]
[6 8]]

[[0 0]
[0 0]]
#### 乘法

1
2
result = okmatrix * 2
print(result)
1
2
[[2 4]
[6 8]]

假如是矩阵和矩阵相乘,它是基于元素进行相乘,每个元素和对应位置的元素相乘。矩阵乘法要和点积(dot product)区分。

1
2
result = okmatrix * okmatrix # Multiply each element by itself
print(result)
1
2
[[ 1  4]
[ 9 16]]
#### 除法

1
2
result = okmatrix / okmatrix
print(result)
1
2
[[1. 1.]
[1. 1.]]

3.2 矩阵的转置

矩阵的转置是指将矩阵沿着对角线进行翻转,行变成列。如果转置前的矩阵是n*m,那么转置后的矩阵是m*nT代表numpy矩阵的转置操作。

1
2
3
4
5
matrix = np.array([[1, 2], [3, 4], [5, 6]]) # Define a 3x2 matrix
print('Original matrix 3 x 2')
print(matrix)
print('Transposed matrix 2 x 3')
print(matrix.T)
1
2
3
4
5
6
7
Original matrix 3 x 2
[[1 2]
[3 4]
[5 6]]
Transposed matrix 2 x 3
[[1 3 5]
[2 4 6]]
转置对一维数组没有作用:
1
2
3
4
5
nparray = np.array([1, 2, 3, 4]) # Define an array
print('Original array')
print(nparray)
print('Transposed array')
print(nparray.T)
1
2
3
4
Original array
[1 2 3 4]
Transposed array
[1 2 3 4]
但是对一维的矩阵(1xn)有作用:
1
2
3
4
5
narray = np.array([[1, 2, 3, 4]])
print('Original array')
print(nparray)
print('Transposed array')
print(nparray.T)
1
2
3
4
5
6
7
Original array
[[1 2 3 4]]
Transposed array
[[1]
[2]
[3]
[4]]
## 4 向量或矩阵的Norm(2-范数,或者叫做模)

此处为2-范数。

向量的2-范数描述向量在空间中的大小(距离)。向量范数的本质是距离,存在的意义是为了实现比较。比如,在一维实数集合中,我们随便取两个点4和9,我们知道9比4大,但是到了二维实数空间中,取两个点(1,1)和(0,3),这个时候我们就没办法比较它们之间的大小,因为它们不是可以比较的实数,于是我们引入范数这个概念,把我们的(1,1)和(0,3)通过范数分别映射到实数\(\sqrt{2}\) 和 3 ,这样我们就比较这两个点了。对于向量\(x = (x_1;x_2; ...; x_n)\),它的Norm为 \[ ||x|| = \sqrt{x^T x} = (\sum_{i=1}^n x_i^2)^{\frac 12} = \sqrt{x_1^2 +x_2^2 + ...+x_n^2} \]

矩阵的对于m*n矩阵\(A\)来说,Norm为: \[ ||A|| = \sqrt{\sum_{ij}{|a_{ij}|}^2} \]

利用numpy下的子包linalg中的norm函数可以进行计算。

1
2
3
4
5
6
7
8
nparray1 = np.array([1, 2, 3, 4])
norm1 = np.linalg.norm(nparray1)

nparray2 = np.array([[1, 2], [3, 4]])
norm2 = np.linalg.norm(nparray2)

print(norm1)
print(norm2)
1
2
5.477225575051661
5.477225575051661
当然对于矩阵来说,可以通过设置norm函数中的参数axis来计算每行或者每列的范数。 * axis=0 得到每列的范数。 * axis=1 得到每行的范数。
1
2
3
4
5
6
7
8
9
10
nparray2 = np.array([[1, 1], [2, 2], [3, 3]]) # Define a 3 x 2 matrix. 
print('nparray2:')
print(nparray2)

normByCols = np.linalg.norm(nparray2, axis=0)
normByRows = np.linalg.norm(nparray2, axis=1)
print('normByCols')
print(normByCols)
print('normByRows')
print(normByRows)
1
2
3
4
5
6
7
8
nparray2:
[[1 1]
[2 2]
[3 3]]
normByCols
[3.74165739 3.74165739]
normByRows
[1.41421356 2.82842712 4.24264069]
## 5 点积

向量的点积:

1
2
3
4
5
nparray1 = np.array([0, 1, 2, 3]) # Define an array
nparray2 = np.array([4, 5, 6, 7]) # Define an array

result = np.dot(nparray1, nparray2)
print(result)
38

6 按行或按列求和

numpy中的sum函数可以进行求和,通过设置axis实现行(1)或列(0)的求和。

1
2
3
4
5
6
7
8
9
10
11
nparray2 = np.array([[1, -1], [2, -2], [3, -3]]) # Define a 3 x 2 matrix. 

print(nparray2)

sumByCols = np.sum(nparray2, axis=0)
sunByRows = np.sum(nparray2, axis=1)

print('Sum by columns: ')
print(sumByCols)
print('Sum by rows:')
print(sumByRows)
1
2
3
4
5
6
7
[[ 1 -1]
[ 2 -2]
[ 3 -3]]
Sum by columns:
[ 6 -6]
Sum by rows:
[0 0 0]
## 7 按行或按列求均值

利用np.mean()或者array.mean()

1
2
3
4
5
6
7
8
9
10
11
12
nparray2 = np.array([[1, -1], [2, -2], [3, -3]]) # Define a 3 x 2 matrix. Chosen to be a matrix with 0 mean

mean = np.mean(nparray2) # Get the mean for the whole matrix
meanByCols = np.mean(nparray2, axis=0) # Get the mean for each column. Returns 2 elements
meanByRows = np.mean(nparray2, axis=1) # get the mean for each row. Returns 3 elements

print('Matrix mean: ')
print(mean)
print('Mean by columns: ')
print(meanByCols)
print('Mean by rows:')
print(meanByRows)
中心化矩阵的列
1
2
3
4
5
6
7
8
9
10
11
12
nparray2 = np.array([[1, 1], [2, 2], [3, 3]]) # Define a 3 x 2 matrix. 


nparrayCentered = nparray2 - np.mean(nparray2, axis=0) # Remove the mean for each column

print('Original matrix')
print(nparray2)
print('Centered by columns matrix')
print(nparrayCentered)

print('New mean by column')
print(nparrayCentered.mean(axis=0))
如果想对矩阵的行进行中心化,需要将矩阵先转置,中心化后,再转置回来。
1
2
3
4
5
6
7
8
9
10
11
12
nparray2 = np.array([[1, 3], [2, 4], [3, 5]]) # Define a 3 x 2 matrix. 

nparrayCentered = nparray2.T - np.mean(nparray2.T, axis=0) # Remove the mean for each row
nparrayCentered = nparrayCentered.T # Transpose back the result

print('Original matrix')
print(nparray2)
print('Centered by columns matrix')
print(nparrayCentered)

print('New mean by rows')
print(nparrayCentered.mean(axis=1))