4. Маршрутизация метаданных#
Примечание
API маршрутизации метаданных является экспериментальным и еще не реализован для всех оценивателей. Пожалуйста, обратитесь к список поддерживаемых и неподдерживаемых
моделей для получения дополнительной информации. Это может измениться без обычного цикла устаревания. По умолчанию эта функция не включена. Вы можете включить её, установив enable_metadata_routing флаг для
True:
>>> import sklearn
>>> sklearn.set_config(enable_metadata_routing=True)
Обратите внимание, что методы и требования, представленные в этом документе, актуальны только
если вы хотите передать метаданные (например, sample_weight) в метод.
Если вы передаете только X и y и никаких других параметров / метаданных для
методов, таких как fit, преобразовать, и т.д., то вам не нужно ничего настраивать.
Это руководство демонстрирует, как метаданные могут быть направлены и переданы между объектами в scikit-learn. Если вы разрабатываете совместимый с scikit-learn оценщик или мета-оценщик, вы можете ознакомиться с нашим руководством для разработчиков: Маршрутизация метаданных.
Метаданные — это данные, которые оценщик, скорер или разделитель CV учитывает, если пользователь явно передает их в качестве параметра. Например, KMeans принимает
sample_weight в его fit() метод и учитывает его для вычисления своих центроидов.
classes потребляются некоторыми классификаторами и groups используются в некоторых разделителях, но
любые данные, передаваемые в методы объекта, кроме X и y, могут рассматриваться как
метаданные. До версии scikit-learn 1.3 не было единого API для передачи
метаданных, если эти объекты использовались вместе с другими объектами, например, с
оценщиком, принимающим sample_weight внутри GridSearchCV.
С API маршрутизации метаданных мы можем передавать метаданные оценщикам, скорерам и разделителям CV с помощью мета-оценщики (такие как Pipeline или
GridSearchCV) или функции, такие как
cross_validate которые направляют данные к другим объектам. Чтобы передать метаданные методу, такому как fit или score, объект, потребляющий метаданные,
должен request это. Это делается через set_{method}_request() методы, где {method}
заменяется именем метода, запрашивающего метаданные. Например,
оценщики, использующие метаданные в своих fit() метод будет использовать set_fit_request(),
и скореры использовали бы set_score_request(). Эти методы позволяют нам указать, какие метаданные запрашивать, например set_fit_request(sample_weight=True).
Для групповых сплиттеров, таких как GroupKFold, a
groups параметр запрашивается по умолчанию. Это лучше всего демонстрируется
следующими примерами.
4.1. Примеры использования#
Здесь мы представляем несколько примеров, чтобы показать некоторые распространённые случаи использования. Наша цель — передать
sample_weight и groups через cross_validate, который направляет метаданные в LogisticRegressionCV и к пользовательской метрике, созданной с помощью make_scorer, оба из которых может использовать метаданные в своих методах. В этих примерах мы хотим индивидуально установить, использовать ли метаданные в различных потребители.
Примеры в этом разделе требуют следующих импортов и данных:
>>> import numpy as np
>>> from sklearn.metrics import make_scorer, accuracy_score
>>> from sklearn.linear_model import LogisticRegressionCV, LogisticRegression
>>> from sklearn.model_selection import cross_validate, GridSearchCV, GroupKFold
>>> from sklearn.feature_selection import SelectKBest
>>> from sklearn.pipeline import make_pipeline
>>> n_samples, n_features = 100, 4
>>> rng = np.random.RandomState(42)
>>> X = rng.rand(n_samples, n_features)
>>> y = rng.randint(0, 2, size=n_samples)
>>> my_groups = rng.randint(0, 10, size=n_samples)
>>> my_weights = rng.rand(n_samples)
>>> my_other_weights = rng.rand(n_samples)
4.1.1. Взвешенное оценивание и обучение#
Разделитель, используемый внутри LogisticRegressionCV,
GroupKFold, requests groups по умолчанию. Однако нам нужно
явно запросить sample_weight для него и для нашего пользовательского скорера, указав
sample_weight=True в LogisticRegressionCV’s set_fit_request()
метод и в make_scorer’s set_score_request() метод. Оба
потребители знать, как использовать sample_weight в их fit() или
score() методы. Затем мы можем передать метаданные в
cross_validate который направит его любому активному потребителю:
>>> weighted_acc = make_scorer(accuracy_score).set_score_request(sample_weight=True)
>>> lr = LogisticRegressionCV(
... cv=GroupKFold(),
... scoring=weighted_acc,
... use_legacy_attributes=False,
... ).set_fit_request(sample_weight=True)
>>> cv_results = cross_validate(
... lr,
... X,
... y,
... params={"sample_weight": my_weights, "groups": my_groups},
... cv=GroupKFold(),
... scoring=weighted_acc,
... )
Обратите внимание, что в этом примере, cross_validate маршруты my_weights
как оценщику, так и LogisticRegressionCV.
Если бы мы передали sample_weight в параметрах
cross_validate, но не устанавливает никакой объект для его запроса,
UnsetMetadataPassedError будет вызвана, намекая нам, что нужно явно установить,
куда его направить. То же самое применяется, если params={"sample_weights": my_weights, ...}
были переданы (обратите внимание на опечатку, т.е. weights вместо weight), поскольку
sample_weights не был запрошен ни одним из его базовых объектов.
4.1.2. Взвешенная оценка и невзвешенное обучение#
При передаче метаданных, таких как sample_weight в маршрутизатор
(мета-оценщики или функция маршрутизации), все sample_weight потребители требуют, чтобы веса были либо явно запрошены, либо явно не запрошены (т.е. True или False). Таким образом, чтобы выполнить невзвешенную подгонку, нам нужно
настроить LogisticRegressionCV не запрашивать веса образцов, чтобы cross_validate не передает веса:
>>> weighted_acc = make_scorer(accuracy_score).set_score_request(sample_weight=True)
>>> lr = LogisticRegressionCV(
... cv=GroupKFold(), scoring=weighted_acc, use_legacy_attributes=False
... ).set_fit_request(sample_weight=False)
>>> cv_results = cross_validate(
... lr,
... X,
... y,
... cv=GroupKFold(),
... params={"sample_weight": my_weights, "groups": my_groups},
... scoring=weighted_acc,
... )
Если linear_model.LogisticRegressionCV.set_fit_request не был вызван,
cross_validate вызовет ошибку, потому что sample_weight
передан, но LogisticRegressionCV не будет явно настроен на распознавание весов.
4.1.3. Не взвешенный отбор признаков#
Маршрутизация метаданных возможна только если метод объекта знает, как использовать метаданные, что в большинстве случаев означает, что они имеют их в качестве явного параметра. Только тогда мы можем установить запрашиваемые значения для метаданных с помощью set_fit_request(sample_weight=True), например.
Это делает объект потребитель.
В отличие от LogisticRegressionCV,
SelectKBest не может обрабатывать веса и, следовательно, нет запрашиваемого значения для sample_weight на его экземпляре установлен и sample_weight не направляется
к ней:
>>> weighted_acc = make_scorer(accuracy_score).set_score_request(sample_weight=True)
>>> lr = LogisticRegressionCV(
... cv=GroupKFold(), scoring=weighted_acc, use_legacy_attributes=False
... ).set_fit_request(sample_weight=True)
>>> sel = SelectKBest(k=2)
>>> pipe = make_pipeline(sel, lr)
>>> cv_results = cross_validate(
... pipe,
... X,
... y,
... cv=GroupKFold(),
... params={"sample_weight": my_weights, "groups": my_groups},
... scoring=weighted_acc,
... )
4.1.4. Различные веса оценки и подгонки#
Несмотря на make_scorer и
LogisticRegressionCV оба ожидают ключ
sample_weight, мы можем использовать псевдонимы для передачи разных весов разным
потребителям. В этом примере мы передаём scoring_weight для оценщика, и
fitting_weight to LogisticRegressionCV:
>>> weighted_acc = make_scorer(accuracy_score).set_score_request(
... sample_weight="scoring_weight"
... )
>>> lr = LogisticRegressionCV(
... cv=GroupKFold(), scoring=weighted_acc, use_legacy_attributes=False
... ).set_fit_request(sample_weight="fitting_weight")
>>> cv_results = cross_validate(
... lr,
... X,
... y,
... cv=GroupKFold(),
... params={
... "scoring_weight": my_weights,
... "fitting_weight": my_other_weights,
... "groups": my_groups,
... },
... scoring=weighted_acc,
... )
4.2. Интерфейс API#
A потребитель является объектом (оценщиком, мета-оценщиком, скоррером, сплиттером), который принимает и использует некоторые метаданные по крайней мере в одном из его методов (например,
fit, predict, inverse_transform, transform, score, split). Мета-оценщики, которые только передают метаданные другим объектам (дочерним оценщикам, скорерам или сплиттерам) и не используют метаданные сами, не являются потребителями. (Мета-)Оценщики, которые направляют метаданные другим объектам, являются маршрутизаторы.
(Мета-)оценщик может быть потребитель и маршрутизатор одновременно. (Мета-)Оценщики и сплиттеры предоставляют set_{method}_request метод для каждого метода,
который принимает хотя бы один метаданный. Например, если оценщик поддерживает
sample_weight в fit и score, он предоставляет
estimator.set_fit_request(sample_weight=value) и
estimator.set_score_request(sample_weight=value). Здесь value может быть:
True: метод запрашиваетsample_weight. Это означает, что если метаданные предоставлены, они будут использованы, в противном случае ошибка не возникает.False: метод не запрашиваетsample_weight.None: router вызовет ошибку, еслиsample_weightпередается. Это почти во всех случаях значение по умолчанию при создании объекта и гарантирует, что пользователь устанавливает запросы метаданных явно, когда передаются метаданные. Единственное исключение —Group*Foldразделителей."param_name": псевдоним дляsample_weightесли мы хотим передать разные веса разным потребителям. Если используется псевдоним, мета-оценщик не должен передавать"param_name"для потребителя, ноsample_weightвместо этого, потому что пользователь будет ожидать параметр с именемsample_weight. Это означает, что соответствие между метаданными, требуемыми объектом, например,sample_weightи имя переменной, предоставленное пользователем, например,my_weightsвыполняется на уровне маршрутизатора, а не самим потребляющим объектом.
Метаданные запрашиваются таким же образом для скореров, использующих set_score_request.
Если метаданные, например, sample_weight, передается пользователем, запрос метаданных для
всех объектов, которые потенциально могут потреблять sample_weight должен быть установлен пользователем,
иначе объект маршрутизатора вызовет ошибку. Например, следующий код
вызывает ошибку, поскольку не было явно указано, следует ли sample_weight
должен ли передаваться оценщику scorer или нет:
>>> param_grid = {"C": [0.1, 1]}
>>> lr = LogisticRegression().set_fit_request(sample_weight=True)
>>> try:
... GridSearchCV(
... estimator=lr, param_grid=param_grid
... ).fit(X, y, sample_weight=my_weights)
... except ValueError as e:
... print(e)
[sample_weight] are passed but are not explicitly set as requested or not
requested for LogisticRegression.score, which is used within GridSearchCV.fit.
Call `LogisticRegression.set_score_request({metadata}=True/False)` for each metadata
you want to request/ignore. See the Metadata Routing User guide
for more information.
Проблему можно решить, явно установив значение запроса:
>>> lr = LogisticRegression().set_fit_request(
... sample_weight=True
... ).set_score_request(sample_weight=False)
В конце Примеры использования разделе, мы отключаем флаг конфигурации для маршрутизации метаданных:
>>> sklearn.set_config(enable_metadata_routing=False)
4.3. Статус поддержки маршрутизации метаданных#
Все потребители (т.е. простые оценщики, которые только потребляют метаданные и не маршрутизируют их) поддерживают маршрутизацию метаданных, что означает, что их можно использовать внутри мета-оценщиков, которые поддерживают маршрутизацию метаданных. Однако разработка поддержки маршрутизации метаданных для мета-оценщиков находится в процессе, и вот список мета-оценщиков и инструментов, которые поддерживают и ещё не поддерживают маршрутизацию метаданных.
Мета-оценщики и функции, поддерживающие маршрутизацию метаданных:
Мета-оценщики и инструменты, еще не поддерживающие маршрутизацию метаданных: