文章目录
NumPy 中的数组和矩阵
NumPy 是一个关于矩阵运算的库,包含两种基本的数据类型:数组(array )和矩阵(matrix)。
-
matrix 是 array 的一个小的分支,所以 matrix 拥有 array 的所有特性。
-
matrix 必须是 2 维的,但是 array 可以是多维的。
-
matrix 主要优势是:相对简单的乘法运算符号。例如,a 和 b 是两个matrix,那么 a ∗ b a*b a∗b,就是矩阵乘法。
import numpy as np
a=np.mat([[4,3], [2,1]])
b=np.mat([[1,2], [3,4]])
print(a*b)
# [[13 20]
# [ 5 8]]
- 相反的是,array 遵从逐个元素的运算,所以 array 对象的 c ∗ d c*d c∗d 代表点乘运算。而矩阵乘法,则需要 np.dot(c,d) 命令 。
c=np.array([[4, 3], [2, 1]])
d=np.array([[1, 2], [3, 4]])
print(c*d)
# [[4 6]
# [6 4]]
print(np.dot(c,d))
# [[13 20]
# [ 5 8]]
- matrix 和 array 都可以通过在对象后面加 .T 得到其转置。但是 matrix 对象还可以在后面加 .H 得到 共轭矩阵, 加 .I 得到 逆矩阵。
问题就出来了,如果一个程序里面既有 matrix 又有 array,会让人脑袋大。实际上只用 array,就可以实现 matrix 的大多数功能。当然还可以通过 np.asmatrix 和 np.asarray 轻松的实现两者之间的转换。
创建数组
import numpy as np
a = np.zeros((2,2)) # Create an array of all zeros
print a # Prints "[[ 0. 0.]
# [ 0. 0.]]"
b = np.ones((1,2)) # Create an array of all ones
print b # Prints "[[ 1. 1.]]"
c = np.full((2,2), 7) # Create a constant array
print c # Prints "[[ 7. 7.]
# [ 7. 7.]]"
d = np.eye(2) # Create a 2x2 identity matrix
print d # Prints "[[ 1. 0.]
# [ 0. 1.]]"
e = np.random.random((2,2)) # Create an array filled with random values
print e # Might print "[[ 0.91940167 0.08143941]
# [ 0.68744134 0.87236687]]"
访问数组
- 切片访问:因为数组可以是多维的,所以必须为每个维度指定好切片。
import numpy as np
# Create the following rank 2 array with shape (3, 4)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
a = np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]])
# Use slicing to pull out the subarray consisting of the first 2 rows
# and columns 1 and 2; b is the following array of shape (2, 2):
# [[2 3]
# [6 7]]
b = a[:2, 1:3]
# A slice of an array is a view into the same data, so modifying it
# will modify the original array.
print a[0, 1] # Prints "2"
b[0, 0] = 77 # b[0, 0] is the same piece of data as a[0, 1]
print a[0, 1] # Prints "77"
# Two ways of accessing the data in the middle row of the array.
# Mixing integer indexing with slices yields an array of lower rank,
# while using only slices yields an array of the same rank as the
# original array:
row_r1 = a[1, :] # Rank 1 view of the second row of a
row_r2 = a[1:2, :] # Rank 2 view of the second row of a
print row_r1, row_r1.shape # Prints "[5 6 7 8] (4,)"
print row_r2, row_r2.shape # Prints "[[5 6 7 8]] (1, 4)"
# We can make the same distinction when accessing columns of an array:
col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print col_r1, col_r1.shape # Prints "[ 2 6 10] (3,)"
print col_r2, col_r2.shape # Prints "[[ 2]
# [ 6]
# [10]] (3, 1)"
- 索引访问
import numpy as np
# Create a new array from which we will select elements
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
print a # prints "array([[ 1, 2, 3],
# [ 4, 5, 6],
# [ 7, 8, 9],
# [10, 11, 12]])"
# Create an array of indices
b = np.array([0, 2, 0, 1])
# Select one element from each row of a using the indices in b
print a[np.arange(4), b] # Prints "[ 1 6 7 11]"
# Mutate one element from each row of a using the indices in b
a[np.arange(4), b] += 10
print a # prints "array([[11, 2, 3],
# [ 4, 5, 16],
# [17, 8, 9],
# [10, 21, 12]])
- 布尔型数组访问:用于选取数组中满足某些条件的元素。
import numpy as np
a = np.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2) # Find the elements of a that are bigger than 2;
# this returns a numpy array of Booleans of the same
# shape as a, where each slot of bool_idx tells
# whether that element of a is > 2.
print bool_idx # Prints "[[False False]
# [ True True]
# [ True True]]"
# We use boolean array indexing to construct a rank 1 array
# consisting of the elements of a corresponding to the True values
# of bool_idx
print a[bool_idx] # Prints "[3 4 5 6]"
# We can do all of the above in a single concise statement:
print a[a > 2] # Prints "[3 4 5 6]"
Numpy 的广播机制 Broadcasting
广播是一种强有力的机制,它让 Numpy 可以让不同大小的矩阵在一起进行数学计算。我们常常会有一个小的矩阵和一个大的矩阵,然后我们会需要用小的矩阵对大的矩阵做一些计算。
举个例子,如果我们想要把一个向量加到矩阵的每一行,我们可以这样做:
import numpy as np
# We will add the vector v to each row of the matrix x,
# storing the result in the matrix y
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) # Create an empty matrix with the same shape as x
# Add the vector v to each row of the matrix x with an explicit loop
for i in range(4):
y[i, :] = x[i, :] + v
# Now y is the following
# [[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]
print y
这样是行得通的,但是当x矩阵非常大,利用循环来计算就会变得很慢。我们可以换一种思路:
import numpy as np
# We will add the vector v to each row of the matrix x,
# storing the result in the matrix y
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
vv = np.tile(v, (4, 1)) # Stack 4 copies of v on top of each other
print vv # Prints "[[1 0 1]
# [1 0 1]
# [1 0 1]
# [1 0 1]]"
y = x + vv # Add x and vv elementwise
print y # Prints "[[ 2 2 4
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]"
Numpy广播机制可以让我们不用创建vv,就能直接运算,看看下面例子:
import numpy as np
# We will add the vector v to each row of the matrix x,
# storing the result in the matrix y
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = x + v # Add v to each row of x using broadcasting
print y # Prints "[[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]"
一些广播机制的使用:
import numpy as np
# Compute outer product of vectors
v = np.array([1,2,3]) # v has shape (3,)
w = np.array([4,5]) # w has shape (2,)
# To compute an outer product, we first reshape v to be a column
# vector of shape (3, 1); we can then broadcast it against w to yield
# an output of shape (3, 2), which is the outer product of v and w:
# [[ 4 5]
# [ 8 10]
# [12 15]]
print np.reshape(v, (3, 1)) * w
# Add a vector to each row of a matrix
x = np.array([[1,2,3], [4,5,6]])
# x has shape (2, 3) and v has shape (3,) so they broadcast to (2, 3),
# giving the following matrix:
# [[2 4 6]
# [5 7 9]]
print x + v
# Add a vector to each column of a matrix
# x has shape (2, 3) and w has shape (2,).
# If we transpose x then it has shape (3, 2) and can be broadcast
# against w to yield a result of shape (3, 2); transposing this result
# yields the final result of shape (2, 3) which is the matrix x with
# the vector w added to each column. Gives the following matrix:
# [[ 5 6 7]
# [ 9 10 11]]
print (x.T + w).T
# Another solution is to reshape w to be a row vector of shape (2, 1);
# we can then broadcast it directly against x to produce the same
# output.
print x + np.reshape(w, (2, 1))
# Multiply a matrix by a constant:
# x has shape (2, 3). Numpy treats scalars as arrays of shape ();
# these can be broadcast together to shape (2, 3), producing the
# following array:
# [[ 2 4 6]
# [ 8 10 12]]
print x * 2
矩阵加法 / 减法
[ 1 3 1 1 0 0 ] + [ 0 0 5 7 5 0 ] = [ 1 + 0 3 + 0 1 + 5 1 + 7 0 + 5 0 + 0 ] = [ 1 3 6 8 5 0 ] \begin{bmatrix} 1 & 3 & 1 \\ 1 & 0 & 0 \end{bmatrix} + \begin{bmatrix} 0 & 0 & 5 \\ 7 & 5 & 0 \end{bmatrix} =\begin{bmatrix} 1+0 & 3+0 & 1+5 \\ 1+7 & 0+5 & 0+0 \end{bmatrix} =\begin{bmatrix} 1 & 3 & 6 \\ 8 & 5 & 0 \end{bmatrix} [113010]+[070550]=[1+01+73+00+51+50+0]=[183560]
import numpy as np
x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)
# Elementwise sum; both produce the array
# [[ 6.0 8.0]
# [10.0 12.0]]
print x + y
print np.add(x, y)
# Elementwise difference; both produce the array
# [[-4.0 -4.0]
# [-4.0 -4.0]]
print x - y
print np.subtract(x, y)
矩阵数乘
2 ⋅ [ 1 8 − 3 4 − 2 5 ] = [ 2 ⋅ 1 2 ⋅ 8 2 ⋅ ( − 3 ) 2 ⋅ 4 2 ⋅ ( − 2 ) 2 ⋅ 5 ] = [ 2 16 − 6 8 − 4 10 ] 2 \cdot \begin{bmatrix} 1 & 8 & -3 \\ 4 & -2 & 5 \end{bmatrix} =\begin{bmatrix} 2 \cdot 1 & 2\cdot 8 & 2\cdot (-3) \\ 2\cdot 4 & 2\cdot (-2) & 2\cdot 5 \end{bmatrix} =\begin{bmatrix} 2 & 16 & -6 \\ 8 & -4 & 10 \end{bmatrix} 2⋅[148−2−35]=[2⋅12⋅42⋅82⋅(−2)2⋅(−3)2⋅5]=[2816−4−610]
>>> from numpy import *
>>> a1=array([1,1,1]) #定义一个数组
>>> a1*2 #乘一个数
array([2, 2, 2])
矩阵转置
m × n 矩 阵 A 的 转 置 是 一 个 n × m 的 矩 阵 , 记 为 A T m\times n矩阵A的转置是一个 n\times m 的矩阵,记为 A^T m×n矩阵A的转置是一个n×m的矩阵,记为AT
[ 1 2 3 0 − 6 7 ] T = [ 1 0 2 − 6 3 7 ] \begin{bmatrix} 1 & 2 & 3 \\ 0 & -6 & 7 \end{bmatrix}^T = \begin{bmatrix} 1 & 0 \\ 2 & -6 \\ 3 & 7 \end{bmatrix} [102−637]T=⎣⎡1230−67⎦⎤
>>> from numpy import *
>>> m1=mat([1,2,3]) # 1行3列
>>> m1
matrix([[1,2,3]])
>>> m1.T # m1.T为转置操作
matrix([[1],
[2],
[3]])
矩阵乘法
两个矩阵的乘法仅当第一个矩阵 A 的列数(column)和另一个矩阵B的行数(row)相等时才能定义。当 A 是 m × n m×n m×n 矩阵和 B 是 n × p n×p n×p 矩阵,它们的乘积AB是一个 m × p m×p m×p 矩阵,例如:
[ 1 0 2 − 1 3 1 ] × [ 3 1 2 1 1 0 ] = [ ( 1 × 3 + 0 × 2 + 2 × 1 ) ( 1 × 1 + 0 × 1 + 2 × 0 ) ( − 1 × 3 + 3 × 2 + 1 × 1 ) ( − 1 × 1 + 3 × 1 + 1 × 0 ) ] = [ 5 1 4 2 ] \begin{bmatrix} 1 & 0 & 2 \\ -1 & 3 & 1 \\ \end{bmatrix} \times \begin{bmatrix} 3 & 1 \\ 2 & 1 \\ 1 & 0 \end{bmatrix} =\begin{bmatrix} (1 \times 3 + 0 \times 2 + 2 \times 1) & (1 \times 1 + 0 \times 1 + 2 \times 0) \\ (-1 \times 3 + 3 \times 2 + 1 \times 1) & (-1 \times 1 + 3 \times 1 + 1 \times 0) \\ \end{bmatrix} = \begin{bmatrix} 5 & 1 \\ 4 & 2 \\ \end{bmatrix} [1−10321]×⎣⎡321110⎦⎤=[(1×3+0×2+2×1)(−1×3+3×2+1×1)(1×1+0×1+2×0)(−1×1+3×1+1×0)]=[5412]

