跳转至

特征值与特征向量

结果范围

eigendecompose_qr() 的头文件注明只返回复特征值的实部。不要把该接口当作完整复数特征值求解器;检查 status 和迭代收敛条件。

接口以 MATH 工程的 middleware/tiny_math/mat/tiny_matrix.hpp 为依据。矩阵元素为 float;先检查尺寸、布局和返回状态,再使用结果。

返回概览 · 历史测试

线性代数 - 特征值与特征向量

结构体:Mat::EigenPair

Mat::EigenPair::EigenPair();
// fields:
// float eigenvalue;      // 特征值(power_iteration 为最大模,inverse_power_iteration 为最小模)
// Mat eigenvector;       // 对应的特征向量(n x 1)
// int iterations;        // 迭代次数(若为迭代法返回)
// tiny_error_t status;   // 计算状态(TINY_OK / 错误码)

描述:

用于保存单一特征值/特征向量对及其计算信息。常由 power_iteration 或 inverse_power_iteration 返回。

说明:

这个结构刻意保持很小:一个特征值、一个特征向量、再加收敛信息。它适合迭代法只关心一个模态的场景。

结构体:Mat::EigenDecomposition

Mat::EigenDecomposition::EigenDecomposition();
// fields:
// Mat eigenvalues;    // n x 1 矩阵,存放特征值
// Mat eigenvectors;   // n x n 矩阵,通常每一列为对应的特征向量
// int iterations;     // 迭代次数(若为迭代法返回)
// tiny_error_t status; // 计算状态(TINY_OK / 错误码)

描述:

用于保存完整的特征值分解结果,包括全部特征值和对应的特征向量矩阵。

说明:

这是完整的谱信息快照。只有在矩阵规模可控、且你确实需要多个模态或基变换时,它才划算。

幂迭代(求主特征值/向量)

Mat::EigenPair Mat::power_iteration(int max_iter, float tolerance) const;

描述:

使用幂迭代法计算矩阵的主特征值(绝对值最大)及对应特征向量。快速方法,适用于实时SHM应用,可快速识别主频率。

数学原理:

幂迭代通过迭代地将矩阵应用于向量来找到绝对值最大的特征值:

  1. 从随机向量v₀开始

  2. 迭代:vₖ₊₁ = A * vₖ / ||A * vₖ||

  3. 特征值估计:λₖ = (vₖ^T * A * vₖ) / (vₖ^T * vₖ) (Rayleigh商)

收敛性:

方法收敛到主特征值,如果:

  • 主特征值是唯一的 (|λ₁| > |λ₂| ≥ ... ≥ |λₙ|)

  • 初始向量在主特征向量方向上有非零分量

参数:

  • int max_iter : 最大迭代次数(典型默认值:1000)。

  • float tolerance : 收敛容差(例如 1e-6)。收敛性通过 |λₖ - λₖ₋₁| < tolerance * |λₖ| 检查。

返回值:

EigenPair,包含 eigenvalue、eigenvector、iterations 和 status。

使用建议:

  • 实时应用: 对于分离良好的特征值快速收敛,适用于实时结构健康监测。

  • 初始化: 实现使用智能初始化策略(列绝对值之和)以避免收敛到较小的特征值。

  • 收敛速度: 收敛是线性的,速度为 |λ₂|/|λ₁|。当特征值接近时较慢。

  • 局限性:

  • 只找到一个特征值-特征向量对

  • 需要 |λ₁| > |λ₂|(主特征值必须唯一)

  • 如果特征值接近,可能收敛缓慢

  • 应用:

  • 主成分分析(第一主成分)

  • PageRank算法

  • 结构动力学(基频)

坑点:

  • 只能得到一个模态: 它不会告诉你其他特征值。

  • 需要明显主导特征值: 如果最大模特征值不够“突出”,收敛会慢,甚至含糊。

  • 缩放会影响收敛: 缩放很差的矩阵会让收敛速度和向量质量变差。

反幂迭代(求最小特征值/向量)

Mat::EigenPair Mat::inverse_power_iteration(int max_iter, float tolerance) const;

描述:

使用反幂迭代法计算矩阵的最小(最小模)特征值及其对应特征向量。对于系统识别至关重要——在结构动力学中找到基频/最低模态。该方法对于SHM应用至关重要,其中最小特征值对应于系统的基本频率。

数学原理:

反幂迭代将幂迭代应用于A^(-1), 其特征值为1/λᵢ。由于1/λₙ是A^(-1) 的最大特征值,该方法收敛到A的最小特征值:

  1. 从向量v₀开始

  2. 迭代:求解A * yₖ = vₖ,然后vₖ₊₁ = yₖ / ||yₖ||

  3. 特征值估计:λₖ = (vₖ^T * A * vₖ) / (vₖ^T * vₖ) (Rayleigh商)

