Eigen::MatrixXd UKF::pdefinite_svd(const Eigen::MatrixXd& m) {
Eigen::JacobiSVD<Eigen::MatrixXd> USV(m, Eigen::ComputeFullU | Eigen::ComputeFullV);
Eigen::VectorXd s = USV.singularValues();
int n = USV.matrixU().rows(), p = USV.matrixV().rows();
Eigen::MatrixXd S = Eigen::MatrixXd::Zero(n, p);
for (int i = 0; i < s.size(); ++i) {
if (s(i) < 0)
S(i, i) = 1e-10;
else
S(i, i) = s(i);
}
return USV.matrixU() * S * USV.matrixV().transpose();
}
以上代码的解释如下:
奇异值分解(Singular Value Decomposition, SVD)是线性代数中一种重要的矩阵分解方法,它将一个矩阵分解为三个特定矩阵的乘积。以下是奇异值分解的详细步骤:
奇异值分解步骤
计算矩阵乘积
计算给定矩阵A的转置AT与A的乘积,即ATA,以及A与AT的乘积,即AAT。这两个乘积都是对称矩阵。
求解特征值和特征向量
对ATA求解特征值和特征向量。特征值按降序排列,这些特征值的平方根即为矩阵A的奇异值。特征向量则用于构造矩阵V(或VT,取决于定义)。
同样地,对AAT求解特征值和特征向量。这些特征向量用于构造矩阵U。
构造奇异值矩阵Σ
奇异值矩阵Σ是一个对角矩阵,其对角线上的元素是ATA特征值的平方根(即奇异值),且按降序排列。
构造正交矩阵U和V(或V^T)
使用AAT的特征向量构造矩阵U。这些特征向量是U的列向量,并且需要单位化(即每个向量的模长为1)。
使用ATA的特征向量构造矩阵V(或VT,取决于SVD的具体定义)。这些特征向量是V(或VT)的列向量,并且也需要单位化。
完成SVD分解
最终,矩阵A被分解为A=UΣVT(或A=UΣV,取决于V的转置)。这个分解揭示了矩阵A在不同维度上的“能量”或“强度”,并且可以用于多种应用,如数据压缩、噪声过滤、降维等。