Skip to content

Commit

Permalink
add chonos decoder feature extractor. add channel filtration. minor a…
Browse files Browse the repository at this point in the history
…pi refactoring, minor loader refactoring
  • Loading branch information
v1docq committed Mar 29, 2024
1 parent f5c7e1c commit 0dddde4
Show file tree
Hide file tree
Showing 16 changed files with 436 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
from fedot.core.pipelines.pipeline_builder import PipelineBuilder

from fedot_ind.api.main import FedotIndustrial
from fedot_ind.tools.loader import DataLoader

if __name__ == "__main__":
dataset_name = 'Epilepsy'
dataset_name = 'PhonemeSpectra'
finetune = True
initial_assumption = PipelineBuilder().add_node('channel_filtration').add_node('quantile_extractor').add_node('rf')

industrial = FedotIndustrial(problem='classification',
metric='f1',
timeout=5,
initial_assumption=initial_assumption,
n_jobs=2,
logging_level=20)

train_data, test_data = DataLoader(dataset_name=dataset_name).load_data()

model = industrial.fit(train_data)
if finetune:
model = industrial.finetune(train_data)
else:
model = industrial.fit(train_data)

labels = industrial.predict(test_data)
probs = industrial.predict_proba(test_data)
Expand Down
29 changes: 16 additions & 13 deletions examples/benchmark_example/time_series_uni_clf_benchmark.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from fedot.core.pipelines.pipeline_builder import PipelineBuilder

from benchmark.benchmark_TSC import BenchmarkTSC

experiment_setup = {'problem': 'classification',
Expand All @@ -8,24 +10,25 @@
'logging_level': 10,
'n_jobs': 2,
'early_stopping_iterations': 5,
'initial_assumption': PipelineBuilder().add_node('chronos_extractor').add_node('logit'),
'early_stopping_timeout': 75}

if __name__ == "__main__":
benchmark = BenchmarkTSC(experiment_setup=experiment_setup,
custom_datasets=[
#'EOGVerticalSignal',
#'LargeKitchenAppliances',
#'SemgHandMovementCh2',
# 'BeetleFly',
# 'InlineSkate',
# 'EthanolLevel',
# 'EOGHorizontalSignal',
# 'FaceFour',
# 'Rock',
'ToeSegmentation1',
'CricketZ',
'PigArtPressure',
'FacesUCR'
'Lightning7',
# 'LargeKitchenAppliances',
# 'SemgHandMovementCh2',
# 'BeetleFly',
# 'InlineSkate',
# 'EthanolLevel',
# 'EOGHorizontalSignal',
# 'FaceFour',
# 'Rock',
'ToeSegmentation1',
'CricketZ',
'PigArtPressure',
'FacesUCR'
],
use_small_datasets=True)
benchmark.run()
Expand Down
Empty file.
Empty file.
56 changes: 30 additions & 26 deletions fedot_ind/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from fedot_ind.api.utils.checkers_collections import DataCheck
from fedot_ind.api.utils.path_lib import DEFAULT_PATH_RESULTS as default_path_to_save_results
from fedot_ind.core.architecture.abstraction.decorators import DaskServer
from fedot_ind.core.architecture.preprocessing.data_convertor import ConditionConverter, ApiConverter
from fedot_ind.core.architecture.settings.computational import BackendMethods
from fedot_ind.core.ensemble.random_automl_forest import RAFensembler
from fedot_ind.core.operation.transformation.splitter import TSTransformer
Expand Down Expand Up @@ -98,6 +99,7 @@ def __init__(self, **kwargs):
self.predicted_probs = None
self.predict_data = None
self.target_encoder = None
self.condition_check = ApiConverter()
# map Fedot params to Industrial params
self.config_dict = kwargs
self.config_dict['history_dir'] = prefix
Expand Down Expand Up @@ -125,18 +127,16 @@ def __init_solver(self):
self.logger.info('Initialising Industrial Repository')
self.repo = IndustrialModels().setup_repository()
if self.config_dict['problem'] == 'ts_forecasting':
solver = self.config_dict['initial_assumption'].build()
solver.root_node.parameters = self.model_params
self.solver = self.config_dict['initial_assumption'].build()
self.solver.root_node.parameters = self.model_params
else:
self.logger.info('Initialising Dask Server')
self.config_dict['initial_assumption'] = self.config_dict['initial_assumption'].build(
)
self.config_dict['initial_assumption'] = self.config_dict['initial_assumption'].build()
self.dask_client = DaskServer().client
self.logger.info(
f'LinK Dask Server - {self.dask_client.dashboard_link}')
self.logger.info('Initialising solver')
solver = Fedot(**self.config_dict)
return solver
self.solver = Fedot(**self.config_dict)

