从协方差矩阵中找出概率椭圆
Figuring out probability ellipse from covariance matrix
我正在尝试将我们的数据逆向工程为显然应该是概率椭圆的数据。作为输入,我得到一个包含神秘成员的结构,特别是 meanX、meanY、Co00、Co01 和 Co10。我猜 x 和 y 是椭圆的中心,CoXX 是协方差矩阵。听起来我应该使用特征值和特征向量来找出椭圆的两个半径。我找到了 Eigen c++ 库,但是当我得到向量和值时,我很难弄清楚我必须对 Eigen 计算结果做什么。我如何找到两个半径和椭圆倾斜度?
设:
m = (meanX)
(meanY)
是(向量)均值并且:
S = (Co00 Co01)
(Co01 Co11)
为数据的协方差矩阵。椭圆的中心是m
,椭圆的轴是矩阵S
的特征向量e1
和e2
(短轴e1
关联到 S
的最小特征值)。半径与 sqrt(λ1)
和 sqrt(λ2)
成正比,其中 λ1
和 λ2
是与 e1
和 e2
关联的特征值。最后,椭圆的倾斜度为 atan2(e2_y, e2_x)
(长轴与 x
轴之间的角度)。
这一切都来自矩阵 S 的对角化和扩展表达式 (X - m)^T S^-1 (X - m) = 1
以匹配预期形式 (x / a)^2 + (y / b)^2 = 1
。请注意,如果查看特定的置信度,则应缩放半径,对于 95% 的置信度,缩放因子为 sqrt(5.911)
.
使用 Eigen,以下代码应该可以工作:
#include <Eigen/Eigenvalues>
// [...]
Vector2d m;
Matrix2d S;
m << meanX, meanY;
S << Co00, Co01, Co01, Co11;
SelfAdjointEigenSolver<Matrix2d> solver(S);
double l1 = solver.eigenvalues().x();
double l2 = solver.eigenvalues().y();
Vector2d e1 = solver.eigenvectors().col(0);
Vector2d e2 = solver.eigenvectors().col(1);
double scale95 = sqrt(5.991);
double R1 = scale95 * sqrt(l1);
double R2 = scale95 * sqrt(l2);
double tilt = atan2(e2.y(), e2.x());
我正在尝试将我们的数据逆向工程为显然应该是概率椭圆的数据。作为输入,我得到一个包含神秘成员的结构,特别是 meanX、meanY、Co00、Co01 和 Co10。我猜 x 和 y 是椭圆的中心,CoXX 是协方差矩阵。听起来我应该使用特征值和特征向量来找出椭圆的两个半径。我找到了 Eigen c++ 库,但是当我得到向量和值时,我很难弄清楚我必须对 Eigen 计算结果做什么。我如何找到两个半径和椭圆倾斜度?
设:
m = (meanX)
(meanY)
是(向量)均值并且:
S = (Co00 Co01)
(Co01 Co11)
为数据的协方差矩阵。椭圆的中心是m
,椭圆的轴是矩阵S
的特征向量e1
和e2
(短轴e1
关联到 S
的最小特征值)。半径与 sqrt(λ1)
和 sqrt(λ2)
成正比,其中 λ1
和 λ2
是与 e1
和 e2
关联的特征值。最后,椭圆的倾斜度为 atan2(e2_y, e2_x)
(长轴与 x
轴之间的角度)。
这一切都来自矩阵 S 的对角化和扩展表达式 (X - m)^T S^-1 (X - m) = 1
以匹配预期形式 (x / a)^2 + (y / b)^2 = 1
。请注意,如果查看特定的置信度,则应缩放半径,对于 95% 的置信度,缩放因子为 sqrt(5.911)
.
使用 Eigen,以下代码应该可以工作:
#include <Eigen/Eigenvalues>
// [...]
Vector2d m;
Matrix2d S;
m << meanX, meanY;
S << Co00, Co01, Co01, Co11;
SelfAdjointEigenSolver<Matrix2d> solver(S);
double l1 = solver.eigenvalues().x();
double l2 = solver.eigenvalues().y();
Vector2d e1 = solver.eigenvectors().col(0);
Vector2d e2 = solver.eigenvectors().col(1);
double scale95 = sqrt(5.991);
double R1 = scale95 * sqrt(l1);
double R2 = scale95 * sqrt(l2);
double tilt = atan2(e2.y(), e2.x());