当前位置: 首页 > news >正文

Eigen中Dense 模块简要介绍和实战应用示例(最小二乘拟合直线、协方差矩阵计算和稀疏求解等)

1、Dense简介

1️.Dense 模块概述

Eigen::Dense 模块是 Eigen 的核心模块之一,主要用于处理 密集矩阵(Dense Matrix)和向量(Dense Vector)。它与 Eigen 的稀疏矩阵模块(Eigen::Sparse)互补。

特点

  1. 支持固定和动态大小

    • 固定大小:如 Matrix3dVector4f
    • 动态大小:如 MatrixXdVectorXd
    • 优势:固定大小矩阵在编译期优化,速度快;动态大小矩阵灵活性高。
  2. 面向表达式模板(Expression Templates)

    • Eigen 的运算不是立即计算,而是构建表达式树
    • 优点:减少临时变量、延迟计算、优化性能
  3. 高性能

    • 内存连续(RowMajor 或 ColumnMajor,可选)
    • 支持 SIMD 向量化(如 SSE、AVX)
    • 适合线性代数、最小二乘、矩阵分解、几何变换等场景
  4. 丰富的线性代数支持

    • 基本运算:加减、乘除、转置
    • 矩阵分解:LU、QR、SVD、Cholesky、EigenSolver
    • 特殊矩阵生成:零矩阵、单位矩阵、全1矩阵
    • 块操作:block()row()col()segment()
  5. 模板化设计

    • 数据类型可选:floatdoubleint
    • 支持矩阵和向量混合运算

2️.Dense 模块核心类型

