Skip to content

Conversation

dmitryglhf
Copy link
Collaborator

@dmitryglhf dmitryglhf commented Apr 12, 2025

This is a 🙋 feature or enhancement.

Summary

todo's:

  • blending
  • compare methods
  • update docs
  • write tests

done:

  • added dummy data forwarding operation
  • added blending implementation
  • fixed fedot[extra] dependencies spam message

Context

#1375

Copy link
Contributor

github-actions bot commented Apr 12, 2025

All PEP8 errors has been fixed, thanks ❤️

Comment last updated at Fri, 27 Jun 2025 20:02:04

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Apr 12, 2025

Enseble assumption compare (benchmark small 1h8c):

Metric (mean) gbm gbm_hybrid gbm_2lvl_stack gbm_hybrid_cb gbm_2lvl_blend
0 auc 0.879746 0.871537 0.859823 0.856519 0.860444
1 acc 0.852339 0.850318 0.83734 0.833489 0.838583
2 balacc 0.822745 0.824295 0.807395 0.807066 0.812628
3 logloss 0.377827 0.471679 0.453203 0.416617 0.432081
4 training_duration 225.525 234.726 353.45 222.308 338.158

Объединять изначальные данные с предсказаниями моделей и далее снова получать мета-данные что в gbm_2lvl_stack, что в gbm_2lvl_blend преимуществ не дает. Скорее всего они просто переобучаются и там нужна более тонкая настройка гиперпараметров или выбор более простых моделей на втором уровне. Сомневаюсь стоит ли ставить эти ансамбли в начальные приближения.

The core idea of gbm_hybrid is to concatenate the original input data with metadata generated by boosting models.
image

The core idea of gbm_2lvl_stack is to concatenate the original data with metadata generated by boosting models, and then use cached models to extract additional metadata for the final logistic regression. Like kind of feature engeneering.
image

upd:
gbm_hybrid_cb
image

gbm_2lvl_blend
image

@dmitryglhf dmitryglhf added enhancement New feature or request in progress task in progress labels Apr 12, 2025
@dmitryglhf dmitryglhf self-assigned this Apr 12, 2025
@dmitryglhf dmitryglhf linked an issue Apr 12, 2025 that may be closed by this pull request
@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Apr 12, 2025

regression datasets (from https://www.jmlr.org/papers/volume25/22-0493/22-0493.pdf)

upd: small version

---

- name: abalone
  openml_task_id: 359944

- name: Allstate_Claims_Severity
  openml_task_id: 233212

- name: black_friday
  openml_task_id: 359937

- name: boston
  openml_task_id: 359950

- name: Brazilian_houses
  openml_task_id: 359938

- name: colleges
  openml_task_id: 359942

- name: house_prices_nominal
  openml_task_id: 359951

- name: house_sales
  openml_task_id: 359949

- name: Mercedes_Benz_Greener_Manufacturing
  openml_task_id: 233215

- name: MIP-2016-regression
  openml_task_id: 360945

- name: Moneyball
  openml_task_id: 167210

- name: pol
  openml_task_id: 359946

@dmitryglhf
Copy link
Collaborator Author

iris_gbm_stacking_preds.csv

Dataset for blending test

"imbalanced"
]
},
"forward": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Может назвать joint или merge?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, думаю стоит

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Apr 17, 2025

Regression small set compare:

Metric (mean) rfr gbm_stacking
0 mae 9150.81 8915.07
1 r2 0.687841 0.664533
2 rmse 16752.9 16037.9
3 training_duration 523.714 163.595

Датасет Allstate_Claims_Severity на текущем начальном приближении почему-то отрабатывал ~7000 секунд. Ансамбль отработал ~1600 секунд. Из-за этого и выросло среднее время. Если сравнивать без этого датасета, то результаты будут следующими:

Metric (mean) rfr gbm_stacking
0 mae 9725.92 9615.79
1 r2 0.698951 0.674907
2 rmse 17827.1 17318.9
3 training_duration 48.0255 32.47

Странновато, что с выключенными тюнером и композером ансамбль из 4 моделей обучается быстрее. Попробую пройтись отладчиком и посмотреть в чем там причина. Думаю можно в этом пиаре попробовать обновить начальные приближения и для регрессии (возможно с блендингом и прокидыванием данных).

Copy link

codecov bot commented Apr 23, 2025

Codecov Report

Attention: Patch coverage is 39.37824% with 117 lines in your changes missing coverage. Please review.

