aimclub / FEDOT

Automated modeling and machine learning framework FEDOT
https://fedot.readthedocs.io
BSD 3-Clause "New" or "Revised" License
619 stars 84 forks source link

Boosting method implementation (XGBoost) #1209

Open RomanKharkovskoy opened 7 months ago

RomanKharkovskoy commented 7 months ago

План

Как работает

Реализован интерфейс fit/predict в родительском классе FedotXGBoostImplementation

Код ```py class FedotXGBoostImplementation(ModelImplementation): __operation_params = ['n_jobs', 'use_eval_set'] def __init__(self, params: Optional[OperationParameters] = None): super().__init__(params) self.model_params = {k: v for k, v in self.params.to_dict().items() if k not in self.__operation_params} self.model = None def fit(self, input_data: InputData): input_data = input_data.get_not_encoded_data() if self.params.get('use_eval_set'): train_input, eval_input = train_test_data_setup(input_data) train_input = self.convert_to_dataframe(train_input) eval_input = self.convert_to_dataframe(eval_input) train_x, train_y = train_input.drop(columns=['target']), train_input['target'] eval_x, eval_y = eval_input.drop(columns=['target']), eval_input['target'] if self.classes_ is None: eval_metric = 'rmse' elif len(self.classes_) < 3: eval_metric = 'auc' else: eval_metric = 'mlogloss' self.model.fit(X=train_x, y=train_y, eval_set=[(eval_x, eval_y)], eval_metric=eval_metric) else: train_data = self.convert_to_dataframe(input_data) train_x, train_y = train_data.drop(columns=['target']), train_data['target'] self.model.fit(X=train_x, y=train_y) return self.model def predict(self, input_data: InputData): input_data = self.convert_to_dataframe(input_data.get_not_encoded_data()) train_x, _ = input_data.drop(columns=['target']), input_data['target'] prediction = self.model.predict(train_x) return prediction ```

Интерфейс fit/predict не поддерживает работу с внутренним типом данных xgboost.DMatrix, поэтому необходимо было найти обходной путь. В данном случае был использован тип данных pandas.DataFrame.

Внутри интерфейса идёт преобразование InputData в pandas.DataFrame (categorical_idx становятся category, а numerical_idx становятся float

Код ```py @staticmethod def convert_to_dataframe(data: Optional[InputData]): dataframe = pd.DataFrame(data=data.features, columns=data.features_names) dataframe['target'] = data.target if data.categorical_idx is not None: for col in dataframe.columns[data.categorical_idx]: dataframe[col] = dataframe[col].astype('category') if data.numerical_idx is not None: for col in dataframe.columns[data.numerical_idx]: dataframe[col] = dataframe[col].astype('float') return dataframe ```

Таблица сравнения метрик из Fedot'а и из без AutoML (inputer+кодирование категориальных данных)

Датасет Метрика Запуск без AutoML FEDOT
Internet-Advertisements ROC-AUC 0,97622 0,97157
adult ROC-AUC 0,92792 0,88797
Amazon_employee_access ROC-AUC 0,81353 0,82456
credit-g ROC-AUC 0,76364 0,73071
blood-transfusion-service-center ROC-AUC 0,68082 0,70955
kc1 ROC-AUC 0,77625 0,80227
bank-marketing ROC-AUC 0,93192 0,92422
qsar-biodeg ROC-AUC 0,92399 0,91268
electricity ROC-AUC 0,96874 0,96539
ozone-level-8hr ROC-AUC 0,91429 0,89595
car LogLoss 0,04482 0,69721
vehicle LogLoss 0,60539 0,55317
mfeat-factors LogLoss 0,12889 0,16635
pendigits LogLoss 0,03452 0,04912
cardiotocography LogLoss 0,00291 0,00478
page-blocks LogLoss 0,10433 0,11678
nursery LogLoss 0,00611 0,18016
mfeat-karhunen LogLoss 0,19698 0,21434
anneal LogLoss 0,41601 0,42384
satimage LogLoss 0,25953 0,24396

Метрики из коробки оказались лучше, чем метрики из Fedot'а, что может быть связано с внутренним препроцессингом внутри Fedot'а.

pep8speaks commented 7 months ago

Hello @RomanKharkovskoy! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! :beers:

Comment last updated at 2024-02-19 12:50:31 UTC
nicl-nno commented 7 months ago

Выставлять на ревью PR-ы без описания и с PEP8-дефектами - плохая практика.

Изменения не покрыты тестами (нужны в случае если поведение чем-то отличается от предыдущей реализации xgb).

codecov[bot] commented 7 months ago

Codecov Report

Attention: 4 lines in your changes are missing coverage. Please review.

Comparison is base (c53881a) 79.82% compared to head (dacd08e) 80.09%.

Files Patch % Lines
...mplementations/models/boostings_implementations.py 93.33% 4 Missing :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #1209 +/- ## ========================================== + Coverage 79.82% 80.09% +0.26% ========================================== Files 150 150 Lines 10322 10378 +56 ========================================== + Hits 8240 8312 +72 + Misses 2082 2066 -16 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

github-actions[bot] commented 5 months ago

All PEP8 errors has been fixed, thanks :heart:

Comment last updated at
RomanKharkovskoy commented 4 months ago

Не совсем понял, как идёт сравнение с Федотом? Берутся xgboost из коробки и федот с 1 моделью (xgboost)? Тогда перед имплементацией стоит взять больше датасетов (хотя бы 10), запустить их минимум по 5 раз и усреднить Возможно, @nicl-nno знаешь более оптимальные цифры или датасеты подскажешь?

Взял по 10 датасетов для классификации (заменил таблицу в шапке PR'а). XGBoost берётся из коробки + заполняются пропуски с помощью sklearn.SimpleInputer и кодируются категориальные признаки с помощью sklearn.OneHotEncoder. А для сравнения с FEDOT берётся predefined_model='xgboost'

andreygetmanov commented 4 months ago

Не совсем понял, как идёт сравнение с Федотом? Берутся xgboost из коробки и федот с 1 моделью (xgboost)? Тогда перед имплементацией стоит взять больше датасетов (хотя бы 10), запустить их минимум по 5 раз и усреднить Возможно, @nicl-nno знаешь более оптимальные цифры или датасеты подскажешь?

Взял по 10 датасетов для классификации (заменил таблицу в шапке PR'а). XGBoost берётся из коробки + заполняются пропуски с помощью sklearn.SimpleInputer и кодируются категориальные признаки с помощью sklearn.OneHotEncoder. А для сравнения с FEDOT берётся predefined_model='xgboost'

А усреднение по скольки запускам считаешь?