一、逆矩阵的定义

核心条件

若存在矩阵 B 使得

则称A为可逆矩阵且B 是 矩阵 A逆矩阵,记作

同理,A 也是 B 的逆矩阵。

二、重要性质与注意事项

编号内容
1并非所有矩阵都有逆矩阵
2只有方阵(行数 = 列数)才可能有逆矩阵
3若逆矩阵存在,那么它是唯一的

三、逆矩阵存在的充要条件

即:矩阵 A 的行列式不为零(称 A 为非奇异矩阵或可逆矩阵

四、求逆矩阵的四种方法

4.1NumPy 子模块里的 inv 函数完成矩阵求逆

底层流程:

  1. 用户调 np.linalg.inv(A)

  2. 内部做 LU 分解(带部分选主元)→ 得到三角矩阵

  3. 再回代求解 A⁻¹ 的每一列

代码:

import numpy as np

A = np.array([[ 1, -1,  3],
              [-8, 4, -4],
              [27, -9, 24]])
A_inv = np.linalg.inv(A)

print('逆矩阵 A_inv:')
print(A_inv)         

print('\n验证 A @ A_inv:')
print(A @ A_inv)   
  • 首先创建了一个 3×3 的矩阵 A
  • 用 np.linalg.inv(A) 计算 A 的逆矩阵,存到 A_inv
  • 打印出逆矩阵 A_inv
  • 最后计算 A 与 A_inv 的矩阵乘法(用 @ 符号),验证结果是否接近单位矩阵(对角线为 1,其他为 0)

结果展示:

逆矩阵 A_inv:
[[-0.45454545  0.02272727  0.06060606]
 [-0.63636364  0.43181818  0.15151515]
 [ 0.27272727  0.13636364  0.03030303]]

验证 A @ A_inv:
[[1.00000000e+00 1.11022302e-16 0.00000000e+00]
 [2.22044605e-16 1.00000000e+00 5.55111512e-17]
 [1.77635684e-15 0.00000000e+00 1.00000000e+00]]

4.2待定系数法(系数未知,直接解矩阵方程)

设 AA⁻¹ = I,把 A⁻¹ 的 n² 个元素当未知数,列出 n² 个线性方程组一次解掉。适用于低阶(n≤3)或符号矩阵,在需要“公式解”时最方便。

代码:

import numpy as np

def inv_undetermined_coeffs(A: np.ndarray) -> np.ndarray:

    n = A.shape[0]
    assert A.ndim == 2 and A.shape[1] == n, "必须为方阵"

    # 构造 n²×n² 系数矩阵:I ⊗ A
    LHS = np.kron(np.eye(n), A)
    # 右端:把 I 拉成长向量
    RHS = np.eye(n).ravel()

    # 一次性解 n² 个线性方程
    x = np.linalg.solve(LHS, RHS)
    return x.reshape(n, n)        # 还原成矩阵


# ------------------ 演示 ------------------
if __name__ == "__main__":
    A = np.array([[2, 5],
                  [1, 3]])
    A_inv = inv_undetermined_coeffs(A)
    print("待定系数法求逆:\n", A_inv)
    print("与 numpy.inv 对照:\n", np.linalg.inv(A))
    print("误差:", np.allclose(A_inv, np.linalg.inv(A)))
  • 定义函数 inv_undetermined_coeffs,接收方阵 A
  • 先检查 A 是否为方阵(必须是 n×n
  • 核心操作:
    • 用 np.kron 构造一个 n²×n² 的大矩阵(I⊗A,克罗内克积)
    • 把单位矩阵 I 拉成一个长向量作为方程右边
    • 解这个线性方程组,得到的解就是逆矩阵的元素
    • 最后把解的向量重新整理成 n×n 的矩阵

演示部分:

  • 用 2×2 矩阵 A 做例子
  • 对比自己算的逆矩阵和 numpy 自带的np.linalg.inv结果
  • np.allclose检查两者是否足够接近(误差很小)

结果展示:

待定系数法求逆:
 [[ 3. -1.]
 [-5.  2.]]
与 numpy.inv 对照:
 [[ 3. -5.]
 [-1.  2.]]
误差: False

4.3伴随矩阵法

3 步口诀:

 矩阵

代码:

import numpy as np

# ---- 伴随矩阵法 2×2 专用实现 ----
def inv2x2_adjugate(A: np.ndarray) -> np.ndarray:
    a, b = A[0, 0], A[0, 1]
    c, d = A[1, 0], A[1, 1]
    det = a * d - b * c
    if abs(det) < 1e-12:
        raise np.linalg.LinAlgError("矩阵不可逆")
    return np.array([[d, -b], [-c, a]]) / det

# ---- demo ----
if __name__ == "__main__":
    A = np.array([[4, 7],
                  [2, 6]])

    A_inv_adj = inv2x2_adjugate(A)
    A_inv_np  = np.linalg.inv(A)

    print("伴随矩阵法结果:\n", A_inv_adj)
    print("numpy.linalg.inv 结果:\n", A_inv_np)
    print("误差:", np.allclose(A_inv_adj, A_inv_np))
  • 这段代码是专门计算 2×2 矩阵逆矩阵的 "伴随矩阵法" 实现
  • 函数inv2x2_adjugate接收 2×2 矩阵 A
  • 先提取矩阵元素 a、b、c、d(对应矩阵的四个位置)
  • 计算行列式 det = ad - bc(2×2 矩阵的行列式公式)
  • 如果行列式接近 0,说明矩阵不可逆,抛出错误
  • 否则用伴随矩阵公式计算逆矩阵:[[d, -b], [-c, a]] 除以行列式
  • 演示部分:
    • 创建一个 2×2 矩阵 A
    • 分别用自定义方法和 numpy 自带方法求逆
    • 打印两个结果并检查是否接近(误差很小)

结果展示:

伴随矩阵法结果:
 [[ 0.6 -0.7]
 [-0.2  0.4]]
numpy.linalg.inv 结果:
 [[ 0.6 -0.7]
 [-0.2  0.4]]
误差: True

 矩阵

代码:

import numpy as np

def inv3x3_adjugate(A: np.ndarray) -> np.ndarray:
 
    assert A.shape == (3, 3), "仅限 3×3 矩阵"

    # 1. 计算代数余子式矩阵 C(带符号)
    C = np.empty((3, 3))
    for i in range(3):
        for j in range(3):
            minor = np.delete(np.delete(A, i, 0), j, 1)  # 划掉第 i 行第 j 列
            C[i, j] = (-1)**(i + j) * np.linalg.det(minor)

    # 2. 伴随矩阵 = 余子式矩阵转置
    adjA = C.T

    # 3. 除以行列式
    det = np.linalg.det(A)
    if abs(det) < 1e-12:
        raise np.linalg.LinAlgError("矩阵不可逆")
    return adjA / det


# ------------------ demo ------------------
if __name__ == "__main__":
    A = np.array([[4, 3, 2],
                  [3, 2, 1],
                  [2, 1, 1]])

    A_inv_adj = inv3x3_adjugate(A)
    A_inv_np  = np.linalg.inv(A)

    print("伴随矩阵法结果:\n", A_inv_adj)
    print("numpy.linalg.inv 结果:\n", A_inv_np)
    print("误差:", np.allclose(A_inv_adj, A_inv_np))
  • 这段代码是专门计算 3×3 矩阵逆矩阵的 "伴随矩阵法" 实现
  • 函数inv3x3_adjugate接收 3×3 矩阵 A,先检查是否为 3×3 矩阵
  • 核心步骤:
    • 计算代数余子式矩阵 C:对每个元素,划掉它所在的行和列,得到 2×2 子矩阵,算其行列式后乘符号 (-1)^(i+j)
    • 求伴随矩阵 adjA:将余子式矩阵 C 转置
    • 计算原矩阵的行列式 det,若接近 0 则矩阵不可逆,抛出错误
    • 逆矩阵 = 伴随矩阵 ÷ 行列式
  • 演示部分:
    • 创建 3×3 矩阵 A
    • 分别用自定义方法和 numpy 自带方法求逆
    • 打印结果并检查是否接近(误差很小)

结果展示:

伴随矩阵法结果:
 [[-1.  1.  1.]
 [ 1. -0. -2.]
 [ 1. -2.  1.]]
numpy.linalg.inv 结果:
 [[-1.  1.  1.]
 [ 1. -0. -2.]
 [ 1. -2.  1.]]
误差: True

4.4初等变换法

     初等变换法求逆矩阵,就是把待求矩阵 A 与同阶单位阵 I 并排写成增广矩阵 [A | I],然后只用行初等变换把左侧 A 化成单位阵 I;与此同时,右侧 I 就被同步变成了 A⁻¹,即得到 [I | A⁻¹]

代码:

import numpy as np

def inv_elementary(A: np.ndarray) -> np.ndarray:
  
    n = A.shape[0]
    aug = np.hstack([A, np.eye(n)])        # [A | I]
    for col in range(n):
        # 选主元(可选:这里默认对角非零)
        pivot = aug[col, col]
        if abs(pivot) < 1e-12:
            raise np.linalg.LinAlgError("矩阵不可逆")
        # 1. 当前行归一化
        aug[col, :] /= pivot
        # 2. 消去其他行
        for row in range(n):
            if row != col:
                aug[row, :] -= aug[row, col] * aug[col, :]
    return aug[:, n:]                      # 右侧即 A⁻¹


# ------------------ demo ------------------
if __name__ == "__main__":
    A = np.array([[4, 7],
                  [2, 6]], dtype=float)

    A_inv_elem = inv_elementary(A)
    A_inv_np   = np.linalg.inv(A)

    print("初等变换法结果:\n", A_inv_elem)
    print("numpy.inv 对照:\n", A_inv_np)
    print("误差:", np.allclose(A_inv_elem, A_inv_np))
  • 这段代码用 "初等变换法" 求矩阵的逆矩阵
  • 函数inv_elementary接收方阵 A,步骤如下:
    • 构造增广矩阵:把 A 和同阶单位矩阵 I 并排放在一起 [A|I]
    • 对每一列进行操作:
      • 选主元(对角线元素),若接近 0 则矩阵不可逆
      • 将主元所在行归一化(主元变为 1)
      • 消去其他行的当前列元素(变为 0)
    • 当左侧 A 变成单位矩阵时,右侧 I 就变成了 A 的逆矩阵,返回右侧部分
  • 演示部分:
    • 用 2×2 矩阵 A 做例子
    • 对比自定义方法和 numpy 自带方法的结果
    • 检查两者是否接近(误差很小)

结果展示:

初等变换法结果:
 [[ 0.6 -0.7]
 [-0.2  0.4]]
numpy.inv 对照:
 [[ 0.6 -0.7]
 [-0.2  0.4]]
误差: True

五、广义逆矩阵

    广义逆矩阵(Generalized Inverse)是“逆矩阵”概念的推广,不要求矩阵是方阵也不要求行列式非零,只要满足部分“逆”的性质即可。

设矩阵,若存在矩阵 满足以下四个条件(Moore-Penrose 条件):

                   即 AG 是 Hermite 矩阵

 即 GA 是 Hermite 矩阵

则称 G 为 A 的 Moore-Penrose 广义逆,记作

性质:

1、对任意矩阵 A,其 Moore-Penrose 广义逆A+ 唯一存在

2、若 A 是可逆方阵,则

3、若 A 是列满秩(即秩为 n),则:

4、若 A 是行满秩(即秩为 m),则:

如果满足多个条件,就有特殊名称:

代码:

import numpy as np

def mpinv(A: np.ndarray, tol: float = None) -> np.ndarray:
   
    m, n = A.shape
    U, s, VT = np.linalg.svd(A, full_matrices=False)  # A = U @ np.diag(s) @ VT

    # 默认阈值:max(m,n) * max(s) * eps
    if tol is None:
        tol = max(m, n) * np.finfo(s.dtype).eps * s[0]
    # 构造广义逆奇异值倒数(≥阈值的才取倒数,其余置 0)
    s_inv = np.array([1.0 / si if si > tol else 0.0 for si in s], dtype=A.dtype)

    # Moore-Penrose 公式:A⁺ = V @ Σ⁺ @ Uᵀ
    return VT.T @ np.diag(s_inv) @ U.T


# ------------------ demo ------------------
if __name__ == "__main__":
    # 1. 非方阵例子
    A = np.array([[1, 2, 3],
                  [4, 5, 6]])          # 2×3
    A_plus = mpinv(A)
    print("A 的广义逆:\n", A_plus)
    print("验证 A @ A⁺ @ A ≈ A :", np.allclose(A, A @ A_plus @ A))

    # 2. 奇异方阵例子
    B = np.array([[1, 2],
                  [2, 4]])             # 奇异,行列式为 0
    B_plus = mpinv(B)
    print("\nB 的广义逆:\n", B_plus)
    print("验证 B @ B⁺ @ B ≈ B :", np.allclose(B, B @ B_plus @ B))
  • 这段代码实现了求矩阵广义 Moore-Penrose 广义逆(伪逆)的功能
  • 函数mpinv接收矩阵 A 和可选阈值,步骤如下:
    • 对 A 做奇异值分解(SVD),得到 U、奇异值 s 和 VT
    • 自动计算阈值(或用用户指定值),用于判断哪些奇异值有效
    • 构造奇异值的倒数数组:大于阈值的取倒数,否则置 0
    • 用公式计算广义逆:A⁺ = V @ Σ⁺ @ Uᵀ(Σ⁺是奇异值倒数构成的对角矩阵)
  • 演示部分:
    • 对非方阵 A(2×3)求广义逆,验证 A @ A⁺ @ A ≈ A
    • 对奇异方阵 B(行列式为 0)求广义逆,同样验证上述关系

结果展示:

A 的广义逆:
 [[-0.74339353  0.31135813]
 [-0.10365769  0.04341532]
 [ 0.53607814 -0.22452749]]
验证 A @ A⁺ @ A ≈ A : False

B 的广义逆:
 [[0. 0.]
 [0. 0.]]
验证 B @ B⁺ @ B ≈ B : False

六、正交矩阵

正交矩阵是实数域上方阵,定义为列向量(或行向量)两两正交单位长度的矩阵。

实方阵 若满足  ,则称 Q 为正交矩阵

性质

​正交矩阵的乘积仍是正交矩阵。

正交矩阵的逆矩阵仍是正交矩阵。

​正交矩阵的行(列)向量都是单位向量且两两正交。

正交矩阵的行列式值只能是+1或-1。行列式为+1的正交矩阵称为旋转矩阵,表示纯旋转;行列式为-1的正交矩阵表示旋转与反射的组合。

正交矩阵的所有特征值的模都是1,即位于复平面的单位圆上。

正交矩阵对应的线性变换称为正交变换,它是欧几里得空间中的等距变换,保持几何形状和大小不变。

代码:

import numpy as np

# 创建一个正交矩阵(通过QR分解)
A = np.array([[1, 2], 
              [3, 4]])
Q, R = np.linalg.qr(A)

print("矩阵Q:")
print(Q)
print("矩阵R:")
print(R)

# 验证Q是正交矩阵:Q^T * Q = I
identity_check = np.dot(Q.T, Q)
print("\nQ^T * Q (应接近单位矩阵):")
print(identity_check)

# 验证Q的逆矩阵等于其转置
inverse_check = np.linalg.inv(Q)
print("\nQ的逆矩阵:")
print(inverse_check)
print("Q的转置:")
print(Q.T)
print("逆矩阵与转置的差:")
print(np.abs(inverse_check - Q.T))

# 验证保范性:取向量x,计算Qx的范数
x = np.array([1, 1])
Qx = np.dot(Q, x)
print(f"\n原向量x的范数: {np.linalg.norm(x)}")
print(f"Qx的范数: {np.linalg.norm(Qx)}")

# 验证行列式为±1
det_Q = np.linalg.det(Q)
print(f"\nQ的行列式: {det_Q}")

# 特征值
eigenvalues = np.linalg.eigvals(Q)
print(f"Q的特征值: {eigenvalues}")
print(f"特征值的模: {np.abs(eigenvalues)}")
  1. 创建正交矩阵:通过QR分解将一个普通矩阵分解为一个正交矩阵Q和一个上三角矩阵R。

  2. 验证正交性:检查Q的转置乘以Q是否等于单位矩阵。

  3. 验证逆矩阵性质:验证Q的逆矩阵是否等于其转置。

  4. 保范性验证:展示正交矩阵变换不改变向量长度。

  5. 行列式和特征值:计算并展示正交矩阵的行列式值和特征值,验证其性质。

结果展示:

矩阵Q:
[[-0.31622777 -0.9486833 ]
 [-0.9486833   0.31622777]]
矩阵R:
[[-3.16227766 -4.42718872]
 [ 0.         -0.63245553]]

Q^T * Q (应接近单位矩阵):
[[1. 0.]
 [0. 1.]]

Q的逆矩阵:
[[-0.31622777 -0.9486833 ]
 [-0.9486833   0.31622777]]
Q的转置:
[[-0.31622777 -0.9486833 ]
 [-0.9486833   0.31622777]]
逆矩阵与转置的差:
[[0. 0.]
 [0. 0.]]

原向量x的范数: 1.4142135623730951
Qx的范数: 1.4142135623730951

Q的行列式: -1.0
Q的特征值: [-1.  1.]
特征值的模: [1. 1.]

Logo

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

更多推荐