Skip to main content
The SVDReducer class performs dimensionality reduction using Singular Value Decomposition (SVD). Given a data matrix X ∈ R^(m×n) with rows as samples and columns as features, the thin SVD is: X = U Σ V^T where Σ = diag(σ₁,…,σ_r), r = min(m,n), and σ₁ ≥ … ≥ σ_r ≥ 0. Dimensionality reduction to k < r dimensions provides the best rank-k approximation (Eckart–Young–Mirsky theorem).

Constructor

SVDReducer svd;
The default constructor requires no parameters.

Methods

fit

Fit the SVD model to the data matrix.
void fit(const Eigen::MatrixXd& X)
X
const Eigen::MatrixXd&
required
Data matrix where rows are samples and columns are features

Example

Eigen::MatrixXd data(100, 10); // 100 samples, 10 features
// ... populate data ...

SVDReducer svd;
svd.fit(data);

transform

Reduce the fitted data to k dimensions.
Eigen::MatrixXd transform(std::size_t k) const
k
std::size_t
required
Number of dimensions to reduce to
return
Eigen::MatrixXd
Reduced representation Z = U_k Σ_k with shape (m×k), where m is the number of samples

Example

// Reduce to 3 dimensions
Eigen::MatrixXd reduced = svd.transform(3);
std::cout << "Reduced shape: " << reduced.rows() 
          << "x" << reduced.cols() << std::endl;

transform_new

Transform a new batch of data using the fitted SVD model.
Eigen::MatrixXd transform_new(const Eigen::MatrixXd& X_new, std::size_t k) const
X_new
const Eigen::MatrixXd&
required
New data matrix to transform
k
std::size_t
required
Number of dimensions to reduce to
return
Eigen::MatrixXd
Transformed new data: X_new V_k

Example

Eigen::MatrixXd new_data(50, 10); // 50 new samples, 10 features
// ... populate new_data ...

// Transform new data to 3 dimensions
Eigen::MatrixXd transformed_new = svd.transform_new(new_data, 3);

reconstruct

Reconstruct data from reduced coordinates (approximate inverse transformation).
Eigen::MatrixXd reconstruct(const Eigen::MatrixXd& Z, std::size_t k) const
Z
const Eigen::MatrixXd&
required
Reduced coordinates from transform or transform_new
k
std::size_t
required
Number of dimensions used in the reduction
return
Eigen::MatrixXd
Reconstructed data in the original dimensional space

Example

Eigen::MatrixXd reduced = svd.transform(3);
Eigen::MatrixXd reconstructed = svd.reconstruct(reduced, 3);
// reconstructed approximates the original data

U

Get the left singular vectors matrix.
const Eigen::MatrixXd& U() const
return
const Eigen::MatrixXd&
Matrix U of left singular vectors with shape (m×r)

Example

const Eigen::MatrixXd& U = svd.U();
std::cout << "U shape: " << U.rows() << "x" << U.cols() << std::endl;

S

Get the singular values vector.
const Eigen::VectorXd& S() const
return
const Eigen::VectorXd&
Vector of singular values (σ₁,…,σ_r) in descending order

Example

const Eigen::VectorXd& S = svd.S();
std::cout << "Singular values: " << S.transpose() << std::endl;

// Analyze explained variance
double total_variance = S.array().square().sum();
for (int i = 0; i < S.size(); ++i) {
    double variance_ratio = (S(i) * S(i)) / total_variance;
    std::cout << "Component " << i << ": " 
              << (variance_ratio * 100) << "%" << std::endl;
}

V

Get the right singular vectors matrix.
const Eigen::MatrixXd& V() const
return
const Eigen::MatrixXd&
Matrix V of right singular vectors with shape (n×r)

Example

const Eigen::MatrixXd& V = svd.V();
std::cout << "V shape: " << V.rows() << "x" << V.cols() << std::endl;

Complete example

#include "SVD.h"
#include <Eigen/Dense>
#include <iostream>

int main() {
    // Create training data
    Eigen::MatrixXd data(100, 10); // 100 samples, 10 features
    data.setRandom();
    
    // Fit SVD
    SVDReducer svd;
    svd.fit(data);
    
    // Transform training data to 3 dimensions
    Eigen::MatrixXd reduced = svd.transform(3);
    std::cout << "Reduced shape: " << reduced.rows() 
              << "x" << reduced.cols() << std::endl;
    
    // Transform new data
    Eigen::MatrixXd new_data(50, 10); // 50 new samples
    new_data.setRandom();
    Eigen::MatrixXd reduced_new = svd.transform_new(new_data, 3);
    
    // Reconstruct data
    Eigen::MatrixXd reconstructed = svd.reconstruct(reduced, 3);
    
    // Access singular values and vectors
    const Eigen::VectorXd& singular_values = svd.S();
    std::cout << "Singular values: " << singular_values.transpose() << std::endl;
    
    // Compute reconstruction error
    double error = (data - reconstructed).norm() / data.norm();
    std::cout << "Relative reconstruction error: " << error << std::endl;
    
    return 0;
}

Build docs developers (and LLMs) love