Skip to main content
Regression algorithms predict continuous numerical outputs from input features. MLPP provides efficient implementations with automatic solver selection and built-in regularization.

Linear regression

Ordinary least squares (OLS) regression solves:
min_w  (1/2n) ||Xw - y||² + (λ/2) ||w||²
The LinearRegression class automatically selects the optimal solver based on problem geometry.

Basic usage

#include <mlpp/regression/linear_regression.hpp>

using namespace mlpp::regression;

// Create model with intercept, no regularization
LinearRegression<double> model(true, 0.0);

// Fit to training data
LinearRegression<double>::Matrix X_train(100, 5);
LinearRegression<double>::Vector y_train(100);
// ... populate X_train and y_train ...

model.fit(X_train, y_train);

// Make predictions
auto y_pred = model.predict(X_test);

// Evaluate R² score
double r2 = model.score(X_test, y_test);

Constructor parameters

fit_intercept
bool
default:"true"
Whether to fit a bias term. Set to false if data is already centered.
regularization
Scalar
default:"0.0"
L2 penalty λ ≥ 0. Use λ > 0 for ridge regression to prevent overfitting.
method
SolveMethod
default:"Auto"
Linear solver strategy:
  • Auto: Chosen automatically (recommended)
  • Cholesky: Normal equations, fast for n >> d
  • SVD: Stable for any problem shape
  • JacobiSVD: Maximally stable for ill-conditioned problems

Methods

fit
void
void fit(const Matrix& X, const Vector& y)
Fit the model to training data.
  • X: Feature matrix, shape (n_samples, n_features)
  • y: Target vector, length n_samples
predict
Vector
Vector predict(const Matrix& X) const
Predict targets for new samples. Returns vector of length n_samples.
score
Scalar
Scalar score(const Matrix& X, const Vector& y) const
Compute coefficient of determination R²:
R² = 1 - SS_res / SS_tot
Returns value in (-∞, 1], where 1.0 is perfect prediction.
residuals
Vector
Vector residuals(const Matrix& X, const Vector& y) const
Compute residual vector: e = y - Xw - b
gradient
Vector
Vector gradient(const Matrix& X, const Vector& y) const
Gradient of the regularized MSE loss:
∇L = (1/n) Xᵀ(Xw - y) + λw
coefficients
const Vector&
const Vector& coefficients() const
Coefficient vector w in original (unscaled) feature space, length n_features.
intercept
Scalar
Scalar intercept() const
Intercept (bias) term. Returns 0 if fit_intercept == false.
condition_number
Scalar
Scalar condition_number() const
Effective condition number of the design matrix (available after SVD solve).

Ridge regression

Ridge regression adds L2 regularization to prevent overfitting:
// Ridge regression with λ = 0.5
LinearRegression<double> ridge(true, 0.5);
ridge.fit(X_train, y_train);
The regularization term shrinks coefficients toward zero:
min_w  (1/2n) ||Xw - y||² + (λ/2) ||w||²
The intercept is never regularized. MLPP centers the data before solving so the bias term is unaffected by λ.

Polynomial regression

Fit non-linear relationships using polynomial feature expansion:
#include <mlpp/regression/polynomial_regression.hpp>

using namespace mlpp::regression;

// Degree-3 polynomial with interactions
PolynomialRegression<double> poly(
    3,      // degree
    true,   // include_interactions
    true,   // fit_intercept
    0.01    // regularization
);

poly.fit(X_train, y_train);
auto y_pred = poly.predict(X_test);

Feature expansion modes

With include_interactions = false, only pure power terms are added:
[1, x₁, x₁², x₁³, x₂, x₂², x₂³, ...]
Output dimension: (include_bias ? 1 : 0) + d·D
PolynomialRegression<double> model(
    3,      // degree
    false,  // no interactions
    true,   // include bias
    0.0
);

Constructor parameters

degree
unsigned
default:"2"
Maximum polynomial degree D ≥ 1. Higher degrees can fit more complex patterns but risk overfitting.
include_interactions
bool
default:"false"
Whether to include cross-feature monomials (e.g., x₁x₂, x₁²x₂). Dramatically increases feature count.
fit_intercept
bool
default:"true"
Forwarded to the underlying LinearRegression model.
regularization
Scalar
default:"0.0"
L2 penalty forwarded to LinearRegression. Strongly recommended for high-degree polynomials.
method
SolveMethod
default:"Auto"
Solve strategy forwarded to LinearRegression.

Methods

PolynomialRegression provides the same interface as LinearRegression:
  • fit(X, y) - Expand features and fit model
  • predict(X) - Expand features and predict
  • score(X, y) - Compute R² score
  • residuals(X, y) - Compute residuals
  • coefficients() - Coefficients in expanded space
  • intercept() - Intercept term

Polynomial features

You can also use PolynomialFeatures independently:
PolynomialFeatures<double> poly(3, true, true);

// Transform features
auto X_expanded = poly.transform(X_train);

// Check output dimension
size_t out_dim = poly.output_dim(X_train.cols());

Example: Complete workflow

#include <mlpp/regression/linear_regression.hpp>
#include <mlpp/regression/polynomial_regression.hpp>
#include <Eigen/Dense>
#include <iostream>

using namespace mlpp::regression;
using Matrix = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using Vector = Eigen::Matrix<double, Eigen::Dynamic, 1>;

int main() {
    // Generate synthetic data
    Matrix X_train(100, 3);
    Vector y_train(100);
    // ... populate data ...
    
    // Try linear regression
    LinearRegression<double> linear(true, 0.0);
    linear.fit(X_train, y_train);
    std::cout << "Linear R²: " << linear.score(X_test, y_test) << std::endl;
    
    // Try ridge regression
    LinearRegression<double> ridge(true, 0.1);
    ridge.fit(X_train, y_train);
    std::cout << "Ridge R²: " << ridge.score(X_test, y_test) << std::endl;
    
    // Try polynomial regression
    PolynomialRegression<double> poly(2, false, true, 0.01);
    poly.fit(X_train, y_train);
    std::cout << "Poly R²: " << poly.score(X_test, y_test) << std::endl;
    
    // Inspect coefficients
    std::cout << "Coefficients: " << poly.coefficients().transpose() << std::endl;
    std::cout << "Intercept: " << poly.intercept() << std::endl;
    
    return 0;
}

Performance tips

Solver selection

Let the Auto solver choose for you unless you have specific requirements:
  • Use Cholesky when n >> d and the problem is well-conditioned
  • Use SVD for rank-deficient or ill-conditioned problems
  • Use JacobiSVD as a last resort for maximum stability

Regularization

Always use regularization for polynomial regression with degree ≥ 3 or when including interactions. Start with λ = 0.01 and tune via cross-validation.

Feature scaling

MLPP handles standardization automatically - you don’t need to scale features manually. The model:
  1. Standardizes features internally (zero mean, unit variance)
  2. Solves the problem in standardized space
  3. Transforms coefficients back to original scale
This ensures numerical stability while maintaining interpretability.

Build docs developers (and LLMs) love