矩阵乘法不满足交换律,一般来说,矩阵A及B的乘积AB存在,但BA不一定存在。即使存在,大多数时候AB ≠ BA。
矩阵的乘法满足结合律和对矩阵加法的分配律(左分配律和右分配律):
-
结合律:(AB)C = A(BC),
-
左分配律:(A + B)C = AC + BC,
-
右分配律:C(A + B) = CA + CB.
>>> from numpy import *
>>> m1=mat([1,2,3]) #1行3列
>>> m2=mat([4,5,6])
>>> m1*m2.T #执行矩阵相乘,注意左列与右行相等 m2.T为转置操作
matrix([[32]])
>>> multiply(m1,m2) #执行点乘操作,要使用函数,特别注意
matrix([[ 4, 10, 18]])
单位矩阵 (Identity matrix)
n 阶单位矩阵,是一个 n × n n×n n×n 的方形矩阵,其主对角线元素为 1,其余元素为0
单位矩阵以 I n I_n In表示:
I 1 = [ 1 ] , I 2 = [ 1 0 0 1 ] , I 3 = [ 1 0 0 0 1 0 0 0 1 ] , ⋯   , I n = [ 1 0 ⋯ 0 0 1 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 ⋯ 1 ] I_{1}={\begin{bmatrix}1\end{bmatrix}},\ I_{2}={\begin{bmatrix}1&0\\0&1\end{bmatrix}},\ I_{3}={\begin{bmatrix}1&0&0\\0&1&0\\0&0&1\end{bmatrix}},\ \cdots ,\ I_{n}={\begin{bmatrix}1&0&\cdots &0\\0&1&\cdots &0\\\vdots &\vdots &\ddots &\vdots \\0&0&\cdots &1\end{bmatrix}} I1=[1], I2=[1001], I3=⎣⎡100010001⎦⎤, ⋯, In=⎣⎢⎢⎢⎡10⋮001⋮0⋯⋯⋱⋯00⋮1⎦⎥⎥⎥⎤
逆矩阵(matrix inversion)
在线性代数中,给定一个 n 阶方阵 A ,若存在 -n 阶方阵 B,使得 AB = BA = I n I_n In,则称 A 是可逆的,且 B 是 A 的逆矩阵,记作 A − 1 A^{-1} A−1。
只有正方形( n × n n×n n×n)的矩阵,亦即方阵,才可能、但非必然有逆矩阵。若方阵 A 的逆矩阵存在,则称 A 为非奇异方阵或可逆方阵。