Първият тип модели, които ми идват на ум, когато мисля за регресията с множество изходи, определено не е GBM. Предпочитам да мисля за невронните мрежи, известни със своята гъвкавост. Създаването на модел за дълбоко обучение е като игра с блокове, докато използването на GBM е по-скоро като, да речем, пране с пералня. Сипвате прах и омекотител, който харесвате, избирате програма, слагате мръсните дрехи и се надявате, че ще работи според очакванията. Не можете лесно да смените двигателя, настроен за дадена задача, или да разширите уреда си с втори барабан за по-голямо пране. Не е възможно без да влезете по-дълбоко и да си изцапате ръцете. Както и да е, връщайки се към точката, ние сме в състояние да генерираме множество изходни данни за всяка входна проба, с която е захранен моделът за усилване на градиента. В тази статия бих искал да отговоря на два въпроса:

  1. Защо може да се нуждаем от регресия с множество изходни данни?
  2. Как можем да извършим регресия с множество изходни данни с GBM?

Необходимостта от регресия с множество изходи

Нека започнем с това — може би неочаквано — съпоставяне на множество резултати срещу множество цели. Изненадващо, тези два термина не са необходими еднакви във всички случаи.

Тук също има много объркващи термини.

  • Не смесвайте термините за множествена регресия и многовариантна регресия. Първият означава, че използваме няколко входни (обяснителни) променливи, докато във втория случай имаме множество целеви променливи.
  • Като вероятностна регресия имам предвид задача, в която трябва да генерираме параметри на разпределение на случайна променлива вместо точкови оценки. Например, приемайки гаусово разпределение, трябва да произведем два параметъра (средно и стандартно отклонение) като изход за всяко наблюдение.
  • В контекста на прогнозирането на времеви редове често искаме да генерираме прогнози за повече от една стъпка напред. Проблемът е, че често използваме закъснели стойности, които не са известни в бъдещето. За да преодолеем това, ние прилагаме напр. рекурсивен или директен подход за прогнозиране.
  • Вероятно най-озадачаващата опция е регресия с ядрени изходни данни.
    Това е техника, която трансформира задача с много изходни данни в нискоразмерен (тук: едноизмерен) сурогатен проблем¹⁵. По време на моето проучване не открих никаква реализация, базирана на GBM, но открих теоретични статии, описващи такова решение за градиентно усилване¹³ и за дърво-базирани модели¹4 като цяло. Като мотивиращ пример ви препоръчвам да проучите документацията на Operalib. Това е библиотека на Python, внедряваща куп модели с ядрено изходно пространство.
  • Разбира се, това не е пълен списък. Може да се нуждаем и от комбинация от по-горе, например многоетапно многовариантно вероятностно прогнозиране:) В такъв случай броят на необходимите прогнози може да се изчисли като horizon_length x n_target_variables x n_distribution_params.

Следващата важна забележка —„можем да получим множество изходи по два начина:

  • създаване на един съвместен модел за всички целеви променливи
  • изграждане на nнезависими, едновариантни модели

Не предполагам, че всеки подмодел приема точно същия набор от функции като вход. Както и да е, трябва да помним, че при втория подход няма взаимодействие между подмоделите по време на обучението. Когато използваме един модел, можем да се възползваме от съвместната оптимизация. Всеки допълнителен член във функцията на загубите може да се разглежда като ограничение, което влияе върху модела подобно на регуляризацията. Понякога допълнителни цели (или изходи за една цел) могат да се използват само като спомагателни задачи¹⁶необходими са ни само по време на обучението.

Многоцелеви набор от данни

За да покажем всички опции, които имаме в тази област, трябва да намерим (или създадем) поне един набор от данни, представящ ситуация, когато наличието на един модел за множество цели е благоприятно. Добър списък с такъв набор от данни е достъпен на уебсайта на стара Java ML библиотека, наречена Mulan². Въпреки че връзката за изтегляне на оригиналния уебсайт изглежда нефункционираща, има и GitHub репо от Григориос Цумакас (един от авторите на Mulan lib), което съдържа наборите от данни, които търсим. Те се съхраняват там в рядко срещан .arffформат. Избрах набор от данни на име enb, описан като:

