Source code for pymcr.regressors

"""
Built-in least squares / regression methods.

All models will follow the formalism, AX = B, solve for X.

NOTE: coef_ will be X.T, which is the formalism that scikit-learn follows

"""

from abc import (ABC as _ABC, abstractmethod as _abstractmethod)

import numpy as _np

from scipy.linalg import lstsq as _lstsq
from scipy.optimize import nnls as _nnls

[docs]class LinearRegression(_ABC): """ Abstract class for linear regression methods """ def __init__(self): self.X_ = None self.residual_ = None @property def coef_(self): """ The transposed form of X. This is the formalism of scikit-learn """ if self.X_ is None: return None else: return self.X_.T
[docs] @_abstractmethod def fit(self, A, B): """ AX = B, solve for X """
[docs]class OLS(LinearRegression): """ Ordinary least squares regression AX = B, solve for X (coefficients.T) Attributes ---------- coef_ : ndarray Regression coefficients (X.T) residual_ : ndarray Residual (sum-of-squares) rank_ : int Effective rank of matrix A svs_ : ndarray Singular values of matrix A Notes ----- This is simply a wrapped version of Ordinary Least Squares (scipy.linalg.lstsq). coef_ is X.T, which is the formalism of scikit-learn """ def __init__(self, *args, **kwargs): super().__init__() self.rank_ = None self.svs_ = None
[docs] def fit(self, A, B): """ Solve for X: AX = B""" self.X_, self.residual_, self.rank_, self.svs_ = _lstsq(A, B)
[docs]class NNLS(LinearRegression): """ Non-negative constrained least squares regression AX = B, solve for X (coeffients.T) Attributes ---------- coef_ : ndarray Regression coefficients residual_ : ndarray Residual (sum-of-squares) Notes ----- This is simply a wrapped version of NNLS (scipy.optimize.nnls). coef_ is X.T, which is the formalism of scikit-learn """ def __init__(self, *args, **kwargs): super().__init__()
[docs] def fit(self, A, B): """ Solve for X: AX = B""" if B.ndim == 2: N = B.shape[-1] else: N = 0 self.X_ = _np.zeros((A.shape[-1], N)) self.residual_ = _np.zeros((N)) # nnls is Ax = b; thus, need to iterate along # columns of B if N == 0: self.X_, self.residual_ = _nnls(A, B) else: for num in range(N): self.X_[:, num], self.residual_[num] = _nnls(A, B[:, num])