矩阵运算

本文深入探讨NumPy库中的数组(array)和矩阵(matrix),包括它们的创建、访问、广播机制、基本运算如加法、减法、数乘、转置、乘法,以及高级功能如单位矩阵和逆矩阵的生成。同时,文章提供了丰富的代码示例,帮助读者理解和应用这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NumPy 中的数组和矩阵

NumPy 是一个关于矩阵运算的库,包含两种基本的数据类型:数组(array )和矩阵(matrix)。

  • matrixarray 的一个小的分支,所以 matrix 拥有 array 的所有特性。

  • matrix 必须是 2 维的,但是 array 可以是多维的。

  • matrix 主要优势是:相对简单的乘法运算符号。例如,a 和 b 是两个matrix,那么 a ∗ b a*b ab,就是矩阵乘法

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 cd 代表点乘运算。而矩阵乘法,则需要 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]]
  • matrixarray 都可以通过在对象后面加 .T 得到其转置。但是 matrix 对象还可以在后面加 .H 得到 共轭矩阵, 加 .I 得到 逆矩阵

问题就出来了,如果一个程序里面既有 matrix 又有 array,会让人脑袋大。实际上只用 array,就可以实现 matrix 的大多数功能。当然还可以通过 np.asmatrixnp.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[148235]=[2124282(2)2(3)25]=[28164610]

>>> 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×nAn×mAT

[ 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} [102637]T=123067

>>> 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} [110321]×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=100010001

逆矩阵(matrix inversion)

在线性代数中,给定一个 n 阶方阵 A ,若存在 -n 阶方阵 B,使得 AB = BA = I n I_n In,则称 A 是可逆的,且 B 是 A 的逆矩阵,记作 A − 1 A^{-1} A1

只有正方形( n × n n×n n×n)的矩阵,亦即方阵,才可能、但非必然有逆矩阵。若方阵 A 的逆矩阵存在,则称 A 为非奇异方阵或可逆方阵。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值