Наборът от данни за енергийни сгради (Tsanas и Xifara 2012) се отнася до предвиждането на изискванията за отоплителен товар и охлаждащ товар на сградите (т.е. енергийна ефективност) като функция на осем параметъра на сградата, като площ на остъкляване, площ на покрива и обща височина, между други.

Наборът от данни има осем колони за входни характеристики и две целеви променливи — можем лесно да го заредим с помощта на кодовия фрагмент на Python, показан по-долу.

from scipy.io import arff
import pandas as pd
import urllib.request
from sklearn.model_selection import train_test_split

def get_multitarget_data(name: str) -> pd.DataFrame:
    """Get multitaget regression dataset"""
    url = \
        f'https://raw.githubusercontent.com/tsoumakas/mulan/master/data/multi-target/{name}.arff'
    urllib.request.urlretrieve(url, f"{name}.arff")
    arff_data = arff.loadarff(f"{name}.arff")
    return pd.DataFrame(arff_data[0])

enb = get_multitarget_data('enb')

X, y = enb.iloc[:, :-2], enb.iloc[:, -2:]
X_train, y_train, X_test, y_test = train_test_split(X, y, test_size=.2)

# Single target variable (Y1 only)
y_train_single, y_test_single = y_train.iloc[:, 0], y_test.iloc[:, 0]

Общи решения за регресия с множество изходи

Множество цели

Най-лесният начин за генериране на множество прогнози наведнъж е да използвате клас MultiOutputRegressor от scikit-learn. Бих искал ясно да подчертая, че това е само вид помощен клас: вместо да пишем цикъл на ръка, ние използваме MultiOutputRegressorкойтовътрешно го прави вместо нас. Така че този подход е приложим само когато искаме да обучим отделни и независими модели, по един за всяка целева променлива.

from sklearn.multioutput import MultiOutputRegressor
from xgboost import XGBRegressor

multi_reg = MultiOutputRegressor(
  estimator = XGBRegressor()
)

multi_reg.fit(X_train, y_train)
multi_reg_pred = multi_reg.predict(X_test)

pd.DataFrame(multi_reg_pred, columns=['Y1', 'Y2'])

Този метод не е подходящ за генериране на множество квантили с помощта на функцията за загуба на квантили, тъй като можем да предадем само един модел като аргумент. След това предаденият оценител се копира автоматично и се използва за моделиране на връзката между всички входни променливи и всяка целева колона поотделно. Еквивалентно можем да използваме нещо като:

