v2.0.0
Loading...
Searching...
No Matches
sts_cov_estimators.cpp
Go to the documentation of this file.
1//=============================================================================================================
34
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
39#include "sts_cov_estimators.h"
40
41//=============================================================================================================
42// STL INCLUDES
43//=============================================================================================================
44
45#include <algorithm>
46
47//=============================================================================================================
48// USED NAMESPACES
49//=============================================================================================================
50
51using namespace STSLIB;
52using namespace Eigen;
53
54//=============================================================================================================
55// DEFINE MEMBER METHODS
56//=============================================================================================================
57
58std::pair<MatrixXd, double> StsCovEstimators::ledoitWolf(const MatrixXd& matData)
59{
60 const int p = static_cast<int>(matData.rows());
61 const int n = static_cast<int>(matData.cols());
62
63 // Sample covariance (using 1/n, matching Ledoit-Wolf and scikit-learn)
64 const MatrixXd S = (matData * matData.transpose()) / static_cast<double>(n);
65
66 // Shrinkage target: mu * I_p
67 const double mu = S.trace() / static_cast<double>(p);
68
69 // delta = ||S - mu * I||^2_F / p
70 MatrixXd centered = S - mu * MatrixXd::Identity(p, p);
71 const double delta = centered.squaredNorm() / static_cast<double>(p);
72
73 // If delta is essentially zero, S is already a scaled identity
74 if (delta < 1e-30) {
75 return {S, 0.0};
76 }
77
78 // Efficient computation of beta:
79 // sum_k ||x_k x_k^T - S||^2_F = sum_k (x_k^T x_k)^2 - n * ||S||^2_F
80 double sumSqNorms = 0.0;
81 for (int k = 0; k < n; ++k) {
82 const double nrm = matData.col(k).squaredNorm();
83 sumSqNorms += nrm * nrm;
84 }
85 const double betaSum = sumSqNorms - static_cast<double>(n) * S.squaredNorm();
86 const double beta = betaSum / (static_cast<double>(n) * static_cast<double>(n) * static_cast<double>(p));
87
88 // Optimal shrinkage coefficient, clipped to [0, 1]
89 const double alpha = std::clamp(beta / delta, 0.0, 1.0);
90
91 // Shrunk covariance: alpha * mu * I + (1 - alpha) * S
92 MatrixXd covShrunk = (1.0 - alpha) * S;
93 covShrunk.diagonal().array() += alpha * mu;
94
95 return {covShrunk, alpha};
96}
StsCovEstimators class declaration.
Statistical testing (t-tests, F-tests, cluster permutation, multiple comparison correction).
static std::pair< Eigen::MatrixXd, double > ledoitWolf(const Eigen::MatrixXd &matData)
Ledoit-Wolf optimal shrinkage covariance estimator.