MultiOutputRegressor: несколько прогнозов с понятными именами

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

Определить, независимы ли задачи обучения

MultiOutputRegressor создаёт отдельный экземпляр базового регрессора для каждого столбца цели. Это удобная обёртка над алгоритмом, который сам не поддерживает несколько выходов. Она не учит общую зависимость между целями: каждый estimator видит свой целевой столбец. Если связь целей важна для постановки, потребуется другой подход.

Некоторые регрессоры уже поддерживают многомерный y. Для них обёртка может оказаться лишней или изменить способ обучения. Сначала проверьте интерфейс выбранного алгоритма. В примере SVR имеет одну цель, поэтому отдельные estimator действительно нужны.

Закрепить порядок выходов до fit

Имена целей задаём вместе с построением y. Первая позиция всегда относится к сборке, вторая — к доставке. После predict связываем значения с тем же списком имён. Сам MultiOutputRegressor не угадывает смысл числового столбца. При сохранении артефакта эти имена должны сопровождать модель.

Учебные цели следуют двум разным линейным зависимостям. Линейное ядро SVR позволяет получить понятную проверку для нового входа. Проверяем два обученных estimator, форму результата и конкретное соответствие значений именам.

from math import isclose
from sklearn.multioutput import MultiOutputRegressor
from sklearn.svm import SVR

target_names = ("assembly_minutes", "delivery_minutes")
X = [[0], [1], [2], [3]]
y = [[2 * i, 100 - 3 * i] for i in range(4)]
model = MultiOutputRegressor(SVR(kernel="linear", C=100,
                                 epsilon=0), n_jobs=1).fit(X, y)
prediction = model.predict([[4]])
assert len(model.estimators_) == 2
assert prediction.shape == (1, 2)
record = dict(zip(target_names, prediction[0].tolist()))
assert isclose(record["assembly_minutes"], 8, abs_tol=1e-3)
assert isclose(record["delivery_minutes"], 88, abs_tol=1e-3)
bundle = {"model": model, "target_names": target_names}
assert bundle["target_names"] == ("assembly_minutes", "delivery_minutes")
print(record)

Описать ограничения результата

Согласуйте единицы каждой цели. Даже две длительности могут относиться к разным точкам отсчёта. Массив подходящей формы не обнаружит, что один столбец интерпретируется в часах вместо минут. Имена, порядок и единицы удобнее хранить как часть контракта артефакта.

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

Закрепить базовую операцию

В первом открытом уроке fit и predict вы пройдёте обучение одной числовой цели. После этого добавьте вторую цель и явно подпишите выходные значения, как в примере. Откройте урок «Первый fit и predict на своих данных». Затем вернитесь к сценарию статьи и проверьте его на своём небольшом наборе. Посмотрите программу курса первой ML-модели, чтобы пройти путь от обучения к использованию результата.

Продолжить на практике