diff --git a/feature/linear.py b/feature/linear.py index c931867..7561f45 100644 --- a/feature/linear.py +++ b/feature/linear.py @@ -4,9 +4,11 @@ from typing import NoReturn, Tuple +import numpy as np import pandas as pd from sklearn.linear_model import LinearRegression, Lasso, Ridge from sklearn.linear_model import LogisticRegression, RidgeClassifier +from sklearn.multiclass import OneVsRestClassifier from feature.base import _BaseSupervisedSelector, _BaseDispatcher from feature.utils import Num, get_task_string @@ -29,10 +31,10 @@ def __init__(self, seed: int, num_features: Num, regularization: str, alpha:Num) "regression_lasso": Lasso(random_state=self.seed), "regression_ridge": Ridge(random_state=self.seed), # "classification_none": LogisticRegression(penalty="none"), # won't converge most times - "classification_none": LogisticRegression(random_state=self.seed, - multi_class="auto", solver="liblinear"), - "classification_lasso": LogisticRegression(random_state=self.seed, penalty='l1', - multi_class="auto", solver="liblinear"), + "classification_none": OneVsRestClassifier( + LogisticRegression(random_state=self.seed, solver="liblinear")), + "classification_lasso": OneVsRestClassifier( + LogisticRegression(random_state=self.seed, penalty='l1', solver="liblinear")), "classification_ridge": RidgeClassifier(random_state=self.seed)} def get_model_args(self, selection_method) -> Tuple: @@ -60,13 +62,18 @@ def fit(self, data: pd.DataFrame, labels: pd.Series) -> NoReturn: # But that does not necessarily mean they are more important # See more discussion here: # https://scikit-learn.org/stable/auto_examples/inspection/plot_linear_model_coefficient_interpretation.html#sphx-glr-auto-examples-inspection-plot-linear-model-coefficient-interpretation-py - self.abs_scores = abs(self.imp.coef_) + if isinstance(self.imp, OneVsRestClassifier): + coefficients = np.vstack([estimator.coef_ for estimator in self.imp.estimators_]) + else: + coefficients = self.imp.coef_ # LogisticRegression/RidgeClassifier returns a coef_ array of (n_classes, n_features) # These coefficients map the importance of the feature for a specific class. # One approach is to average the importances - if isinstance(self.imp, LogisticRegression) or isinstance(self.imp, RidgeClassifier): - self.abs_scores = abs(self.imp.coef_.mean(0)) + if isinstance(self.imp, (OneVsRestClassifier, LogisticRegression, RidgeClassifier)): + self.abs_scores = abs(coefficients.mean(0)) + else: + self.abs_scores = abs(coefficients) def transform(self, data: pd.DataFrame) -> pd.DataFrame: