计算逆矩阵



前言

  逆矩阵是我们线性代数所学习的,在Python中我们可以通过numpy.linalg一个包含线性代数的函数模块。使用这个模块,我们可以实现计算逆矩阵。


一、矩阵

  矩阵与数组的概念有着本质的区别:①数组是计算机专业的概念,矩阵是数学专业的概念;②数组可以是一维、二维、三维或其他任意维度的,矩阵只能且必须是二维的;③数组中可以包含任意类型的数据,矩阵中元素必须是数值;④数组乘法与矩阵乘法的规则不同。

定义矩阵的两种方式,代码如下:

import numpy as np
A = np.matri`x([[1, 2], [3, 4]])      # 列表
B = np.mat('5 6; 7 8')               # 字符串
print(A)
print(B)

二、逆矩阵

1.逆矩阵的定义

   A、B为同阶矩阵,如果存在AB = BA = E,即称B为A的逆矩阵,同理,A也是B的逆矩阵,记作在这里插入图片描述.

  • 注意

1)不是所有的矩阵都存在逆矩阵

2)只有方阵才存在逆矩阵

3)如果逆矩阵存在,逆矩阵唯一

4)逆矩阵存在的条件|A| != 0,即可逆矩阵的行列式不为0

2.计算逆矩阵

   拓展库Numpy 的线性代数子模块linalg中提供了用来计算逆矩阵的函数inv()。
计算方阵的逆矩阵

代码如下:

(1)方阵求逆

A = np.array([[4, 7],
              [2, 6]])
det_A = np.linalg.det(A) #计算行列式
print('A =\n', A)
print('det(A) = {:.2f}'.format(det_A))

A_inv = np.linalg.inv(A)          # 求逆
I_check = A @ A_inv               # 原矩阵 × 逆矩阵
print('A_inv =\n', A_inv)
print('A · A_inv =\n', I_check)
print('是否单位矩阵?', np.allclose(I_check, np.eye(2)))

运行结果:
在这里插入图片描述
(2)非方阵求逆(报错):

B = np.array([[1, 2, 3],
              [4, 5, 6]])
print('B =\n', B)
try:
    np.linalg.inv(B)
except np.linalg.LinAlgError as e:
    print('非方阵求逆报错:', e)

运行结果:
在这里插入不是方阵无法求逆图片描述
(3)奇异矩阵求逆(报错):

C = np.array([[1, 2],
              [2, 4]])        # 第 2 行是第一行的 2=> 行列式 = 0
print('C =\n', C)
print('det(C) = {:.2f}'.format(np.linalg.det(C)))
try:
    np.linalg.inv(C)
except np.linalg.LinAlgError as e:
    print('奇异矩阵求逆报错:', e)

运行结果:
在这里插入图片描述

3.广义逆矩阵

对于任意矩阵A,存在一个唯一的的矩阵M使得下面三个条件同时成立:

(1)AMA=A
(2)MAM=M
(3)AM与MA均为对称矩阵
这样的矩阵M称为矩阵A的Moore-Penrose广义逆矩阵,奇异矩阵也可以计算广义逆矩阵。

在Python中,可以使用numpy库中的numpy.linalg.pinv函数来计算矩阵的Moore-Penrose逆矩阵:

代码如下:

A = np.random.RandomState(42).rand(4, 3)
print('A (4×3):\n', A)

# 计算 Moore-Penrose 广义逆
B = np.linalg.pinv(A)
print('B (3×4)——A 的广义逆:\n', B)

# 验证三个 Moore-Penrose 条件
print('验证 A B A = A:', np.allclose(A, A @ B @ A))
print('验证 B A B = B:', np.allclose(B, B @ A @ B))
print('验证 (A B)^T = A B:', np.allclose(A @ B, (A @ B).T))
print('验证 (B A)^T = B A:', np.allclose(B @ A, (B @ A).T))

在这里插入图片描述
计算奇异矩阵的广义逆矩阵:

import numpy as np

C = np.array([[1, 2, 3],
              [2, 4, 6],
              [3, 6, 9]], dtype=float)
print('C (3×3 奇异矩阵):\n', C)
print('det(C) =', np.linalg.det(C))

# 广义逆
D = np.linalg.pinv(C)
print('D (3×3)——C 的广义逆:\n', D)

# 验证三个 Moore-Penrose 条件
print('验证 C D C = C:', np.allclose(C, C @ D @ C))
print('验证 D C D = D:', np.allclose(D, D @ C @ D))
print('验证 (C D)^T = C D:', np.allclose(C @ D, (C @ D).T))
print('验证 (D C)^T = D C:', np.allclose(D @ C, (D @ C).T))

运行结果:
在这里插入图片描述


4.判断是否为正交矩阵

(1)正交矩阵的定义
  如果AAT=E(E为单位矩阵,AT表示“矩阵A的转置矩阵”)或ATA=E,则n阶实矩阵A称为正交矩阵。
(2)正交矩阵的性质

  • 正交矩阵的行向量和列向量都是单位向量(即长度为1)。
  • 行向量与列向量两两正交,任意两行(或两列)的点积为0。
  • 逆矩阵等于转置矩阵:A−1=AT
  • 行列式的绝对值为1,即|det(A)|=1。
# 1. 单位矩阵
mat = np.matrix([[1,0,0],[0,1,0],[0,0,1]])
print('inv(mat) == mat.T:\n', np.linalg.inv(mat) == mat.T)
print('det(mat) =', np.linalg.det(mat))

# 2. 对角反射矩阵
mat = np.matrix([[1,0], [0,-1]])
print('inv(mat) == mat.T:\n', np.linalg.inv(mat) == mat.T)
print('det(mat) =', np.linalg.det(mat))

# 3. 正交矩阵的逆矩阵仍是正交矩阵
mat_inv = np.linalg.inv(mat)
print('mat_inv @ mat_inv.T =\n', np.dot(mat_inv, mat_inv.T))

运行结果:
在这里插入图片描述

①单位矩阵逆等于转置且行列式为1,是最基本的纯旋转正交矩阵;
②二阶对角反射矩阵同样逆等于转置但行列式为–1,表明它也是正交矩阵,仅做一次镜像翻转;
③最后计算该矩阵的逆再乘其转置得到单位矩阵,证实正交矩阵的逆依旧是正交矩阵。

三、拓展内容

1.特征值、特征向量与逆矩阵的关系

  对于矩阵 A A A,如果存在非零向量 v \mathbf{v} v 和标量 λ \lambda λ,使得 A v = λ v A\mathbf{v}=\lambda\mathbf{v} Av=λv,则 λ \lambda λ A A A 的特征值, v \mathbf{v} v 是对应的特征向量;若 A A A 可逆,则 A − 1 A^{-1} A1 的特征值为 λ − 1 \lambda^{-1} λ1,且特征向量与 A A A 相同。

import numpy as np
# 定义矩阵 A
A = np.array([[4, 7], [2, 6]])
# 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
# 计算矩阵的逆
A_inv = np.linalg.inv(A)
# 验证逆矩阵的特征值是原矩阵特征值的倒数
inv_eigenvalues = 1 / eigenvalues
# 验证逆矩阵的特征向量与原矩阵相同
inv_eigenvectors = eigenvectors
print("矩阵 A 的特征值:", eigenvalues)
print("矩阵 A 的特征向量:\n", eigenvectors)
print("矩阵 A 的逆矩阵的特征值:", inv_eigenvalues)
print("矩阵 A 的逆矩阵的特征向量:\n", inv_eigenvectors)

在这里插入图片描述

2.稀疏矩阵的逆矩阵

  稀疏矩阵是指矩阵中大部分元素为零的矩阵称为稀疏矩阵。计算稀疏矩阵的逆矩阵时,可以使用稀疏矩阵库(如 SciPy 的 scipy.sparse)来提高效率。

import numpy as np
from scipy.sparse import csc_matrix, spdiags
from scipy.sparse.linalg import inv
import matplotlib.pyplot as plt

# 8×8 对角稀疏矩阵:对角线 8 个非零元,其余全是 0
n = 8
vals = np.array([5, 8, 2, 7, 4, 9, 1, 6], dtype=float)  # 对角元
A = spdiags(vals, 0, n, n).tocsc()        # 快速生成对角稀疏矩阵

A_inv = inv(A)           # 现在可逆

print("稀疏矩阵 A (8×8):")
print(A.toarray())
print("\nA 的逆矩阵:")
print(A_inv.toarray())

稀疏矩阵示意图

在这里插入图片描述

3.逆矩阵实现图像变换

  将图片中的每个像素坐标 ( x , y ) (x,y) (x,y)写成齐次坐标列向量 p = [ x , y , 1 ] T \mathbf{p}=[x,y,1]^T p=[x,y,1]T,图像变换就是左乘一个 3 × 3 3\times3 3×3矩阵 M M M 计算目标坐标: p ′ = M p \mathbf{p}'=M\mathbf{p} p=Mp。若是要实现逆向变换图片则需要计算 M − 1 M^{-1} M1,将目标坐标 p ′ \mathbf{p}' p再映射回原始坐标 p \mathbf{p} p
  参数解释:
M = cv2.getRotationMatrix2D(center, angle=45, scale=1.0)
(1) center=(cx,cy) —— 旋转中心 像素坐标(非矩阵下标);
(2)angle=45 —— 逆时针角度(单位 °),负值即顺时针;
(3) scale=1.0 —— 旋转后缩放比例,1.0 原大,0.5 半倍,2.0 两倍。
齐次矩阵  M = [cosθ -sinθ tx;sinθ cosθ ty; 0 0 1]

import cv2
import numpy as np

img = cv2.imread(r'C:\Users\wangyuyan\Pictures\Screenshots\houzi.png', cv2.IMREAD_COLOR)
if img is None:
    raise FileNotFoundError("图片路径不对或文件不存在")

h, w = img.shape[:2]          # 只取高、宽
center = (w // 2, h // 2)

# 正向旋转 45°
M = cv2.getRotationMatrix2D(center, 45, 1.0)
rot = cv2.warpAffine(img, M, (w, h))

# 反向旋转 45°
M_inv = cv2.getRotationMatrix2D(center, -45, 1.0)
restored = cv2.warpAffine(rot, M_inv, (w, h))

cv2.imshow("Original", img)
cv2.imshow("Transformed", rot)
cv2.imshow("Restored", restored)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

总结

  本文围绕Python中逆矩阵的计算与应用展开,先明确矩阵与数组的本质区别,介绍逆矩阵“仅非奇异方阵存在、且唯一”的核心特性;接着讲解用numpy.linalg.inv()计算常规逆矩阵的方法,以及非方阵、奇异矩阵求逆的报错情况;随后引入广义逆矩阵(通过np.linalg.pinv()实现,适用于任意矩阵,需满足4个验证条件),并阐述正交矩阵“逆等于转置、行列式绝对值为1”的特殊性质;最后拓展了逆矩阵在特征值关系(逆矩阵特征值为原矩阵倒数)、稀疏矩阵(用scipy.sparse库高效计算)、图像变换(通过旋转矩阵及其逆实现正向变换与逆向恢复)中的应用,形成从基础概念到实践操作的完整知识体系。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