-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add two step classifier #431
base: main
Are you sure you want to change the base?
Changes from all commits
bf480ff
e6d3e3b
1c2065c
29168e4
124260f
6480c6a
e450f24
5850360
e8fcc3f
052c109
9df38a8
9e8c0c8
1605cfa
8551503
2d2be2a
7a1f4a7
ceabe7c
fdf62db
1c8157f
e6d6b95
65a11bb
ef6fc45
584bab7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .logistic_regression import LogisticRegressionClassifier | ||
from .two_step_classifier import TwoStepClassifier | ||
|
||
__all__ = ["LogisticRegressionClassifier", "TwoStepClassifier"] | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import logging | ||
|
||
import numpy as np | ||
from sklearn.linear_model import LogisticRegression | ||
from sklearn.preprocessing import StandardScaler | ||
|
||
from alphadia.fdrexperimental import Classifier | ||
|
||
logger = logging.getLogger() | ||
|
||
|
||
class LogisticRegressionClassifier(Classifier): | ||
def __init__(self) -> None: | ||
"""Binary classifier using a logistic regression model.""" | ||
self.scaler = StandardScaler() | ||
self.model = LogisticRegression() | ||
self._fitted = False | ||
|
||
@property | ||
def fitted(self) -> bool: | ||
return self._fitted | ||
|
||
def fit(self, x: np.ndarray, y: np.ndarray) -> None: | ||
"""Fit the classifier to the data. | ||
|
||
Parameters | ||
---------- | ||
|
||
x : np.array, dtype=float | ||
Training data of shape (n_samples, n_features). | ||
|
||
y : np.array, dtype=int | ||
Target values of shape (n_samples,) or (n_samples, n_classes). | ||
|
||
""" | ||
x_scaled = self.scaler.fit_transform(x) | ||
self.model.fit(x_scaled, y) | ||
self._fitted = True | ||
|
||
def predict(self, x: np.ndarray) -> np.ndarray: | ||
"""Predict the class of the data. | ||
|
||
Parameters | ||
---------- | ||
|
||
x : np.array, dtype=float | ||
Data of shape (n_samples, n_features). | ||
Comment on lines
+46
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. at other places you are using capital (and adapt also |
||
|
||
Returns | ||
------- | ||
|
||
y : np.array, dtype=float | ||
Predicted class probabilities of shape (n_samples, n_classes). | ||
|
||
""" | ||
x_scaled = self.scaler.transform(x) | ||
return self.model.predict(x_scaled) | ||
|
||
def predict_proba(self, x: np.ndarray) -> np.ndarray: | ||
"""Predict the class probabilities of the data. | ||
|
||
Parameters | ||
---------- | ||
|
||
x : np.array, dtype=float | ||
Data of shape (n_samples, n_features). | ||
|
||
Returns | ||
------- | ||
|
||
y : np.array, dtype=float | ||
Predicted class probabilities of shape (n_samples, n_classes). | ||
|
||
""" | ||
x_scaled = self.scaler.transform(x) | ||
return self.model.predict_proba(x_scaled) | ||
|
||
def to_state_dict(self) -> dict: | ||
"""Return the state of the classifier as a dictionary. | ||
|
||
Returns | ||
------- | ||
|
||
dict : dict | ||
Dictionary containing the state of the classifier. | ||
|
||
""" | ||
state_dict = {"_fitted": self._fitted} | ||
|
||
if self._fitted: | ||
state_dict.update( | ||
{ | ||
"scaler_mean": self.scaler.mean_, | ||
"scaler_var": self.scaler.var_, | ||
"scaler_scale": self.scaler.scale_, | ||
"scaler_n_samples_seen": self.scaler.n_samples_seen_, | ||
"model_coef": self.model.coef_, | ||
"model_intercept": self.model.intercept_, | ||
"model_classes": self.model.classes_, | ||
"is_fitted": self._fitted, | ||
} | ||
) | ||
|
||
return state_dict | ||
|
||
def from_state_dict(self, state_dict: dict) -> None: | ||
"""Load the state of the classifier from a dictionary. | ||
|
||
Parameters | ||
---------- | ||
|
||
dict : dict | ||
Dictionary containing the state of the classifier. | ||
|
||
""" | ||
self._fitted = state_dict["_fitted"] | ||
|
||
if self.fitted: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please check if this should rather be |
||
self.scaler = StandardScaler() | ||
self.scaler.mean_ = np.array(state_dict["scaler_mean"]) | ||
self.scaler.var_ = np.array(state_dict["scaler_var"]) | ||
self.scaler.scale_ = np.array(state_dict["scaler_scale"]) | ||
self.scaler.n_samples_seen_ = np.array(state_dict["scaler_n_samples_seen"]) | ||
|
||
self.model = LogisticRegression() | ||
self.model.coef_ = np.array(state_dict["model_coef"]) | ||
self.model.intercept_ = np.array(state_dict["model_intercept"]) | ||
self.model.classes_ = np.array(state_dict["model_classes"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need the logic in this file? (especially the
__all__
-> we're not using that idiom anywhere else in alphadia)