import numpy as np
from scipy.sparse.linalg import lsqr
from sklearn.datasets import load_iris, load_breast_cancer
from sklearn.linear_model import RidgeClassifier as skRidgeClassifier
class RidgeClassifier:
def __init__(self, alpha=1.0):
self.alpha = alpha
def _encode(self, y):
classes = np.unique(y)
y_train = np.full((y.shape[0], len(classes)), -1)
for i, c in enumerate(classes):
y_train[y == c, i] = 1
if len(classes) == 2:
y_train = y_train[:, 1].reshape(-1, 1)
return classes, y_train
def _solve_lsqr(self, X, y):
coefs = np.zeros((y.shape[1], X.shape[1]))
for i in range(y.shape[1]):
cur_y = y[:, i]
info = lsqr(X, cur_y, np.sqrt(self.alpha))
coefs[i] = info[0]
return coefs
def fit(self, X, y):
self.classes_, y_train = self._encode(y)
X_mean = np.mean(X, axis=0)
y_mean = np.mean(y_train, axis=0)
X_train = X - X_mean
y_train = y_train - y_mean
self.coef_ = self._solve_lsqr(X_train, y_train)
self.intercept_ = y_mean - np.dot(X_mean, self.coef_.T)
return self
def decision_function(self, X):
scores = np.dot(X, self.coef_.T) + self.intercept_
if scores.shape[1] == 1:
return scores.ravel()
else:
return scores
def predict(self, X):
scores = self.decision_function(X)
if len(scores.shape) == 1:
indices = (scores > 0).astype(int)
else:
indices = np.argmax(scores, axis=1)
return self.classes_[indices]
# binary classification
for alpha in [0.1, 1, 10]:
X, y = load_breast_cancer(return_X_y = True)
clf1 = RidgeClassifier(alpha=alpha).fit(X, y)
clf2 = skRidgeClassifier(alpha=alpha, solver='lsqr',
# keep consisent with scipy default
tol=1e-8).fit(X, y)
assert clf1.coef_.shape == (1, X.shape[1])
assert np.allclose(clf1.coef_, clf2.coef_)
assert np.allclose(clf1.intercept_, clf2.intercept_)
prob1 = clf1.decision_function(X)
prob2 = clf2.decision_function(X)
pred1 = clf1.predict(X)
pred2 = clf2.predict(X)
assert np.allclose(prob1, prob2)
assert np.array_equal(pred1, pred2)
# multiclass classification
for alpha in [0.1, 1, 10]:
X, y = load_iris(return_X_y = True)
clf1 = RidgeClassifier(alpha=alpha).fit(X, y)
clf2 = skRidgeClassifier(alpha=alpha, solver='lsqr',
# keep consisent with scipy default
tol=1e-8).fit(X, y)
assert clf1.coef_.shape == (len(np.unique(y)), X.shape[1])
assert np.allclose(clf1.coef_, clf2.coef_)
assert np.allclose(clf1.intercept_, clf2.intercept_)
prob1 = clf1.decision_function(X)
prob2 = clf2.decision_function(X)
pred1 = clf1.predict(X)
pred2 = clf2.predict(X)
assert np.allclose(prob1, prob2)
assert np.array_equal(pred1, pred2)