收敛性:

收敛到最小特征值,如果:

  • 最小特征值是唯一的 (|λₙ| < |λₙ₋₁| ≤ ... ≤ |λ₁|)

  • 矩阵A是可逆的(非奇异)

  • 初始向量在最小特征向量方向上有分量

参数:

  • int max_iter : 最大迭代次数(默认:1000)。

  • float tolerance : 收敛容差(默认:1e-6)。使用相对容差:|λₖ - λₖ₋₁| < tolerance * max(|λₖ|, 1.0)。

返回值:

EigenPair,包含最小特征值、特征向量、迭代次数和状态。

算法步骤:

  1. 初始化归一化特征向量v(使用交替符号以避免与主特征向量对齐)

  2. 迭代:使用solve()求解A * y = v(等价于y = A^(-1) * v)

  3. 归一化y得到新的v

  4. 使用Rayleigh商计算特征值估计:λ = (v^T * A * v) / (v^T * v)

  5. 使用相对容差检查收敛性

使用建议:

  • 系统识别: 对于在结构动力学中查找基频至关重要,其中最小特征值对应于最低固有频率。

  • 数值稳定性: 实现包括对奇异矩阵的检查,并优雅地处理近奇异情况。

  • 初始化策略: 使用交替符号模式以避免收敛到较大的特征值,确保收敛到最小特征值。

  • 性能: 每次迭代需要求解线性系统(对于稠密矩阵为O(n³)),但通常比幂迭代收敛更快。

  • 与幂迭代互补:

  • 幂迭代:找到λ_max(最高频率)

  • 反幂迭代:找到λ_min(基频)

  • 两者一起提供系统的频率范围

  • 应用:

  • 结构健康监测(基频检测)

  • 模态分析(最低模态形状)

  • 系统识别

  • 稳定性分析(最小特征值表示稳定性裕度)

注意:

  • 要求矩阵为方阵且数据指针非空;否则返回错误状态。

  • 矩阵必须是可逆的(非奇异)才能使此方法工作。如果矩阵是奇异的或接近奇异的,该方法将优雅地失败。

  • 反幂迭代只返回最小特征值/向量对。若需全部特征值/向量请使用下面的分解函数。

坑点:

  • 要求可逆: 奇异或近奇异矩阵会让每一步求解变得不稳定甚至不可行。

  • 每次迭代都要解线性方程: 所以它只适合你只想要一个极值特征对的场景。

  • 最小模不等于最小数值: 对有正有负的谱来说,“绝对值最小”和“最负”不是一回事。

Jacobi 特征分解(对称矩阵)

Mat::EigenDecomposition Mat::eigendecompose_jacobi(float tolerance, int max_iter) const;

描述:

使用Jacobi方法计算完整的特征值分解。推荐用于对称矩阵(良好的精度和稳定性,适用于结构动力学应用)。稳健且准确,是结构动力学矩阵的理想选择。

数学原理:

Jacobi方法通过一系列正交相似变换(Givens旋转)对角化对称矩阵: 1. 找到最大的非对角元素aₚq 2. 计算旋转角θ以将该元素置零 3. 应用旋转:A' = J^T * A * J,其中J是旋转矩阵 4. 重复直到所有非对角元素低于容差

收敛性:

当最大非对角元素低于容差时方法收敛。每次旋转将一个非对角元素置零,过程持续直到矩阵对角化。

参数:

  • float tolerance : 收敛阈值(例如 1e-6)。允许的非对角元素最大幅度。

  • int max_iter : 最大迭代次数(例如 100)。对于n×n矩阵,通常需要O(n²)次迭代收敛。

返回值:

EigenDecomposition,包含 eigenvalues、eigenvectors、iterations 和 status。

使用建议:

  • 对称矩阵: 专为对称矩阵设计。对于非对称矩阵,使用QR方法。

  • 数值稳定性: 对于对称矩阵非常稳定,具有良好的正交性保持。

  • 精度: 高精度,适用于需要精确特征值/特征向量对的应用。

  • 性能: 每次迭代O(n³),但对于对称矩阵通常比QR需要更少的迭代。

  • 应用:

  • 结构动力学:刚度和质量矩阵是对称的

  • 主成分分析(PCA)

  • 谱聚类

  • 二次型优化

注意:

如果矩阵不是近似对称,函数会发出警告,但仍可能运行。对于非对称矩阵,推荐使用QR方法。

坑点:

  • 对称性是前提: 该方法依赖正交相似变换。非对称输入会破坏算法假设。

  • 迭代次数有限: 很小的容差可能需要很多轮旋转,注意 max_iter 是否足够。

  • 对角化后仍是近似值: 浮点误差会留下极小的非对角项,要把结果当作近似对角化。

QR 特征分解(一般矩阵)

