Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion DashAI/back/converters/category/feature_selection.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from typing import Final
from typing import TYPE_CHECKING, Final, Union

from DashAI.back.converters.base_converter import BaseConverter
from DashAI.back.core.utils import MultilingualString
from DashAI.back.static.icons import Icon
from DashAI.back.types.dashai_data_type import DashAIDataType

if TYPE_CHECKING:
from DashAI.back.dataloaders.classes.dashai_dataset import DashAIDataset


class FeatureSelectionConverter(BaseConverter):
Expand All @@ -15,6 +19,10 @@ class FeatureSelectionConverter(BaseConverter):

Use these converters to reduce overfitting, speed up training, and improve
model interpretability by retaining only the most informative features.

These converters only drop columns; the retained columns keep their
original values untouched, so their data types must be preserved instead of
being coerced to float.
"""

CATEGORY = MultilingualString(
Expand All @@ -26,3 +34,57 @@ class FeatureSelectionConverter(BaseConverter):
)
ICON: Final[str] = Icon.FilterList.value
COLOR: Final[str] = "rgb(255, 206, 86)"

def fit(
self, x: "DashAIDataset", y: Union["DashAIDataset", None] = None
) -> "FeatureSelectionConverter":
"""Fit the selector while remembering the input column types.

Feature selection only keeps a subset of the input columns without
modifying their values, so the original types are captured here to be
returned later by ``get_output_type``. Types are recorded during ``fit``
(rather than ``transform``) because scikit-learn auto-wraps ``transform``
on subclasses and would coerce its output back to a pandas DataFrame.

Parameters
----------
x : DashAIDataset
The input dataset to fit the selector on.
y : DashAIDataset, optional
Target values for the supervised selectors. Defaults to None.

Returns
-------
FeatureSelectionConverter
The fitted selector instance (self).
"""
if hasattr(x, "types") and x.types is not None:
self._input_types = dict(x.types)
return super().fit(x, y)

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the original DashAI data type of a retained column.

Since feature selection leaves the retained columns' values unchanged,
the output type matches the input type of that column.

Parameters
----------
column_name : str, optional
The name of the retained column. Defaults to None.

Returns
-------
DashAIDataType
The original type of the column. Falls back to ``float64`` when the
input type is unknown (feature selectors only operate on numbers).
"""
input_types = getattr(self, "_input_types", None)
if input_types is not None and column_name in input_types:
return input_types[column_name]

import pyarrow as pa

from DashAI.back.types.value_types import Float

return Float(arrow_type=pa.float64())
19 changes: 0 additions & 19 deletions DashAI/back/converters/scikit_learn/generic_univariate_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
)
from DashAI.back.core.schema_fields.base_schema import BaseSchema
from DashAI.back.core.utils import MultilingualString
from DashAI.back.types.dashai_data_type import DashAIDataType
from DashAI.back.types.value_types import Float, Integer


Expand Down Expand Up @@ -83,21 +82,3 @@ class GenericUnivariateSelect(
)
IMAGE_PREVIEW = "generic_univariate_select.png"
metadata = {"allowed_types": [Float, Integer], "allowed_dtypes": []}

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
"""
import pyarrow as pa

return Float(arrow_type=pa.float64())
19 changes: 0 additions & 19 deletions DashAI/back/converters/scikit_learn/select_fdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from DashAI.back.core.schema_fields import float_field, schema_field
from DashAI.back.core.schema_fields.base_schema import BaseSchema
from DashAI.back.core.utils import MultilingualString
from DashAI.back.types.dashai_data_type import DashAIDataType
from DashAI.back.types.value_types import Float, Integer


Expand Down Expand Up @@ -104,21 +103,3 @@ def __init__(self, **kwargs):
schema fields. Forwarded to the underlying scikit-learn class.
"""
super().__init__(**kwargs)

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
"""
import pyarrow as pa

return Float(arrow_type=pa.float64())
19 changes: 0 additions & 19 deletions DashAI/back/converters/scikit_learn/select_fpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from DashAI.back.core.schema_fields import float_field, schema_field
from DashAI.back.core.schema_fields.base_schema import BaseSchema
from DashAI.back.core.utils import MultilingualString
from DashAI.back.types.dashai_data_type import DashAIDataType
from DashAI.back.types.value_types import Float, Integer


Expand Down Expand Up @@ -95,21 +94,3 @@ def __init__(self, **kwargs):
schema fields. Forwarded to the underlying scikit-learn class.
"""
super().__init__(**kwargs)

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
"""
import pyarrow as pa

return Float(arrow_type=pa.float64())
19 changes: 0 additions & 19 deletions DashAI/back/converters/scikit_learn/select_fwe.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from DashAI.back.core.schema_fields import float_field, schema_field
from DashAI.back.core.schema_fields.base_schema import BaseSchema
from DashAI.back.core.utils import MultilingualString
from DashAI.back.types.dashai_data_type import DashAIDataType
from DashAI.back.types.value_types import Float, Integer


Expand Down Expand Up @@ -96,24 +95,6 @@ class SelectFwe(FeatureSelectionConverter, SklearnWrapper, SelectFweOperation):
IMAGE_PREVIEW = "select_fwe.png"
metadata = {"allowed_types": [Float, Integer], "allowed_dtypes": []}

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
"""
import pyarrow as pa