def shutdown(self):
self.dask_client.close()
Expand Down Expand Up @@ -194,7 +194,7 @@ def fit(self,
task_params=self.task_params)
self.train_data = input_preproc.check_input_data()
self.target_encoder = input_preproc.get_target_encoder()
self.solver = self.__init_solver()
self.__init_solver()
if self.preprocessing:
self._preprocessing_strategy(self.train_data)
self.solver.fit(self.train_data)
Expand All @@ -217,18 +217,18 @@ def predict(self,
self.predict_data = DataCheck(input_data=self.predict_data,
task=self.config_dict['problem'],
task_params=self.task_params).check_input_data()
if predict_mode == 'RAF_ensemble':
if self.condition_check.ensemble_mode(predict_mode):
self.predicted_labels = self._predict_raf_ensemble()
else:
if isinstance(self.solver, Fedot):
if self.condition_check.solver_is_fedot_class(self.solver):
predict = self.solver.predict(self.predict_data)
else:
predict = self.solver.predict(self.predict_data, 'labels').predict
if self.config_dict['problem'] == 'classification' \
and self.predict_data.target.min() - predict.min() != 0 \
and len(np.unique(predict).shape) != 1:
if self.condition_check.is_multiclf_with_labeling_problem(self.config_dict['problem'],
self.predict_data.target,
predict):
predict = predict + (self.predict_data.target.min() - predict.min())
if self.target_encoder is not None:
if self.condition_check.solver_have_target_encoder(self.target_encoder):
self.predicted_labels = self.target_encoder.inverse_transform(predict)
self.predict_data.target = self.target_encoder.inverse_transform(self.predict_data.target)
else:
Expand All @@ -254,15 +254,16 @@ def predict_proba(self,
self.predict_data = DataCheck(input_data=self.predict_data,
task=self.config_dict['problem'],
task_params=self.task_params).check_input_data()
if predict_mode == 'RAF_ensemble':
if self.condition_check.ensemble_mode(predict_mode):
predict = self.predicted_labels = self._predict_raf_ensemble()
else:
if isinstance(self.solver, Fedot):
if self.condition_check.solver_is_fedot_class(self.solver):
predict = self.solver.predict_proba(self.predict_data)
else:
predict = self.solver.predict(self.predict_data, 'probs').predict
if self.config_dict['problem'] == 'classification' and \
self.predict_data.target.min() - predict.min() != 0:
if self.condition_check.is_multiclf_with_labeling_problem(self.config_dict['problem'],
self.predict_data.target,
predict):
predict = predict + (self.predict_data.target.min() - predict.min())
self.predicted_probs = predict
return self.predicted_probs
Expand All @@ -281,17 +282,20 @@ def finetune(self,
"""

train_data = DataCheck(
input_data=train_data, task=self.config_dict['problem']).check_input_data()
tuning_params = {} if tuning_params is None else tuning_params
train_data = DataCheck(input_data=train_data, task=self.config_dict['problem']).check_input_data()
tuning_params = ApiConverter.tuning_params_is_none(tuning_params)
tuned_metric = 0
tuning_params['metric'] = FEDOT_TUNING_METRICS[self.config_dict['problem']]
for tuner_name, tuner_type in FEDOT_TUNER_STRATEGY.items():
model_to_tune = deepcopy(self.solver.current_pipeline) if isinstance(self.solver, Fedot) \
else deepcopy(self.solver)
if self.condition_check.solver_is_fedot_class(self.solver):
model_to_tune = deepcopy(self.solver.current_pipeline)
elif self.condition_check.solver_is_none(self.solver):
self.__init_solver()
model_to_tune = deepcopy(self.config_dict['initial_assumption'])
else:
model_to_tune = deepcopy(self.solver)
tuning_params['tuner'] = tuner_type
pipeline_tuner, model_to_tune = build_tuner(
self, model_to_tune, tuning_params, train_data, mode)
pipeline_tuner, model_to_tune = build_tuner(self, model_to_tune, tuning_params, train_data, mode)
if abs(pipeline_tuner.obtained_metric) > tuned_metric:
tuned_metric = abs(pipeline_tuner.obtained_metric)
self.solver = model_to_tune
Expand Down Expand Up @@ -386,10 +390,10 @@ def save_optimization_history(self, **kwargs):
f"{self.output_folder}/optimization_history.json")

def save_best_model(self):
if isinstance(self.solver, Fedot):
if self.condition_check.solver_is_fedot_class(self.solver):
return self.solver.current_pipeline.save(path=self.output_folder, create_subdir=True,
is_datetime_in_path=True)
elif isinstance(self.solver, Pipeline):
elif self.condition_check.solver_is_pipeline_class(self.solver):
return self.solver.save(path=self.output_folder, create_subdir=True,
is_datetime_in_path=True)
else:
Expand Down
43 changes: 43 additions & 0 deletions fedot_ind/core/architecture/preprocessing/data_convertor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import pandas as pd
import torch
import torch.nn as nn
from fedot import Fedot
from fedot.core.data.data import InputData, OutputData
from fedot.core.pipelines.pipeline import Pipeline
from fedot.core.repository.dataset_types import DataTypesEnum
from fedot.core.repository.tasks import Task, TaskTypesEnum
from pymonad.list import ListMonad
Expand Down Expand Up @@ -404,6 +406,14 @@ def is_regression_of_forecasting_task(self):
def is_multi_output_target(self):
return isinstance(self.operation_implementation.classes_, list)

@property
def solver_is_fedot_class(self):
return isinstance(self.operation_implementation, Fedot)

@property
def solver_is_none(self):
return self.operation_implementation is None

def output_mode_converter(self, output_mode, n_classes):
if output_mode == 'labels':
return self.operation_implementation.predict(self.train_data.features).reshape(-1, 1)
Expand All @@ -427,6 +437,39 @@ def probs_prediction_converter(self, output_mode, n_classes):
return prediction


class ApiConverter:

@staticmethod
def solver_is_fedot_class(operation_implementation):
return isinstance(operation_implementation, Fedot)

@staticmethod
def solver_is_none(operation_implementation):
return operation_implementation is None

@staticmethod
def solver_is_pipeline_class(operation_implementation):
return isinstance(operation_implementation, Pipeline)

@staticmethod
def tuning_params_is_none(tuning_params):
return {} if tuning_params is None else tuning_params

@staticmethod
def ensemble_mode(predict_mode):
return predict_mode == 'RAF_ensemble'

@staticmethod
def solver_have_target_encoder(encoder):
return encoder is not None

def is_multiclf_with_labeling_problem(self, problem, target, predict):
clf_problem = problem == 'classification'
uncorrect_labels = target.min() - predict.min() != 0
multiclass = len(np.unique(predict).shape) != 1
return clf_problem and uncorrect_labels and multiclass


class DataConverter(TensorConverter, NumpyConverter):
def __init__(self, data):
super().__init__(data)
Expand Down
10 changes: 4 additions & 6 deletions fedot_ind/core/models/manifold/riemann_embeding.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ def extract_centroid_distance(self, input_data: InputData):
SPD = self.covarince_transformer.transform(input_data.features)
SPD = self.shinkage.fit_transform(SPD)


self.covmeans_ = [mean_covariance(SPD[np.array(input_data.target == ll).flatten()],
metric=self.covariance_metric) for ll in self.classes_]

Expand Down Expand Up @@ -140,12 +139,11 @@ def _transform(self, input_data: InputData) -> np.array:
with IndustrialModels():
# riemann_extractor
# pipeline = PipelineBuilder().add_node('eigen_basis').add_node('quantile_extractor').add_node('rf').build()
pipeline = PipelineBuilder().add_node('riemann_extractor', params={'n_filter': 3})\
.add_node('quantile_extractor')\
.add_node('mlp')\
.build()
pipeline = PipelineBuilder().add_node('riemann_extractor', params={'n_filter': 3}) \
.add_node('quantile_extractor') \
.add_node('mlp') \
.build()
pipeline.fit(init_train)
pred = pipeline.predict(init_test)
acc = accuracy_score(y_test, np.round(pred.predict))
print(acc)

Loading

0 comments on commit 0dddde4

Please sign in to comment.