models = {}
predictions = {

# Training
for target_column in targets:
  models[target_column] = XGBRegressor().fit(X_train, y_train[target_column])

# Predicting
for target_column in targets:
  predictions[target_column] = models[target_column].predictt(X_test)

predictions = pd.DataFrame(predictions)

Една цел, множество изходи

Нека се върнем към случая с квантилна регресия. Ако искаме да приложим обвивка с API като scikit-learn, трябва да се запознаем с библиотеката ML-Ensemble. Ако не посочим никакъв мета-оценител, нашият SuperLearner пасва на всички подмодели и връща прогнози от всичките им прогнози. Това е един от най-типичните сценарии на регресия с множество изходи с една цел.

from mlens.ensemble import SuperLearner
from lightgbm import LGBMRegressor

ensemble = SuperLearner()
ensemble.add([
    LGBMRegressor(objective='quantile', alpha=.1), 
    LGBMRegressor(objective='quantile', alpha=.5),
    LGBMRegressor(objective='quantile', alpha=.9)
])
ensemble.fit(X_train, y_train_single)
multi_quantile_pred = ensemble.predict(X_test)

pd.DataFrame(
    multi_quantile_pred, 
    columns=['quantile_10', 'quantile_50', 'quantile_90']
)

Можем да постигнем същия ефект, като използваме StackingRegressor от scikit-learn и получаваме изходни данни за подмодели чрез извикване на метода transform, но това решение е малко хакерско и не мога да го препоръчам. Това е така, защото StackingRegressor е предназначен да бъде модел, който винаги обучава своя мета-оценител и комбинира прогнозите на подмоделите, когато извиква метода predict.

Решения, свързани с времеви редове

Има няколко библиотеки на Python, свързани с времеви серии, които предоставят приятен интерфейс, улесняващ многоетапното прогнозиране. Те заслужават отделна дискусия, така че не искам да навлизам в подробности тук. Бих искал да покажа само прост пример за употреба.

from sktime.datasets import load_airline
from sktime.forecasting.compose import make_reduction
from sktime.forecasting.model_selection import temporal_train_test_split
from xgboost import XGBRegressor

# Dataset
y_ts = load_airline()
y_train_ts, y_test_ts = temporal_train_test_split(y_ts, test_size=24)

# Creating & fitting the model
# Deasonalization is not mandatory in this particular example, 
# but I encourage you to experiment and try it as well
dir_reg = TransformedTargetForecaster(
    [
        # ("deseasonalize", Deseasonalizer(model="multiplicative", sp=12)),
        ("detrend", Detrender(forecaster=PolynomialTrendForecaster(degree=1))),
        ("forecast", make_reduction(
              XGBRegressor(), window_length=12, strategy="direct"
            ),
        ),
    ]
)

dir_reg.fit(y=y_train_ts, fh=list(range(1, 25)))

# dir_reg is an object of class DirectTabularRegressionForecaster
# with 10 submodels, for each defined step of the future horizon
print(dir_reg.estimators)

# Forecasting - if we don't use any exogenous regressors (variables), 
# we call the predict function without any additional arguments
pred = pd.DataFrame(dir_reg.predict())
pred = pred.reset_index()
pred.columns = ['period', 'pred']

y_ts = pd.DataFrame(y_ts.reset_index())
y_ts.columns = ['period', 'actual']

results = y_ts.merge(pred, how='outer')
results.plot(x='period', y=['actual', 'pred'])

С дървовиден модел трябва да сме особено внимателни. Способността на дървовидните модели за екстраполация е много ограничена. Добра практика тогава е да се разлагат времевите редове и да се прогнозират всички компоненти поотделно (тенденция, сезонност, остатъци).

Други забележителни библиотеки, предлагащи подобни функции, са skforecast и tspiral. За готов за използване модел на времеви серии, базиран на XGBoost, разгледайте библиотеката darts. Всички тези обвивки клонират базовия обект многократно (стратегия за директно прогнозиране) или генерират прогнози в цикъл, като използват прогнозата t-1 като вход за генериране на прогнозата за следващата стъпка.

Регресия с множество изходи с помощта на GBM библиотеки

Може да не сте наясно с това, но повечето от често използваните модели за усилване на градиента в Python могат да генерират множество изходни данни за проба наведнъж. Има две основни стратегии, които те използват за постигане на тази цел, аналогични на двата подхода, които представих в първия раздел.

Както виждаме, схемата по-горе се разклонява като фрактал в десния клон. Избирайки втората опция (напр. отказ от MultipleOutputRegressor в полза на единичен GBM модел), се изправяме пред подобен избор:

  • един слаб модел за всяка итерация
  • множество независими слаби модели за всяка итерация

Подходът с независими модели се нарича „един срещу всички в няколко статии⁹, но мисля, че този термин подхожда повече на проблема с класификацията. Възниква следният въпрос: различават ли се подходите на множество ансамбъли и единичен ансамбъл + множество слаби модели или всъщност са идентични?
Не се колебайте да ме поправите, ако греша, но вярвам, че за повечето задачи, резултатите от единичен модел с множество слаби модели трябва да бъдат еквивалентни за обучение на множество, независими ансамбли от модели. Поне стига да не използваме функция на загуба, която изрично взема предвид взаимодействието между изходните стойности (вижте: вероятностна регресия). Но ако използваме например MSE за множество цели, мисля, че вариантът „единичен ансамбъл + множество слаби модели“ може да се разглежда като обучение на множество ансамбъли паралелно.

Тук също е добре да споменем, че DecisionTreeRegressorна scikit-learn поддържа и „множество изходи“. В края на тази статия ще се опитаме да внедрим персонализиран GBM модел, като използваме точно този оценител като слаб инструмент.

Обобщавайки останалата част от статията, подготвих таблица, показваща, доколкото ми е известно, какви са механизмите, използвани за предсказване на множество изходи в конкретни GBM библиотеки на Python.

LightGBM

В момента LightGBM (най-популярният GBM модел в Kaggle) няма директна поддръжка за мулти-изходна регресия. Но има „скелетен ключ“, който да отвори тази врата. Това е така, защото LightGBM всъщност е в състояние да решава задачи с множество изходи. Той използва множество слаби обучаеми, което може ясно да се види в кода на C++, където броят на класовете се счита за „броя дървета на итерация“. След това можем да използваме необработен клас Booster(или функция train) и да се преструваме, че решаваме задача за класификация. Трябва да дефинираме персонализирана функция за загуба и да използваме целевите колони от глобалната променлива, защото не можем да я предадем чрез обект от клас Набор от данни.

import lightgbm as lgb

# Compare: https://github.com/microsoft/LightGBM/blob/ffb298626e131b9d213b34b3655846be441fdc12/src/objective/regression_objective.hpp#L127
def multi_mse(y_hat, dtrain): 
    """Based on the simplified MSE commonly used in GBM models"""
    y_true = y_train.values
    grad = y_hat.reshape(y_true.shape, order="F") - y_true
    hess = np.ones_like(y_true)
    return grad.flatten("F"), hess.flatten("F")

# We should choose a relatively small value of min_data_in_leaf in this task
# Otherwise, we'll get:
# [LightGBM] [Warning] No further splits with positive gain, best gain: -inf
params = {
    "num_class": 2,
    "random_seed": 7,
    "verbose": 1,
    "num_boost_round": 100,
    "min_data_in_leaf": 5
}

# Please note, that we don't pass y_train as label argument of 
# the Dataset class object, because LightGBM doesn't accept 
# multiple target columns and raises the following error:
# (ValueError: DataFrame for label cannot have multiple columns).
dtrain = lgb.Dataset(X_train)

lgb_model = lgb.train(
    train_set = dtrain,
    params    = params,
    fobj      = multi_mse
)

lgb_pred = lgb_model.predict(X_test)
pd.DataFrame(lgb_pred, columns=['Y1', 'Y2'])

Ако трябва да върнем набор от параметри на вероятностното разпределение (една цел, множество изходни данни) за всяка проба, можем да предадем цел с една колона като етикет и да използваме подходяща функция за загуба. Вдъхновяващо изпълнение може да се намери в хранилището на LightGBMLSS.

XGBoost

В случая с библиотеката XGBoost не е нужно да прибягваме до никакви трикове, за да стартираме регресионен модел с множество изходи. Нека погледнем за момент съответната част от документацията на XGBoost (Множество изходи).

Вътрешно XGBoost изгражда един модел за всяка цел, подобно на sklearn meta оценителите, с допълнителното предимство от повторно използване на данни и други интегрирани функции като SHAP.

Използването е доста лесно и изглежда по следния начин:

xgb_reg = XGBRegressor()
xgb_reg.fit(X_train, y_train)
xgb_pred = xgb_reg.predict(X_test)
pd.DataFrame(xgb_pred, columns=['Y1', 'Y2'])

Дори не е необходимо да пропускаме специален аргумент, за да посочим броя на изходите. Всичко е направено при монтаж на модел. Според документацията текущата версия за разработка (2.0) поддържа моделиране на множество квантили наведнъж. Освен това, ровейки в чистия C++ код, срещаме файл, който предполага, че решение, базирано на многоцелеви дървета, може да бъде налично в бъдеще (multi_target_tree.cc).

CatBoost

Не е изрично написано в официалната документация, но един от разработчиците на CatBoost (Евгени Петров) твърди в коментар към издание на GitHub:

Мултирегресията е функция на загуба, включваща множество целеви колони.
Catboost изгражда един модел, за да минимизира тази загуба.
Тази загуба се изчислява съгласно https://catboost.ai/docs/concepts/loss -functions-multiregression.html

Изглежда, че CatBoost изгражда един общ модел за всички цели.

from catboost import CatBoostRegressor

cb_reg = CatBoostRegressor(objective='MultiRMSE', verbose=0)
cb_reg.fit(X_train, y_train)
cb_pred = cb_reg.predict(X_test)
pd.DataFrame(cb_pred, columns=['Y1', 'Y2'])

Друг интересен пример за използване на тази функция CatBoost може да бъде намерен на Kaggle в „бележник за състезания“ (Прогнозиране на механизми на действие (MoA)).

scikit-learn

GradientBoostRegressorв момента не поддържа многоцелева регресия. Но си струва да споменем, че scikit-learn вече предлага няколко модела, които го правят: LinearRegression(и свързани), KNeighborsRegressor, DecisionTreeRegressor, RandomForestRegressor (и свързани)³. Интересното е, че те все още не са изброени в съответния раздел в документацията на scikit-learn. Както и да е, те могат лесно да бъдат идентифицирани въз основа на подробности в документите на API за метод за прилягане, напр. за LinearRegression можем да видим:

fit(X, y, sample_weight=None)

yподобна на масив форма (n_samples,) или (n_samples, n_targets)

Надявам се, че GBM за регресия с множество изходи ще бъде добавен в бъдеще.

NGboost

NGBoost е по-малко известна библиотека, която използва естествен градиент.⁵ Тя е много по-модулна от най-популярното трио (LightGBM, XGBoost, CatBoost) и ни позволява да изберем персонализиран базов оценител и да дефинираме вид разпределение на вероятността за целева променлива(и). Оптимизацията се извършва съвместно, но във всяка итерация обучава толкова оценители, колкото параметри има избраното разпределение. И така, като се има предвид и пример с едномерно разпределение на Гаус в i-татаитерация, имаме един слаб обучаем, който оценява средната стойност, и вторият, който оценява стандартното отклонение. Този подход може да бъде разширен и до многовариантна вероятностна регресия⁶ — много цели и (потенциално) много резултати за всяка цел. За многомерното нормално разпределение броят на параметрите се изчислява като d(d+1)/2, където d означава броя на целевите променливи. Това означава, че за две цели имаме пет слаби модела на итерация, за три — девет слаби модела и т.н.

Що се отнася до самия естествен градиент, това е интересна идея, която взема предвид локалната кривина, за да ограничи дължината на конкретните стойности във вектора на градиента. Каня ви да се запознаете с по-подробни материали по тази вдъхновяваща тема.⁷

from ngboost import NGBRegressor
from ngboost.distns import MultivariateNormal

dist = MultivariateNormal(2)
ngb = NGBRegressor(Dist=dist).fit(X_train, y_train)
pd.DataFrame(ngb_pred, columns=['Y1', 'Y2'])

# Check also:
# ngb_dist = ngb.pred_dist(X_test)
# ngb_dist.params

TensorFlow Decision Forest

Към момента на писане на тази статия регресията с множество изходи е налична само като набор от независимо обучени модели (поисках това в „проблем на GitHub“). Въпреки това, както разбрах, идва нова версия и тя ще донесе нови механизми за справяне с регресионни задачи с множество изходи.

Последната версия на TF-DF все още има независими модели за всяка цел. Въпреки това, „скорошен ангажимент“ към YDF позволи многозадачно обучение, при което изходът от модели, обучени като вторични, се използва като вход за „първичния“ модел. Тези (и вероятно още) промени в многозадачните модели ще се приземят със следващата версия на TF-DF.

YDF означава Yggdrasil Decision Forest, името на C++ библиотеката, на която се базира TF-DF.⁸

import tensorflow_decision_forests as tfdf
import pandas as pd

# Load a dataset in a Pandas dataframe.

train_df = enb.loc[X_train.index]
test_df = enb.loc[X_test.index]

mulitask = [tfdf.keras.MultiTaskItem(label=t, task=tfdf.keras.Task.REGRESSION)
           for t in ENB_TARGETS]

# Train a GBM model
model = tfdf.keras.GradientBoostedTreesModel(
    multitask = mulitask,
    loss = 'SQUARED_ERROR'
)

# Instead of passing arrays, you can also make use of TensorFlow Dataset
# See: tfdf.keras.pd_dataframe_to_tf_dataset
y_dict = {
    'Y1':y_train.iloc[:, 0].values,
    'Y2':y_train.iloc[:, 1].values
}
model.fit(X_train.values, y_dict)
tdff_pred = model.predict(X_test.values)
pd.DataFrame({k:v.ravel() for k, v in tdff_pred.items()})

Ако сте заинтригувани от Keras, който неочаквано се появява в контекста на GBM, моля, вижте TF-DF уроци. Keras е адаптиран като име за удобен за потребителя интерфейс, версията за дълбоко обучение също. Особено любопитно е, че GBM и NN „Kerases“ са съвместими и можете да поставите GBM (или произволна гора) модел като част от конвейер на Keras.

Py-Boost

Съдейки по звездите на GitHub, това е много ниша библиотека, доста свежа, но непозната от ML общността. Реших да го представя тук поради добрата му поддръжка за регресия с множество изходи. Тази библиотека приема няколко метода, които са насочени към трансформиране на проблеми с множество изходи в по-прости. Разделителите на цели се използват за разделяне на целевите променливи на групи, докато опцията за скициране служи за намаляване на проблема (напр. чрез премахване на някои целеви променливи от изчисленията) и прави обучението по-евтино от изчислителна гледна точка .⁹

from py_boost import GradientBoosting, SketchBoost
# strategies to deal with multiple outputs
from py_boost.multioutput.sketching import *
from py_boost.multioutput.target_splitter import *

# Sketching - a method to reduce the dimensionality of the output space
# during the training
sketch = RandomProjectionSketch(1)
# sketch = RandomSamplingSketch(10)
# sketch = TopOutputsSketch(10)
# sketch = SVDSketch(n_components=1)

pb_reg = GradientBoosting(
      loss = 'mse', 
      ntrees=100, 
      target_splitter='Single',
      multioutput_sketch=sketch
)

# The only diffrence in SketchBoost is the fact we can define 
# Target splitter is defined as 'Single' by default
pb_reg = SketchBoost(
      loss = 'mse', 
      ntrees=100, 
      sketch_method='topk'
)

pb_reg.fit(X_train, y_train)
pd.DataFrame(ngb_pred, columns=['Y1', 'Y2'])

За съжаление, не можах да тествам тази библиотека поради проблемите, които срещнах, когато се опитвах да я използвам на две различни машини (вероятно свързани с версията cupy). Ако не ви е обезсърчило, моля, погледнете уроците по Py-Boost и този преносим компютър Kaggle.

Писане на многоизходен GBM модел от нулата

Приключваме нашето пътуване — накрая ще се опитаме да внедрим персонализиран GBM регресор с много изходи, използвайки sklearn DecisionTreeRegressor
като седмичен обучаем. Както вече споменах, той поддържа множество изходи, така че ще използваме тази функция. Ще внедрим прост, ванилов GBM без хеси и други фантастични неща. Ще използваме еквивалент на MSE, обикновено използван в библиотеките на GBM, изчислен като:

Използвайки този леко модифициран вариант на MSE, получаваме по-проста производна w. r. T. прогноза.

Псевдоостатъците, които търсим тук, са просто остатъци (градиент пъти -1). Можем да пропуснем третата стъпка в цикъла, т.е. коригиране на прогнозите в листата на дървото, защото DecisionTreeRegressorвече прави това, което искаме.

class MultiOutputGBM:
    
    def __init__(self, 
                 n_estimators: int = 100, 
                 max_depth: int = 3,
                 eta: float = .1):
        self.eta = eta
        self.estimators_ = [
            DecisionTreeRegressor(max_depth=max_depth) 
            for _ in range(n_estimators)
        ]
    
    def fit(self, X, y):

        # Calculate mean
        self.n_outputs = y.shape[1]
        self.mean = y.mean(axis=0)
        pred = np.ones(y.shape) * self.mean.values
        
        for est in self.estimators_:
            
            # Gradient vector multiplied by -1
            pseudo_residuals = y - pred
            
            # Fitting the model, returning predictions
            est.fit(X, pseudo_residuals)
            
            # In the third step, we have to adjust the prediction 
            # in the "terminal regions", i.e. leaves of the regression tree
            # Gamma may be a single value or a vector of different values for each 
            # leaf of the tree. See: Friedman TreeBoost
            # leaves = tree.apply(X_train)
            
            # In this particular case, we can skip this step
            
            pred += est.predict(X) * self.eta
            
    def predict(self, X):
        pred = np.ones((len(X), self.n_outputs)) * self.mean.values
        for est in self.estimators_:
            pred += est.predict(X) * self.eta
        return pred

mgbm = MultiOutputGBM()
mgbm.fit(X_train, y_train)
mgbm_pred = mgbm.predict(X_test)
pd.DataFrame(mgbm_pred, columns=['Y1', 'Y2'])

Получените прогнози изглеждат подобни на резултатите от други модели на GBM. Можем да разширим нашия модел с някои механизми, заимствани от доказани библиотеки за усилване на градиента като XGBoost или LightGBM.

Препратки

  1. форум на numer.ai (2021) Машини за повишаване на градиента за многоцелева регресия
  2. Mulan: Библиотека на Java за обучение с множество етикетиотTsoumakas G., Spyromitros-Xioufis E., Vilcek J. (достъп до април 2023 г.)
  3. Как да разработим многоизходни регресионни модели с Python — MachineLearningMastery.comот Джейсън Браунли (достъп април 2023 г.)
  4. März A. (2019) XGBoostLSS — Разширение на XGBoost за вероятностно прогнозиране
  5. Дуан Т., Авати А., И Динг Д., Тай Кх. K., Basu S., Ng A. Y. и Schuler A. (2019) NGBoost: Усилване на естествен градиент за вероятностно прогнозиране
  6. O’Malley M., Sykulski A., Lumpkin R. и Schuler A. (2021) Многовариантна вероятностна регресия с усилване на естествен градиент
  7. Амари С., (1998) Защо естествен градиент?
  8. Guillame-Bert M., Bruch S., Stotz R. и Pfeifer J. (2022) Yggdrasil Decision Forests: A Fast and Extensible Decision Forests Library
  9. Iosipoi L. и Vakhrushev A. (2022) SketchBoost: Дърво на вземане на решения с бърз градиент за многоизходни проблеми
  10. Borchani H., Varando Gh., Bielza C. и Larranaga P. (2015) Проучване за регресия с множество изходни данни
  11. Xu D., Shi Y., Tsang I. W., Ong Y-S, Gong Ch. и Шен X. (2019) Проучване за обучението с множество резултати
  12. Zhang Zh., Jung Ch. (2019) GBDT-MO: Градиентно подсилени дървета на решения за множество изходи
  13. Geurts P., Wehenkel L. и d’Alché-Buc F., (2007) Усилване на градиента за ядрени изходни пространства
  14. Geurts, P., Wehenkel, L. и d’Alché Buc F. (2006). Кърнелизиране на изхода на методите, базирани на дърво
  15. d’Alché Buc F., (2022) Да се ​​научим да предвиждаме сложни резултати (презентация)
  16. Li X., Zhu D. и Levy Ph. (2018) Използване на спомагателни мерки: дълбока многозадачна невронна мрежа за прогнозно моделиране в клинични изследвания