类型描述备注
Matrix<T, Rows, Cols>通用矩阵RowsCols 可固定或动态(用 Dynamic
Vector<T, Size>列向量等价于 Matrix<T, Size, 1>
RowVector<T, Size>行向量等价于 Matrix<T, 1, Size>
Array<T, Rows, Cols>元素逐一运算用于逐元素加减乘除等
DiagonalMatrix<T, Size>对角矩阵可与矩阵相乘或求逆
Quaternion<T>四元数用于旋转表示
AngleAxis<T>旋转轴角表示可转换为旋转矩阵

3.Dense 模块内部机制

  1. 内存布局

    • 默认按列主序(ColumnMajor)
    • 可改为行主序(Matrix<T, Rows, Cols, RowMajor>
  2. 表达式模板

    • 避免临时矩阵
    • 支持链式运算 A + B + C 高效执行
  3. 固定 vs 动态大小

    • 固定大小在编译期优化,适合小矩阵(如 2x2, 3x3)
    • 动态大小适合大矩阵(如点云处理、最小二乘)
  4. SIMD 向量化

    • 自动利用 CPU SIMD 指令(SSE/AVX)
    • 速度可接近手写优化代码

2、Eigen/Dense 基础

2.1 引入头文件

#include <Eigen/Dense>
#include <iostream>using namespace Eigen;
using namespace std;
  • Eigen/Dense 会自动包含 Eigen 所有核心模块,适合大部分线性代数操作。
  • 使用 using namespace Eigen 简化类型书写。

2.2 向量类型

Eigen 中向量是矩阵的特殊情况,行向量或列向量。

Vector3d v1(1.0, 2.0, 3.0);   // 列向量 3x1, double 类型
Vector3f v2(1.0f, 2.0f, 3.0f); // float 类型
VectorXd vDynamic(5);           // 动态大小向量
vDynamic << 1, 2, 3, 4, 5;
  • Vector3d → 3维 double 列向量
  • VectorXd → 动态维度列向量
  • << 可快速赋值

2.3 矩阵类型

Matrix3d A; // 3x3 double 矩阵
MatrixXd B(2, 3); // 2x3 动态矩阵A << 1, 2, 3,4, 5, 6,7, 8, 9;B << 1, 2, 3,4, 5, 6;
  • Matrix3d → 3x3 固定大小矩阵
  • MatrixXd → 动态大小矩阵
  • << 支持逐行填充

2.4 矩阵操作

Matrix3d M;
M << 1, 2, 3,0, 1, 4,5, 6, 0;// 转置
Matrix3d Mt = M.transpose();// 逆矩阵
Matrix3d Minv = M.inverse();// 矩阵乘法
Matrix3d R = M * Mt;// 元素逐一操作
Matrix3d N = M.array() + 1.0; // 每个元素加1
Matrix3d P = M.array() * 2;   // 每个元素乘2
  • matrix.array() → 逐元素操作
  • matrix * matrix2 → 矩阵乘法
  • matrix.inverse() → 求逆(仅对方阵有效)

2.5 特殊矩阵生成

Matrix3d I = Matrix3d::Identity(); // 单位矩阵
MatrixXd Z = MatrixXd::Zero(2, 3); // 零矩阵
MatrixXd O = MatrixXd::Ones(2, 3); // 全1矩阵

2.6 矩阵块操作

Matrix3d M;
M << 1,2,3,4,5,6,7,8,9;// 提取子矩阵
Matrix2d sub = M.block<2,2>(0,0); // 左上角2x2块// 改变子矩阵
M.block<2,2>(1,1) = Matrix2d::Identity();
  • block<rows,cols>(i,j) → 固定大小块
  • block(i,j,rows,cols) → 动态块

2.7 特征值与奇异值分解

Matrix3d A;
A << 1, 2, 3,0, 1, 4,5, 6, 0;// Eigen值分解(仅对方阵)
EigenSolver<Matrix3d> es(A);
cout << "Eigenvalues:\n" << es.eigenvalues() << endl;
cout << "Eigenvectors:\n" << es.eigenvectors() << endl;// 奇异值分解
JacobiSVD<MatrixXd> svd(A, ComputeFullU | ComputeFullV);
cout << "U:\n" << svd.matrixU() << endl;
cout << "S:\n" << svd.singularValues() << endl;
cout << "V:\n" << svd.matrixV() << endl;
  • EigenSolver → 特征值与特征向量
  • JacobiSVD → 奇异值分解,用于非方阵或最小二乘

3、Eigen 实战示例

示例1:最小二乘拟合直线

int n = 5;
VectorXd x(n), y(n);
x << 0, 1, 2, 3, 4;
y << 1, 3, 7, 13, 21;// 构造 A*x = b
MatrixXd A(n,2);
A.col(0) = VectorXd::Ones(n);
A.col(1) = x;VectorXd coeff = A.colPivHouseholderQr().solve(y);
cout << "y = " << coeff(1) << " * x + " << coeff(0) << endl;
  • colPivHouseholderQr() 进行最小二乘求解
  • 输出拟合直线参数

示例2:旋转矩阵 + 向量变换(机器人/SLAM常用)

Matrix3d R;
R = AngleAxisd(M_PI/4, Vector3d::UnitZ()).toRotationMatrix();
Vector3d t(1, 2, 3);
Vector3d p(1, 0, 0);// 变换
Vector3d p_trans = R * p + t;
cout << "Transformed point: " << p_trans.transpose() << endl;
  • AngleAxisd → 构造绕某轴旋转的旋转矩阵
  • R*p + t → 坐标变换

示例3:点云质心和协方差矩阵

MatrixXd points(3,5);
points << 1,2,3,4,5,0,1,0,1,0,2,3,4,5,6;// 计算质心
Vector3d centroid = points.rowwise().mean();// 去质心
MatrixXd centered = points.colwise() - centroid;// 协方差矩阵
Matrix3d cov = (centered * centered.transpose()) / (points.cols() - 1);
cout << "Covariance matrix:\n" << cov << endl;
  • 常用于 PCA、点云处理、SLAM

示例4:动态稀疏求解(大规模线性系统)

MatrixXd A = MatrixXd::Random(1000, 500);
VectorXd b = VectorXd::Random(1000);// 最小二乘解
VectorXd x = A.colPivHouseholderQr().solve(b);
cout << "Residual norm: " << (A*x - b).norm() << endl;
  • 大规模系统可直接用 Eigen 的 QRSVD 求解
  • 高性能场景可使用稀疏模块(Eigen/Sparse

4、️总结与应用场景

Dense 模块特点

  • 面向密集矩阵、向量运算
  • 支持固定和动态维度
  • 支持矩阵运算、分解、块操作
  • 高度模板化,性能优秀

实战应用

  • 机器人/SLAM:位姿变换、最小二乘优化、点云协方差计算
  • 计算机视觉:PCA、SVD、特征提取
  • 数值计算:大规模线性方程求解、矩阵分解、特征值问题

http://www.dtcms.com/a/340059.html

相关文章:

  • 三极管驱动led灯搭配的电阻选取方法
  • 跟随广州AI导游深度探寻广州历史底蕴​
  • 如何做一次AIMD
  • 农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
  • [OWASP]智能体应用安全保障指南
  • 英伟达显卡驱动怎么更新 详细步骤教程
  • MySQL练习题50题(附带详细教程)
  • Day13_【DataFrame数据组合concat连接】【案例】
  • C5.5:VDB及后面的电路讨论
  • 决策树(2)
  • Yum使用时报错
  • Spring Boot 全局异常处理
  • 快速了解Anaconda系统
  • 08.5【C++ 初阶】实现一个相对完整的日期类--附带源码
  • implement libtime on Windows
  • MyCAT基础概念
  • Python函数总结
  • week2-[一维数组]最大元素
  • 单细胞格式转换 rds 转成 h5ad
  • transformer模型初理解
  • Transformer、BERT、BEiT等模型相关八股及代码【自用】
  • HJ4 字符串分隔
  • 神经网络训练过程详解
  • 电流采样实现方法
  • JavaScript 代码保护与混淆
  • Vue2+Vue3前端开发_Day1
  • 端口映射原理操作详解教程:实现外网访问内网服务,本地路由器端口映射公网ip和软件端口映射域名2种方法
  • Qwen2.5-vl源码解读系列:LLM的Embedding层
  • MySQL常用函数
  • 首届机器人足球运动会技术复盘:从赛场表现看智能机器人核心技术突破