• Eigen::svd和 np.linalg.svd的不同之处


    SVD奇异值分解与PCA主成分分析

    SVD动画图解–Wiki
    请添加图片描述
    Eigen Svd 和 np.linalg.svd都可以用于SVD计算,但两者却存在细微的差别。

    python

    import numpy as np
    data=np.array([
                         [0.99337785, 0.08483806, 0.07747866, -92.91055059],
                         [-0.07889607, 0.99392169, -0.07677948, -42.2437898],
                         [-0.08352154, 0.07015827, 0.99403318, 396.22910711],
                         [0, 0, 0, 1]])
    U, S, Vt = np.linalg.svd(data)
    k = 4
    U_reduced = U[:, :k]
    S_reduced = np.diag(S[:k])
    Vt_reduced = Vt[:k, :]
    
    # 重构原始数据
    # reconstructed_data = np.dot(U_reduced, np.dot(S_reduced, Vt_reduced))
    reconstructed_data = np.dot(U*S, Vt)
    print(f"原始数据:\n{data}")
    print(f"重构的数据:\n{reconstructed_data}")
    print(f"U:\n{U_reduced}")
    print(f"S:\n{S}")
    print(f"Vt:\n{Vt_reduced}")
    
    np.allclose(data, reconstructed_data, rtol=1e-05, atol=1e-08) #true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    原始数据:
    [[ 0.99337785 0.08483806 0.07747866 -92.91055059]
    [ -0.07889607 0.99392169 -0.07677948 -42.2437898 ]
    [ -0.08352154 0.07015827 0.99403318 396.22910711]
    [ 0. 0. 0. 1. ]]
    重构的数据:
    [[ 0.99337785 0.08483806 0.07747866 -92.91055059]
    [ -0.07889607 0.99392169 -0.07677948 -42.2437898 ]
    [ -0.08352154 0.07015827 0.99403318 396.22910711]
    [ -0. 0. -0. 1. ]]
    U:
    [[-0.22707395 0.44440135 0.86657057 -0.00055497]
    [-0.10324408 0.87381543 -0.47517069 -0.00025233]
    [ 0.96838634 0.19736775 0.15253937 0.00236674]
    [ 0.00244399 0. -0. -0.99999701]]
    S:
    [409.16550869 1. 0.99999999 0.002444 ]
    Vt:
    [[-0.00072906 -0.00013183 0.00232899 0.99999701]
    [ 0.35603339 0.92005324 0.16353062 0. ]
    [ 0.88558079 -0.38806239 0.25525328 -0. ]
    [-0.2983058 -0.05394073 0.9529418 -0.00244399]]
    True

    c++

    // 定义给定的变换矩阵
    Eigen::Matrix4f transformation_matrix1;
    transformation_matrix1 << 0.99337785, 0.08483806, 0.07747866, -92.91055059,
                            -0.07889607, 0.99392169, -0.07677948, -42.2437898,
                            -0.08352154, 0.07015827, 0.99403318, 396.22910711,
                            0, 0, 0, 1;
                            
    // 从变换矩阵中解析欧拉角
    Eigen::Vector3f euler_angles1 = transformation_matrix1.block<3, 3>(0, 0).eulerAngles(0, 2, 1);
    
    // 输出解析出的欧拉角
    std::cout << "解析出的欧拉角 (ZYX 顺序):"<<euler_angles1 << std::endl;
    
    Eigen::JacobiSVD<Eigen::MatrixXf> svd;
    //svd.setThreshold(1e-10);
    svd.compute(transformation_matrix1, Eigen::ComputeFullU | Eigen::ComputeFullV);
    Eigen::VectorXf singularValues = svd.singularValues();
    Eigen::MatrixXf singularValueMatrix = singularValues.asDiagonal();
    Eigen::MatrixXf U = svd.matrixU();
    Eigen::MatrixXf V = svd.matrixV();
    //Displaying the results
    std::cout << "原始数据:\n" << transformation_matrix1  << std::endl;
    std::cout << "重构数据:\n" << U * singularValueMatrix * V.transpose() << std::endl;
    std::cout << "U:\n" << U << "\n\n";
    std::cout <<  "S:\n" << singularValueMatrix << "\n\n";
    std::cout << "V:\n" << V << "\n\n";
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    原始数据:
    0.993378 0.0848381 0.0774787 -92.9106
    -0.0788961 0.993922 -0.0767795 -42.2438
    -0.0835215 0.0701583 0.994033 396.229
    0 0 0 1
    重构数据:
    0.9934 0.0848412 0.077413 -92.9106
    -0.0788853 0.993924 -0.0768136 -42.2438
    -0.0835193 0.070161 0.994014 396.229
    0 9.21136e-09 2.32831e-10 1
    U:
    -0.227074 0.457935 0.859496 -0.000554795
    -0.103244 -0.888896 0.446323 -0.000252237
    0.968386 0.0126106 0.249125 0.00236679
    0.00244399 8.88704e-10 2.06488e-07 -0.999997
    S:
    409.166 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 0.002444
    V:
    -0.000729068 0.52398 0.797807 -0.298242
    -0.000131827 -0.843758 0.534011 -0.0538979
    0.00232899 0.116264 0.279886 0.952964
    0.999997 3.72529e-09 2.01166e-07 -0.00244399

    结论

    M = U Σ V T M = U \Sigma V^{T} M=UΣVT

    当分解的矩阵M相同时,不同库得出的U, Σ \Sigma Σ是相同的,V却不相同。numpy给出的直接就是VT,而EIGEN得出的为V.

    参考

    1. https://eigen.tuxfamily.org/dox/group__SVD__Module.html
    2. https://numpy.org/doc/stable/reference/generated/numpy.linalg.svd.html
    3. https://stackoverflow.com/questions/75500005/linalg-svd-and-jacobisvdmatrixxf-svd-the-results-are-different
    4. https://stackoverflow.com/questions/74322089/difference-between-eigen-svd-and-np-linag-svd
    5. https://en.wikipedia.org/wiki/Singular_value_decomposition
  • 相关阅读:
    Springboot 实践(21)服务熔断机制
    【Redis学习笔记二】三种特殊数据类型、事务的基本操作、锁、持久化、发布订阅、主从复制、哨兵模式
    Hadoop 安装教程 (Mac m1/m2版)
    『Echarts』基本使用
    MyBatis主要的类层次结构(Mybatis工具类)
    机器学习里的信息论
    图论-SPFA算法
    Java二叉树(1)
    Vue - 图片浏览组件v-viewer
    洛谷刷题C语言:Physics Problem、PARKING、Trol、信息学竞赛、POT
  • 原文地址:https://blog.csdn.net/qq_35215756/article/details/138214635