Mat::EigenDecomposition Mat::eigendecompose_qr(int max_iter, float tolerance) const;

描述:

使用QR算法计算特征值分解。适用于一般(可能非对称)矩阵。支持非对称矩阵,但可能产生复数特征值(仅返回实部)。

数学原理:

QR算法迭代应用QR分解:

  1. 从A₀ = A开始

  2. 对于k = 0, 1, 2, ...: 计算QR分解:Aₖ = Qₖ * Rₖ,然后更新:Aₖ₊₁ = Rₖ * Qₖ

  3. Aₖ收敛到上三角形式(Schur形式),特征值在对角线上

收敛性:

当Aₖ近似上三角(次对角元素 < 容差)时算法收敛。特征值出现在对角线上,特征向量从Q矩阵累积。

参数:

  • int max_iter : 最大QR迭代次数(默认:100)。

  • float tolerance : 收敛容差(例如 1e-6)。使用相对容差,比较次对角元素与对角元素。

返回值:

EigenDecomposition,包含特征值、特征向量、迭代次数和状态。

使用建议:

  • 一般矩阵: 可以处理非对称矩阵,与Jacobi方法不同。

  • 复数特征值: 非对称矩阵可能具有复数特征值;当前实现仅返回实部。

  • 数值稳定性: 使用改进的Gram-Schmidt和重新正交化以提高稳定性。

  • 性能: 每次迭代O(n³)。可能需要多次迭代才能收敛,特别是对于病态矩阵。

  • 收敛加速: 实现可以从移位(Wilkinson移位)中受益以加快收敛,但当前版本使用基本QR迭代。

  • 应用:

  • 一般矩阵特征值问题

  • 动力系统分析

  • 控制理论(系统极点)

注意:

QR在此实现中使用Gram–Schmidt构造Q/R;对于病态矩阵可能不太稳定。对于对称矩阵,由于更好的稳定性和精度,推荐使用Jacobi。

坑点:

  • 复谱限制: 当前接口只保留特征值实部,不是完整的复数特征值求解器。

  • 收敛可能较慢: 如果没有位移策略,困难矩阵上 QR 可能需要很多轮迭代。

  • 正交化质量很重要: Q 用 Gram-Schmidt 构造,病态输入会影响迭代质量。

自动特征分解(根据矩阵特性选择方法)

Mat::EigenDecomposition Mat::eigendecompose(float tolerance = 1e-6f, int max_iter = 100) const;

描述:

简便接口,会自动根据矩阵特性选择最优算法。先调用 is_symmetric(tolerance * 10.0f) 判断矩阵是否近似对称:

  • 若为对称,使用 eigendecompose_jacobi(tolerance, max_iter)(更稳定和精确);
  • 否则使用 eigendecompose_qr(max_iter, tolerance)(处理一般矩阵)。

算法选择流程:

  1. 测试矩阵是否对称:is_symmetric(tolerance * 10.0f)
  2. 若对称 → 使用 eigendecompose_jacobi(tolerance, max_iter)
  3. 若非对称 → 使用 eigendecompose_qr(max_iter, tolerance)

参数:

  • float tolerance:用于对称性检测与分解收敛判断(默认 1e-6f)。
  • int max_iter:最大迭代次数(必须 > 0,默认值 = 100)。

返回值:

EigenDecomposition 结构,包含所有特征值和特征向量。

使用建议:

  • 自动优化:无需手动选择算法,同时仍能获得最佳性能。

  • 边缘计算:非常适合嵌入式系统,无需手动调优即可获得良好性能。

  • 鲁棒性:对称性测试使用放宽的容差(10×),以处理数值误差,确保正确识别对称矩阵。

实用技巧:

  • 已知对称性:若明确知道矩阵为对称矩阵(如刚度矩阵、质量矩阵),直接使用 eigendecompose_jacobi 可获得最佳稳定性和略好的性能。

  • 未知特性:对于一般矩阵或对称性未知的情况,使用 eigendecompose 进行自动选择。

  • 性能考虑:

  • 在嵌入式平台上,对大型矩阵进行特征分解的计算成本很高
  • 对于 n > 20,当只需要少数特征值时,考虑使用降阶方法或迭代方法(幂迭代)
  • 对于实时应用,使用 power_iteration() 或 inverse_power_iteration() 计算单个特征值

  • 内存使用:完全特征分解需要存储所有特征向量(n×n 矩阵),对于大型矩阵可能占用大量内存。

坑点:

  • 自动不等于免费: 对称性测试和分解本身都要耗时。若你已经知道矩阵类别,直接调用专用方法更好。

  • 容差有双重作用: 它同时影响对称性判定和收敛条件,所以调它会影响算法选择和数值停止条件。

  • 大矩阵不友好: 在嵌入式平台上,完整特征分解很容易成为时间和内存瓶颈。