Project coverage is 80.02%. Comparing base (0cd7f05) to head (92c37fb).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...ation/operation_implementations/models/blending.py 27.35% 85 Missing ⚠️
fedot/core/operations/evaluation/ensemble.py 50.00% 22 Missing ⚠️
fedot/core/pipelines/verification_rules.py 45.45% 6 Missing ⚠️
...erations/topological/fast_topological_extractor.py 25.00% 3 Missing ⚠️
fedot/core/operations/evaluation/boostings.py 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1385      +/-   ##
==========================================
- Coverage   80.77%   80.02%   -0.75%     
==========================================
  Files         148      151       +3     
  Lines       10755    10946     +191     
==========================================
+ Hits         8687     8760      +73     
- Misses       2068     2186     +118     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Apr 24, 2025

Сравнение ансамблей на бенчмарке 1h8c

Metric (mean) gbm_logit gbm_blending bagging_gbm_blending bagging_gbm_logit
0 auc 0.879746 0.878133 0.867138 0.881507
1 acc 0.852339 0.854805 0.854593 0.85425
2 balacc 0.822745 0.827653 0.824738 0.822385
3 logloss 0.377827 0.336674 0.416477 0.51269
4 training_duration 79.7875 82.4544 542.762 538.448

Стекинг через линейную регрессию с разными регуляризаторами:

Metric (mean) stack_no_penalty stack_l1_saga stack_l2_lbfgs stack_elasticnet
0 auc 0.871348 0.875342 0.879746 0.878615
1 acc 0.848532 0.85287 0.852339 0.852256
2 balacc 0.821035 0.82583 0.822745 0.823983
3 logloss 0.724979 0.394178 0.377827 0.382851
4 training_duration 79.6825 80.1513 79.9606 79.5794

В основном блендинг показывает себя эффективнее. При этом его реализация пока что черновая, можно попробовать добиться более хороших показателей, если настраивать количество итераций, прунинг и выбор алгоритма оптимизации весов.

upd upd:
очень странно, но после последних подтянутых изменений (до кеша) время обучения сильно снизилось

upd upd upd:
в среднем все же l2 регрессия как мета-модель лучше, чем эластик или l1

gbm_logit:
image

gbm_blending:
image

bagging_gbm_blending:
image

@dmitryglhf
Copy link
Collaborator Author

/fix-pep8

@dmitryglhf
Copy link
Collaborator Author

Metric (mean) meta_dt
0 auc 0.850675
1 acc 0.727823
2 balacc 0.701652
3 logloss 1.06223
4 training_duration 219.317

В качестве ансамблирующего узла здесь были применены деревья решений с фиксированной макс. глубиной = 3. Довольно нестабильные результаты, скорее всего дерево переобучается.

image

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented May 11, 2025

Сравнение обычных бустингов с бэггингами, в которых эстиматорами являются бустинги:

  • по auc, accuracy, balanced accuracy бэггинг выигрывает у всех моделей.
  • модель cb_bag показывает лучшие результаты, но серьезно дольше обучается и видимо становится не такой уверенной, раз лосс заметно вырос
  • lgbm_bag от бэггинга выиграл больше остальных моделей
  • xgb_bag от бэггинга не сильно выигрывает, но просто показывает довольно неплохие результаты

В целом, результаты бэггингов сопоставимы с ансамблем из бустингов. Дальше попробую запустить на бенчмарке ансамбль из этих бэггингов через линейную регрессию и через средневзвешенное.

upd: сравнение для случайного леса

Metric (mean) catboost cb_bag lgbm lgbm_bag xgboost xgb_bag rf rf_bag
0 auc 0.87359 0.881677 0.861714 0.881694 0.871553 0.876589 0.875267 0.881177
1 acc 0.846294 0.857782 0.824486 0.846193 0.847917 0.850999 0.846349 0.844233
2 balacc 0.813449 0.827728 0.800927 0.818779 0.819958 0.821379 0.816384 0.812029
3 logloss 0.350001 0.402061 0.41169 0.372419 0.369402 0.370547 0.440977 0.417781
4 training_duration 100.405 382.174 119.953 118.354 97.1181 171.209 83.2906 121.602

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Jun 7, 2025

optuna n_trials = 100
scipy.linporg max_iter = 100

Metric (mean) gbm_blending_bayesian gbm_blending_linprog
auc 0.877191 0.876343
acc 0.850666 0.850019
balacc 0.825441 0.824303
logloss 0.358187 0.366337
training_duration 170.124 159.581
predict_duration 4.91425 4.74556

