pin_drop当前位置:知识文库 ❯ 图文
NumPy线性代数完整教程 - 矩阵运算与SVD分解
一、概述
NumPy的linalg模块提供了完整的线性代数运算功能,包括矩阵乘法、矩阵分解(LU、QR、SVD、Cholesky)、行列式计算、逆矩阵、特征值与特征向量、解线性方程组等。这些功能是科学计算、机器学习和工程计算的基础工具。
无论是解决多元一次方程组,还是进行主成分分析(PCA)降维,线性代数运算都是不可或缺的。NumPy将这些底层复杂的数学运算封装为简洁的API,让开发者无需手动实现复杂的算法。
二、语法与常用函数
NumPy线性代数运算的核心入口是numpy.linalg模块。以下是常用语法概览:
代码示例
import numpy as np
from numpy import linalg
np.dot(a, b) # 点积
linalg.inv(a) # 逆矩阵
linalg.det(a) # 行列式
linalg.eig(a) # 特征值和特征向量
linalg.solve(a, b) # 解线性方程组
linalg.norm(a) # 范数
linalg.svd(a) # 奇异值分解三、参数说明
以下是linalg模块中各核心函数的参数说明:
四、矩阵基本运算
矩阵运算是线性代数的基础。NumPy提供了矩阵乘法、求逆、行列式和矩阵秩等常用运算,下面通过代码示例来演示:
代码示例
import numpy as np
from numpy import linalg
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 矩阵乘法
print(f"A @ B:\n{A @ B}")
# 逆矩阵
A_inv = linalg.inv(A)
print(f"\nA的逆矩阵:\n{A_inv}")
print(f"验证 A @ A_inv:\n{np.round(A @ A_inv)}")
# 行列式
print(f"\nA的行列式: {linalg.det(A):.1f}")
# 矩阵秩
print(f"A的秩: {linalg.matrix_rank(A)}")输出结果:
代码示例
A @ B:
[[19 22]
[43 50]]
A的逆矩阵:
[[-2. 1. ]
[ 1.5 -0.5]]
验证 A @ A_inv:
[[1. 0.]
[0. 1.]]
A的行列式: -2.0
A的秩: 2小贴士
在NumPy中,矩阵乘法推荐使用@运算符(Python 3.5+),它比np.dot()语义更清晰。行列式为0表示矩阵不可逆,此时调用linalg.inv()会抛出LinAlgError。
五、特征值与特征向量
特征值和特征向量描述了矩阵变换中的不变方向。对于一个方阵A,如果存在非零向量v和标量λ,使得A @ v = λ * v,则λ是特征值,v是对应的特征向量。
代码示例
import numpy as np
from numpy import linalg
A = np.array([[4, 2], [1, 3]])
# 特征值和特征向量
eigenvalues, eigenvectors = linalg.eig(A)
print(f"特征值: {eigenvalues}")
print(f"特征向量:\n{eigenvectors}")
# 验证: A @ v = lambda * v
for i in range(len(eigenvalues)):
v = eigenvectors[:, i]
lam = eigenvalues[i]
print(f"\nlambda={lam:.2f}: A@v = {A @ v}, lambda*v = {lam * v}")输出结果:
代码示例
特征值: [5. 2.]
特征向量:
[[ 0.89442719 -0.70710678]
[ 0.4472136 0.70710678]]
lambda=5.00: A@v = [4.47213595 2.23606798], lambda*v = [4.47213595 2.23606798]
lambda=2.00: A@v = [-1.41421356 1.41421356], lambda*v = [-1.41421356 1.41421356]代码验证了特征值和特征向量的定义:矩阵A乘以特征向量v等于特征值λ乘以v,说明计算结果正确。
六、解线性方程组与SVD分解
解线性方程组:对于方程组Ax=b,linalg.solve()可以直接求解。奇异值分解(SVD)是最通用的矩阵分解方法,可将任意矩阵分解为U、Σ、Vt三个矩阵的乘积。
代码示例
import numpy as np
from numpy import linalg
# 解线性方程组: 2x + y = 5, x + 3y = 10
A = np.array([[2, 1], [1, 3]])
b = np.array([5, 10])
x = linalg.solve(A, b)
print(f"方程组解: x={x[0]:.2f}, y={x[1]:.2f}")
print(f"验证: A@x = {A @ x}")
# SVD分解
M = np.array([[1, 2], [3, 4], [5, 6]])
U, S, Vt = linalg.svd(M)
print(f"\nSVD分解:")
print(f"U shape: {U.shape}, S: {S}, Vt shape: {Vt.shape}")
# 重构矩阵
S_matrix = np.zeros((3, 2))
S_matrix[:2, :2] = np.diag(S)
reconstructed = U @ S_matrix @ Vt
print(f"重构矩阵:\n{np.round(reconstructed)}")
# 范数计算
v = np.array([3, 4])
print(f"\nL2范数: {linalg.norm(v)}")
print(f"L1范数: {linalg.norm(v, ord=1)}")
print(f"无穷范数: {linalg.norm(v, ord=np.inf)}")输出结果:
代码示例
方程组解: x=1.00, y=3.00
验证: A@x = [ 5. 10.]
SVD分解:
U shape: (3, 3), S: [9.52551809 0.51430058], Vt shape: (2, 2)
重构矩阵:
[[1. 2.]
[3. 4.]
[5. 6.]]
L2范数: 5.0
L1范数: 7.0
无穷范数: 4.0提示:向量v=[3,4]的L2范数为√(3²+4²)=5,L1范数为|3|+|4|=7,无穷范数为max(|3|,|4|)=4。
七、实际应用场景
-
场景1:机器学习中,使用SVD进行主成分分析(PCA)降维,减少特征维度的同时保留主要信息
-
场景2:工程计算中,使用solve求解电路方程、结构力学方程等线性方程组
-
场景3:推荐系统中,使用矩阵分解进行协同过滤,预测用户对物品的评分
八、注意事项
注意:linalg.inv()要求矩阵必须可逆(行列式不为0),否则抛出LinAlgError。不可逆矩阵也称为奇异矩阵。
注意:数值计算中逆矩阵可能不稳定,推荐优先使用solve()而非inv()求解方程组。solve内部使用LU分解,数值稳定性更好。
注意:对称矩阵使用eigh()比eig()更高效且数值更稳定,因为eigh利用了对称性进行优化。
九、线性代数函数对比
十、练习题
练习1
创建一个3x3的可逆矩阵,计算其逆矩阵,并验证A @ A_inv = I
练习2
使用linalg.solve()解三元一次方程组:x+y+z=6, 2x-y+z=3, x+y-2z=-2
练习3
对一个4x3的随机矩阵进行SVD分解,用前2个奇异值重构矩阵,计算重构误差
常见问题
为什么推荐使用solve()而不是inv()求解方程组?
solve()内部使用LU分解,数值稳定性更好,计算速度也更快。inv()需要先计算完整的逆矩阵,再与b相乘,增加了数值误差的累积。
SVD分解在数据压缩中如何应用?
SVD可以将矩阵分解为U、Σ、Vt,通过保留前k个最大奇异值(截断SVD),可以用更少的存储空间近似原矩阵。奇异值越大,包含的信息量越多。
矩阵的行列式代表什么几何意义?
行列式的绝对值表示矩阵所代表的线性变换对空间体积的缩放比例。行列式为0表示变换将空间压缩到了低维(不可逆),行列式为1表示保持体积不变。
eigh和eig有什么区别?
eigh专门用于对称/厄米特矩阵,利用对称性进行优化,计算速度更快、数值稳定性更好。当确定矩阵是对称矩阵时,应优先使用eigh。
本文涉及AI创作
内容由AI创作,请仔细甄别