Python用NumPy求矩阵的逆:np.linalg.inv基础用法
np.linalg.inv() 函数。调用时只需传入一个二维方阵,该函数就会返回对应的逆矩阵;如果矩阵不可逆或形状不满足方阵要求,程序将抛出 LinAlgError 异常。
一、矩阵逆运算的基本原理与NumPy接口
在数学上,设 $A$ 是一个 $n \times n$ 的方阵,若存在一个矩阵 $A^{-1}$ 使得 $A \cdot A^{-1} = A^{-1} \cdot A = I$(其中 $I$ 为 $n$ 阶单位矩阵),则称 $A$ 是可逆矩阵,$A^{-1}$ 即为 $A$ 的逆矩阵。
NumPy 将求逆功能封装在 numpy.linalg.inv(a) 中。传入参数 a 必须是包含浮点数或复数类型的方阵(最后两个维度相等且至少为2维)。求解过程底层调用了 LAPACK 库的高性能数值算法(通常基于 LU 分解),兼具执行效率与数值稳定性。
二、标准调用步骤与代码实操
使用 np.linalg.inv() 求逆的基本流程分为三个环节:准备并定义输入方阵、调用接口获取逆矩阵、对计算结果进行浮点精度验证。
步骤一:定义合法的二维方阵
首先导入 NumPy 模块,并使用 np.array() 构建目标方阵。这里以一个 $2 \times 2$ 的整型方阵为例:
import numpy as np
# 定义一个 2x2 矩阵
A = np.array([[4.0, 7.0],
[2.0, 6.0]])
print("原矩阵 A:\n", A)
print("形状:", A.shape)
示例输出:
原矩阵 A:
[[4. 7.]
[2. 6.]]
形状: (2, 2)
步骤二:调用 np.linalg.inv 求逆
直接将方阵 A 传入 np.linalg.inv(),得到返回的逆矩阵数组:
# 计算矩阵的逆
A_inv = np.linalg.inv(A)
print("A 的逆矩阵:\n", A_inv)
示例输出:
A 的逆矩阵:
[[ 0.6 -0.7]
[-0.2 0.4]]
步骤三:验算求逆结果
理论上,原矩阵与逆矩阵相乘 A @ A_inv 结果应严格等于单位矩阵 np.eye(2)。但在计算机内部,由于双精度浮点数舍入误差的存在,部分非对角元素可能为接近于 0 的极小浮点数(如 1e-17),而不会严格等于 0.0。因此,严禁使用 == 判断相等,必须使用 np.allclose() 进行容差比较:
# 矩阵乘法验证
product = A @ A_inv
identity = np.eye(2)
print("A @ A_inv 乘积:\n", product)
# 使用 np.allclose 校验,允许浮点容差
is_valid = np.allclose(product, identity)
print("验算是否为单位矩阵:", is_valid) # 输出 True
三、常见错误与前置条件判定
调用 np.linalg.inv() 时,最常见的两种运行期错误都属于 np.linalg.LinAlgError 异常:
1. 形状错误:传入非方阵
求逆运算在数学上仅对方阵定义。如果传入的数组最后两个维度不一致(例如 $2 \times 3$ 矩阵),NumPy 会立刻抛出错误:
non_square = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
try:
np.linalg.inv(non_square)
except np.linalg.LinAlgError as e:
print("捕获错误:", e)
报错信息示例:
捕获错误: Last 2 dimensions of the array must be square
2. 奇异矩阵(不可逆矩阵)错误
即使矩阵是方阵,如果其行列式等于 0(或者矩阵存在线性相关的行/列),该矩阵被称为“奇异矩阵”(Singular Matrix),数学上没有逆矩阵。此时 np.linalg.inv() 无法求解:
singular_matrix = np.array([[1.0, 2.0],
[2.0, 4.0]]) # 第二行是第一行的2倍
try:
np.linalg.inv(singular_matrix)
except np.linalg.LinAlgError as e:
print("捕获错误:", e)
报错信息示例:
捕获错误: Singular matrix
np.linalg.pinv(A)(Pseudo-inverse),它能在矩阵不可逆时返回数值上稳定的伪逆矩阵。
四、批量求逆技巧(高维数组广播)
np.linalg.inv() 原生支持高维张量的批量求逆。当输入数组的维度大于 2 时,NumPy 会将前面的维度视为“批次索引”(Batch Dimensions),只对最后两个维度 (..., N, N) 分别执行求逆操作。
# 构造形状为 (3, 2, 2) 的批次方阵,代表 3 个 2x2 方阵
batch_A = np.array([
[[1.0, 2.0], [3.0, 4.0]],
[[5.0, 2.0], [2.0, 1.0]],
[[3.0, 0.0], [0.0, 2.0]]
])
# 一次性对全部 3 个方阵求逆
batch_inv = np.linalg.inv(batch_A)
print("批次求逆结果形状:", batch_inv.shape) # 输出: (3, 2, 2)
# 批量验证 A @ A_inv 是否全为单位矩阵
batch_identity = batch_A @ batch_inv
all_correct = np.allclose(batch_identity, np.eye(2))
print("批量验算一致性:", all_correct) # 输出: True
这种矢量化批处理方式避免了 Python 层的 for 循环,在处理海量小方阵求逆(如卡尔曼滤波、三维变换矩阵堆叠)时性能大幅提升。
五、实际应用中的性能与替代方案
在工程实践中,求逆矩阵最常见的目的是为了求解线性方程组 $Ax = b$。初学者往往习惯写成:
# 不推荐:先显式求逆再做乘法
x = np.linalg.inv(A) @ b
但这种写法在数值分析中通常不被推荐,原因如下:
- 运算量翻倍:显式计算 $A^{-1}$ 再乘向量需要先完成矩阵求逆再做矩阵-向量乘法,耗时明显高于直接解方程。
- 累积误差更大:显式求逆过程会放大病态矩阵(高条件数矩阵)的浮点舍入误差。
正确的替代方案是直接使用 np.linalg.solve(A, b):
# 推荐:直接求解线性方程组 Ax = b
x = np.linalg.solve(A, b)
np.linalg.solve() 内部利用高斯消元法或 LU 分解直接求出未知向量 $x$,不仅速度更快,而且在数值上更加稳定。
六、知识梳理与核心要点总结
| 功能 / 问题 | 代码或判断方法 | 注意事项 |
|---|---|---|
| 标准矩阵求逆 | np.linalg.inv(A) |
输入必须为非奇异方阵,数据类型通常为浮点数 |
| 结果正确性验算 | np.allclose(A @ A_inv, np.eye(n)) |
计算机存在浮点舍入微小误差,切忌使用 == 比较 |
| 长方阵或奇异矩阵 | np.linalg.pinv(A) |
当原矩阵不可逆时,使用广义逆(SVD分解)获取数值解 |
| 求解线性方程 $Ax=b$ | np.linalg.solve(A, b) |
比 inv(A) @ b 速度更快、精度更高,应作为首选 |
| 多方阵批处理 | 输入形状为 (..., N, N) |
NumPy 会自动在批次维度上广播运算,无需编写循环 |
掌握 np.linalg.inv() 的关键在于明确其“方阵且满秩”的前置要求,养成用 np.allclose() 检验计算结果的习惯,并在实际求解方程组时合理选用 solve(),从而在保证算法正确性的同时兼顾数值稳定性与计算效率。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