@dmitryglhf
Copy link
Collaborator Author

/fix-pep8

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Jun 9, 2025

@nicl-nno @Lopa10ko @DRMPN

Как вам текущая реализация блендинга? Пока убрал его из начальных приближений и из доступа для композера, чтобы покрывать больше краевых случаев с уже обкатанным стекингом через линейную регрессию. Но он работает и им можно пользоваться. Добавил обработку в graph_verification, так что эволюция должна работать корректно.

И по поводу бэггинга? Решил использовать наиболее подходящие на мой взгляд захардкоженные модели. В планах было сделать универсальный узел, который будет принимать модель и обучать её на подвыборках, но, наверное, для этого нужно делать константный репозиторий по которому можно будет подтягивать модели для обучения. Как грамотно использовать модели не через константный репозиторий, а прокидывать в пайплайне у меня пока идей нет. И как-будто в бэггинге нуждаются не все модели.

Comment on lines 28 to 33
'cb_bag': CatBoostBaggingClassification,
'cbreg_bag': CatBoostBaggingRegression,
'xgb_bag': XGBoostBaggingClassification,
'xgbreg_bag': XGBoostBaggingRegression,
'lgbm_bag': LGBMBaggingClassification,
'lgbmreg_bag': LGBMBaggingRegression
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: есть смысл семантически вынести все, что является bagging атомарными моделями, в BaggingStrategy или переименовать BoostingStrategy в EnsembleStrategy

upd: оказыватся, EnsembleStrategy уже есть. тогда, видимо, первый вариант будет норм, если еще и расплодить ...Strategy из (Boosting..., Bagging..., Blending..., Stacking...)

Comment on lines 17 to 24
if 'is_extra_deps_installed' not in globals():
is_extra_deps_installed = True
if is_extra_deps_installed:
logging.log(100,
"Topological features operation requires extra dependencies for time series forecasting, "
"which are not installed. It can infuence the performance. "
"Please install it by 'pip install fedot[extra]'")
is_extra_deps_installed = False
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

правильно ли я понял, что это изменение для того, чтобы в одном рантайме не засорять лог советами установить fedot[extra]?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

да


def __init__(self, params: Optional[OperationParameters] = None):
super().__init__(params)
self.seed = 42 # constant seed for optuna
Copy link
Collaborator

@Lopa10ko Lopa10ko Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: даже если это внутренний seed для TPESampler, хочется иметь возможность его передавать в конструкторе в виде параметра

Suggested change
self.seed = 42 # constant seed for optuna
self.seed = self.params.get('seed', 42) # constant seed for optuna

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.seed = 42
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь seed захардкожен?

Copy link
Collaborator Author

@dmitryglhf dmitryglhf Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

да, потому что он влияет только на оптимизацию весов моделей. мне показалось, что сид здесь лучше сделать постоянным. по совету выше добавил возможность передавать его через params

upd: прошу прощения, перепутал классы, здесь это лишний параметр

@dmitryglhf
Copy link
Collaborator Author

/fix-pep8

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Jun 14, 2025

Вроде вышло сделать бэггинг унифицированным узлом, который принимает любую модель и обучает её на подвыборках. Из ограничений:

  • решил отказаться от того, чтобы обучать сразу несколько моделей, приходящий в бэггинг, в связи с непредсказуемым поведением
  • бэггинг не может идти после ансамблевой операции (н-р blending)
  • бэггинг не может принимать операцию над данными (н-р scaling).

Из проблем: модель обучается дважды, на предыдущем шаге и в узле бэггинга. Пока думаю как можно убрать обучения предыдущей модели, при этом сохранив возможность получать её инстанс из PipelineNode. Есть вариант обходить граф перед обучением и создавать тэг для моделей, идущих перед бэггингом, но что делать после этого пока идей нет.

bag

Без тюнинга гиперпараметров иногда получается серьезно бустануть метрику (здесь accuracy на задаче с каггла):

image

@nicl-nno
Copy link
Collaborator

модель обучается дважды, на предыдущем шаге и в узле бэггинга

Текущая реализация кэша тут не поможет?

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Jun 15, 2025

модель обучается дважды, на предыдущем шаге и в узле бэггинга

Текущая реализация кэша тут не поможет?

Раньше input_data.supplementary_data.previous_operations принимал список названий предыдущих моделей, но теперь он получает список самих предыдущих узлов (PipelineNode).

