selective 1.2.0__tar.gz → 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {selective-1.2.0/selective.egg-info → selective-1.2.1}/PKG-INFO +1 -1
- {selective-1.2.0 → selective-1.2.1}/feature/_version.py +1 -1
- {selective-1.2.0 → selective-1.2.1}/feature/linear.py +27 -15
- {selective-1.2.0 → selective-1.2.1}/feature/text_based.py +1 -1
- {selective-1.2.0 → selective-1.2.1}/feature/utils.py +2 -6
- {selective-1.2.0 → selective-1.2.1/selective.egg-info}/PKG-INFO +1 -1
- {selective-1.2.0 → selective-1.2.1}/LICENSE.md +0 -0
- {selective-1.2.0 → selective-1.2.1}/MANIFEST.in +0 -0
- {selective-1.2.0 → selective-1.2.1}/NOTICES +0 -0
- {selective-1.2.0 → selective-1.2.1}/README.md +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/__init__.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/base.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/correlation.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/kl_divergence.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/selector.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/statistical.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/tree_based.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/feature/variance.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/requirements.txt +0 -0
- {selective-1.2.0 → selective-1.2.1}/selective.egg-info/SOURCES.txt +0 -0
- {selective-1.2.0 → selective-1.2.1}/selective.egg-info/dependency_links.txt +0 -0
- {selective-1.2.0 → selective-1.2.1}/selective.egg-info/requires.txt +0 -0
- {selective-1.2.0 → selective-1.2.1}/selective.egg-info/top_level.txt +0 -0
- {selective-1.2.0 → selective-1.2.1}/setup.cfg +0 -0
- {selective-1.2.0 → selective-1.2.1}/setup.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_base.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_benchmark.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_correlation.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_linear.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_parallel.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_stat_anova.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_stat_chi.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_stat_kl.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_stat_maximal.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_stat_mutual.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_stat_vif.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_text.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_tree.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_utils.py +0 -0
- {selective-1.2.0 → selective-1.2.1}/tests/test_variance.py +0 -0
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
|
|
5
5
|
from typing import NoReturn, Tuple
|
|
6
|
-
|
|
6
|
+
import numpy as np
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from sklearn.linear_model import LinearRegression, Lasso, Ridge
|
|
9
9
|
from sklearn.linear_model import LogisticRegression, RidgeClassifier
|
|
10
|
-
|
|
10
|
+
from sklearn.multiclass import OneVsRestClassifier
|
|
11
11
|
from feature.base import _BaseSupervisedSelector, _BaseDispatcher
|
|
12
12
|
from feature.utils import Num, get_task_string
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class _Linear(_BaseSupervisedSelector, _BaseDispatcher):
|
|
16
16
|
|
|
17
|
-
def __init__(self, seed: int, num_features: Num, regularization: str, alpha:Num):
|
|
17
|
+
def __init__(self, seed: int, num_features: Num, regularization: str, alpha: Num):
|
|
18
18
|
super().__init__(seed)
|
|
19
19
|
|
|
20
20
|
self.num_features = num_features # this could be int or float
|
|
@@ -28,20 +28,17 @@ class _Linear(_BaseSupervisedSelector, _BaseDispatcher):
|
|
|
28
28
|
self.factory = {"regression_none": LinearRegression(),
|
|
29
29
|
"regression_lasso": Lasso(random_state=self.seed),
|
|
30
30
|
"regression_ridge": Ridge(random_state=self.seed),
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
multi_class="auto", solver="liblinear"),
|
|
31
|
+
"classification_none": OneVsRestClassifier(
|
|
32
|
+
LogisticRegression(random_state=self.seed, solver="liblinear")),
|
|
33
|
+
"classification_lasso": OneVsRestClassifier(
|
|
34
|
+
LogisticRegression(random_state=self.seed, penalty='l1', solver="liblinear")),
|
|
36
35
|
"classification_ridge": RidgeClassifier(random_state=self.seed)}
|
|
37
36
|
|
|
38
37
|
def get_model_args(self, selection_method) -> Tuple:
|
|
39
|
-
|
|
40
38
|
# Pack model argument
|
|
41
39
|
return selection_method.regularization
|
|
42
40
|
|
|
43
41
|
def dispatch_model(self, labels: pd.Series, *args):
|
|
44
|
-
|
|
45
42
|
# Unpack model argument
|
|
46
43
|
regularization = args[0]
|
|
47
44
|
|
|
@@ -49,7 +46,18 @@ class _Linear(_BaseSupervisedSelector, _BaseDispatcher):
|
|
|
49
46
|
self.imp = self.factory.get(get_task_string(labels) + regularization)
|
|
50
47
|
|
|
51
48
|
def fit(self, data: pd.DataFrame, labels: pd.Series) -> NoReturn:
|
|
49
|
+
"""
|
|
50
|
+
Fits the underlying linear model to the data and calculates absolute feature importances.
|
|
51
|
+
|
|
52
|
+
This method identifies the appropriate model context (regression vs. classification),
|
|
53
|
+
fits it to the training data, and extracts the coefficient weights. For multi-class
|
|
54
|
+
classifiers, it computes a global score by averaging the class-specific absolute weights.
|
|
52
55
|
|
|
56
|
+
:param data: The input features dataframe of shape (n_samples, n_features).
|
|
57
|
+
:param labels: The target labels series. Automatically determines whether the task
|
|
58
|
+
is regression or classification.
|
|
59
|
+
|
|
60
|
+
"""
|
|
53
61
|
# Fit linear model
|
|
54
62
|
self.imp.fit(X=data, y=labels)
|
|
55
63
|
|
|
@@ -60,15 +68,19 @@ class _Linear(_BaseSupervisedSelector, _BaseDispatcher):
|
|
|
60
68
|
# But that does not necessarily mean they are more important
|
|
61
69
|
# See more discussion here:
|
|
62
70
|
# 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
|
|
63
|
-
self.abs_scores = abs(self.imp.coef_)
|
|
64
|
-
|
|
65
71
|
# LogisticRegression/RidgeClassifier returns a coef_ array of (n_classes, n_features)
|
|
66
72
|
# These coefficients map the importance of the feature for a specific class.
|
|
67
73
|
# One approach is to average the importances
|
|
68
|
-
if isinstance(self.imp,
|
|
69
|
-
|
|
74
|
+
if isinstance(self.imp, OneVsRestClassifier):
|
|
75
|
+
coefficients = np.vstack([estimator.coef_ for estimator in self.imp.estimators_])
|
|
76
|
+
else:
|
|
77
|
+
coefficients = np.asarray(self.imp.coef_)
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
if isinstance(self.imp, (LogisticRegression, OneVsRestClassifier, RidgeClassifier)):
|
|
80
|
+
self.abs_scores = np.abs(coefficients.mean(0))
|
|
81
|
+
else:
|
|
82
|
+
self.abs_scores = np.abs(coefficients)
|
|
72
83
|
|
|
84
|
+
def transform(self, data: pd.DataFrame) -> pd.DataFrame:
|
|
73
85
|
# Select top-k from data based on abs_scores and num_features
|
|
74
86
|
return self.get_top_k(data, self.abs_scores)
|
|
@@ -647,7 +647,7 @@ def process_category_data(input_df: pd.DataFrame, categories: List[str]) -> pd.D
|
|
|
647
647
|
matrix = (input_df.labels.str.split('|', expand=True)
|
|
648
648
|
.stack()
|
|
649
649
|
.str.get_dummies()
|
|
650
|
-
.groupby(level=0
|
|
650
|
+
.groupby(level=0)
|
|
651
651
|
.sum()).T
|
|
652
652
|
|
|
653
653
|
check_true(matrix.ndim == 2, ValueError("Process Data Error: matrix should 2D"))
|
|
@@ -16,7 +16,6 @@ from sklearn.feature_selection import SelectKBest, SelectPercentile
|
|
|
16
16
|
from sklearn.impute import SimpleImputer
|
|
17
17
|
from sklearn.preprocessing import StandardScaler
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
Num = Union[int, float]
|
|
21
20
|
"""Num type is defined as integer or float."""
|
|
22
21
|
|
|
@@ -52,7 +51,6 @@ def get_data_label(sklearn_dataset):
|
|
|
52
51
|
|
|
53
52
|
|
|
54
53
|
def get_task_string(labels: pd.Series):
|
|
55
|
-
|
|
56
54
|
if labels is None:
|
|
57
55
|
return "unsupervised_"
|
|
58
56
|
|
|
@@ -65,7 +63,6 @@ def is_classification(labels: pd.Series):
|
|
|
65
63
|
|
|
66
64
|
|
|
67
65
|
def get_selector(score_func, k: Union[int, float]):
|
|
68
|
-
|
|
69
66
|
# Top K or Top Percentile
|
|
70
67
|
if isinstance(k, int):
|
|
71
68
|
return SelectKBest(score_func, k=k)
|
|
@@ -131,7 +128,6 @@ class DataTransformer:
|
|
|
131
128
|
"""
|
|
132
129
|
|
|
133
130
|
def __init__(self):
|
|
134
|
-
|
|
135
131
|
# Imputation
|
|
136
132
|
self.imp = SimpleImputer(strategy='median')
|
|
137
133
|
|
|
@@ -206,7 +202,7 @@ def reduce_memory(df: pd.DataFrame, verbose=True) -> pd.DataFrame:
|
|
|
206
202
|
|
|
207
203
|
# Print current column type
|
|
208
204
|
if verbose:
|
|
209
|
-
print(20*"=")
|
|
205
|
+
print(20 * "=")
|
|
210
206
|
print("Column ", i, ":", col)
|
|
211
207
|
print("dtype_before: ", df[col].dtype)
|
|
212
208
|
|
|
@@ -255,7 +251,7 @@ def reduce_memory(df: pd.DataFrame, verbose=True) -> pd.DataFrame:
|
|
|
255
251
|
# Print new column type
|
|
256
252
|
if verbose:
|
|
257
253
|
print("dtype_after: ", df[col].dtype)
|
|
258
|
-
print(20*"=")
|
|
254
|
+
print(20 * "=")
|
|
259
255
|
|
|
260
256
|
memory_after = df.memory_usage().sum() / 1024 ** 2
|
|
261
257
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|