← 返回首页
线性代数基础(二)
发表时间:2024-05-06 08:42:47
矩阵、矩阵运算与常见矩阵

1.矩阵

矩阵(Matrix),可以简单理解为一组向量,在代码中可以视为一个二维数组,其中的每个元素可以是标量。 在数学中,矩阵通常表示为一个矩形的数组,例如:

其中,是矩阵中的元素,m表示行数,n表示列数。

例如:

2.矩阵的运算

1).矩阵加法(Matrix Addition)

矩阵的加法是指对应位置上的元素相加的运算。如果有两个矩阵 A 和 B,它们的维度相同(即行数和列数相等),则可以将它们相加得到另一个矩阵 C。对于 C 的每个元素 C(i,j),都是对应位置上 A(i,j) 和 B(i,j) 元素的和。

例如,如果有两个 2x2 的矩阵 A 和 B:

需要注意的是,矩阵加法满足交换律和结合律,即 A + B = B + A,以及 (A + B) + C = A + (B + C)。

实例:

import numpy as np

#矩阵加法
A = np.array([[1, 3], [2, 4]])
B = np.array([[2, 0], [1, 5]])
C = A + B
print(C)

运行结果:

[[3 3]
 [3 9]]

在机器学习中,尤其是在梯度下降法中,矩阵加法用于更新权重。新的权重是通过将旧的权重矩阵与一个由梯度和学习率乘积构成的矩阵相加得到的。

矩阵所有元素的求和,有以下三种方式实现:

import sympy as sp
import numpy as np

# 创建一个矩阵
M = sp.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 求所有元素的和
# 方法一:直接使用sum
print(sum(M))

# 方法二:使用numpy的sum
print(np.sum(M))

# 方法三:使用sympy的迭代器
sum = 0
for value in sp.Matrix.iter_values(M):
    sum += value

print(sum)

2).矩阵乘法(Matrix Multiplication)

矩阵乘法涉及的是行列之间的点乘运算。矩阵乘法的规则如下:

假设有两个矩阵 A 和 B,如果 A 的列数等于 B 的行数,则可以将它们相乘得到一个新的矩阵 C。新矩阵 C 的行数与矩阵 A 相同,列数与矩阵 B 相同。

设 A 是一个 m × n 的矩阵,B 是一个 n × p 的矩阵,则它们的乘积 C 是一个 m × p 的矩阵。矩阵 C 的每个元素 C(i,j) 是通过将 A 的第 i 行与 B 的第 j 列对应元素相乘后再求和得到的。具体地,可以通过以下公式计算矩阵 C 的元素:

需要注意的是,矩阵乘法不满足交换律,即一般情况下,AB ≠ BA。即便是A和B矩阵的维度相同也通常不满足交换律。

实例:

# 矩阵相乘
A = np.array([[1, 2], [3, 4]])
B = np.array([[2, 0], [1, 2]])
# C = np.dot(A, B)  # or A @ B
# 注意:即便是维度相同也不满足交换律
C = np.dot(A, B)
print(C)
print("------矩阵相乘通常不满足交换律-------")
C = np.dot(B, A)
print(C)

运行结果:

[[ 4  4]
 [10  8]]
------矩阵相乘通常不满足交换律-------
[[ 2  4]
 [ 7 10]]

测试两个维度不同的矩阵乘积的效果。注意观察矩阵乘积不满足交换律。

print('--------测试两个维度不同的矩阵相乘---------')
A = np.array([[2], [1]])
B = np.array([[1, 3]])
C = np.dot(A, B)
print(C)
print("------矩阵相乘通常不满足交换律-------")
C = np.dot(B, A)
print(C)

运行结果:

--------测试两个维度不同的矩阵相乘---------
[[2 6]
 [1 3]]
------矩阵相乘通常不满足交换律-------
[[5]]

3).矩阵内积

矩阵的内积通常指的是矩阵的点积(或者称为内积或标量积)。内积是一种对两个相同大小的矩阵进行的运算,它是将两个矩阵中对应位置上的元素相乘,并将所有乘积的结果相加得到一个标量(单个数值)。

设有两个相同大小的矩阵 A 和 B,它们都是 m × n 的矩阵,内积(点积)的计算方式如下:

计算时,将 A 和 B 对应位置上的元素相乘,然后将所有乘积的结果相加,得到一个标量值。

实例:

import numpy as np

# 定义两个矩阵 A 和 B
A = np.array([[1, 2], [3, 4]])
B = np.array([[2, 0], [1, 2]])

# 计算矩阵内积
inner_product = np.vdot(A, B)

print("矩阵 A:")
print(A)
print("矩阵 B:")
print(B)
print("矩阵内积:")
print(inner_product)

运行结果:

矩阵 A:
[[1 2]
 [3 4]]
矩阵 B:
[[2 0]
 [1 2]]
矩阵内积:
13

注意:两个矩阵内积会尝试自动转换为形状相同的矩阵,并且矩阵的内积满足交换律。

# 矩阵常见的数学运算。
import numpy as np
import sympy as sp
from sympy import Matrix

#以下是两个形状不同的矩阵进行内积。
matrix_a = Matrix([[3,5,9], [1,4,7]])
matrix_b = Matrix([[2,3],[4,5],[7,9]])

print("---------矩阵的点积是满足交换律的------")
print(np.vdot(matrix_a, matrix_b))
print(np.vdot(matrix_b,matrix_a))

运行结果:

---------矩阵的点积是满足交换律的------
153
153

使用sympy求矩阵的内积。

import sympy as sp

matrix_a = sp.Matrix([[1,2],[3,4]])
matrix_b = sp.Matrix([[5,6],[7,8]])

#矩阵的内积,使用sympy实现。
print("------------sympy实现--------------")
print(matrix_a.multiply_elementwise(matrix_b))
result_matrix = matrix_a.multiply_elementwise(matrix_b)
sum =0
for value in sp.Matrix.iter_values(result_matrix):
    sum+= value
print("matrix_a和matrix_b内积的结果:",sum)

print(matrix_b.multiply_elementwise(matrix_a))
result_matrix = matrix_a.multiply_elementwise(matrix_b)
sum =0
for value in sp.Matrix.iter_values(result_matrix):
    sum+= value
print("matrix_b和matrix_a内积的结果:",sum)

运行结果:

------------sympy实现--------------
Matrix([[5, 12], [21, 32]])
matrix_a和matrix_b内积的结果: 70
Matrix([[5, 12], [21, 32]])
matrix_b和matrix_a内积的结果: 70

4).矩阵转置(Matrix Transposition)

想象你有一个矩阵,它就像一个长方形的表格,有很多行和列。现在,转置矩阵就像是把这个表格顺时针旋转90度,行变成列,列变成行。举个例子,如果你有一个矩阵:

它有两行三列。通过转置,你会得到一个新的矩阵:

实例:

import numpy as np
import sympy as sp

A = np.array([[1, 2,3], [4,5,6]])
B = sp.Matrix([[1,2,3],[4,5,6]])

print("--------使用numpy转置--------")
A_T = A.T
print("原矩阵:")
print(A)
print("转置矩阵:")
print(A_T)

print("-------使用sympy进行专置--------")
print(B)
print(B.T)

运行结果:

转置矩阵:
[[1 4]
 [2 5]
 [3 6]]

5).矩阵逆(Matrix Inversion)

逆矩阵就是这样一个矩阵 B,如果你把原始矩阵 A 乘以它,得到的结果是一个单位矩阵。所谓单位矩阵就是是一个特殊的方阵,其主对角线上的元素全为1,而其他元素全为0。其数学定义如下:

B被称为A的逆矩阵,记为

需要注意的是只有方阵才可计算其逆矩阵。也就是说A 必须是n*n的矩阵。

实例:

import numpy as np
A = np.array([[2, 1], [5, 3]])
A_inv = np.linalg.inv(A)
print("逆矩阵是:")
print(A_inv)

或者:

import numpy as np
A = np.array([[2, 1], [5, 3]])
matrix = np.mat(A)
print("逆矩阵是:")
print(matrix.I)

运行结果:

逆矩阵是:
[[ 3. -1.]
 [-5.  2.]]

矩阵可逆的判断条件是:对于给定一个 n × n 的矩阵 A,如果其行列式(det(A))不等于0,则矩阵 A 可逆,且其逆矩阵存在。

换句话说,如果一个矩阵的行列式不为零,那么它就是可逆的。行列式为零的矩阵称为奇异矩阵,它们是不可逆的。

逆矩阵有以下性质:

  1. 可逆矩阵一定是方阵。
  2. 如果矩阵A是可逆的,其逆矩阵是唯一的。
  3. A的逆矩阵的逆矩阵还是A。记作(A-1)-1=A。
  4. 可逆矩阵A的转置矩阵AT也可逆,并且(AT)-1=(A-1)T(转置的逆等于逆的转置)。
  5. 若矩阵A可逆,则矩阵A满足消去律。即AB=O(或BA=O),则B=O,AB=AC(或BA=CA),则B=C。
  6. 两个可逆矩阵的乘积依然可逆。
  7. 矩阵可逆当且仅当它是满秩矩阵。

逆矩阵的计算公式:

其中A*称为A的伴随矩阵,|A|是矩阵行列式的值。

伴随矩阵A* 有以下性质:

AA=AA=|A|E

下面是逆矩阵的伴随矩阵求解的python代码实现。

import numpy as np  # 导入numpy
from fractions import Fraction as F
import sympy as sp

# 计算代数余子式
def Aij(A, i, j):
    up = np.hstack((A[:i, :j], A[:i, j + 1:]))  # 横向连接上方片段
    lo = np.hstack((A[i + 1:, :j], A[i + 1:, j + 1:]))  # 横向连接下方片段
    M = np.vstack((up, lo))  # 纵向连接
    return ((-1) ** (i + j)) * np.linalg.det(M)  # 代数余子式

# 求伴随矩阵
def adjointMatrix(A):
    n, _ = A.shape  # 获取阶数n
    Am = np.zeros((n, n))  # Am初始化为零阵
    for i in range(n):  # 每一行
        for j in range(n):  # 每一列
            Am[i, j] = Aij(A, i, j)  # 伴随阵元素
    return Am.T


np.set_printoptions(formatter={'all': lambda x:str(F(x).limit_denominator())})
A = np.array([[1, 2, 3],  # 设置矩阵A
              [2, 2, 1],
              [3, 4, 3]])


Am = adjointMatrix(A)  # A的伴随阵

#计算A的行列式
# 使用sympy计算行列式
determinant = sp.Matrix(A).det()
print("---A的行列式的值----")
print(determinant)
print("---A的伴随矩阵----")
print(Am)
print("-----AA*=A*A=|A|E-----")
print(np.matmul(A, Am))

3.矩阵与行列式的区别

矩阵和行列式是线性代数中两个相关但又不同的概念。具体区别如下:

  1. 定义:矩阵是一个矩形排列的数值阵列,而行列式是一个与方阵相关的数值。
  2. 构成:矩阵由行和列组成,而行列式是方阵的一个数值。
  3. 表示:矩阵通常用方括号或圆括号表示,而行列式通常用竖线表示。