NumPy计算矩阵特征值与特征向量
一、引言
1.核心价值
从本质上看,矩阵可被理解为一种线性变换的 “算子”,当它作用于一个向量时,会对向量进行拉伸、旋转等操作。而特征值与特征向量,正是捕捉这种变换 “本质特征” 的工具:特征向量是经过矩阵变换后,仅发生缩放、不改变方向的特殊向量;特征值则是这种缩放的 “比例系数”。它们共同描绘出矩阵在变换过程中 “最具代表性” 的行为模式,是理解矩阵内在结构与作用规律的关键。

2.应用场景
-
机器学习(PCA 降维中通过特征值筛选主成分)
在主成分分析(PCA)中,我们需要从高维数据里提取最具代表性的低维特征。此时,数据协方差矩阵的特征值就像 “权重”,特征值越大,对应特征向量所代表的维度对数据的 “解释力” 越强。通过筛选最大的几个特征值及其特征向量,就能实现数据的降维,既保留核心信息,又简化计算。
- 物理领域(振动系统的固有频率与振型)
对于振动系统(如桥梁、机械结构的振动),系统的质量矩阵和刚度矩阵的特征值,对应着系统的固有频率 —— 这是系统自身的 “振动密码”,决定了系统在何种频率下最易发生共振;而特征向量则对应振型,描绘了系统在固有频率下各部分的振动形态,是工程设计中规避共振风险、优化结构稳定性的核心依据。
- 图像处理(特征脸提取)等
在 “特征脸”(Eigenface)技术中,人脸图像的协方差矩阵的特征向量被称为 “特征脸”。每一个特征脸都代表了人脸的一种 “典型特征模式”,特征值的大小反映了该模式在所有人脸中的普遍程度。通过这些特征脸的组合,能够高效地对人脸进行识别、压缩与重建。
3.本文目标
鉴于特征值与特征向量的重要性,掌握其计算方法至关重要。Python 的扩展库 NumPy,凭借其强大的线性代数子模块linalg,为我们提供了便捷高效的工具来计算特征值与特征向量。本文将围绕 NumPy 中的相关函数,详细介绍特征值与特征向量的计算过程,帮助读者不仅能快速上手实操,更能深入理解其背后的线性代数原理。
二、理论基础:特征值与特征向量的核心概念
1.数学定义
对于 n×n 方阵 A,如果存在标量 λ 和 n 维非零向量 x,使得 A⋅x=λ⋅x 成立,那么称 λ 是方阵 A 的一个特征值,x 为对应于 λ 的特征向量。这里强调 “非零向量”,是因为若 x 为零向量,无论 λ 取何值,A⋅x=λ⋅x 都恒成立,这样的 “特征值” 和 “特征向量” 是没有实际意义的。
2.关键性质
特征向量的非零性:如数学定义所述,特征向量必须是非零向量,这是由特征值与特征向量的定义所严格限定的,用于排除无意义的零向量情况。
特征向量的多解性(成比例):对于一个确定的特征值 λ ,可以有多个特征向量与之对应,但这些特征向量之间是成比例的关系。也就是说,如果 x 是对应于 λ 的特征向量,那么对于任意非零标量 k,kx 也一定是对应于 λ 的特征向量,因为
特殊矩阵的特性:
-
若 A 是实对称矩阵,则它的所有特征值都是实数,并且不同特征值对应的特征向量是相互正交的。这一性质在很多领域(如主成分分析(PCA))中有着重要应用,因为正交的特征向量可以构建出相互独立的新坐标系。
-
若 A 是复埃尔米特矩阵(实对称矩阵在复数域的推广,满足 A = A^H),其中 A^H 是 A 的共轭转置),其特征值也为实数,特征向量具有正交性等良好性质。
3.几何意义
从几何角度来看,矩阵乘以一个向量,本质上是对这个向量进行了一次线性变换,实现了从一个坐标系到另一个坐标系的转换。在这个变换过程中,向量主要会发生旋转和缩放这两种变化。而特征向量的特殊之处就在于,当矩阵作用于它时,向量只发生了缩放变化,没有进行旋转。此时,缩放的比例就是对应的特征值。
换一种更形象的说法,特征向量可以看作是对数据进行旋转操作之后,所得到的 “理想坐标轴” 之一;而特征值则代表了原向量在该坐标轴上的 “投影大小” 或者 “贡献程度”。特征值越大,意味着这个坐标轴对原向量的表达越重要,原向量在这个坐标轴上的投影也就越大。
进一步地,一个矩阵的所有特征向量共同组成了该矩阵的一组基,这组基就相当于新坐标系中的坐标轴。当我们得到了矩阵的特征值和特征向量后,原向量就能够在由这些特征向量构成的新坐标系中进行表示,从而为我们分析和处理向量与矩阵的关系提供了新的视角与便利。
三、NumPy 工具:计算函数与参数解析
在 Python 中,NumPy 库的线性代数子模块 numpy.linalg 封装了高效的特征值与特征向量计算工具,无需手动实现复杂的线性代数算法,即可快速求解各类矩阵的特征值与特征向量。其中,eig 和 eigh 是最核心的两个函数,分别针对不同类型的矩阵设计,需根据矩阵特性选择使用。
1.核心函数详解
np.linalg.eig(A):通用方阵的特征值与特征向量计算
这是最基础的特征值计算函数,适用于任意 n 阶方阵(包括实矩阵、复矩阵、非对称矩阵等)。其核心功能是求解满足 A⋅x=λ⋅x 的特征值 λ 和右特征向量 x。
-
返回值:函数返回一个元组
(eigenvalues, eigenvectors),其中:-
eigenvalues是一个 1 维数组,存储矩阵的所有特征值(可能包含复数); -
eigenvectors是一个 n×n 矩阵,每一列对应一个特征值的右特征向量。
-
-
适用场景:当矩阵为非对称、非埃尔米特矩阵(如实数非对称矩阵、一般复矩阵)时,必须使用
eig函数。例如,旋转矩阵、随机生成的非对称矩阵等。
np.linalg.eigh(A):对称 / 埃尔米特矩阵的高效计算
该函数是专为实对称矩阵(满足 A = A^T,即矩阵等于其转置)和复埃尔米特矩阵(满足 A = A^H,即矩阵等于其共轭转置)设计的优化函数。由于这类矩阵具有 “特征值为实数、特征向量正交” 的良好性质,eigh 利用这些特性实现了更高效、数值更稳定的计算。
- 返回值:同样返回元组
(eigenvalues, eigenvectors),但具有特殊性质:eigenvalues是 1 维实数组(无复数),且默认按升序排列(这与eig不同,eig的特征值顺序无严格规则);eigenvectors是 n×n 矩阵,每一列是对应特征值的特征向量,且不同特征值的特征向量相互正交,适合直接用于正交变换(如 PCA 中的投影)。
- 适用场景:处理协方差矩阵(实对称)、自伴算子矩阵(复埃尔米特)等,例如机器学习中的数据降维、信号处理中的特征提取等。
2.参数说明与输入要求
输入类型:
两个函数均支持多种输入格式,但需确保输入为方阵(行数 = 列数),否则会抛出 LinAlgError 异常。具体支持的输入包括:
- Python 列表(如
[[1, 2], [3, 4]]),但需注意列表需为二维且行列数相等; - NumPy 数组(推荐,如
np.array([[1, 2], [3, 4]])),需通过ndim == 2且shape[0] == shape[1]验证为方阵; - NumPy 矩阵对象(如
np.matrix([[1, 2], [3, 4]])),但矩阵对象在现代 NumPy 中已逐渐被数组替代,建议优先使用数组。
特殊参数(以 eigh 为例):
UPLO:指定计算时使用矩阵的上三角部分('U')还是下三角部分('L'),默认值为 'L'。由于对称 / 埃尔米特矩阵的上三角与下三角是对称的,仅需使用其中一部分即可完成计算,该参数可减少冗余运算,提升效率。
3.返回值的注意事项
eig 的返回值特性:
- 特征值可能为复数:即使输入是实矩阵,若矩阵非对称,特征值可能出现共轭复数对(如旋转矩阵的特征值为
cosθ ± i sinθ); - 特征向量的规范性:返回的特征向量通常已归一化(即向量的 L2 范数为 1),但不同特征值的特征向量不一定正交(非对称矩阵无正交性保证);
- 顺序无严格规则:特征值的排列顺序不固定,需根据实际需求手动排序(如按绝对值大小)。
eigh 的返回值特性:
- 特征值必为实数:由于对称 / 埃尔米特矩阵的数学性质,特征值无虚部,返回值为实数组;
- 特征向量正交性:不同特征值对应的特征向量严格正交,相同特征值(重根)对应的特征向量可通过正交化处理(函数内部已处理),因此可直接用于构建正交基;
- 升序排列:特征值默认按从小到大排序,便于快速筛选最大 / 最小特征值(如 PCA 中取前 k 个最大特征值)。
四、实践演示:分场景案例教学
通过具体代码案例,展示不同类型矩阵的特征值 / 特征向量计算,并验证结果正确性。
案例1:一般实方阵的计算
定义一个 3 阶实方阵。
用np.linalg.eig(x)计算特征值和特征向量。
- 结果验证:
- 验证 A⋅x=λ⋅x:通过
np.allclose(np.dot(A, eigenvectors), eigenvalues * eigenvectors)判断是否近似成立。 - 验证特征方程
:计算行列式
np.linalg.det(A - np.diag(eigenvalues)),确认结果接近 0。
- 验证 A⋅x=λ⋅x:通过
import numpy as np
# 定义一个3阶实方阵
x = np.array([[1, -3, 3], [3, -5, 3], [6, -6, 4]])
# 计算特征值(e)和特征向量(v,每列是一个特征向量)
e, v = np.linalg.eig(x)
print("特征值:")
print(e) # 输出特征值
print("特征向量矩阵:")
print(v) # 输出特征向量矩阵
# 仅计算特征值(验证与eig结果一致)
eigvals_result = np.linalg.eigvals(x)
print("仅计算特征值的结果:")
print(eigvals_result) # 结果与e相同
# 验证特征值与特征向量的定义:A·x = λ·x
dot_result = np.dot(x, v)
mul_result = e * v
allclose_result = np.allclose(dot_result, mul_result)
print("验证 A·x = λ·x 是否成功:", allclose_result) # 验证两者是否近似相等(因浮点误差),返回True
# 验证特征方程:|A - λI| = 0(特征值对应的行列式为0)
det_matrix = x - np.eye(3, 3) * e
det_result = np.linalg.det(det_matrix)
isclose_result = np.isclose(det_result, 0)
print("验证 |A - λI| = 0 是否成功:", isclose_result) # 验证行列式是否接近0,返回True
特征值:
[ 4. -2. -2.]
特征向量矩阵:
[[-0.40824829 -0.81034214 0.1932607 ]
[-0.40824829 -0.31851537 -0.59038328]
[-0.81649658 0.49182677 -0.78364398]]
仅计算特征值的结果:
[ 4. -2. -2.]
验证 A·x = λ·x 是否成功: True
验证 |A - λI| = 0 是否成功: True
案例 2:实对称矩阵的计算
定义一个实对称矩阵(B = np.array([[1, 2], [2, 5]]),满足B = B^T)。
分别用eig和eigh计算,对比结果:
特征值是否均为实数;
特征向量是否正交(用np.dot(eigenvectors.T, eigenvectors)验证是否为对角矩阵)。
说明eigh的优势:针对对称矩阵优化,计算更快,数值更稳定。
import numpy as np
# 1. 定义一个2阶实对称矩阵(满足 B = B^T)
B = np.array([[1, 2],
[2, 5]])
print("===== 实对称矩阵的特征值与特征向量 =====")
print("原矩阵 B:\n", B)
print("验证 B 是否对称(B == B^T):", np.allclose(B, B.T)) # 应返回True
# 2. 分别用eig和eigh计算
eig_vals, eig_vecs = np.linalg.eig(B) # 通用函数
eigh_vals, eigh_vecs = np.linalg.eigh(B) # 对称矩阵专用函数
# 3. 对比特征值(是否均为实数)
print("\neig计算的特征值:\n", eig_vals) # 理论上应为实数(但可能带极小虚部)
print("eigh计算的特征值(实对称矩阵必为实数):\n", eigh_vals) # 无虚部
# 4. 对比特征向量(是否正交)
# 正交性验证:特征向量矩阵的转置 × 自身 应接近对角矩阵(单位矩阵,因已归一化)
print("\neig特征向量的正交性(转置×自身):\n", np.dot(eig_vecs.T, eig_vecs))
print("eigh特征向量的正交性(转置×自身):\n", np.dot(eigh_vecs.T, eigh_vecs)) # 更接近单位矩阵
# 5. 验证特征值定义(A·x = λ·x)
print("\neig验证 A·x = λ·x:", np.allclose(np.dot(B, eig_vecs), eig_vals * eig_vecs)) # True
print("eigh验证 A·x = λ·x:", np.allclose(np.dot(B, eigh_vecs), eigh_vals * eigh_vecs)) # True
===== 实对称矩阵的特征值与特征向量 =====
原矩阵 B:
[[1 2]
[2 5]]
验证 B 是否对称(B == B^T): True
eig计算的特征值:
[0.17157288 5.82842712]
eigh计算的特征值(实对称矩阵必为实数):
[0.17157288 5.82842712]
eig特征向量的正交性(转置×自身):
[[1.00000000e+00 2.58605321e-17]
[2.58605321e-17 1.00000000e+00]]
eigh特征向量的正交性(转置×自身):
[[ 1.00000000e+00 -2.16349973e-17]
[-2.16349973e-17 1.00000000e+00]]
eig验证 A·x = λ·x: True
eigh验证 A·x = λ·x: True
案例 3:复矩阵的计算
定义一个复埃尔米特矩阵(如a = np.array([[1, -2j], [2j, 5]]),满足C = C^H,即共轭转置等于自身)。
用eigh计算,验证特征值为实数,特征向量正交。
import numpy as np
# 定义一个复埃尔米特矩阵(实对称矩阵的复数推广)
a = np.array([[1, -2j], [2j, 5]]) # 元素(0,1)与(1,0)共轭,满足a = a^H(共轭转置)
print("复埃尔米特矩阵 a:\n", a)
# 验证矩阵是否满足 a = a^H(共轭转置)
is_hermitian = np.allclose(a, a.conj().T)
print("验证 a 是否为复埃尔米特矩阵(a == a^H):", is_hermitian)
# 用eigh计算特征值(w)和特征向量(v)(专为埃尔米特矩阵设计)
w, v = np.linalg.eigh(a)
print("\neigh计算的特征值(应为实数):\n", w)
print("eigh计算的特征向量矩阵:\n", v)
# 验证定义:A·x = λ·x
verify_eigh_def = np.allclose(np.dot(a, v), w * v)
print("验证 eigh 结果满足 A·x = λ·x:", verify_eigh_def)
# 用普通eigvals验证特征值(结果应与eigh一致,且为实数)
eigvals_result = np.linalg.eigvals(a)
print("\neigvals计算的特征值:\n", eigvals_result)
verify_eigvals = np.allclose(eigvals_result, w) # 对比eigvals与eigh的特征值
print("验证 eigvals 与 eigh 的特征值是否一致:", verify_eigvals)
# 验证eigh的UPLO参数(指定用矩阵的上三角部分计算,结果不变)
w_u, v_u = np.linalg.eigh(a, UPLO='U') # 用矩阵上三角部分计算
print("\nUPLO='U'时eigh计算的特征值:\n", w_u)
verify_uplo = np.allclose(np.dot(a, v_u), w_u * v_u) # 验证特征值定义
print("验证 UPLO='U'时结果满足 A·x = λ·x:", verify_uplo)
print("验证 UPLO='U'与默认参数的特征值是否一致:", np.allclose(w, w_u))
复埃尔米特矩阵 a:
[[ 1.+0.j -0.-2.j]
[ 0.+2.j 5.+0.j]]
验证 a 是否为复埃尔米特矩阵(a == a^H): True
eigh计算的特征值(应为实数):
[0.17157288 5.82842712]
eigh计算的特征向量矩阵:
[[-0.92387953+0.j -0.38268343+0.j ]
[ 0. +0.38268343j 0. -0.92387953j]]
验证 eigh 结果满足 A·x = λ·x: True
eigvals计算的特征值:
[0.17157288+0.j 5.82842712+0.j]
验证 eigvals 与 eigh 的特征值是否一致: True
UPLO='U'时eigh计算的特征值:
[0.17157288 5.82842712]
验证 UPLO='U'时结果满足 A·x = λ·x: True
验证 UPLO='U'与默认参数的特征值是否一致: True
五、常见问题与注意事项
-
输入必须是方阵:非方阵调用
eig会报错,需提前检查矩阵维度。 -
浮点精度问题:由于数值计算误差,验证时需用
np.allclose(而非==)判断近似相等。 -
复数特征值的意义:实矩阵可能有复特征值(共轭成对出现),对应 “旋转 + 缩放” 的变换(如旋转矩阵的特征值为复数)。
-
特征向量的非唯一性:特征向量是 “方向唯一”,其长度可任意缩放(NumPy 返回的特征向量通常已归一化)。
六、应用拓展:从计算到实际场景
-
PCA 降维:对数据协方差矩阵(对称矩阵)用
eigh计算特征值,取前 k 个最大特征值对应的特征向量,将高维数据投影到低维空间。 -
物理系统分析:用特征值表示系统的固有频率,特征向量表示振型,通过 NumPy 快速求解复杂系统的振动特性。
七、总结与展望
-
总结:回顾 NumPy 中
eig和eigh的用法,强调根据矩阵类型(一般方阵 / 对称矩阵)选择合适函数的重要性。 -
拓展:提及更高阶的需求,如稀疏矩阵的特征值计算(可结合
scipy.sparse.linalg),或大规模矩阵的近似求解方法。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)