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])