return Float(arrow_type=pa.float64())

def __init__(self, **kwargs):
"""Initialize the SelectFwe converter.

Expand Down
19 changes: 0 additions & 19 deletions DashAI/back/converters/scikit_learn/select_k_best.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
)
from DashAI.back.core.schema_fields.base_schema import BaseSchema
from DashAI.back.core.utils import MultilingualString
from DashAI.back.types.dashai_data_type import DashAIDataType
from DashAI.back.types.value_types import Float, Integer


Expand Down Expand Up @@ -83,24 +82,6 @@ class SelectKBest(FeatureSelectionConverter, SklearnWrapper, SelectKBestOperatio
IMAGE_PREVIEW = "select_k_best.png"
metadata = {"allowed_types": [Float, Integer], "allowed_dtypes": []}

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
"""
import pyarrow as pa

return Float(arrow_type=pa.float64())

def __init__(self, **kwargs):
"""Initialize the SelectKBest converter.

Expand Down
19 changes: 0 additions & 19 deletions DashAI/back/converters/scikit_learn/select_percentile.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from DashAI.back.core.schema_fields import int_field, schema_field
from DashAI.back.core.schema_fields.base_schema import BaseSchema
from DashAI.back.core.utils import MultilingualString
from DashAI.back.types.dashai_data_type import DashAIDataType
from DashAI.back.types.value_types import Float, Integer


Expand Down Expand Up @@ -87,24 +86,6 @@ class SelectPercentile(
IMAGE_PREVIEW = "select_percentile.png"
metadata = {"allowed_types": [Float, Integer], "allowed_dtypes": []}

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
"""
import pyarrow as pa

return Float(arrow_type=pa.float64())

def __init__(self, **kwargs):
"""Initialize the SelectPercentile converter.

Expand Down
39 changes: 28 additions & 11 deletions DashAI/back/converters/scikit_learn/variance_threshold.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,25 +96,35 @@ class VarianceThreshold(
def fit(
self, x: "DashAIDataset", y: Union["DashAIDataset", None] = None
) -> "VarianceThreshold":
"""Fit the transformer, allowing all features to be removed if none pass.
"""Fit the selector, remembering input types and tolerating empty output.

sklearn raises a ValueError when no feature meets the threshold; we catch
it and return self instead so that ``transform`` can legitimately return a
dataset with zero columns. ``self.variances_`` is already populated by
sklearn before it raises, so the internal state is correct.
VarianceThreshold only drops low-variance columns without modifying the
retained columns' values, so their original types are captured here to be
returned later by ``get_output_type`` instead of coercing to float. Types
are recorded during ``fit`` (rather than ``transform``) because
scikit-learn auto-wraps ``transform`` on subclasses and would coerce its
output back to a pandas DataFrame.

Additionally, sklearn raises a ValueError when no feature meets the
threshold; we catch it and return self instead so that ``transform`` can
legitimately return a dataset with zero columns. ``self.variances_`` is
already populated by sklearn before it raises, so the internal state is
correct.

Parameters
----------
x : DashAIDataset
Input dataset.
The input dataset to fit the selector on.
y : DashAIDataset, optional
Ignored; present for API consistency.

Returns
-------
VarianceThreshold
The fitted instance.
The fitted selector instance (self).
"""
if hasattr(x, "types") and x.types is not None:
self._input_types = dict(x.types)
try:
return super().fit(x, y)
except ValueError as e:
Expand All @@ -125,19 +135,26 @@ def fit(
return self

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.
"""Return the original DashAI data type of a retained column.

Since the selection leaves the retained columns' values unchanged, the
output type matches the input type of that column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.
The name of the retained column. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
The original type of the column. Falls back to ``float64`` when the
input type is unknown (the selector only operates on numbers).
"""
input_types = getattr(self, "_input_types", None)
if input_types is not None and column_name in input_types:
return input_types[column_name]

import pyarrow as pa

return Float(arrow_type=pa.float64())
Expand Down
Loading