Проблема в следующем:
Чтобы извлечь класс модели из узла и обучить его на подвыборках (в бэггинге), нужно сначала обучить сам узел, тогда экземпляр модели появится в атрибуте fitted_model.

Даже если модель закеширована на предыдущем шаге, её всё равно нужно загрузить и переобучить внутри бэггинга. Это приводит к двойному обучению: cначала на предыдущем шаге, затем на каждой подвыборке в бэггинге.

Время обучения увеличивается почти вдвое, хотя можно было бы передать необученный инстанс модели и обучать его только на подвыборках.

@dmitryglhf
Copy link
Collaborator Author

dmitryglhf commented Jun 20, 2025

Убрал имплементацию бэггинга

Blending with average strategy:

Metric (mean) blend_average
0 auc 0.883921
1 acc 0.844852
2 balacc 0.812706
3 logloss 0.357775
4 training_duration 27.2189
5 predict_duration 0.908108

Mean for each task:

task auc acc balacc logloss training_duration predict_duration
0 Australian 0.936599 0.866666 0.86444 0.370817 1.47 0.062
1 blood-transfusion 0.739766 0.758072 0.545537 0.490869 1.11 0.023
2 car nan 0.737287 0.663491 0.451923 1.83 0.08
3 christine 0.807658 0.730957 0.730957 0.537347 240.387 7.2125
4 cnae-9 nan 0.912963 0.912963 0.286278 27.01 1.4
5 credit-g 0.771381 0.756 0.652381 0.511409 1.88 0.092
6 dilbert nan nan nan nan nan nan
7 fabert nan 0.705353 0.677538 0.866471 145.06 5.27
8 jasmine 0.867779 0.807968 0.807964 0.414122 5.53 0.2
9 kc1 nan nan nan nan 1.87 0.067
10 kr-vs-kp 0.998956 0.989361 0.989365 0.0350383 3.42 0.1
11 mfeat-factors nan 0.9735 0.9735 0.104299 11.17 0.2
12 phoneme 0.950598 0.887678 0.861174 0.258132 2.57 0.032
13 segment nan 0.974892 0.974892 0.077791 3.18 0.07
14 sylvine 0.983379 0.944381 0.944378 0.153016 2.64 0.041
15 vehicle nan 0.76007 0.76296 0.487254 1.79 0.033

Blending with weighted strategy:

Metric (mean) blend_weighted
0 auc 0.88104
1 acc 0.851347
2 balacc 0.821692
3 logloss 0.344111
4 training_duration 20.2568
5 predict_duration 0.61777

Mean for each task:

task auc acc balacc logloss training_duration predict_duration
0 Australian 0.93345 0.863768 0.863956 0.330122 3.85 0.064
1 blood-transfusion 0.72025 0.768775 0.582043 0.507416 3.38 0.023
2 car nan 0.743067 0.665589 0.45351 4.26 0.084
3 christine 0.790265 0.708334 0.708344 0.579956 243.025 7.325
4 cnae-9 nan 0.92037 0.92037 0.258993 29.52 1.4
5 credit-g 0.761762 0.745 0.664524 0.575221 4.17 0.094
6 dilbert nan nan nan nan nan nan
7 fabert nan 0.704714 0.680351 0.872901 148.983 5.41667
8 jasmine 0.860097 0.803965 0.803969 0.430116 7.87 0.2
9 kc1 nan nan nan nan 4.17 0.071
10 kr-vs-kp 0.999184 0.99061 0.990618 0.0335936 5.75 0.1
11 mfeat-factors nan 0.976667 0.976667 0.091979 13.2333 0.2
12 phoneme 0.947464 0.884715 0.85853 0.273286 4.91 0.031
13 segment nan 0.970996 0.970996 0.0839645 5.5 0.075
14 sylvine 0.981387 0.944772 0.944768 0.170103 5.07 0.043
15 vehicle nan 0.761177 0.763922 0.484204 4.61 0.042

@dmitryglhf dmitryglhf force-pushed the ensemble-operations branch from 51ecb5f to 5d5a018 Compare June 21, 2025 11:18
@dmitryglhf
Copy link
Collaborator Author

/fix-pep8

@dmitryglhf
Copy link
Collaborator Author

/fix-pep8

@dmitryglhf dmitryglhf requested a review from nicl-nno July 9, 2025 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request in progress task in progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add ensemble operations
4 participants