78 lines
2.0 KiB
Python
Executable File
78 lines
2.0 KiB
Python
Executable File
import numpy as np
|
|
from prml.linear.classifier import Classifier
|
|
|
|
|
|
class LogisticRegression(Classifier):
|
|
"""
|
|
Logistic regression model
|
|
|
|
y = sigmoid(X @ w)
|
|
t ~ Bernoulli(t|y)
|
|
"""
|
|
|
|
@staticmethod
|
|
def _sigmoid(a):
|
|
return np.tanh(a * 0.5) * 0.5 + 0.5
|
|
|
|
def fit(self, X:np.ndarray, t:np.ndarray, max_iter:int=100):
|
|
"""
|
|
maximum likelihood estimation of logistic regression model
|
|
|
|
Parameters
|
|
----------
|
|
X : (N, D) np.ndarray
|
|
training data independent variable
|
|
t : (N,) np.ndarray
|
|
training data dependent variable
|
|
binary 0 or 1
|
|
max_iter : int, optional
|
|
maximum number of paramter update iteration (the default is 100)
|
|
"""
|
|
w = np.zeros(np.size(X, 1))
|
|
for _ in range(max_iter):
|
|
w_prev = np.copy(w)
|
|
y = self._sigmoid(X @ w)
|
|
grad = X.T @ (y - t)
|
|
hessian = (X.T * y * (1 - y)) @ X
|
|
try:
|
|
w -= np.linalg.solve(hessian, grad)
|
|
except np.linalg.LinAlgError:
|
|
break
|
|
if np.allclose(w, w_prev):
|
|
break
|
|
self.w = w
|
|
|
|
def proba(self, X:np.ndarray):
|
|
"""
|
|
compute probability of input belonging class 1
|
|
|
|
Parameters
|
|
----------
|
|
X : (N, D) np.ndarray
|
|
training data independent variable
|
|
|
|
Returns
|
|
-------
|
|
(N,) np.ndarray
|
|
probability of positive
|
|
"""
|
|
return self._sigmoid(X @ self.w)
|
|
|
|
def classify(self, X:np.ndarray, threshold:float=0.5):
|
|
"""
|
|
classify input data
|
|
|
|
Parameters
|
|
----------
|
|
X : (N, D) np.ndarray
|
|
independent variable to be classified
|
|
threshold : float, optional
|
|
threshold of binary classification (default is 0.5)
|
|
|
|
Returns
|
|
-------
|
|
(N,) np.ndarray
|
|
binary class for each input
|
|
"""
|
|
return (self.proba(X) > threshold).astype(np.int)
|